From cb893e1e5e4820cb800836cf6b8a79a1cd986cdc Mon Sep 17 00:00:00 2001 From: chai Date: Thu, 22 Jul 2021 18:34:47 +0800 Subject: *misc --- Assets/ActionTool/Editor/ActionData.cs | 9 +- Assets/ActionTool/Editor/ActionEditorStyles.cs | 19 +++- Assets/ActionTool/Editor/ActionEventEditor.cs | 144 +++++++++++++++++++++++- Assets/ActionTool/Editor/ActionManager.cs | 80 ++++++++++++- Assets/ActionTool/Editor/ActionPreviewEditor.cs | 130 ++++++++++++++++++--- Assets/ActionTool/Resources/hitbox.png | Bin 193 -> 194 bytes Assets/ActionTool/Resources/hurtbox.png | Bin 247 -> 247 bytes 7 files changed, 355 insertions(+), 27 deletions(-) (limited to 'Assets/ActionTool') diff --git a/Assets/ActionTool/Editor/ActionData.cs b/Assets/ActionTool/Editor/ActionData.cs index c00dd269..77935f68 100644 --- a/Assets/ActionTool/Editor/ActionData.cs +++ b/Assets/ActionTool/Editor/ActionData.cs @@ -20,6 +20,8 @@ namespace ActionTool private AnimationEventBase m_CurEventInfo; // 当前正在编辑的event + private TimelineEvent m_Timeline; + #region metadata private float m_TotalFrame; //timeline采样的总帧数 public float totalFrame { get { return m_TotalFrame; } } @@ -64,6 +66,7 @@ namespace ActionTool m_PrevLocalTime = 0; m_Animator.Play(kStateName, 0, 0); m_RootMotion = rootmotion; + m_Timeline = m_Animator.gameObject.GetComponent(); } public void SetCurrentAnimTime(float time) @@ -180,7 +183,9 @@ namespace ActionTool } public void RunEvent() - { + { + if (m_Timeline != null) + m_Timeline.ExecuteAnimationEvents(ActionManager.animationData, m_CurAnimFrame); } public void CreateEvent(TimelineEvent.EEventType eventtype, int startFrame) @@ -202,7 +207,7 @@ namespace ActionTool if(type != null) { var e = Activator.CreateInstance(type) as AnimationEventBase; - e.type = eventtype; + //e.type = eventtype; e.startFrame = startFrame; AddEvent(e); } diff --git a/Assets/ActionTool/Editor/ActionEditorStyles.cs b/Assets/ActionTool/Editor/ActionEditorStyles.cs index 2a3695b2..a7ec4b88 100644 --- a/Assets/ActionTool/Editor/ActionEditorStyles.cs +++ b/Assets/ActionTool/Editor/ActionEditorStyles.cs @@ -7,6 +7,7 @@ namespace ActionTool { internal class ActionEditorStyles { + public GUIStyle textBoldBig; public GUIStyle textBold; public GUIStyle selectObj; public GUIStyle textSmall; @@ -18,6 +19,7 @@ namespace ActionTool public Texture2D addFileIcon; public Texture2D saveFileIcon; public Texture2D deleteIcon; + public Texture2D infoIcon; private static ActionEditorStyles s_instance; public static ActionEditorStyles Get() @@ -39,6 +41,13 @@ namespace ActionTool addFileIcon = EditorGUIUtility.FindTexture("d_Collab.FileAdded"); saveFileIcon = EditorGUIUtility.FindTexture("d_Collab.FileUpdated"); deleteIcon = EditorGUIUtility.FindTexture("d_P4_DeletedLocal"); + infoIcon = EditorGUIUtility.FindTexture("console.infoicon"); + + InitStyle(out textBoldBig, GUI.skin.label, s => { + s.fontStyle = FontStyle.Bold; + s.fontSize = 20; + s.alignment = TextAnchor.MiddleCenter; + }); InitStyle(out textBold, GUI.skin.label, s => { s.fontStyle = FontStyle.Bold; @@ -48,7 +57,6 @@ namespace ActionTool s.active.background = selectIcon; s.focused.background = selectIcon; s.hover.background = selectIcon; - s.normal.background = selectIcon; }); InitStyle(out textSmall, GUI.skin.label, s => { s.fontSize = 8; @@ -61,7 +69,14 @@ namespace ActionTool s.onActive.textColor = Color.white; }); InitStyle(out keyFrameButton, GUI.skin.button, s => { - s.fontSize = 8; + s.fontSize = 9; + s.clipping = TextClipping.Overflow; + s.alignment = TextAnchor.MiddleCenter; + s.fontStyle = FontStyle.Bold; + s.normal.textColor = Color.yellow; + s.active.textColor = Color.yellow; + s.focused.textColor = Color.yellow; + s.hover.textColor = Color.yellow; }); } diff --git a/Assets/ActionTool/Editor/ActionEventEditor.cs b/Assets/ActionTool/Editor/ActionEventEditor.cs index 70a75011..82580b17 100644 --- a/Assets/ActionTool/Editor/ActionEventEditor.cs +++ b/Assets/ActionTool/Editor/ActionEventEditor.cs @@ -1,23 +1,155 @@ -using System.Collections; +using System; +using System.Collections; using System.Collections.Generic; +using System.Reflection; using UnityEngine; +using UnityEditor; namespace ActionTool { - public class ActionEventEditor : MonoBehaviour + // 编辑事件 + public class ActionEventEditor : EditorWindow { + EditorWindow sceneView; + ActionEditorStyles styles; + AnimationEventBase animEvent; - // Start is called before the first frame update - void Start() + private void OnEnable() { + titleContent = new GUIContent("Event Editor"); + } + private void OnDisable() + { + ActionManager.OnSelectAnimationEvent(null); + } + + private void Update() + { } - // Update is called once per frame - void Update() + Vector2 scroll; + private void OnGUI() { + animEvent = ActionManager.animationEvent; + if (animEvent == null) + { + this.Close(); + return; + } + + if (styles == null) styles = ActionEditorStyles.Get(); + + string eventName = animEvent.name; + int frame = animEvent.startFrame; + + Type type = animEvent.GetType(); + + GUILayout.Space(2); + + EditorGUILayout.LabelField(eventName, styles.textBoldBig, GUILayout.Height(30)); + + GUILayout.Space(5); + + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Save")) + { + + } + if (GUILayout.Button("Revert")) + { + + } + Color prevColor = GUI.backgroundColor; + GUI.backgroundColor = Color.red; + if (GUILayout.Button("Delete")) + { + ActionManager.DeleteEvent(animEvent); + ActionManager.OnSelectAnimationEvent(null); + } + GUI.backgroundColor = prevColor; + EditorGUILayout.EndHorizontal(); + + GUILayout.Space(5); + + EditorGUILayout.LabelField("startFrame (int)", styles.textBold); + GUI.enabled = false; + EditorGUILayout.TextField(frame.ToString()); + GUI.enabled = true; + + GUILayout.Space(5); + scroll = EditorGUILayout.BeginScrollView(scroll); + + GUILayout.Space(5); + + FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); + if(fields != null && fields.Length > 0) + { + for(int i = 0; i < fields.Length; ++i) + { + FieldInfo field = fields[i]; + string name = field.Name + " (" + field.FieldType.Name + ")"; + string tooltip = ""; + foreach(var attr in field.GetCustomAttributes()) + { + if(attr.GetType() == typeof(TooltipAttribute)) + { + TooltipAttribute tooltipattr = attr as TooltipAttribute; + if(tooltip != null) + { + tooltip = tooltipattr.tooltip; + } + } + } + EditorGUILayout.LabelField(new GUIContent(name, tooltip), styles.textBold); + if (field.FieldType == typeof(Vector3)) + { + field.SetValue(animEvent, GUI_Vector3((Vector3)field.GetValue(animEvent))); + } + else if (field.FieldType == typeof(Vector2)) + { + field.SetValue(animEvent, GUI_Vector2((Vector2)field.GetValue(animEvent))); + } + else if (field.FieldType == typeof(string)) + { + field.SetValue(animEvent, GUI_String((string)field.GetValue(animEvent))); + } + else if (field.FieldType == typeof(bool)) + { + field.SetValue(animEvent, GUI_Bool((bool)field.GetValue(animEvent))); + } + GUILayout.Space(5); + } + } + + EditorGUILayout.EndScrollView(); + } + + Vector3 GUI_Vector3(Vector3 value) + { + Rect rect = EditorGUILayout.GetControlRect(); + return EditorGUI.Vector3Field(rect, "", value); + } + + Vector2 GUI_Vector2(Vector2 value) + { + Rect rect = EditorGUILayout.GetControlRect(); + return EditorGUI.Vector2Field(rect, "", value); + } + + string GUI_String(string value) + { + Rect rect = EditorGUILayout.GetControlRect(); + return EditorGUI.TextField(rect, "", value); } + + bool GUI_Bool(bool value) + { + Rect rect = EditorGUILayout.GetControlRect(); + return GUI.Toggle(rect, value, ""); + } + } } \ No newline at end of file diff --git a/Assets/ActionTool/Editor/ActionManager.cs b/Assets/ActionTool/Editor/ActionManager.cs index 396e0342..cc8a7dfd 100644 --- a/Assets/ActionTool/Editor/ActionManager.cs +++ b/Assets/ActionTool/Editor/ActionManager.cs @@ -1,4 +1,5 @@ -using System.Collections; +using System; +using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; @@ -53,6 +54,8 @@ namespace ActionTool private static RootMotionData s_RootMotion; + private static AnimationData m_SharedAnimationData; // 资源 + public static AnimationData sharedAnimationData { get { return m_SharedAnimationData; } } private static AnimationData m_AnimationData; public static AnimationData animationData { @@ -70,6 +73,9 @@ namespace ActionTool } } + private static AnimationEventBase m_CurAnimationEvent; + public static AnimationEventBase animationEvent { get { return m_CurAnimationEvent; } } + private static ColliderData s_CurColliderData; public static ColliderData colliderData { get { return s_CurColliderData; } } @@ -134,7 +140,18 @@ namespace ActionTool s_CurActionData.Initialize(s_Animator, clip, s_RootMotion); string animationDataPath = s_AnimationDataFolder + unitName + "/" + animation + ".asset"; - animationData = AssetDatabase.LoadAssetAtPath(animationDataPath); + AnimationData asset = AssetDatabase.LoadAssetAtPath(animationDataPath); + m_SharedAnimationData = asset; + if(asset != null) + animationData = UnityEngine.Object.Instantiate(asset); + else + animationData = null; + + OnSelectAnimationEvent(null); + OnSelectColliderFrame(null); + OnSelectBox(null); + if (EventEditWindow) EventEditWindow.Close(); + if (ColliderWindow) ColliderWindow.Close(); } public static bool HasSelectObj() @@ -163,6 +180,7 @@ namespace ActionTool s_CurActionData = null; s_CurEditColliderFrame = null; s_CurColliderData = null; + s_CurrentAnimationName = null; } private static void InitializeUnitInstance(GameObject unit) @@ -270,7 +288,8 @@ namespace ActionTool animData.animationPath = animpath; AssetDatabase.CreateAsset(animData, animationDataPath); AssetDatabase.Refresh(); - animationData = animData; + m_SharedAnimationData = animData; + animationData = UnityEngine.Object.Instantiate(animData); } public static void SaveAnimationData() @@ -280,7 +299,12 @@ namespace ActionTool Debug.LogError("[ActionTool] 没有animation data数据"); return; } - EditorUtility.SetDirty(animationData); + string unitName = s_CurrentUnit.name; + string animation = s_CurrentAnimationName; + string animationDataPath = s_AnimationDataFolder + unitName + "/" + animation + ".asset"; + EditorUtility.CopySerialized(animationData, m_SharedAnimationData); + m_SharedAnimationData.OnSaveToDisk(); + EditorUtility.SetDirty(m_SharedAnimationData); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); } @@ -368,5 +392,53 @@ namespace ActionTool } } + public static void AddNewEvent(object param) + { + EventParam eventParam = (EventParam )param; + string eventName = eventParam.eventName; // TimelineEvent.EEventType + int frame = eventParam.frame; + Debug.Log("[ActionTool] Add new event " + eventName); + if (animationData == null) + { + Debug.LogError("[ActionTool] 没有animation data数据"); + return; + } + Type type = TimelineEvent.GetTypeByName(eventName); + if(type == null) + { + Debug.LogError("[ActionTool] 没有创建对应的类, " + eventName); + return; + } + AnimationEventBase animEvent = Activator.CreateInstance(type) as AnimationEventBase; + if(animEvent) + { + animEvent.name = animEvent.type.ToString(); + animEvent.startFrame = frame; + animationData.AddEvent(animEvent); + OnSelectAnimationEvent(animEvent); + } + else + { + Debug.LogError("[ActionTool] 实例化失败, " + eventName); + return; + } + } + + public static void OnSelectAnimationEvent(AnimationEventBase animEvent) + { + m_CurAnimationEvent = animEvent; + if(animEvent != null) + { + EventEditWindow = EditorWindow.GetWindow(true); + } + } + + public static void DeleteEvent(AnimationEventBase animEvent) + { + if (animationData == null) + return; + animationData.DeleteEvent(animEvent); + } + } } \ No newline at end of file diff --git a/Assets/ActionTool/Editor/ActionPreviewEditor.cs b/Assets/ActionTool/Editor/ActionPreviewEditor.cs index 45048f0e..f277ce97 100644 --- a/Assets/ActionTool/Editor/ActionPreviewEditor.cs +++ b/Assets/ActionTool/Editor/ActionPreviewEditor.cs @@ -1,4 +1,5 @@ -using System.Collections; +using System; +using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; @@ -12,6 +13,12 @@ namespace ActionTool public int frame; } + public struct EventParam + { + public string eventName; + public int frame; + } + public class ActionPreviewEditor : EditorWindow { Texture m_UITextureStop; @@ -100,6 +107,7 @@ namespace ActionTool GUI.enabled = ActionManager.animationData != null; GUI_Toolbar_NewHurtBox(ref x, ref y); GUI_Toolbar_NewHitBox(ref x, ref y); + GUI_Toolbar_Detail(ref x, ref y); GUI_Toolbar_Delete(ref x, ref y); GUI.enabled = true; @@ -306,11 +314,6 @@ namespace ActionTool ui.DrawVerticalLineFast(kTimeLineViewXOffset + bgRect.width * action.curAnimTimeNormal, y, y + ActionManager.eventAndBoxCount * kFrameHeight, Color.red); } - void GUI_Events() - { - - } - void GUI_Boxes() { float y = m_GridY + ActionManager.kMaxEventsPerFrame * kFrameHeight; @@ -319,7 +322,7 @@ namespace ActionTool return; DrawBoxList(animData.hurtBoxes, ref y, Color.green); DrawBoxList(animData.hitBoxes, ref y, Color.red); - DrawBoxFrameMenuItem(); + GenericMenu_BoxFrame(); } void DrawBoxList(List boxes, ref float y, Color c) @@ -374,10 +377,10 @@ namespace ActionTool bool frameSelect = GUI.Toggle(frameRect, frameSelected, "",styles.keyFrameButton); if(!frameSelected && frameSelect) { - ActionManager.OnSelectBox(box); - ActionManager.OnSelectColliderFrame(frame); - } - else if(frameSelect && !frameSelect) + ActionManager.OnSelectBox(box); + ActionManager.OnSelectColliderFrame(frame); + } + else if(frameSelect && !frameSelect) { ActionManager.OnSelectColliderFrame(null); } @@ -404,7 +407,7 @@ namespace ActionTool GUI.color = prevColor; } - void DrawBoxFrameMenuItem() + void GenericMenu_BoxFrame() { Event e = Event.current; if (e.button != 1 || !e.isMouse || e.type != EventType.MouseDown) @@ -470,6 +473,18 @@ namespace ActionTool x += kToolbarControlSize; } + void GUI_Toolbar_Detail(ref float x, ref float y) + { + x += kToolbarControlMargin; + Rect rect = new Rect(x, y, kToolbarControlSize, kToolbarControlSize); + GUI.enabled = ActionManager.colliderData != null; + if (GUI.Button(rect, new GUIContent(styles.infoIcon, "Detail"))) + { + } + GUI.enabled = true; + x += kToolbarControlSize; + } + void GUI_Toolbar_Delete(ref float x, ref float y) { x += kToolbarControlMargin; @@ -498,13 +513,102 @@ namespace ActionTool { x += kToolbarControlMargin; Rect rect = new Rect(x, y, kToolbarControlSize, kToolbarControlSize); + //Color c = GUI.backgroundColor; if (GUI.Button(rect, new GUIContent(styles.saveFileIcon, "Save"))) { ActionManager.SaveAnimationData(); } + //GUI.backgroundColor = c; x += kToolbarControlSize; } - } + void GUI_Events() + { + DrawAllEvents(); + GenericMenu_Event(); + } + + void DrawAllEvents() + { + if (ActionManager.animationData == null) + return; + + List frames = ActionManager.animationData.GetAnimationEventFrameIndices(); + if (frames == null || frames.Count == 0) + return; + for(int i= 0;i < frames.Count; ++ i) + { + int frame = frames[i]; + DrawFrameEvent(frame); + } + ListPool.Release(frames); + } + + void DrawFrameEvent(int frame) + { + List animEvents = ActionManager.animationData.GetAnimationEventsAtFrame(frame); + if (animEvents == null || animEvents.Count == 0) + return; + float y = m_GridY; + for (int i = 0; i < animEvents.Count; ++i) + { + var animEvent = animEvents[i]; + if (animEvent == null) + continue; + Vector2 pos = new Vector2(kTimeLineViewXOffset + frame * kFrameWidth, y); + Rect frameRect = new Rect(pos.x, pos.y, kFrameWidth, kFrameHeight); + bool isSelect = ActionManager.animationEvent == animEvent; + bool frameSelect = GUI.Toggle(frameRect, isSelect, "E", styles.keyFrameButton); + if(!isSelect && frameSelect) + { + ActionManager.OnSelectAnimationEvent(animEvent); + } + y += kFrameHeight; + } + ListPool.Release(animEvents); + } + + void GenericMenu_Event() + { + Event e = Event.current; + if (e.button != 1 || !e.isMouse || e.type != EventType.MouseDown) + return; + + ActionData action = ActionManager.actionData; + Vector2 position = Event.current.mousePosition; + Rect eventRegion = new Rect(kTimeLineViewXOffset, m_GridY, action.totalFrame * kFrameWidth, TimelineEvent.kMaxEventsPerFrame * kFrameHeight); + if (!eventRegion.Contains(position)) + return; + + Vector2 pos = new Vector2(position.x - eventRegion.x, position.y - eventRegion.y); + int frame = (int)(pos.x / kFrameWidth); + + GenericMenu eventMenu = new GenericMenu(); + foreach(var name in Enum.GetNames(typeof(TimelineEvent.EEventType))) + { + GUIContent item = null; + string shortName = name.Replace("Event", ""); + int underscore = shortName.IndexOf('_'); + if(underscore != -1) + { + string category = shortName.Substring(0, underscore); + shortName = shortName.Substring(underscore + 1, shortName.Length - underscore - 1); + item = new GUIContent("New Event/" + category + "/" + shortName); + } + else + { + item = new GUIContent("New Event/" + shortName); + } + EventParam param = new EventParam(); + param.eventName = name; + param.frame = frame; + eventMenu.AddItem(item, false, ActionManager.AddNewEvent, param); + } + eventMenu.AddItem(new GUIContent("Copy"), false, null); + eventMenu.AddItem(new GUIContent("Paste"), false, null); + eventMenu.ShowAsContext(); + } + + } } \ No newline at end of file diff --git a/Assets/ActionTool/Resources/hitbox.png b/Assets/ActionTool/Resources/hitbox.png index a2d0ded9..f31ecc4a 100644 Binary files a/Assets/ActionTool/Resources/hitbox.png and b/Assets/ActionTool/Resources/hitbox.png differ diff --git a/Assets/ActionTool/Resources/hurtbox.png b/Assets/ActionTool/Resources/hurtbox.png index eb9613fe..e299a7a4 100644 Binary files a/Assets/ActionTool/Resources/hurtbox.png and b/Assets/ActionTool/Resources/hurtbox.png differ -- cgit v1.1-26-g67d0