From 6ea42a28cde6881f25ef7a6b3e5080d16833f2d3 Mon Sep 17 00:00:00 2001 From: ALEXTANG <574809918@qq.com> Date: Thu, 4 May 2023 13:23:21 +0800 Subject: [PATCH] Update AnimationHierarchyEditorTool.cs --- .../Editor/AnimationHierarchyEditorTool.cs | 407 ++++++++++++++---- 1 file changed, 317 insertions(+), 90 deletions(-) diff --git a/Assets/TEngine/Thirdly/Animation/Editor/AnimationHierarchyEditorTool.cs b/Assets/TEngine/Thirdly/Animation/Editor/AnimationHierarchyEditorTool.cs index a2354617..a31c13f8 100644 --- a/Assets/TEngine/Thirdly/Animation/Editor/AnimationHierarchyEditorTool.cs +++ b/Assets/TEngine/Thirdly/Animation/Editor/AnimationHierarchyEditorTool.cs @@ -10,12 +10,14 @@ /// using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using UnityEditor; using UnityEngine; +using System.IO; +using System.Reflection; +using UnityEngine.Profiling; // Local Namespace namespace CGF.Editor.Tools @@ -29,13 +31,13 @@ namespace CGF.Editor.Tools public EditorCurveBinding EditorCurve; - public PathData(string clipName, string currentPath, string lastPath, EditorCurveBinding editorCurve,AnimationClip clip) + public PathData(string clipName, string currentPath, string lastPath, EditorCurveBinding editorCurve, AnimationClip clip) { ClipName = clipName; CurrentPath = currentPath; LastPath = lastPath; EditorCurve = editorCurve; - Clip= clip; + Clip = clip; } } @@ -47,12 +49,11 @@ namespace CGF.Editor.Tools /// \endenglish /// \spanish /// - /// Herramienta que permite canviar la ruta de la jerarqua de las animaciones de un clip de animacin. + /// Herramienta que permite canviar la ruta de la jerarqu韆 de las animaciones de un clip de animaci髇. /// /// \endspanish public class CGFAnimationHierarchyEditorTool : EditorWindow { - #region Public Variables #endregion @@ -62,7 +63,6 @@ namespace CGF.Editor.Tools private enum TypeGameObject { - None, GameObject, @@ -70,7 +70,6 @@ namespace CGF.Editor.Tools /*AnimationClip, RuntimeAnimatorController*/ - }; private TypeGameObject _currentSelectionGameObject; @@ -115,16 +114,13 @@ namespace CGF.Editor.Tools [MenuItem("Tools/Animation Hierarchy Editor Tool")] private static void ShowWindow() { - EditorWindow window = EditorWindow.GetWindow(typeof(CGFAnimationHierarchyEditorTool), false, "Animation Hierarchy Editor Tool", true); window.minSize = new Vector2(1024, 250); - } public CGFAnimationHierarchyEditorTool() { - _currentSelectionGameObject = new TypeGameObject(); _currentSelectionGameObject = TypeGameObject.None; @@ -132,7 +128,6 @@ namespace CGF.Editor.Tools _myanimationClips = new List(); _gameObjects = new List(); - } private void OnEnable() @@ -145,7 +140,6 @@ namespace CGF.Editor.Tools ResetSelection(); this.Repaint(); - } private void ResetSelection() @@ -164,15 +158,11 @@ namespace CGF.Editor.Tools if (Selection.activeGameObject is GameObject) { - _currentSelectionGameObject = TypeGameObject.GameObject; - } else { - _currentSelectionGameObject = TypeGameObject.None; - } DrawSeletedAnimator(); @@ -180,7 +170,6 @@ namespace CGF.Editor.Tools private void DrawSeletedAnimator() { - if (_currentSelectionGameObject != TypeGameObject.GameObject) { return; @@ -212,18 +201,14 @@ namespace CGF.Editor.Tools foreach (AnimationClip i in _myruntime.animationClips) { - _myanimationClips.Add(i); - } _clipNames.Add("All Clips"); foreach (AnimationClip e in _myanimationClips) { - _clipNames.Add(e.name); - } if (_myanimationClips.Count > 0) @@ -240,7 +225,6 @@ namespace CGF.Editor.Tools private void DrawGui() { - bool animations = true; EditorGUILayout.Space(); @@ -279,7 +263,6 @@ namespace CGF.Editor.Tools switch (_selectedMode) { - case 0: GUILayout.Label("Path"); @@ -295,7 +278,6 @@ namespace CGF.Editor.Tools _replaceGameObject = (GameObject)EditorGUILayout.ObjectField(_replaceGameObject, typeof(GameObject), true); break; - } EditorGUILayout.EndHorizontal(); @@ -308,7 +290,6 @@ namespace CGF.Editor.Tools switch (_currentSelectionGameObject) { - case TypeGameObject.GameObject: GUI.enabled = true; @@ -322,7 +303,7 @@ namespace CGF.Editor.Tools else { _currentAnimationClips = new List() { _myanimationClips[index - 1] }; - } + } break; case TypeGameObject.None: @@ -349,7 +330,6 @@ namespace CGF.Editor.Tools switch (_selectedMode) { - case 0: _replacementPath = EditorGUILayout.TextField(_replacementPath); @@ -361,7 +341,6 @@ namespace CGF.Editor.Tools _replacementGameObject = (GameObject)EditorGUILayout.ObjectField(_replacementGameObject, typeof(GameObject), true); break; - } EditorGUILayout.EndHorizontal(); @@ -395,26 +374,22 @@ namespace CGF.Editor.Tools if (GUILayout.Button("Apply All", EditorStyles.toolbarButton, GUILayout.Width(70))) { - foreach (var pathData in _pathDataList) { UpdatePath(pathData); } EditorGUI.FocusTextInControl(null); - } if (GUILayout.Button("Revert All", EditorStyles.toolbarButton, GUILayout.Width(70))) { - foreach (var pathData in _pathDataList) { Revert(pathData); } EditorGUI.FocusTextInControl(null); - } GUI.enabled = true; @@ -425,7 +400,6 @@ namespace CGF.Editor.Tools if (_currentSelectionGameObject != TypeGameObject.None) { - if (_pathDataList != null) { scrollPosContent = EditorGUILayout.BeginScrollView(scrollPosContent); @@ -437,7 +411,6 @@ namespace CGF.Editor.Tools EditorGUILayout.EndScrollView(); } - } if (!animations) @@ -473,9 +446,7 @@ namespace CGF.Editor.Tools GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); - } - } private void Revert(PathData pathData) @@ -487,10 +458,8 @@ namespace CGF.Editor.Tools private void Replace() { - switch (_selectedMode) { - case 0: if (string.IsNullOrEmpty(_replacePath)) @@ -518,7 +487,6 @@ namespace CGF.Editor.Tools { pathData.CurrentPath = ChildPath(_replacementGameObject); } - } break; @@ -532,7 +500,6 @@ namespace CGF.Editor.Tools private void GUICreatePathItem(PathData pathData) { - GameObject newObj; GameObject obj; @@ -548,11 +515,9 @@ namespace CGF.Editor.Tools if (obj == null || obj.GetComponent(pathData.EditorCurve.type) == null) { - propertyNameStyle.normal.textColor = Color.yellow; pathNameStyle.normal.textColor = Color.yellow; - } EditorGUILayout.LabelField(pathData.ClipName, GUILayout.Width(280)); @@ -574,11 +539,9 @@ namespace CGF.Editor.Tools if (!pathData.CurrentPath.Equals(pathData.EditorCurve.path)) { - buttonStyle.fontStyle = FontStyle.Bold; pathNameStyle.fontStyle = FontStyle.Bold; - } pathData.CurrentPath = EditorGUILayout.TextField(pathData.CurrentPath, pathNameStyle); @@ -587,14 +550,11 @@ namespace CGF.Editor.Tools if (obj != null) { - GUI.color = Color.white; - } if (obj == null || obj.GetComponent(pathData.EditorCurve.type) == null) { - GUI.color = Color.yellow; } @@ -617,55 +577,40 @@ namespace CGF.Editor.Tools if (GUILayout.Button("Apply", buttonStyle) && !pathData.CurrentPath.Equals(pathData.EditorCurve.path)) { - UpdatePath(pathData); EditorGUI.FocusTextInControl(null); - } buttonStyle.fontStyle = !pathData.LastPath.Equals(pathData.EditorCurve.path) ? FontStyle.Bold : FontStyle.Normal; if (GUILayout.Button("Revert", buttonStyle) && pathData.CurrentPath.Equals(pathData.EditorCurve.path)) { - - Revert(pathData); - } EditorGUILayout.EndHorizontal(); try { - if (obj != newObj) { - pathData.CurrentPath = ChildPath(newObj); - } - } catch (UnityException ex) { - Debug.LogError(ex.Message); - } - } private void OnInspectorUpdate() { - this.Repaint(); - } private void FillModel() { - try { _pathDataList = new List(); @@ -674,7 +619,8 @@ namespace CGF.Editor.Tools { var pathDataListByClip = FillModelWithCurves(currentAnimationClip.name, AnimationUtility.GetCurveBindings(currentAnimationClip), currentAnimationClip); - var pathDataListByObjectReference = FillModelWithCurves(currentAnimationClip.name, AnimationUtility.GetObjectReferenceCurveBindings(currentAnimationClip), currentAnimationClip); + var pathDataListByObjectReference = FillModelWithCurves(currentAnimationClip.name, AnimationUtility.GetObjectReferenceCurveBindings(currentAnimationClip), + currentAnimationClip); _pathDataList.AddRange(pathDataListByClip); @@ -683,16 +629,12 @@ namespace CGF.Editor.Tools } catch (Exception e) { - Console.WriteLine(e); - } - } - - private List FillModelWithCurves(string clipName, EditorCurveBinding[] curves,AnimationClip clip) + private List FillModelWithCurves(string clipName, EditorCurveBinding[] curves, AnimationClip clip) { var pathDataList = new List(); @@ -712,12 +654,10 @@ namespace CGF.Editor.Tools } return pathDataList; - } private void UpdatePath(PathData pathData) { - if (pathData.CurrentPath.Equals(pathData.EditorCurve.path)) { return; @@ -762,71 +702,51 @@ namespace CGF.Editor.Tools FillModel(); this.Repaint(); - } private GameObject FindObjectInRoot(string path) { - if (_animatorObject == null) { - return null; - } Transform child = _animatorObject.transform.Find(path); if (child != null) { - return child.gameObject; - } else { - return null; - } } private string ChildPath(GameObject obj, bool sep = false) { - if (_animatorObject == null) { - throw new UnityException("Please assign Referenced Animator (Root) first!"); - } if (obj == _animatorObject.gameObject) { - return ""; - } else { - if (obj.transform.parent == null) { - throw new UnityException("Object must belong to " + _animatorObject.ToString() + "!"); - } else { - return ChildPath(obj.transform.parent.gameObject, true) + obj.name + (sep ? "/" : ""); - } - } - } #endregion @@ -840,7 +760,314 @@ namespace CGF.Editor.Tools #region Utility Events #endregion + } +} + +namespace TEngine.Editor +{ + class AnimationOpt + { + static Dictionary _FLOAT_FORMAT; + static MethodInfo getAnimationClipStats; + static FieldInfo sizeInfo; + static object[] _param = new object[1]; + + static AnimationOpt() + { + _FLOAT_FORMAT = new Dictionary(); + for (uint i = 1; i < 6; i++) + { + _FLOAT_FORMAT.Add(i, "f" + i.ToString()); + } + + Assembly asm = Assembly.GetAssembly(typeof(UnityEditor.Editor)); + getAnimationClipStats = typeof(AnimationUtility).GetMethod( + "GetAnimationClipStats", + BindingFlags.Static | BindingFlags.NonPublic + ); + Type aniclipstats = asm.GetType("UnityEditor.AnimationClipStats"); + sizeInfo = aniclipstats.GetField("size", BindingFlags.Public | BindingFlags.Instance); + } + + AnimationClip _clip; + string _path; + + public string path + { + get { return _path; } + } + + public long originFileSize { get; private set; } + + public int originMemorySize { get; private set; } + + public int originInspectorSize { get; private set; } + + public long optFileSize { get; private set; } + + public int optMemorySize { get; private set; } + + public int optInspectorSize { get; private set; } + + public AnimationOpt(string path, AnimationClip clip) + { + _path = path; + _clip = clip; + _GetOriginSize(); + } + + void _GetOriginSize() + { + originFileSize = _GetFileZie(); + originMemorySize = _GetMemSize(); + originInspectorSize = _GetInspectorSize(); + } + + void _GetOptSize() + { + optFileSize = _GetFileZie(); + optMemorySize = _GetMemSize(); + optInspectorSize = _GetInspectorSize(); + } + + long _GetFileZie() + { + FileInfo fi = new FileInfo(_path); + return fi.Length; + } + + int _GetMemSize() + { + return Profiler.GetRuntimeMemorySize(_clip); + } + + int _GetInspectorSize() + { + _param[0] = _clip; + var stats = getAnimationClipStats.Invoke(null, _param); + return (int)sizeInfo.GetValue(stats); + } + + void _OptmizeAnimationScaleCurve() + { + if (_clip != null) + { + //去除scale曲线 + foreach (EditorCurveBinding theCurveBinding in AnimationUtility.GetCurveBindings(_clip)) + { + string name = theCurveBinding.propertyName.ToLower(); + if (name.Contains("scale")) + { + AnimationUtility.SetEditorCurve(_clip, theCurveBinding, null); + Debug.LogFormat("关闭{0}的scale curve", _clip.name); + } + } + } + } + + void _OptmizeAnimationFloat_X(uint x) + { + if (_clip != null && x > 0) + { + //浮点数精度压缩到f3 + AnimationClipCurveData[] curves = null; + curves = AnimationUtility.GetAllCurves(_clip); + Keyframe key; + Keyframe[] keyFrames; + string floatFormat; + if (_FLOAT_FORMAT.TryGetValue(x, out floatFormat)) + { + if (curves != null && curves.Length > 0) + { + for (int ii = 0; ii < curves.Length; ++ii) + { + AnimationClipCurveData curveDate = curves[ii]; + if (curveDate.curve == null || curveDate.curve.keys == null) + { + //Debug.LogWarning(string.Format("AnimationClipCurveData {0} don't have curve; Animation name {1} ", curveDate, animationPath)); + continue; + } + + keyFrames = curveDate.curve.keys; + for (int i = 0; i < keyFrames.Length; i++) + { + key = keyFrames[i]; + key.value = float.Parse(key.value.ToString(floatFormat)); + key.inTangent = float.Parse(key.inTangent.ToString(floatFormat)); + key.outTangent = float.Parse(key.outTangent.ToString(floatFormat)); + key.inWeight = float.Parse(key.inWeight.ToString(floatFormat)); + key.outWeight = float.Parse(key.outWeight.ToString(floatFormat)); + keyFrames[i] = key; + } + + curveDate.curve.keys = keyFrames; + _clip.SetCurve( + curveDate.path, + curveDate.type, + curveDate.propertyName, + curveDate.curve + ); + } + } + } + else + { + Debug.LogErrorFormat("目前不支持{0}位浮点", x); + } + } + } + + public void Optimize(bool scaleOpt, uint floatSize) + { + if (scaleOpt) + { + _OptmizeAnimationScaleCurve(); + } + + _OptmizeAnimationFloat_X(floatSize); + _GetOptSize(); + } + + public void Optimize_Scale_Float3() + { + Optimize(false, 3); + } + + public void LogOrigin() + { + _logSize(originFileSize, originMemorySize, originInspectorSize); + } + + public void LogOpt() + { + _logSize(optFileSize, optMemorySize, optInspectorSize); + } + + public void LogDelta() + { + } + + void _logSize(long fileSize, int memSize, int inspectorSize) + { + Debug.LogFormat( + "{0} \nSize=[ {1} ]", + _path, + string.Format( + "FSize={0} ; Mem->{1} ; inspector->{2}", + EditorUtility.FormatBytes(fileSize), + EditorUtility.FormatBytes(memSize), + EditorUtility.FormatBytes(inspectorSize) + ) + ); + } } + public class OptimizeAnimationClipTool + { + static List _AnimOptList = new List(); + static List _Errors = new List(); + static int _Index = 0; + + [MenuItem("Assets/Animation/裁剪浮点数去除Scale")] + public static void Optimize() + { + _AnimOptList = FindAnims(); + if (_AnimOptList.Count > 0) + { + _Index = 0; + _Errors.Clear(); + EditorApplication.update = ScanAnimationClip; + } + } + + private static void ScanAnimationClip() + { + AnimationOpt _AnimOpt = _AnimOptList[_Index]; + bool isCancel = EditorUtility.DisplayCancelableProgressBar( + "优化AnimationClip", + _AnimOpt.path, + (float)_Index / (float)_AnimOptList.Count + ); + _AnimOpt.Optimize_Scale_Float3(); + _Index++; + if (isCancel || _Index >= _AnimOptList.Count) + { + EditorUtility.ClearProgressBar(); + Debug.Log( + string.Format( + "--优化完成-- 错误数量: {0} 总数量: {1}/{2} 错误信息↓:\n{3}\n----------输出完毕----------", + _Errors.Count, + _Index, + _AnimOptList.Count, + string.Join(string.Empty, _Errors.ToArray()) + ) + ); + Resources.UnloadUnusedAssets(); + GC.Collect(); + AssetDatabase.SaveAssets(); + EditorApplication.update = null; + _AnimOptList.Clear(); + _cachedOpts.Clear(); + _Index = 0; + } + } + + static Dictionary _cachedOpts = new Dictionary(); + + static AnimationOpt _GetNewAOpt(string path) + { + AnimationOpt opt = null; + if (!_cachedOpts.ContainsKey(path)) + { + AnimationClip clip = AssetDatabase.LoadAssetAtPath(path); + if (clip != null) + { + opt = new AnimationOpt(path, clip); + _cachedOpts[path] = opt; + } + } + + return opt; + } + + static List FindAnims() + { + string[] guids = null; + List path = new List(); + List assets = new List(); + UnityEngine.Object[] objs = Selection.GetFiltered(typeof(object), SelectionMode.Assets); + if (objs.Length > 0) + { + for (int i = 0; i < objs.Length; i++) + { + if (objs[i].GetType() == typeof(AnimationClip)) + { + string p = AssetDatabase.GetAssetPath(objs[i]); + AnimationOpt animopt = _GetNewAOpt(p); + if (animopt != null) assets.Add(animopt); + } + else + path.Add(AssetDatabase.GetAssetPath(objs[i])); + } + + if (path.Count > 0) + guids = AssetDatabase.FindAssets( + string.Format("t:{0}", typeof(AnimationClip).ToString().Replace("UnityEngine.", "")), + path.ToArray() + ); + else + guids = new string[] { }; + } + + for (int i = 0; i < guids.Length; i++) + { + string assetPath = AssetDatabase.GUIDToAssetPath(guids[i]); + AnimationOpt animopt = _GetNewAOpt(assetPath); + if (animopt != null) assets.Add(animopt); + } + + return assets; + } + } } \ No newline at end of file