From 5f28ce21d68b579f1d3cb19101d953dc819b99ed Mon Sep 17 00:00:00 2001 From: pharan Date: Fri, 10 Aug 2018 23:51:07 +0800 Subject: [PATCH] [unity] Some inspector improvements. --- .../Editor/AnimationReferenceAssetEditor.cs | 5 +- .../Editor/SkeletonDataAssetInspector.cs | 180 ++++++++++-------- .../spine-unity/Editor/SkeletonDebugWindow.cs | 5 +- .../Editor/SkeletonRendererInspector.cs | 26 +-- .../Editor/SpineAtlasAssetInspector.cs | 2 +- .../Editor/SpineInspectorUtility.cs | 4 + .../SkeletonRenderSeparatorInspector.cs | 2 +- .../Components/SkeletonRenderer.cs | 24 ++- 8 files changed, 146 insertions(+), 102 deletions(-) diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/AnimationReferenceAssetEditor.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/AnimationReferenceAssetEditor.cs index 15991bbcb..726f0ce9a 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/AnimationReferenceAssetEditor.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/AnimationReferenceAssetEditor.cs @@ -56,6 +56,7 @@ namespace Spine.Unity.Editor { bool changeNextFrame = false; SerializedProperty animationNameProperty; SkeletonDataAsset lastSkeletonDataAsset; + SkeletonData lastSkeletonData; void OnEnable () { HandleOnEnablePreview(); } void OnDestroy () { HandleOnDestroyPreview(); } @@ -76,7 +77,7 @@ namespace Spine.Unity.Editor { if (changeNextFrame) { changeNextFrame = false; - if (ThisSkeletonDataAsset != lastSkeletonDataAsset) { + if (ThisSkeletonDataAsset != lastSkeletonDataAsset || ThisSkeletonDataAsset.GetSkeletonData(true) != lastSkeletonData) { preview.Clear(); preview.Initialize(Repaint, ThisSkeletonDataAsset, LastSkinName); @@ -91,7 +92,9 @@ namespace Spine.Unity.Editor { if (!string.IsNullOrEmpty(animationNameProperty.stringValue)) preview.PlayPauseAnimation(animationNameProperty.stringValue, true); } + lastSkeletonDataAsset = ThisSkeletonDataAsset; + lastSkeletonData = ThisSkeletonDataAsset.GetSkeletonData(true); //EditorGUILayout.HelpBox(AnimationReferenceAssetEditor.InspectorHelpText, MessageType.Info, true); EditorGUILayout.Space(); diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDataAssetInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDataAssetInspector.cs index a067b1c09..c5da65de2 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDataAssetInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDataAssetInspector.cs @@ -355,27 +355,35 @@ namespace Spine.Unity.Editor { using (new SpineInspectorUtility.IndentScope()) SpineInspectorUtility.PropertyFieldWideLabel(defaultMix, DefaultMixLabel, 160); - // Do not use EditorGUIUtility.indentLevel. It will add spaces on every field. - for (int i = 0; i < fromAnimation.arraySize; i++) { - SerializedProperty from = fromAnimation.GetArrayElementAtIndex(i); - SerializedProperty to = toAnimation.GetArrayElementAtIndex(i); - SerializedProperty durationProp = duration.GetArrayElementAtIndex(i); - using (new EditorGUILayout.HorizontalScope()) { - GUILayout.Space(16f); - EditorGUILayout.PropertyField(from, GUIContent.none); - EditorGUILayout.PropertyField(to, GUIContent.none); - durationProp.floatValue = EditorGUILayout.FloatField(durationProp.floatValue, GUILayout.MinWidth(25f), GUILayout.MaxWidth(60f)); - if (GUILayout.Button("Delete", EditorStyles.miniButton)) { - duration.DeleteArrayElementAtIndex(i); - toAnimation.DeleteArrayElementAtIndex(i); - fromAnimation.DeleteArrayElementAtIndex(i); + + if (fromAnimation.arraySize > 0) { + using (new SpineInspectorUtility.IndentScope()) { + EditorGUILayout.LabelField("Custom Mix Durations", EditorStyles.boldLabel); + } + + for (int i = 0; i < fromAnimation.arraySize; i++) { + SerializedProperty from = fromAnimation.GetArrayElementAtIndex(i); + SerializedProperty to = toAnimation.GetArrayElementAtIndex(i); + SerializedProperty durationProp = duration.GetArrayElementAtIndex(i); + using (new EditorGUILayout.HorizontalScope()) { + GUILayout.Space(16f); // Space instead of EditorGUIUtility.indentLevel. indentLevel will add the space on every field. + EditorGUILayout.PropertyField(from, GUIContent.none); + //EditorGUILayout.LabelField(">", EditorStyles.miniLabel, GUILayout.Width(9f)); + EditorGUILayout.PropertyField(to, GUIContent.none); + //GUILayout.Space(5f); + durationProp.floatValue = EditorGUILayout.FloatField(durationProp.floatValue, GUILayout.MinWidth(25f), GUILayout.MaxWidth(60f)); + if (GUILayout.Button("Delete", EditorStyles.miniButton)) { + duration.DeleteArrayElementAtIndex(i); + toAnimation.DeleteArrayElementAtIndex(i); + fromAnimation.DeleteArrayElementAtIndex(i); + } } } - } + } using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.Space(); - if (GUILayout.Button("Add Mix")) { + if (GUILayout.Button("Add Custom Mix")) { duration.arraySize++; toAnimation.arraySize++; fromAnimation.arraySize++; @@ -438,59 +446,75 @@ namespace Spine.Unity.Editor { if (!showSlotList) return; if (!preview.IsValid) return; - EditorGUI.indentLevel++; - showAttachments = EditorGUILayout.ToggleLeft("Show Attachments", showAttachments); - var slotAttachments = new List(); - var slotAttachmentNames = new List(); - var defaultSkinAttachmentNames = new List(); - var defaultSkin = targetSkeletonData.Skins.Items[0]; + var defaultSkin = targetSkeletonData.DefaultSkin; Skin skin = preview.Skeleton.Skin ?? defaultSkin; - var slotsItems = preview.Skeleton.Slots.Items; - for (int i = preview.Skeleton.Slots.Count - 1; i >= 0; i--) { - Slot slot = slotsItems[i]; - EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(slot.Data.Name, Icons.slot)); - if (showAttachments) { - - EditorGUI.indentLevel++; - slotAttachments.Clear(); - slotAttachmentNames.Clear(); - defaultSkinAttachmentNames.Clear(); + using (new SpineInspectorUtility.IndentScope()) { - skin.FindNamesForSlot(i, slotAttachmentNames); - skin.FindAttachmentsForSlot(i, slotAttachments); - - if (skin != defaultSkin) { - defaultSkin.FindNamesForSlot(i, defaultSkinAttachmentNames); - defaultSkin.FindNamesForSlot(i, slotAttachmentNames); - defaultSkin.FindAttachmentsForSlot(i, slotAttachments); - } else { - defaultSkin.FindNamesForSlot(i, defaultSkinAttachmentNames); + using (new EditorGUILayout.HorizontalScope()) { + showAttachments = EditorGUILayout.ToggleLeft("Show Attachments", showAttachments, GUILayout.MaxWidth(150f)); + if (showAttachments) { + if (skin != null && skin != defaultSkin) + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(skin.Name, Icons.skin)); } + } - for (int a = 0; a < slotAttachments.Count; a++) { - Attachment attachment = slotAttachments[a]; - string attachmentName = slotAttachmentNames[a]; - Texture2D icon = Icons.GetAttachmentIcon(attachment); - bool initialState = slot.Attachment == attachment; - bool toggled = EditorGUILayout.ToggleLeft(SpineInspectorUtility.TempContent(attachmentName, icon), slot.Attachment == attachment); + var slotAttachments = new List(); + var slotAttachmentNames = new List(); + var defaultSkinAttachmentNames = new List(); + var slotsItems = preview.Skeleton.Slots.Items; + for (int i = preview.Skeleton.Slots.Count - 1; i >= 0; i--) { + Slot slot = slotsItems[i]; + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(slot.Data.Name, Icons.slot)); + if (showAttachments) { + slotAttachments.Clear(); + slotAttachmentNames.Clear(); + defaultSkinAttachmentNames.Clear(); - if (!defaultSkinAttachmentNames.Contains(attachmentName)) { - Rect skinPlaceHolderIconRect = GUILayoutUtility.GetLastRect(); - skinPlaceHolderIconRect.width = Icons.skinPlaceholder.width; - skinPlaceHolderIconRect.height = Icons.skinPlaceholder.height; - GUI.DrawTexture(skinPlaceHolderIconRect, Icons.skinPlaceholder); + using (new SpineInspectorUtility.IndentScope()) { + { + skin.FindNamesForSlot(i, slotAttachmentNames); + skin.FindAttachmentsForSlot(i, slotAttachments); + + if (skin != defaultSkin) { + defaultSkin.FindNamesForSlot(i, defaultSkinAttachmentNames); + defaultSkin.FindNamesForSlot(i, slotAttachmentNames); + defaultSkin.FindAttachmentsForSlot(i, slotAttachments); + } else { + defaultSkin.FindNamesForSlot(i, defaultSkinAttachmentNames); + } + } + + for (int a = 0; a < slotAttachments.Count; a++) { + Attachment attachment = slotAttachments[a]; + string attachmentName = slotAttachmentNames[a]; + bool attachmentIsFromSkin = !defaultSkinAttachmentNames.Contains(attachmentName); + + Texture2D attachmentTypeIcon = Icons.GetAttachmentIcon(attachment); + bool initialState = slot.Attachment == attachment; + + Texture2D iconToUse = attachmentIsFromSkin ? Icons.skinPlaceholder : attachmentTypeIcon; + bool toggled = EditorGUILayout.ToggleLeft(SpineInspectorUtility.TempContent(attachmentName, iconToUse), slot.Attachment == attachment, GUILayout.MinWidth(150f)); + + if (attachmentIsFromSkin) { + Rect extraIconRect = GUILayoutUtility.GetLastRect(); + extraIconRect.x += extraIconRect.width - (attachmentTypeIcon.width * 2f); + extraIconRect.width = attachmentTypeIcon.width; + extraIconRect.height = attachmentTypeIcon.height; + GUI.DrawTexture(extraIconRect, attachmentTypeIcon); + } + + if (toggled != initialState) { + slot.Attachment = toggled ? attachment : null; + preview.RefreshOnNextUpdate(); + } + } } - if (toggled != initialState) { - slot.Attachment = toggled ? attachment : null; - preview.RefreshOnNextUpdate(); - } } - EditorGUI.indentLevel--; } } - EditorGUI.indentLevel--; + } void DrawUnityTools () { @@ -498,29 +522,29 @@ namespace Spine.Unity.Editor { using (new SpineInspectorUtility.BoxScope()) { isMecanimExpanded = EditorGUILayout.Foldout(isMecanimExpanded, SpineInspectorUtility.TempContent("SkeletonAnimator", SpineInspectorUtility.UnityIcon())); if (isMecanimExpanded) { - EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(controller, SpineInspectorUtility.TempContent("Controller", SpineInspectorUtility.UnityIcon())); - if (controller.objectReferenceValue == null) { + using (new SpineInspectorUtility.IndentScope()) { + EditorGUILayout.PropertyField(controller, SpineInspectorUtility.TempContent("Controller", SpineInspectorUtility.UnityIcon())); + if (controller.objectReferenceValue == null) { + + // Generate Mecanim Controller Button + using (new GUILayout.HorizontalScope()) { + GUILayout.Space(EditorGUIUtility.labelWidth); + if (GUILayout.Button(SpineInspectorUtility.TempContent("Generate Mecanim Controller"), GUILayout.Height(20))) + SkeletonBaker.GenerateMecanimAnimationClips(targetSkeletonDataAsset); + } + EditorGUILayout.HelpBox("SkeletonAnimator is the Mecanim alternative to SkeletonAnimation.\nIt is not required.", MessageType.Info); + + } else { + + // Update AnimationClips button. + using (new GUILayout.HorizontalScope()) { + GUILayout.Space(EditorGUIUtility.labelWidth); + if (GUILayout.Button(SpineInspectorUtility.TempContent("Force Update AnimationClips"), GUILayout.Height(20))) + SkeletonBaker.GenerateMecanimAnimationClips(targetSkeletonDataAsset); + } - // Generate Mecanim Controller Button - using (new GUILayout.HorizontalScope()) { - GUILayout.Space(EditorGUIUtility.labelWidth); - if (GUILayout.Button(SpineInspectorUtility.TempContent("Generate Mecanim Controller"), GUILayout.Height(20))) - SkeletonBaker.GenerateMecanimAnimationClips(targetSkeletonDataAsset); } - EditorGUILayout.HelpBox("SkeletonAnimator is the Mecanim alternative to SkeletonAnimation.\nIt is not required.", MessageType.Info); - - } else { - - // Update AnimationClips button. - using (new GUILayout.HorizontalScope()) { - GUILayout.Space(EditorGUIUtility.labelWidth); - if (GUILayout.Button(SpineInspectorUtility.TempContent("Force Update AnimationClips"), GUILayout.Height(20))) - SkeletonBaker.GenerateMecanimAnimationClips(targetSkeletonDataAsset); - } - } - EditorGUI.indentLevel--; } } #endif diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDebugWindow.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDebugWindow.cs index 9373f93ad..7bf8406e6 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDebugWindow.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonDebugWindow.cs @@ -446,6 +446,9 @@ namespace Spine.Unity.Editor { } showDrawOrderTree.target = EditorGUILayout.Foldout(showDrawOrderTree.target, SpineInspectorUtility.TempContent("Draw Order and Separators", Icons.slotRoot), BoldFoldoutStyle); + + //var separatorSlotNamesField = + //SpineInspectorUtility.ge if (showDrawOrderTree.faded > 0) { using (new SpineInspectorUtility.IndentScope()) { using (new EditorGUILayout.FadeGroupScope(showDrawOrderTree.faded)) { @@ -459,7 +462,7 @@ namespace Spine.Unity.Editor { } } else { foreach (var slot in skeleton.DrawOrder) { - var slotNames = skeletonRenderer.separatorSlotNames; + var slotNames = SkeletonRendererInspector.GetSeparatorSlotMember(skeletonRenderer); for (int i = 0, n = slotNames.Length; i < n; i++) { if (string.Equals(slotNames[i], slot.Data.Name, System.StringComparison.Ordinal)) { EditorGUILayout.LabelField(SeparatorString); diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs index 631550222..4b93eb6f7 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SkeletonRendererInspector.cs @@ -33,6 +33,7 @@ using UnityEditor; using System.Collections.Generic; using UnityEngine; +using System.Reflection; namespace Spine.Unity.Editor { using Event = UnityEngine.Event; @@ -43,6 +44,8 @@ namespace Spine.Unity.Editor { public class SkeletonRendererInspector : UnityEditor.Editor { public static bool advancedFoldout; + const string SeparatorSlotNamesFieldName = "separatorSlotNames"; + protected SerializedProperty skeletonDataAsset, initialSkinName; protected SerializedProperty initialFlipX, initialFlipY; protected SerializedProperty singleSubmesh, separatorSlotNames, clearStateOnDisable, immutableTriangles; @@ -112,24 +115,6 @@ namespace Spine.Unity.Editor { sortingProperties = new SpineInspectorUtility.SerializedSortingProperties(rso); } - public static void ReapplySeparatorSlotNames (SkeletonRenderer skeletonRenderer) { - if (!skeletonRenderer.valid) return; - - var separatorSlots = skeletonRenderer.separatorSlots; - var separatorSlotNames = skeletonRenderer.separatorSlotNames; - var skeleton = skeletonRenderer.skeleton; - - separatorSlots.Clear(); - for (int i = 0, n = separatorSlotNames.Length; i < n; i++) { - var slot = skeleton.FindSlot(separatorSlotNames[i]); - if (slot != null) { - separatorSlots.Add(slot); - } else { - Debug.LogWarning(separatorSlotNames[i] + " is not a slot in " + skeletonRenderer.skeletonDataAsset.skeletonJSON.name); - } - } - } - GUIContent[] skins; ExposedList loadedSkinList; @@ -333,6 +318,11 @@ namespace Spine.Unity.Editor { } } + public static string[] GetSeparatorSlotMember (SkeletonRenderer skeletonRenderer) { + var field = SpineInspectorUtility.GetNonPublicField(typeof(SkeletonRenderer), SeparatorSlotNamesFieldName); + return field.GetValue(skeletonRenderer) as string[]; + } + public static void SeparatorsField (SerializedProperty separatorSlotNames) { bool multi = separatorSlotNames.serializedObject.isEditingMultipleObjects; bool hasTerminalSlot = false; diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAtlasAssetInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAtlasAssetInspector.cs index de693f737..758bfe748 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAtlasAssetInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineAtlasAssetInspector.cs @@ -63,7 +63,7 @@ namespace Spine.Unity.Editor { } static List GetRegions (Atlas atlas) { - FieldInfo regionsField = typeof(Atlas).GetField("regions", BindingFlags.Instance | BindingFlags.NonPublic); + FieldInfo regionsField = SpineInspectorUtility.GetNonPublicField(typeof(Atlas), "regions"); return (List)regionsField.GetValue(atlas); } diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineInspectorUtility.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineInspectorUtility.cs index 4dee79d9f..49a8b6c46 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineInspectorUtility.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Editor/SpineInspectorUtility.cs @@ -83,6 +83,10 @@ namespace Spine.Unity.Editor { return EditorGUIUtility.ObjectContent(null, type).image as Texture2D; } + public static FieldInfo GetNonPublicField (System.Type type, string fieldName) { + return type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance); + } + #region SerializedProperty Helpers public static SerializedProperty FindBaseOrSiblingProperty (this SerializedProperty property, string propertyName) { if (string.IsNullOrEmpty(propertyName)) return null; diff --git a/spine-unity/Assets/Spine/Editor/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs b/spine-unity/Assets/Spine/Editor/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs index 856e5318b..0114cbbb5 100644 --- a/spine-unity/Assets/Spine/Editor/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs +++ b/spine-unity/Assets/Spine/Editor/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs @@ -211,7 +211,7 @@ namespace Spine.Unity.Modules { serializedObject.ApplyModifiedProperties(); if (slotsReapplyRequired && UnityEngine.Event.current.type == EventType.Repaint) { - SkeletonRendererInspector.ReapplySeparatorSlotNames(component.SkeletonRenderer); + component.SkeletonRenderer.ReapplySeparatorSlotNames(); component.SkeletonRenderer.LateUpdate(); SceneView.RepaintAll(); slotsReapplyRequired = false; diff --git a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs index e4e25d464..5d80c81e3 100644 --- a/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs +++ b/spine-unity/Assets/Spine/Runtime/spine-unity/Components/SkeletonRenderer.cs @@ -53,7 +53,7 @@ namespace Spine.Unity { #region Advanced // Submesh Separation - [UnityEngine.Serialization.FormerlySerializedAs("submeshSeparators")] [SpineSlot] public string[] separatorSlotNames = new string[0]; + [UnityEngine.Serialization.FormerlySerializedAs("submeshSeparators")][SerializeField][SpineSlot] protected string[] separatorSlotNames = new string[0]; [System.NonSerialized] public readonly List separatorSlots = new List(); [Range(-0.1f, 0f)] public float zSpacing; @@ -61,7 +61,7 @@ namespace Spine.Unity { public bool useClipping = true; public bool immutableTriangles = false; public bool pmaVertexColors = true; - /// Clears the state when this component or its GameObject is disabled. This prevents previous state from being retained when it is enabled again. When pooling your skeleton, setting this to true can be helpful. + /// Clears the state of the render and skeleton when this component or its GameObject is disabled. This prevents previous state from being retained when it is enabled again. When pooling your skeleton, setting this to true can be helpful. public bool clearStateOnDisable = false; public bool tintBlack = false; public bool singleSubmesh = false; @@ -323,5 +323,25 @@ namespace Spine.Unity { meshFilter.sharedMesh = currentMesh; currentSmartMesh.instructionUsed.Set(currentInstructions); } + + public void ReapplySeparatorSlotNames () { + if (!valid) + return; + + separatorSlots.Clear(); + for (int i = 0, n = separatorSlotNames.Length; i < n; i++) { + var slot = skeleton.FindSlot(separatorSlotNames[i]); + if (slot != null) { + separatorSlots.Add(slot); + } + #if UNITY_EDITOR + else + { + Debug.LogWarning(separatorSlotNames[i] + " is not a slot in " + skeletonDataAsset.skeletonJSON.name); + } + #endif + } + } + } }