ro-webgl/Assets/Editor/AssetCheckEditor/AnimationClipper.cs
2021-12-21 09:40:39 +08:00

196 lines
5.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEditor;
using UnityEngine;
using System.IO;
using System.Collections.Generic;
public class AnimationClipper : EditorWindow
{
private static AnimationClipper _window = null;
[MenuItem("Tools/优化/动作/动画剪裁")]
public static void ClipAnimation()
{
_window = EditorWindow.GetWindow<AnimationClipper>(false, "AnimationClipWindow", true);
_window.Show();
}
public void OnGUI()
{
if (GUILayout.Button("开始剪裁"))
{
foreach(var obj in Selection.objects)
{
if(obj.GetType() == typeof(AnimationClip))
{
ClipAnimationCurveData((AnimationClip)obj);
EditorUtility.SetDirty(obj);
}
else
{
var path = AssetDatabase.GetAssetPath(obj);
if(Directory.Exists(path))
{
ClipAnimationsInDirectory(path);
}
}
}
AssetDatabase.SaveAssets();
}
}
private static void ClipAnimationsInDirectory(string path)
{
string pathDir = FileUtils.ExtractAssetRelativePath(path);
var files = Directory.GetFiles(pathDir, "*.anim", SearchOption.AllDirectories);
foreach (var file in files)
{
string fileName = FileUtils.ExtractAssetRelativePath(file);
var clip = (AnimationClip)AssetDatabase.LoadAssetAtPath(fileName, typeof(AnimationClip));
if (null != clip)
{
ClipAnimationCurveData((AnimationClip)clip);
EditorUtility.SetDirty(clip);
}
}
}
public static bool ClipAnimationCurveData(AnimationClip clip)
{
if (clip == null)
{
return false;
}
EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(clip);
if (curveBindings == null)
{
return false;
}
AnimationCurve[] curves = new AnimationCurve[curveBindings.Length];
for (int idx =0; idx < curveBindings.Length;idx++)
{
AnimationCurve curve = AnimationUtility.GetEditorCurve(clip, curveBindings[idx]);
curves[idx] = curve;
}
// 清除原来所有的数据
clip.ClearCurves();
float len = clip.length;
for (int idx = 0; idx < curveBindings.Length; idx++)
{
EditorCurveBinding ecb = curveBindings[idx];
AnimationCurve curve = curves[idx];
// 进行过滤
if (IsFilterCurveData(curveBindings[idx].propertyName, curve))
{
continue;
}
// 将数据存回去
clip.SetCurve(ecb.path, ecb.type, ecb.propertyName, curve);
}
curves = null;
return true;
}
public static bool IsFilterCurveData(string propertyName, AnimationCurve curve)
{
if (propertyName.Contains("Position"))
{
return IsNoEffectCurvy(curve, 0);
}
if (propertyName.Contains("Scale"))
{
return IsNoEffectCurvy(curve, 1, true);
}
if (propertyName.Contains("Rotation"))
{
return IsNoEffectCurvy(curve, 0, true);
}
return false;
}
public static bool IsNoEffectCurvy(AnimationCurve curve, float identity, bool reserveIdentity = false)
{
if(curve.keys == null || curve.keys.Length == 0)
{
return true;
}
var keys = new List<Keyframe>(curve.keys);
// 减去多余的帧
for(int i = 0; i < keys.Count;)
{
if(i - 1 < 0)
{
i++;
continue;
}
if(i + 1 >= keys.Count)
{
i++;
continue;
}
// 如果一帧的前一帧和后一帧都和当前帧相等,那么可以删除自己
if (IsKeyFrameEqual(keys[i-1], keys[i]) && IsKeyFrameEqual(keys[i], keys[i+1]))
{
keys.RemoveAt(i);
continue;
}
i++;
}
// 如果只剩下2帧了那么这两帧肯定是相等的根据参数判断是否整个曲线都去掉
if(keys.Count <= 2)
{
if (Mathf.Abs(keys[0].value - identity) < 0.001f && !reserveIdentity)
{
return true;
}
}
curve.keys = keys.ToArray();
return false;
}
private static bool IsKeyFrameEqual(Keyframe frame1, Keyframe frame2)
{
if (Mathf.Abs(frame1.value - frame2.value) > 0.001f)
{
return false;
}
if (Mathf.Abs(frame1.inTangent - frame2.inTangent) > 0.001f)
{
return false;
}
if (Mathf.Abs(frame1.outTangent - frame2.outTangent) > 0.001f)
{
return false;
}
if (Mathf.Abs(frame1.tangentMode - frame2.tangentMode) > 0.001f)
{
return false;
}
return true;
}
}