From a0577c8f3415b3173f8d57af631785b43c18d086 Mon Sep 17 00:00:00 2001 From: chai Date: Thu, 8 Jul 2021 22:52:08 +0800 Subject: *Action Editor --- Assets/ActionTool/Editor/ActionData.cs | 52 ++++++--- Assets/ActionTool/Editor/ActionEditor.cs | 23 +++- Assets/ActionTool/Editor/ActionEditorStyles.cs | 18 +++- Assets/ActionTool/Editor/ActionEditorUI.cs | 23 +++- Assets/ActionTool/Editor/ActionManager.cs | 69 +++++++++++- Assets/ActionTool/Editor/ActionPreviewEditor.cs | 138 ++++++++++++++++++++---- 6 files changed, 276 insertions(+), 47 deletions(-) (limited to 'Assets/ActionTool/Editor') diff --git a/Assets/ActionTool/Editor/ActionData.cs b/Assets/ActionTool/Editor/ActionData.cs index 4465d314..958e2c53 100644 --- a/Assets/ActionTool/Editor/ActionData.cs +++ b/Assets/ActionTool/Editor/ActionData.cs @@ -20,11 +20,29 @@ namespace ActionTool private AnimationEventBase m_CurEventInfo; // 当前正在编辑的event - private float m_TotalFrame; - private int m_PrevFrame; + #region metadata + private float m_TotalFrame; //timeline采样的总帧数 + public float totalFrame { get { return m_TotalFrame; } } + private float m_SampleRate; // 每次采样的时间间隔 + public float sampleRate { get { return m_SampleRate; } } + #endregion + + public float curAnimFrame { get { return m_CurAnimFrame; } } - private float m_AnimRate; // 每帧时间 + public float curAnimTimeNormal + { + get + { + return m_CurAnimFrame / m_TotalFrame; + } + set + { + float v = value % m_TotalFrame; + m_CurAnimFrame = v * m_TotalFrame; + } + } + private int m_PrevFrame; private float m_CurAnimFrame; private double m_PrevLocalTime; @@ -39,7 +57,7 @@ namespace ActionTool if(m_Clip != null) { m_TotalFrame = m_Clip.length * ActionManager.FPS; - m_AnimRate = m_Clip.length / m_TotalFrame; + m_SampleRate = m_Clip.length / m_TotalFrame; } m_PrevFrame = -1; m_CurAnimFrame = 0; @@ -114,19 +132,19 @@ namespace ActionTool public void UpdateFrame() { - if (!ActionManager.IsPlay) - return; - - m_CurAnimFrame += (float)(EditorApplication.timeSinceStartup - m_PrevLocalTime) * (ActionManager.FPS * ActionManager.Speed); + if (ActionManager.IsPlay) + { + m_CurAnimFrame += (float)(EditorApplication.timeSinceStartup - m_PrevLocalTime) * (ActionManager.FPS * ActionManager.Speed); - if (m_CurAnimFrame > m_TotalFrame) - { - m_Animator.transform.position = ActionManager.s_InitPosition; - m_Animator.transform.rotation = ActionManager.s_InitRotation; + if (m_CurAnimFrame > m_TotalFrame) + { + m_Animator.transform.position = ActionManager.s_InitPosition; + m_Animator.transform.rotation = ActionManager.s_InitRotation; + } + m_CurAnimFrame %= m_TotalFrame; } - m_CurAnimFrame %= m_TotalFrame; - SampleFrame(EditorApplication.timeSinceStartup - m_PrevLocalTime); + SampleFrame(); RunEvent(); @@ -134,7 +152,7 @@ namespace ActionTool } // 播放当前帧 - public void SampleFrame(double dt) + public void SampleFrame() { if (m_Animator == null) return; @@ -154,7 +172,7 @@ namespace ActionTool public int GetCurrentFrame() { - float animTime = m_AnimRate * m_CurAnimFrame; + float animTime = sampleRate * m_CurAnimFrame; int curFrame = Mathf.RoundToInt(animTime * ActionManager.FPS); return curFrame; } @@ -220,7 +238,7 @@ namespace ActionTool m_CurAnimFrame = 0; m_PrevFrame = 0; m_PrevLocalTime = 0; - m_AnimRate = 0; + m_SampleRate = 0; } } diff --git a/Assets/ActionTool/Editor/ActionEditor.cs b/Assets/ActionTool/Editor/ActionEditor.cs index 71942d34..2835714a 100644 --- a/Assets/ActionTool/Editor/ActionEditor.cs +++ b/Assets/ActionTool/Editor/ActionEditor.cs @@ -15,11 +15,13 @@ namespace ActionTool ActionManager.AnimationWindow = GetWindow(); } - private string m_SearchText = ""; + string m_SearchText = ""; + ActionEditorStyles styles; + ActionEditorUI ui; public void OnEnable() { - + titleContent = new GUIContent("Action Editor"); } public void OnDisable() @@ -28,6 +30,11 @@ namespace ActionTool public void OnGUI() { + if (styles == null) styles = ActionEditorStyles.Get(); + if (ui == null) ui = ActionEditorUI.Get(); + if (ActionManager.CurrentUnit == null) + ActionManager.Release(); + GUILayout.Space(5); GUI_SelectUnit(); GUILayout.Space(5); @@ -68,7 +75,7 @@ namespace ActionTool private void GUI_AnimationList() { if (!ActionManager.HasSelectObj()) - return; + return; string unitName = ActionManager.GetUnitName(); @@ -102,11 +109,17 @@ namespace ActionTool if (!show) continue; bool bChecked = ActionManager.CurrentAnimationName == animName; - bool check = GUILayout.Toggle(bChecked, animName, style, GUILayout.Height(15)); + EditorGUILayout.BeginHorizontal(); + bool check = GUILayout.Toggle(bChecked, animName, style, GUILayout.Width(position.width - 42), GUILayout.Height(15)); if (check && ActionManager.CurrentAnimationName != animName) ActionManager.OnSelectAnimation(animName); + if(GUILayout.Button("", styles.selectObj, GUILayout.Width(15), GUILayout.Height(15))) + { + ui.SelectObject(file); + } + EditorGUILayout.EndHorizontal(); } - + EditorGUILayout.EndScrollView(); style.alignment = prevAnchor; diff --git a/Assets/ActionTool/Editor/ActionEditorStyles.cs b/Assets/ActionTool/Editor/ActionEditorStyles.cs index c7c15aaf..664753ef 100644 --- a/Assets/ActionTool/Editor/ActionEditorStyles.cs +++ b/Assets/ActionTool/Editor/ActionEditorStyles.cs @@ -8,9 +8,12 @@ namespace ActionTool internal class ActionEditorStyles { public GUIStyle textBold; + public GUIStyle selectObj; + public GUIStyle textSmall; - private static ActionEditorStyles s_instance; + Texture2D m_SelectIcon; + private static ActionEditorStyles s_instance; public static ActionEditorStyles Get() { bool flag = s_instance == null; @@ -23,9 +26,22 @@ namespace ActionTool private ActionEditorStyles() { + m_SelectIcon = (Texture2D)Resources.Load("select_white"); + m_SelectIcon.filterMode = FilterMode.Point; + InitStyle(out textBold, GUI.skin.label, s => { s.fontStyle = FontStyle.Bold; }); + InitStyle(out selectObj, GUI.skin.button, s => { + s.normal.background = m_SelectIcon; + s.active.background = m_SelectIcon; + s.focused.background = m_SelectIcon; + s.hover.background = m_SelectIcon; + s.normal.background = m_SelectIcon; + }); + InitStyle(out textSmall, GUI.skin.label, s => { + s.fontSize = 8; + }); } private delegate void Initter(GUIStyle style); diff --git a/Assets/ActionTool/Editor/ActionEditorUI.cs b/Assets/ActionTool/Editor/ActionEditorUI.cs index effa6be7..f04c10ea 100644 --- a/Assets/ActionTool/Editor/ActionEditorUI.cs +++ b/Assets/ActionTool/Editor/ActionEditorUI.cs @@ -7,7 +7,11 @@ namespace ActionTool { internal class ActionEditorUI { - private static ActionEditorUI s_instance; + static ActionEditorUI s_instance; + + static Material m_material; + + public Material defaultUIMaterail { get { return m_material; } } public static ActionEditorUI Get() { @@ -21,6 +25,8 @@ namespace ActionTool private ActionEditorUI() { + m_material = new Material(Shader.Find("Hidden/Internal-Colored")); + m_material.hideFlags = HideFlags.HideAndDontSave; } public void DrawVerticalLineFast(float x, float minY, float maxY, Color color) @@ -61,5 +67,20 @@ namespace ActionTool } } + public void SelectObject(Object obj) + { + Selection.activeObject = obj; + EditorGUIUtility.PingObject(obj); + } + + public void SelectObject(string path) + { + Object obj = AssetDatabase.LoadAssetAtPath(path, typeof(Object)) as Object; + if(obj) + { + SelectObject(obj); + } + } + } } \ No newline at end of file diff --git a/Assets/ActionTool/Editor/ActionManager.cs b/Assets/ActionTool/Editor/ActionManager.cs index 32c71434..08d48781 100644 --- a/Assets/ActionTool/Editor/ActionManager.cs +++ b/Assets/ActionTool/Editor/ActionManager.cs @@ -17,6 +17,7 @@ namespace ActionTool public static ActionEventEditor EventEditWindow; public static ActionColliderEditor ColliderWindow; + //规定timeline上事件的采样频率是30帧 public const int FPS = 30; public static float Speed = 1; @@ -44,6 +45,7 @@ namespace ActionTool private static AnimatorOverrideController s_OverrideContorller; private static ActionData s_CurActionData; + public static ActionData actionData { get { return s_CurActionData; } } public static Vector3 s_InitPosition = Vector3.zero; @@ -51,9 +53,18 @@ namespace ActionTool private static RootMotionData s_RootMotion; + private static ActionToolGizmos s_Gizmos; + public static ActionToolGizmos gizmos { get { return s_Gizmos; } } + + // 是否在自动播放 private static bool s_IsPlay; public static bool IsPlay { get { return s_IsPlay; } } + private static GameObject s_RootActionTool; + private const string kRootActionTool = "RootActionTool"; + + public const int kMaxEventsPerFrame = 10; + public static void OnSelectObj(GameObject obj) { Release(); @@ -79,7 +90,7 @@ namespace ActionTool s_OverrideContorller["EmptyAction"] = clip; } - string rootmotionData = s_RootMotionDataFolder + s_CurrentUnit.name + "/" + animation.Replace(' ', '_') + ".asset"; + string rootmotionData = s_RootMotionDataFolder + s_CurrentUnit.name + "/" + animation + ".asset"; s_RootMotion = AssetDatabase.LoadAssetAtPath(rootmotionData); if (s_RootMotion == null) { @@ -89,7 +100,6 @@ namespace ActionTool if (s_CurActionData == null) s_CurActionData = new ActionData(); s_CurActionData.Initialize(s_Animator, clip, s_RootMotion); - } public static bool HasSelectObj() @@ -112,6 +122,10 @@ namespace ActionTool s_CurrentUnit = null; s_CurrentAnimationName = null; s_Animator = null; + s_RootActionTool = GameObject.Find(kRootActionTool); + if (s_RootActionTool) + GameObject.DestroyImmediate(s_RootActionTool); + s_CurActionData = null; } private static void InitializeUnitInstance(GameObject unit) @@ -122,6 +136,12 @@ namespace ActionTool unit.transform.position = s_InitPosition; unit.transform.rotation = s_InitRotation; + s_RootActionTool = GameObject.Find(kRootActionTool); + if(s_RootActionTool == null) + s_RootActionTool = new GameObject(kRootActionTool); + + unit.transform.SetParent(s_RootActionTool.transform); + s_Animator = unit.GetComponentInChildren(); if(s_Animator == null) { @@ -141,6 +161,8 @@ namespace ActionTool s_Animator.runtimeAnimatorController = s_OverrideContorller; s_Animator.applyRootMotion = false; + + s_Gizmos = unit.AddComponent(); } public static void UpdateFrame() @@ -154,10 +176,51 @@ namespace ActionTool s_IsPlay = !s_IsPlay; if(s_IsPlay && s_CurActionData != null) { - s_CurActionData.SetCurrentAnimTime(0); s_CurActionData.StartFrame(); } } + public static void Start() + { + if (s_CurActionData != null) + s_CurActionData.curAnimTimeNormal = 0; + } + + public static void Stop() + { + if (s_CurActionData != null) + { + if (s_IsPlay) + Pause(); + s_CurActionData.curAnimTimeNormal = 0; + } + } + + public static void Previous() + { + if (s_IsPlay) + Pause(); + float cur = s_CurActionData.curAnimFrame; + float pre = Mathf.Ceil(cur - 1); + pre = (int)Mathf.Clamp(pre, 0, s_CurActionData.totalFrame); + s_CurActionData.SetCurrentAnimTime(pre); + } + + public static void Next() + { + if (s_IsPlay) + Pause(); + float cur = s_CurActionData.curAnimFrame; + float next = Mathf.Floor(cur + 1); + next = (int)Mathf.Clamp(next, 0, s_CurActionData.totalFrame); + s_CurActionData.SetCurrentAnimTime(next); + } + + public static void End() + { + if (s_CurActionData != null) + s_CurActionData.curAnimTimeNormal = 1; + } + } } \ No newline at end of file diff --git a/Assets/ActionTool/Editor/ActionPreviewEditor.cs b/Assets/ActionTool/Editor/ActionPreviewEditor.cs index 9b557128..d0934cf9 100644 --- a/Assets/ActionTool/Editor/ActionPreviewEditor.cs +++ b/Assets/ActionTool/Editor/ActionPreviewEditor.cs @@ -8,22 +8,25 @@ namespace ActionTool public class ActionPreviewEditor : EditorWindow { - private Texture m_UITextureStop; - private Texture m_UITexturePause; - private Texture m_UITexturePlay; - private Texture m_UITextureNext; - private Texture m_UITextureEnd; - private Texture m_UITexturePrevious; - private Texture m_UITextureStart; + Texture m_UITextureStop; + Texture m_UITexturePause; + Texture m_UITexturePlay; + Texture m_UITextureNext; + Texture m_UITextureEnd; + Texture m_UITexturePrevious; + Texture m_UITextureStart; - private GUIStyle m_StyleBold; + GUIStyle m_StyleBold; - private const float kToolbarControlMargin = 5; - private const float kToolbarHeight = 50; - private const float kToolbarControlSize = kToolbarHeight - kToolbarControlMargin * 2; + const float kToolbarControlMargin = 5; + const float kToolbarHeight = 50; + const float kToolbarControlSize = kToolbarHeight - kToolbarControlMargin * 2; + const float kTimeLineViewXOffset = 20; + const float kFrameWidth = 10; + const float kFrameHeight = 20; - private ActionEditorStyles styles; - private ActionEditorUI ui; + ActionEditorStyles styles; + ActionEditorUI ui; private void OnEnable() { @@ -40,6 +43,11 @@ namespace ActionTool styles = ActionEditorStyles.Get(); } + void Update() + { + ActionManager.UpdateFrame(); + } + private void OnDisable() { ActionManager.PreviewWindow = null; @@ -58,6 +66,7 @@ namespace ActionTool GUI_Toolbar(); GUI_Detail(); + GUI_TimeLineView(); } void GUI_Toolbar() @@ -83,7 +92,7 @@ namespace ActionTool Rect rect = new Rect(x, y, kToolbarControlSize, kToolbarControlSize); if(GUI.Button(rect, m_UITextureStart)) { - + ActionManager.Start(); } x += kToolbarControlSize; } @@ -94,7 +103,7 @@ namespace ActionTool Rect rect = new Rect(x, y, kToolbarControlSize, kToolbarControlSize); if (GUI.Button(rect, m_UITexturePrevious)) { - + ActionManager.Previous(); } x += kToolbarControlSize; } @@ -105,7 +114,7 @@ namespace ActionTool Rect rect = new Rect(x, y, kToolbarControlSize, kToolbarControlSize); if (GUI.Button(rect, m_UITextureStop)) { - + ActionManager.Stop(); } x += kToolbarControlSize; } @@ -128,7 +137,7 @@ namespace ActionTool Rect rect = new Rect(x, y, kToolbarControlSize, kToolbarControlSize); if (GUI.Button(rect, m_UITextureNext)) { - + ActionManager.Next(); } x += kToolbarControlSize; } @@ -139,7 +148,7 @@ namespace ActionTool Rect rect = new Rect(x, y, kToolbarControlSize, kToolbarControlSize); if (GUI.Button(rect, m_UITextureEnd)) { - + ActionManager.End(); } x += kToolbarControlSize; } @@ -153,12 +162,101 @@ namespace ActionTool x += 105; GUI.Label(new Rect(x, y, 210, 20), ActionManager.CurrentAnimationName, styles.textBold); x += 200; + } + void GUI_TimeLineView() + { + if (ActionManager.actionData == null) + return; + + float y = 80; + + GUI_FrameText(ref y); + GUI_Slider(ref y); + GUI_Grid(ref y); + GUI_Events(ref y); } - void Update() + void GUI_FrameText(ref float y) { - ActionManager.UpdateFrame(); + ActionData action = ActionManager.actionData; + int sampleCount = (int)action.totalFrame + 1; + Rect rect = new Rect(0, y, 20, 15); + for(int i = 0; i < sampleCount; i++) + { + rect.x = kTimeLineViewXOffset + i * kFrameWidth - 7; + if(i % 5 == 0) + { + Color c = GUI.color; + GUI.color = i % 10 == 0 ? Color.yellow : GUI.color; + GUI.Label(rect, i.ToString(), styles.textSmall); + GUI.color = c; + } + } + y += 15; + } + + void GUI_Slider( ref float y) + { + ActionData action = ActionManager.actionData; + Rect rect = new Rect(kTimeLineViewXOffset - 4, y, action.totalFrame * kFrameWidth + 8, 15); + float t = GUI.HorizontalSlider(rect,action.curAnimTimeNormal, 0, 1); + if(t != action.curAnimTimeNormal) + { + if(ActionManager.IsPlay) + ActionManager.Pause(); + action.curAnimTimeNormal = t; + } + + if(ActionManager.IsPlay) + { + this.Repaint(); + } + + y += 20; + } + + void GUI_Grid(ref float y) + { + ActionData action = ActionManager.actionData; + int sampleCount = (int)action.totalFrame + 1; + + Rect bgRect = new Rect(kTimeLineViewXOffset, y, action.totalFrame * kFrameWidth, ActionManager.kMaxEventsPerFrame * kFrameHeight); + GUI.Box(bgRect, ""); + + ui.defaultUIMaterail.SetPass(0); + GL.PushMatrix(); + GL.LoadPixelMatrix(); + bool bWin = Application.platform == RuntimePlatform.WindowsEditor; + if (bWin) + GL.Begin(GL.QUADS); + else + GL.Begin(GL.LINES); + Color lineColor = new Color(0.3f, 0.3f, 0.3f); + Color lineColor2 = new Color(0.5f, 0.5f, 0.5f); + for (int i = 0; i < ActionManager.kMaxEventsPerFrame + 1; i++) + { + ui.DrawHorizontalLineFast(y + i * kFrameHeight, kTimeLineViewXOffset, kTimeLineViewXOffset + action.totalFrame * kFrameWidth, lineColor); + } + for(int i = 0; i <= sampleCount; ++i) + { + Color c = i % 5 == 0 ? lineColor2 : lineColor; + float x = kTimeLineViewXOffset + i * kFrameWidth; + x = Mathf.Clamp(x, kTimeLineViewXOffset, kTimeLineViewXOffset + action.totalFrame * kFrameWidth); + ui.DrawVerticalLineFast(x, y, y + ActionManager.kMaxEventsPerFrame * kFrameHeight, c); + } + + ui.DrawVerticalLineFast(kTimeLineViewXOffset + bgRect.width * action.curAnimTimeNormal, y, y + ActionManager.kMaxEventsPerFrame * kFrameHeight, Color.red); + + GL.PopMatrix(); + GL.End(); + + y += ActionManager.kMaxEventsPerFrame * kFrameHeight; + } + + void GUI_Events(ref float y) + { + } } -- cgit v1.1-26-g67d0