diff --git a/spine-unity/Assets/spine-unity/Asset Types/Editor/AtlasAssetInspector.cs b/spine-unity/Assets/spine-unity/Asset Types/Editor/AtlasAssetInspector.cs index 9a6bc98fa..e6dacfe1c 100644 --- a/spine-unity/Assets/spine-unity/Asset Types/Editor/AtlasAssetInspector.cs +++ b/spine-unity/Assets/spine-unity/Asset Types/Editor/AtlasAssetInspector.cs @@ -120,7 +120,7 @@ namespace Spine.Unity.Editor { } if (materials.arraySize == 0) { - EditorGUILayout.LabelField(new GUIContent("Error: Missing materials", SpineEditorUtilities.Icons.warning)); + EditorGUILayout.HelpBox("Missing materials", MessageType.Error); return; } @@ -128,7 +128,7 @@ namespace Spine.Unity.Editor { SerializedProperty prop = materials.GetArrayElementAtIndex(i); Material mat = (Material)prop.objectReferenceValue; if (mat == null) { - EditorGUILayout.LabelField(new GUIContent("Error: Materials cannot be null", SpineEditorUtilities.Icons.warning)); + EditorGUILayout.HelpBox("Materials cannot be null.", MessageType.Error); return; } } diff --git a/spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs b/spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs index f38fc8f53..382cfff06 100644 --- a/spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs +++ b/spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs @@ -126,7 +126,7 @@ namespace Spine.Unity.Editor { if (serializedObject.isEditingMultipleObjects) { using (new SpineInspectorUtility.BoxScope()) { EditorGUILayout.LabelField("SkeletonData", EditorStyles.boldLabel); - EditorGUILayout.PropertyField(skeletonJSON, new GUIContent(skeletonJSON.displayName, Icons.spine)); + EditorGUILayout.PropertyField(skeletonJSON, SpineInspectorUtility.TempContent(skeletonJSON.displayName, Icons.spine)); EditorGUILayout.PropertyField(scale); } @@ -162,7 +162,7 @@ namespace Spine.Unity.Editor { serializedObject.Update(); - EditorGUILayout.LabelField(new GUIContent(target.name + " (SkeletonDataAsset)", Icons.spine), EditorStyles.whiteLargeLabel); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(target.name + " (SkeletonDataAsset)", Icons.spine), EditorStyles.whiteLargeLabel); if (m_skeletonData != null) { EditorGUILayout.LabelField("(Drag and Drop to instantiate.)", EditorStyles.miniLabel); } @@ -181,7 +181,7 @@ namespace Spine.Unity.Editor { // } } - EditorGUILayout.PropertyField(skeletonJSON, new GUIContent(skeletonJSON.displayName, Icons.spine)); + EditorGUILayout.PropertyField(skeletonJSON, SpineInspectorUtility.TempContent(skeletonJSON.displayName, Icons.spine)); EditorGUILayout.PropertyField(scale); } @@ -239,7 +239,7 @@ namespace Spine.Unity.Editor { #if !SPINE_TK2D // Reimport Button using (new EditorGUI.DisabledGroupScope(skeletonJSON.objectReferenceValue == null)) { - if (GUILayout.Button(new GUIContent("Attempt Reimport", Icons.warning))) { + if (GUILayout.Button(SpineInspectorUtility.TempContent("Attempt Reimport", Icons.warning))) { DoReimport(); } } @@ -249,7 +249,7 @@ namespace Spine.Unity.Editor { // List warnings. foreach (var line in warnings) - EditorGUILayout.LabelField(new GUIContent(line, Icons.warning)); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(line, Icons.warning)); } if (!Application.isPlaying) @@ -259,16 +259,16 @@ namespace Spine.Unity.Editor { void DrawUnityTools () { #if SPINE_SKELETON_ANIMATOR using (new SpineInspectorUtility.BoxScope()) { - isMecanimExpanded = EditorGUILayout.Foldout(isMecanimExpanded, new GUIContent("SkeletonAnimator", Icons.unityIcon)); + isMecanimExpanded = EditorGUILayout.Foldout(isMecanimExpanded, SpineInspectorUtility.TempContent("SkeletonAnimator", Icons.unityIcon)); if (isMecanimExpanded) { EditorGUI.indentLevel++; - EditorGUILayout.PropertyField(controller, new GUIContent("Controller", Icons.controllerIcon)); + EditorGUILayout.PropertyField(controller, SpineInspectorUtility.TempContent("Controller", Icons.controllerIcon)); if (controller.objectReferenceValue == null) { // Generate Mecanim Controller Button using (new GUILayout.HorizontalScope()) { GUILayout.Space(EditorGUIUtility.labelWidth); - if (GUILayout.Button(new GUIContent("Generate Mecanim Controller"), GUILayout.Height(20))) + if (GUILayout.Button(SpineInspectorUtility.TempContent("Generate Mecanim Controller"), GUILayout.Height(20))) SkeletonBaker.GenerateMecanimAnimationClips(m_skeletonDataAsset); } EditorGUILayout.HelpBox("SkeletonAnimator is the Mecanim alternative to SkeletonAnimation.\nIt is not required.", MessageType.Info); @@ -278,7 +278,7 @@ namespace Spine.Unity.Editor { // Update AnimationClips button. using (new GUILayout.HorizontalScope()) { GUILayout.Space(EditorGUIUtility.labelWidth); - if (GUILayout.Button(new GUIContent("Force Update AnimationClips"), GUILayout.Height(20))) + if (GUILayout.Button(SpineInspectorUtility.TempContent("Force Update AnimationClips"), GUILayout.Height(20))) SkeletonBaker.GenerateMecanimAnimationClips(m_skeletonDataAsset); } @@ -414,12 +414,12 @@ namespace Spine.Unity.Editor { } void DrawAnimationList () { - showAnimationList = EditorGUILayout.Foldout(showAnimationList, new GUIContent(string.Format("Animations [{0}]", m_skeletonData.Animations.Count), Icons.animationRoot)); + showAnimationList = EditorGUILayout.Foldout(showAnimationList, SpineInspectorUtility.TempContent(string.Format("Animations [{0}]", m_skeletonData.Animations.Count), Icons.animationRoot)); if (!showAnimationList) return; if (m_skeletonAnimation != null && m_skeletonAnimation.state != null) { - if (GUILayout.Button(new GUIContent("Setup Pose", Icons.skeleton), GUILayout.Width(105), GUILayout.Height(18))) { + if (GUILayout.Button(SpineInspectorUtility.TempContent("Setup Pose", Icons.skeleton), GUILayout.Width(105), GUILayout.Height(18))) { StopAnimation(); m_skeletonAnimation.skeleton.SetToSetupPose(); m_requireRefresh = true; @@ -428,7 +428,7 @@ namespace Spine.Unity.Editor { EditorGUILayout.HelpBox("Animations can be previewed if you expand the Preview window below.", MessageType.Info); } - EditorGUILayout.LabelField("Name", "Duration"); + EditorGUILayout.LabelField("Name", " Duration"); foreach (Spine.Animation animation in m_skeletonData.Animations) { using (new GUILayout.HorizontalScope()) { if (m_skeletonAnimation != null && m_skeletonAnimation.state != null) { @@ -445,13 +445,13 @@ namespace Spine.Unity.Editor { } else { GUILayout.Label("-", GUILayout.Width(24)); } - EditorGUILayout.LabelField(new GUIContent(animation.Name, Icons.animation), new GUIContent(animation.Duration.ToString("f3") + "s" + ("(" + (Mathf.RoundToInt(animation.Duration * 30)) + ")").PadLeft(12, ' '))); + EditorGUILayout.LabelField(new GUIContent(animation.Name, Icons.animation), SpineInspectorUtility.TempContent(animation.Duration.ToString("f3") + "s" + ("(" + (Mathf.RoundToInt(animation.Duration * 30)) + ")").PadLeft(12, ' '))); } } } void DrawSlotList () { - showSlotList = EditorGUILayout.Foldout(showSlotList, new GUIContent("Slots", Icons.slotRoot)); + showSlotList = EditorGUILayout.Foldout(showSlotList, SpineInspectorUtility.TempContent("Slots", Icons.slotRoot)); if (!showSlotList) return; if (m_skeletonAnimation == null || m_skeletonAnimation.skeleton == null) return; @@ -467,7 +467,7 @@ namespace Spine.Unity.Editor { for (int i = m_skeletonAnimation.skeleton.Slots.Count - 1; i >= 0; i--) { Slot slot = slotsItems[i]; - EditorGUILayout.LabelField(new GUIContent(slot.Data.Name, Icons.slot)); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(slot.Data.Name, Icons.slot)); if (showAttachments) { EditorGUI.indentLevel++; @@ -491,7 +491,7 @@ namespace Spine.Unity.Editor { string attachmentName = slotAttachmentNames[a]; Texture2D icon = Icons.GetAttachmentIcon(attachment); bool initialState = slot.Attachment == attachment; - bool toggled = EditorGUILayout.ToggleLeft(new GUIContent(attachmentName, icon), slot.Attachment == attachment); + bool toggled = EditorGUILayout.ToggleLeft(SpineInspectorUtility.TempContent(attachmentName, icon), slot.Attachment == attachment); if (!defaultSkinAttachmentNames.Contains(attachmentName)) { Rect skinPlaceHolderIconRect = GUILayoutUtility.GetLastRect(); @@ -831,13 +831,13 @@ namespace Spine.Unity.Editor { popRect.x += 4; popRect.height = 24; popRect.width = 40; - EditorGUI.DropShadowLabel(popRect, new GUIContent("Skin", Icons.skinsRoot)); + EditorGUI.DropShadowLabel(popRect, SpineInspectorUtility.TempContent("Skin")); popRect.y += 11; popRect.width = 150; popRect.x += 44; - if (GUI.Button(popRect, label, EditorStyles.popup)) { + if (GUI.Button(popRect, SpineInspectorUtility.TempContent(label, Icons.skin), EditorStyles.popup)) { DrawSkinDropdown(); } } @@ -954,7 +954,7 @@ namespace Spine.Unity.Editor { */ public override GUIContent GetPreviewTitle () { - return new GUIContent("Preview"); + return SpineInspectorUtility.TempContent("Preview"); } public override void OnPreviewSettings () { @@ -997,7 +997,7 @@ namespace Spine.Unity.Editor { void DrawSkinDropdown () { var menu = new GenericMenu(); foreach (Skin s in m_skeletonData.Skins) - menu.AddItem(new GUIContent(s.Name), this.m_skeletonAnimation.skeleton.Skin == s, SetSkin, s); + menu.AddItem(new GUIContent(s.Name, Icons.skin), this.m_skeletonAnimation.skeleton.Skin == s, SetSkin, s); menu.ShowAsContext(); } diff --git a/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs b/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs index fa4bd882f..9327fbfeb 100644 --- a/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs +++ b/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs @@ -167,16 +167,14 @@ namespace Spine.Unity.Editor { bool hasCollider2D = targetBoneFollower.GetComponent() != null || targetBoneFollower.GetComponent() != null; bool hasCollider3D = !hasCollider2D && targetBoneFollower.GetComponent(); - if (hasCollider2D || hasCollider3D) { - if (targetBoneFollower.GetComponent() == null) { - using (new SpineInspectorUtility.BoxScope()) { - EditorGUILayout.HelpBox("Collider detected. Unity recommends adding a Rigidbody to the parent Transforms of any colliders that are intended to be dynamically repositioned and rotated.", MessageType.Warning); - string rbLabel = hasCollider2D ? "Add Rigidbody2D" : "Add Rigidbody"; - var rbType = hasCollider2D ? typeof(Rigidbody2D) : typeof(Rigidbody); - var rbContent = new GUIContent(rbLabel, "Add a rigidbody to this GameObject to be the Box2D parent of the attached collider."); - rbContent.image = EditorGUIUtility.ObjectContent(null, rbType).image; - if (SpineInspectorUtility.CenteredButton(rbContent)) targetBoneFollower.gameObject.AddComponent(rbType); - } + bool missingRigidBody = (hasCollider2D && targetBoneFollower.GetComponent() == null) || (hasCollider3D && targetBoneFollower.GetComponent() == null); + if (missingRigidBody) { + using (new SpineInspectorUtility.BoxScope()) { + EditorGUILayout.HelpBox("Collider detected. Unity recommends adding a Rigidbody to the parent Transforms of any colliders that are intended to be dynamically repositioned and rotated.", MessageType.Warning); + var rbType = hasCollider2D ? typeof(Rigidbody2D) : typeof(Rigidbody); + string rbLabel = string.Format("Add {0}", rbType.Name); + var rbContent = SpineInspectorUtility.TempContent(rbLabel, SpineInspectorUtility.UnityIcon(rbType), "Add a rigidbody to this GameObject to be the Box2D parent of the attached collider."); + if (SpineInspectorUtility.CenteredButton(rbContent)) targetBoneFollower.gameObject.AddComponent(rbType); } } } else { diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-attachment.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-attachment.png new file mode 100644 index 000000000..4e14f9898 Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-attachment.png differ diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-attachment.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-attachment.png.meta new file mode 100644 index 000000000..1316c3d3a --- /dev/null +++ b/spine-unity/Assets/spine-unity/Editor/GUI/icon-attachment.png.meta @@ -0,0 +1,92 @@ +fileFormatVersion: 2 +guid: 04ae56b3698d3e844844cfcef2f009e7 +timeCreated: 1494928093 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 0 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 2 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: Android + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + - buildTarget: WebGL + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs index 0dd5f6a94..9a53b3104 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs @@ -88,6 +88,7 @@ namespace Spine.Unity.Editor { EditorGUILayout.PropertyField(timeScale, TimeScaleLabel); var component = (SkeletonAnimation)target; component.timeScale = Mathf.Max(component.timeScale, 0); + EditorGUILayout.Space(); } if (!isInspectingPrefab) { diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonDebugWindow.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonDebugWindow.cs index 169933e93..37ab3303b 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonDebugWindow.cs +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonDebugWindow.cs @@ -42,6 +42,7 @@ namespace Spine.Unity.Editor { public class SkeletonDebugWindow : EditorWindow { const bool IsUtilityWindow = true; + internal static bool showBoneNames, showPaths = true, showShapes = true, showConstraints = true; [MenuItem("CONTEXT/SkeletonRenderer/Open Skeleton Debug Window", false, 5000)] public static void Init () { @@ -79,7 +80,28 @@ namespace Spine.Unity.Editor { readonly Dictionary> attachmentTable = new Dictionary>(); + static bool staticLostValues = true; + + void OnSceneGUI (SceneView sceneView) { + if (skeleton == null || skeletonRenderer == null || !skeletonRenderer.valid || isPrefab) + return; + + var transform = skeletonRenderer.transform; + if (showPaths) SpineHandles.DrawPaths(transform, skeleton); + if (showConstraints) SpineHandles.DrawConstraints(transform, skeleton); + if (showBoneNames) SpineHandles.DrawBoneNames(transform, skeleton); + if (showShapes) SpineHandles.DrawBoundingBoxes(transform, skeleton); + + if (bone != null) { + SpineHandles.DrawBone(skeletonRenderer.transform, bone, 1.5f, Color.cyan); + Handles.Label(bone.GetWorldPosition(skeletonRenderer.transform) + (Vector3.down * 0.15f), bone.Data.Name, SpineHandles.BoneNameStyle); + } + } + void OnSelectionChange () { + SceneView.onSceneGUIDelegate -= this.OnSceneGUI; + SceneView.onSceneGUIDelegate += this.OnSceneGUI; + bool noSkeletonRenderer = false; var selectedObject = Selection.activeGameObject; @@ -90,6 +112,11 @@ namespace Spine.Unity.Editor { if (selectedSkeletonRenderer == null) { noSkeletonRenderer = true; } else if (skeletonRenderer != selectedSkeletonRenderer) { + + bone = null; + if (skeletonRenderer != null && skeletonRenderer.SkeletonDataAsset != selectedSkeletonRenderer.SkeletonDataAsset) + boneName = null; + skeletonRenderer = selectedSkeletonRenderer; skeletonRenderer.Initialize(false); skeletonRenderer.LateUpdate(); @@ -99,19 +126,43 @@ namespace Spine.Unity.Editor { } } - if (noSkeletonRenderer) { - skeletonRenderer = null; - skeleton = null; - attachmentTable.Clear(); - isPrefab = false; - boneName = string.Empty; - bone = null; - } - + if (noSkeletonRenderer) Clear(); Repaint(); } + void Clear () { + skeletonRenderer = null; + skeleton = null; + attachmentTable.Clear(); + isPrefab = false; + boneName = string.Empty; + bone = null; + SceneView.onSceneGUIDelegate -= this.OnSceneGUI; + } + + void OnDestroy () { + Clear(); + } + + static void FalseDropDown (string label, string stringValue, Texture2D icon = null, bool disabledGroup = false) { + if (disabledGroup) EditorGUI.BeginDisabledGroup(true); + var pos = EditorGUILayout.GetControlRect(true); + pos = EditorGUI.PrefixLabel(pos, SpineInspectorUtility.TempContent(label)); + GUI.Button(pos, SpineInspectorUtility.TempContent(stringValue, icon), EditorStyles.popup); + if (disabledGroup) EditorGUI.EndDisabledGroup(); + } + + // Window GUI void OnGUI () { + bool requireRepaint = false; + + if (staticLostValues) { + Clear(); + OnSelectionChange(); + staticLostValues = false; + requireRepaint = true; + } + if (SlotsRootLabel == null) { SlotsRootLabel = new GUIContent("Slots", Icons.slotRoot); SkeletonRootLabel = new GUIContent("Skeleton", Icons.skeleton); @@ -121,21 +172,24 @@ namespace Spine.Unity.Editor { BoldFoldoutStyle.fixedWidth = 0; } - bool requireRepaint = false; + EditorGUILayout.Space(); EditorGUI.BeginDisabledGroup(true); - EditorGUILayout.ObjectField("Debug Selection", skeletonRenderer, typeof(SkeletonRenderer), true); + EditorGUILayout.ObjectField(SpineInspectorUtility.TempContent("Debug Selection", Icons.spine), skeletonRenderer, typeof(SkeletonRenderer), true); EditorGUI.EndDisabledGroup(); - if (skeleton == null || skeletonRenderer == null || !skeletonRenderer.valid) return; + if (skeleton == null || skeletonRenderer == null) { + EditorGUILayout.HelpBox("No SkeletonRenderer Spine GameObject selected.", MessageType.Info); + return; + } if (isPrefab) { - GUILayout.Label(new GUIContent("Cannot edit Prefabs", Icons.warning)); + EditorGUILayout.HelpBox("SkeletonDebug only debugs Spine GameObjects in the scene.", MessageType.Warning); return; } if (!skeletonRenderer.valid) { - GUILayout.Label(new GUIContent("Spine Component invalid. Check Skeleton Data Asset.", Icons.warning)); + EditorGUILayout.HelpBox("Spine Component is invalid. Check SkeletonData Asset.", MessageType.Error); return; } @@ -145,7 +199,7 @@ namespace Spine.Unity.Editor { scrollPos = EditorGUILayout.BeginScrollView(scrollPos); using (new SpineInspectorUtility.BoxScope(false)) { - if (SpineInspectorUtility.CenteredButton(new GUIContent("Skeleton.SetToSetupPose()"))) { + if (SpineInspectorUtility.CenteredButton(SpineInspectorUtility.TempContent("Skeleton.SetToSetupPose()"))) { skeleton.SetToSetupPose(); requireRepaint = true; } @@ -153,10 +207,10 @@ namespace Spine.Unity.Editor { EditorGUI.BeginChangeCheck(); EditorGUILayout.LabelField("Scene View", EditorStyles.boldLabel); using (new SpineInspectorUtility.LabelWidthScope()) { - SkeletonRendererInspector.showBoneNames = EditorGUILayout.Toggle("Show Bone Names", SkeletonRendererInspector.showBoneNames); - SkeletonRendererInspector.showPaths = EditorGUILayout.Toggle("Show Paths", SkeletonRendererInspector.showPaths); - SkeletonRendererInspector.showShapes = EditorGUILayout.Toggle("Show Shapes", SkeletonRendererInspector.showShapes); - SkeletonRendererInspector.showConstraints = EditorGUILayout.Toggle("Show Constraints", SkeletonRendererInspector.showConstraints); + showBoneNames = EditorGUILayout.Toggle("Show Bone Names", showBoneNames); + showPaths = EditorGUILayout.Toggle("Show Paths", showPaths); + showShapes = EditorGUILayout.Toggle("Show Shapes", showShapes); + showConstraints = EditorGUILayout.Toggle("Show Constraints", showConstraints); } requireRepaint |= EditorGUI.EndChangeCheck(); @@ -168,6 +222,10 @@ namespace Spine.Unity.Editor { using (new EditorGUILayout.FadeGroupScope(showSkeleton.faded)) { EditorGUI.BeginChangeCheck(); + EditorGUI.BeginDisabledGroup(true); + FalseDropDown(".Skin", skeleton.Skin != null ? skeletonRenderer.Skeleton.Skin.Name : "", Icons.skin); + EditorGUI.EndDisabledGroup(); + // Flip EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(160f)); EditorGUILayout.LabelField("Flip", GUILayout.MaxWidth(EditorGUIUtility.labelWidth - 20f)); @@ -184,12 +242,13 @@ namespace Spine.Unity.Editor { } // Bone - showInspectBoneTree.target = EditorGUILayout.Foldout(showInspectBoneTree.target, new GUIContent("Bone", Icons.bone), BoldFoldoutStyle); + showInspectBoneTree.target = EditorGUILayout.Foldout(showInspectBoneTree.target, SpineInspectorUtility.TempContent("Bone", Icons.bone), BoldFoldoutStyle); if (showInspectBoneTree.faded > 0) { using (new SpineInspectorUtility.IndentScope()) { using (new EditorGUILayout.FadeGroupScope(showInspectBoneTree.faded)) { + showBoneNames = EditorGUILayout.Toggle("Show Bone Names", showBoneNames); if (bpo == null) bpo = new SerializedObject(this).FindProperty("boneName"); - EditorGUILayout.PropertyField(bpo); + EditorGUILayout.PropertyField(bpo, SpineInspectorUtility.TempContent("Bone")); if (!string.IsNullOrEmpty(bpo.stringValue)) { if (bone == null || bone.Data.Name != bpo.stringValue) { bone = skeleton.FindBone(bpo.stringValue); @@ -197,18 +256,48 @@ namespace Spine.Unity.Editor { if (bone != null) { using (new EditorGUI.DisabledGroupScope(true)) { - var boneParent = bone.Parent; - if (boneParent != null) EditorGUILayout.TextField("parent", boneParent.Data.Name); + var wm = EditorGUIUtility.wideMode; + EditorGUIUtility.wideMode = true; + EditorGUILayout.Slider("Local Rotation", ViewRound(bone.Rotation), -180f, 180f); + EditorGUILayout.Vector2Field("Local Position", RoundVector2(bone.X, bone.Y)); + EditorGUILayout.Vector2Field("Local Scale", RoundVector2(bone.ScaleX, bone.ScaleY)); + EditorGUILayout.Vector2Field("Local Shear", RoundVector2(bone.ShearX, bone.ShearY)); + EditorGUILayout.Space(); - EditorGUILayout.Slider("Local Rotation", bone.Rotation, -180f, 180f); - EditorGUILayout.Vector2Field("Local Position", new Vector2(bone.X, bone.Y)); - EditorGUILayout.Vector2Field("Local Scale", new Vector2(bone.ScaleX, bone.ScaleY)); - EditorGUILayout.Vector2Field("Local Shear", new Vector2(bone.ShearX, bone.ShearY)); -// EditorGUILayout.Space(); -// EditorGUILayout.LabelField("LocalToWorld Matrix"); -// EditorGUILayout.Vector2Field("AB", new Vector2(bone.A, bone.B)); -// EditorGUILayout.Vector2Field("CD", new Vector2(bone.C, bone.D)); + var boneParent = bone.Parent; + if (boneParent != null) FalseDropDown("Parent", boneParent.Data.Name, Icons.bone); + + const string RoundFormat = "0.##"; + var lw = EditorGUIUtility.labelWidth; + var fw = EditorGUIUtility.fieldWidth; + EditorGUIUtility.labelWidth *= 0.25f; + EditorGUIUtility.fieldWidth *= 0.5f; + EditorGUILayout.LabelField("LocalToWorld"); + + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.Space(); + EditorGUILayout.TextField(".A", bone.A.ToString(RoundFormat)); + EditorGUILayout.TextField(".B", bone.B.ToString(RoundFormat)); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.Space(); + EditorGUILayout.TextField(".C", bone.C.ToString(RoundFormat)); + EditorGUILayout.TextField(".D", bone.D.ToString(RoundFormat)); + EditorGUILayout.EndHorizontal(); + + EditorGUIUtility.labelWidth = lw * 0.5f; + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.Space(); + EditorGUILayout.Space(); + EditorGUILayout.TextField(".WorldX", bone.WorldX.ToString(RoundFormat)); + EditorGUILayout.TextField(".WorldY", bone.WorldY.ToString(RoundFormat)); + EditorGUILayout.EndHorizontal(); + + EditorGUIUtility.labelWidth = lw; + EditorGUIUtility.fieldWidth = fw; + EditorGUIUtility.wideMode = wm; + } } requireRepaint = true; @@ -224,7 +313,7 @@ namespace Spine.Unity.Editor { showSlotsTree.target = EditorGUILayout.Foldout(showSlotsTree.target, SlotsRootLabel, BoldFoldoutStyle); if (showSlotsTree.faded > 0) { using (new EditorGUILayout.FadeGroupScope(showSlotsTree.faded)) { - if (SpineInspectorUtility.CenteredButton(new GUIContent("Skeleton.SetSlotsToSetupPose()"))) { + if (SpineInspectorUtility.CenteredButton(SpineInspectorUtility.TempContent("Skeleton.SetSlotsToSetupPose()"))) { skeleton.SetSlotsToSetupPose(); requireRepaint = true; } @@ -235,7 +324,7 @@ namespace Spine.Unity.Editor { using (new EditorGUILayout.HorizontalScope()) { EditorGUI.indentLevel = baseIndent + 1; - EditorGUILayout.LabelField(new GUIContent(slot.Data.Name, Icons.slot), GUILayout.ExpandWidth(false)); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(slot.Data.Name, Icons.slot), GUILayout.ExpandWidth(false)); EditorGUI.BeginChangeCheck(); Color c = EditorGUILayout.ColorField(new Color(slot.R, slot.G, slot.B, slot.A), GUILayout.Width(60)); if (EditorGUI.EndChangeCheck()) { @@ -249,7 +338,7 @@ namespace Spine.Unity.Editor { EditorGUI.indentLevel = baseIndent + 2; var icon = Icons.GetAttachmentIcon(attachment); bool isAttached = (attachment == slot.Attachment); - bool swap = EditorGUILayout.ToggleLeft(new GUIContent(attachment.Name, icon), attachment == slot.Attachment); + bool swap = EditorGUILayout.ToggleLeft(SpineInspectorUtility.TempContent(attachment.Name, icon), attachment == slot.Attachment); if (isAttached != swap) { slot.Attachment = isAttached ? null : attachment; requireRepaint = true; @@ -263,18 +352,24 @@ namespace Spine.Unity.Editor { // Constraints const string NoneText = ""; - showConstraintsTree.target = EditorGUILayout.Foldout(showConstraintsTree.target, new GUIContent("Constraints", Icons.constraintRoot), BoldFoldoutStyle); + showConstraintsTree.target = EditorGUILayout.Foldout(showConstraintsTree.target, SpineInspectorUtility.TempContent("Constraints", Icons.constraintRoot), BoldFoldoutStyle); if (showConstraintsTree.faded > 0) { using (new SpineInspectorUtility.IndentScope()) { using (new EditorGUILayout.FadeGroupScope(showConstraintsTree.faded)) { const float MixMin = 0f; const float MixMax = 1f; + EditorGUI.BeginChangeCheck(); + showConstraints = EditorGUILayout.Toggle("Show Constraints", showConstraints); + requireRepaint |= EditorGUI.EndChangeCheck(); - EditorGUILayout.LabelField(new GUIContent(string.Format("IK Constraints ({0})", skeleton.IkConstraints.Count), Icons.constraintIK), EditorStyles.boldLabel); + EditorGUILayout.Space(); + + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(string.Format("IK Constraints ({0})", skeleton.IkConstraints.Count), Icons.constraintIK), EditorStyles.boldLabel); using (new SpineInspectorUtility.IndentScope()) { if (skeleton.IkConstraints.Count > 0) { foreach (var c in skeleton.IkConstraints) { - EditorGUILayout.LabelField(new GUIContent(c.Data.Name, Icons.constraintIK)); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(c.Data.Name, Icons.constraintIK)); + FalseDropDown("Goal", c.Data.Target.Name, Icons.bone, true); EditorGUI.BeginChangeCheck(); c.Mix = EditorGUILayout.Slider("Mix", c.Mix, MixMin, MixMax); @@ -289,11 +384,14 @@ namespace Spine.Unity.Editor { } } - EditorGUILayout.LabelField(new GUIContent(string.Format("Transform Constraints ({0})", skeleton.TransformConstraints.Count), Icons.constraintTransform), EditorStyles.boldLabel); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(string.Format("Transform Constraints ({0})", skeleton.TransformConstraints.Count), Icons.constraintTransform), EditorStyles.boldLabel); using (new SpineInspectorUtility.IndentScope()) { if (skeleton.TransformConstraints.Count > 0) { foreach (var c in skeleton.TransformConstraints) { - EditorGUILayout.LabelField(new GUIContent(c.Data.Name, Icons.constraintTransform)); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(c.Data.Name, Icons.constraintTransform)); + EditorGUI.BeginDisabledGroup(true); + FalseDropDown("Goal", c.Data.Target.Name, Icons.bone); + EditorGUI.EndDisabledGroup(); EditorGUI.BeginChangeCheck(); c.TranslateMix = EditorGUILayout.Slider("TranslateMix", c.TranslateMix, MixMin, MixMax); @@ -309,14 +407,24 @@ namespace Spine.Unity.Editor { } } - EditorGUILayout.LabelField(new GUIContent(string.Format("Path Constraints ({0})", skeleton.PathConstraints.Count), Icons.constraintPath), EditorStyles.boldLabel); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(string.Format("Path Constraints ({0})", skeleton.PathConstraints.Count), Icons.constraintPath), EditorStyles.boldLabel); + + EditorGUI.BeginChangeCheck(); + showPaths = EditorGUILayout.Toggle("Show Paths", showPaths); + requireRepaint |= EditorGUI.EndChangeCheck(); + using (new SpineInspectorUtility.IndentScope()) { if (skeleton.PathConstraints.Count > 0) { foreach (var c in skeleton.PathConstraints) { - EditorGUILayout.LabelField(new GUIContent(c.Data.Name, Icons.constraintPath)); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(c.Data.Name, Icons.constraintPath)); + EditorGUI.BeginDisabledGroup(true); + FalseDropDown("Path Slot", c.Data.Target.Name, Icons.slot); + var activeAttachment = c.Target.Attachment; + FalseDropDown("Active Path", activeAttachment != null ? activeAttachment.Name : "", activeAttachment is PathAttachment ? Icons.path : null); EditorGUILayout.LabelField("PositionMode." + c.Data.PositionMode); EditorGUILayout.LabelField("SpacingMode." + c.Data.SpacingMode); EditorGUILayout.LabelField("RotateMode." + c.Data.RotateMode); + EditorGUI.EndDisabledGroup(); EditorGUI.BeginChangeCheck(); c.RotateMix = EditorGUILayout.Slider("RotateMix", c.RotateMix, MixMin, MixMax); @@ -336,26 +444,28 @@ namespace Spine.Unity.Editor { } } - showDrawOrderTree.target = EditorGUILayout.Foldout(showDrawOrderTree.target, new GUIContent("Draw Order and Separators", Icons.slotRoot), BoldFoldoutStyle); + showDrawOrderTree.target = EditorGUILayout.Foldout(showDrawOrderTree.target, SpineInspectorUtility.TempContent("Draw Order and Separators", Icons.slotRoot), BoldFoldoutStyle); if (showDrawOrderTree.faded > 0) { using (new SpineInspectorUtility.IndentScope()) { using (new EditorGUILayout.FadeGroupScope(showDrawOrderTree.faded)) { + const string SeparatorString = "------------- v SEPARATOR v -------------"; + if (Application.isPlaying) { foreach (var slot in skeleton.DrawOrder) { - if (skeletonRenderer.separatorSlots.Contains(slot)) EditorGUILayout.LabelField("------"); - EditorGUILayout.LabelField(new GUIContent(slot.Data.Name, Icons.slot), GUILayout.ExpandWidth(false)); + if (skeletonRenderer.separatorSlots.Contains(slot)) EditorGUILayout.LabelField(SeparatorString); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(slot.Data.Name, Icons.slot), GUILayout.ExpandWidth(false)); } } else { foreach (var slot in skeleton.DrawOrder) { var slotNames = skeletonRenderer.separatorSlotNames; for (int i = 0, n = slotNames.Length; i < n; i++) { if (string.Equals(slotNames[i], slot.Data.Name, System.StringComparison.Ordinal)) { - EditorGUILayout.LabelField("------"); + EditorGUILayout.LabelField(SeparatorString); break; } } - EditorGUILayout.LabelField(new GUIContent(slot.Data.Name, Icons.slot), GUILayout.ExpandWidth(false)); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(slot.Data.Name, Icons.slot), GUILayout.ExpandWidth(false)); } } @@ -363,13 +473,13 @@ namespace Spine.Unity.Editor { } } - showEventDataTree.target = EditorGUILayout.Foldout(showEventDataTree.target, new GUIContent("Events", Icons.userEvent), BoldFoldoutStyle); + showEventDataTree.target = EditorGUILayout.Foldout(showEventDataTree.target, SpineInspectorUtility.TempContent("Events", Icons.userEvent), BoldFoldoutStyle); if (showEventDataTree.faded > 0) { using (new SpineInspectorUtility.IndentScope()) { using (new EditorGUILayout.FadeGroupScope(showEventDataTree.faded)) { if (skeleton.Data.Events.Count > 0) { foreach (var e in skeleton.Data.Events) { - EditorGUILayout.LabelField(new GUIContent(e.Name, Icons.userEvent)); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent(e.Name, Icons.userEvent)); } } else { EditorGUILayout.LabelField(NoneText); @@ -378,6 +488,8 @@ namespace Spine.Unity.Editor { } } + // TODO: Data counts. bones, slots, constraints, skins, etc... + if (IsAnimating(showSlotsTree, showSkeleton, showConstraintsTree, showDrawOrderTree, showEventDataTree, showInspectBoneTree)) Repaint(); } @@ -391,6 +503,18 @@ namespace Spine.Unity.Editor { EditorGUILayout.EndScrollView(); } + static float ViewRound (float x) { + const float Factor = 100f; + const float Divisor = 1f/Factor; + return Mathf.Round(x * Factor) * Divisor; + } + + static Vector2 RoundVector2 (float x, float y) { + const float Factor = 100f; + const float Divisor = 1f/Factor; + return new Vector2(Mathf.Round(x * Factor) * Divisor, Mathf.Round(y * Factor) * Divisor); + } + static bool IsAnimating (params AnimBool[] animBools) { foreach (var a in animBools) if (a.isAnimating) return true; diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs index 8ebb49769..899f854a0 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs @@ -42,7 +42,6 @@ namespace Spine.Unity.Editor { [CanEditMultipleObjects] public class SkeletonRendererInspector : UnityEditor.Editor { protected static bool advancedFoldout; - internal static bool showBoneNames, showPaths, showShapes, showConstraints = true; protected SerializedProperty skeletonDataAsset, initialSkinName; protected SerializedProperty initialFlipX, initialFlipY; @@ -131,6 +130,9 @@ namespace Spine.Unity.Editor { } } + GUIContent[] skins; + ExposedList loadedSkinList; + protected virtual void DrawInspectorGUI (bool multi) { bool valid = TargetIsValid; var reloadWidth = GUILayout.Width(GUI.skin.label.CalcSize(new GUIContent(ReloadButtonLabel)).x + 20); @@ -216,17 +218,27 @@ namespace Spine.Unity.Editor { // Initial skin name. if (component.valid) { - string[] skins = new string[component.skeleton.Data.Skins.Count]; + var skeletonDataSkins = component.skeleton.Data.Skins; + int skinCount = skeletonDataSkins.Count; + if (loadedSkinList != skeletonDataSkins) { + skins = new GUIContent[skinCount]; + loadedSkinList = skeletonDataSkins; + for (int i = 0; i < skins.Length; i++) { + string skinNameString = skeletonDataSkins.Items[i].Name; + skins[i] = new GUIContent(skinNameString, Icons.skin); + } + } + int skinIndex = 0; for (int i = 0; i < skins.Length; i++) { - string skinNameString = component.skeleton.Data.Skins.Items[i].Name; - skins[i] = skinNameString; + string skinNameString = skeletonDataSkins.Items[i].Name; if (skinNameString == initialSkinName.stringValue) skinIndex = i; } - skinIndex = EditorGUILayout.Popup("Initial Skin", skinIndex, skins); + + skinIndex = EditorGUILayout.Popup(SpineInspectorUtility.TempContent("Initial Skin"), skinIndex, skins); if (skins.Length > 0) // Support attachmentless/skinless SkeletonData. - initialSkinName.stringValue = skins[skinIndex]; + initialSkinName.stringValue = skins[skinIndex].text; } } @@ -268,7 +280,6 @@ namespace Spine.Unity.Editor { if (singleSubmesh != null) EditorGUILayout.PropertyField(singleSubmesh, SingleSubmeshLabel); if (meshes != null) EditorGUILayout.PropertyField(meshes, MeshesLabel); if (immutableTriangles != null) EditorGUILayout.PropertyField(immutableTriangles, ImmubleTrianglesLabel); - EditorGUILayout.PropertyField(tintBlack, TintBlackLabel); EditorGUILayout.PropertyField(clearStateOnDisable, ClearStateOnDisableLabel); EditorGUILayout.Space(); } @@ -283,8 +294,10 @@ namespace Spine.Unity.Editor { EditorGUILayout.Space(); using (new SpineInspectorUtility.LabelWidthScope()) { - EditorGUILayout.LabelField("Vertex Data", EditorStyles.boldLabel); + //EditorGUILayout.LabelField("Vertex Data", EditorStyles.boldLabel); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Vertex Data", EditorGUIUtility.ObjectContent(null, typeof(MeshFilter)).image as Texture2D), EditorStyles.boldLabel); if (pmaVertexColors != null) EditorGUILayout.PropertyField(pmaVertexColors, PMAVertexColorsLabel); + EditorGUILayout.PropertyField(tintBlack, TintBlackLabel); // Optional fields. May be disabled in SkeletonRenderer. if (normals != null) EditorGUILayout.PropertyField(normals, NormalsLabel); @@ -344,7 +357,7 @@ namespace Spine.Unity.Editor { using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { const string SeparatorsDescription = "Stored names of slots where the Skeleton's render will be split into different batches. This is used by separate components that split the render into different MeshRenderers or GameObjects."; if (separatorSlotNames.isExpanded) { - EditorGUILayout.PropertyField(separatorSlotNames, new GUIContent(separatorSlotNames.displayName + terminalSlotWarning, SeparatorsDescription), true); + EditorGUILayout.PropertyField(separatorSlotNames, SpineInspectorUtility.TempContent(separatorSlotNames.displayName + terminalSlotWarning, Icons.slotRoot, SeparatorsDescription), true); GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); if (GUILayout.Button("+", GUILayout.MaxWidth(28f), GUILayout.MaxHeight(15f))) { @@ -364,11 +377,7 @@ namespace Spine.Unity.Editor { var transform = skeletonRenderer.transform; if (skeleton == null) return; - if (showPaths) SpineHandles.DrawPaths(transform, skeleton); SpineHandles.DrawBones(transform, skeleton); - if (showConstraints) SpineHandles.DrawConstraints(transform, skeleton); - if (showBoneNames) SpineHandles.DrawBoneNames(transform, skeleton); - if (showShapes) SpineHandles.DrawBoundingBoxes(transform, skeleton); } override public void OnInspectorGUI () { diff --git a/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs b/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs index a962b7863..43ce4e00e 100644 --- a/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs +++ b/spine-unity/Assets/spine-unity/Editor/SpineAttributeDrawers.cs @@ -50,11 +50,22 @@ namespace Spine.Unity.Editor { public abstract class SpineTreeItemDrawerBase : PropertyDrawer where T:SpineAttributeBase { protected SkeletonDataAsset skeletonDataAsset; - internal const string NoneLabel = ""; + internal const string NoneString = ""; + // Analysis disable once StaticFieldInGenericType + static GUIContent noneLabel; + static GUIContent NoneLabel (Texture2D image = null) { + if (noneLabel == null) + noneLabel = new GUIContent(NoneString); + noneLabel.image = image; + return noneLabel; + } + protected T TargetAttribute { get { return (T)attribute; } } protected SerializedProperty SerializedProperty { get; private set; } + protected abstract Texture2D Icon { get; } + public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) { SerializedProperty = property; @@ -89,11 +100,10 @@ namespace Spine.Unity.Editor { } position = EditorGUI.PrefixLabel(position, label); - + var image = Icon; var propertyStringValue = (property.hasMultipleDifferentValues) ? SpineInspectorUtility.EmDash : property.stringValue; - if (GUI.Button(position, string.IsNullOrEmpty(propertyStringValue) ? NoneLabel : propertyStringValue, EditorStyles.popup)) + if (GUI.Button(position, string.IsNullOrEmpty(propertyStringValue) ? NoneLabel(image) : SpineInspectorUtility.TempContent(propertyStringValue, image), EditorStyles.popup)) Selector(property); - } public ISkeletonComponent GetTargetSkeletonComponent (SerializedProperty property) { @@ -138,6 +148,8 @@ namespace Spine.Unity.Editor { [CustomPropertyDrawer(typeof(SpineSlot))] public class SpineSlotDrawer : SpineTreeItemDrawerBase { + protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.slot; } } + protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineSlot targetAttribute, SkeletonData data) { for (int i = 0; i < data.Slots.Count; i++) { string name = data.Slots.Items[i].Name; @@ -177,6 +189,8 @@ namespace Spine.Unity.Editor { [CustomPropertyDrawer(typeof(SpineSkin))] public class SpineSkinDrawer : SpineTreeItemDrawerBase { + protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.skin; } } + protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineSkin targetAttribute, SkeletonData data) { menu.AddDisabledItem(new GUIContent(skeletonDataAsset.name)); menu.AddSeparator(""); @@ -192,11 +206,14 @@ namespace Spine.Unity.Editor { [CustomPropertyDrawer(typeof(SpineAnimation))] public class SpineAnimationDrawer : SpineTreeItemDrawerBase { + + protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.animation; } } + protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineAnimation targetAttribute, SkeletonData data) { var animations = skeletonDataAsset.GetAnimationStateData().SkeletonData.Animations; // item - menu.AddItem(new GUIContent(NoneLabel), string.IsNullOrEmpty(property.stringValue), HandleSelect, new SpineDrawerValuePair("", property)); + menu.AddItem(new GUIContent(NoneString), string.IsNullOrEmpty(property.stringValue), HandleSelect, new SpineDrawerValuePair(string.Empty, property)); for (int i = 0; i < animations.Count; i++) { string name = animations.Items[i].Name; @@ -209,11 +226,14 @@ namespace Spine.Unity.Editor { [CustomPropertyDrawer(typeof(SpineEvent))] public class SpineEventNameDrawer : SpineTreeItemDrawerBase { + + protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.userEvent; } } + protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineEvent targetAttribute, SkeletonData data) { var events = skeletonDataAsset.GetSkeletonData(false).Events; // item - menu.AddItem(new GUIContent(NoneLabel), string.IsNullOrEmpty(property.stringValue), HandleSelect, new SpineDrawerValuePair("", property)); + menu.AddItem(new GUIContent(NoneString), string.IsNullOrEmpty(property.stringValue), HandleSelect, new SpineDrawerValuePair(string.Empty, property)); for (int i = 0; i < events.Count; i++) { string name = events.Items[i].Name; @@ -226,6 +246,9 @@ namespace Spine.Unity.Editor { [CustomPropertyDrawer(typeof(SpineAttachment))] public class SpineAttachmentDrawer : SpineTreeItemDrawerBase { + + protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.genericAttachment; } } + protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineAttachment targetAttribute, SkeletonData data) { ISkeletonComponent skeletonComponent = GetTargetSkeletonComponent(property); var validSkins = new List(); @@ -252,7 +275,8 @@ namespace Spine.Unity.Editor { menu.AddDisabledItem(new GUIContent(skeletonDataAsset.name)); menu.AddSeparator(""); - menu.AddItem(new GUIContent("Null"), property.stringValue == "", HandleSelect, new SpineDrawerValuePair("", property)); + const string NullAttachmentName = ""; + menu.AddItem(new GUIContent("Null"), property.stringValue == NullAttachmentName, HandleSelect, new SpineDrawerValuePair(NullAttachmentName, property)); menu.AddSeparator(""); Skin defaultSkin = data.Skins.Items[0]; @@ -260,9 +284,8 @@ namespace Spine.Unity.Editor { SerializedProperty slotProperty = property.serializedObject.FindProperty(targetAttribute.slotField); string slotMatch = ""; if (slotProperty != null) { - if (slotProperty.propertyType == SerializedPropertyType.String) { + if (slotProperty.propertyType == SerializedPropertyType.String) slotMatch = slotProperty.stringValue.ToLower(); - } } foreach (Skin skin in validSkins) { @@ -307,10 +330,15 @@ namespace Spine.Unity.Editor { [CustomPropertyDrawer(typeof(SpineBone))] public class SpineBoneDrawer : SpineTreeItemDrawerBase { + + protected override Texture2D Icon { get { return SpineEditorUtilities.Icons.bone; } } + protected override void PopulateMenu (GenericMenu menu, SerializedProperty property, SpineBone targetAttribute, SkeletonData data) { menu.AddDisabledItem(new GUIContent(skeletonDataAsset.name)); menu.AddSeparator(""); + menu.AddItem(new GUIContent(NoneString), string.IsNullOrEmpty(property.stringValue), HandleSelect, new SpineDrawerValuePair(string.Empty, property)); + for (int i = 0; i < data.Bones.Count; i++) { string name = data.Bones.Items[i].Name; if (name.StartsWith(targetAttribute.startsWith, StringComparison.Ordinal)) diff --git a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs index cc6ed2878..9202a8c91 100644 --- a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs +++ b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs @@ -59,6 +59,7 @@ namespace Spine.Unity.Editor { public static Texture2D slotRoot; public static Texture2D skinPlaceholder; public static Texture2D image; + public static Texture2D genericAttachment; public static Texture2D boundingBox; public static Texture2D mesh; public static Texture2D weights; @@ -90,11 +91,13 @@ namespace Spine.Unity.Editor { slot = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-slot.png"); slotRoot = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-slotRoot.png"); skinPlaceholder = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skinPlaceholder.png"); + + genericAttachment = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-attachment.png"); image = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-image.png"); boundingBox = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-boundingBox.png"); mesh = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-mesh.png"); weights = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-weights.png"); - skin = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skinPlaceholder.png"); + skin = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skin.png"); skinsRoot = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skinsRoot.png"); animation = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-animation.png"); animationRoot = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-animationRoot.png"); @@ -1559,15 +1562,25 @@ namespace Spine.Unity.Editor { } static Material _boneMaterial; - public static Material BoneMaterial { + static Material BoneMaterial { get { if (_boneMaterial == null) { _boneMaterial = new Material(Shader.Find("Hidden/Spine/Bones")); _boneMaterial.SetColor("_Color", SpineHandles.BoneColor); } + return _boneMaterial; } } + public static Material GetBoneMaterial () { + BoneMaterial.SetColor("_Color", SpineHandles.BoneColor); + return BoneMaterial; + } + + public static Material GetBoneMaterial (Color color) { + BoneMaterial.SetColor("_Color", color); + return BoneMaterial; + } static Material _ikMaterial; public static Material IKMaterial { @@ -1661,7 +1674,7 @@ namespace Spine.Unity.Editor { const float my = 1.5f; scale.y *= (SpineHandles.handleScale + 1f) * 0.5f; scale.y = Mathf.Clamp(scale.x, -my, my); - SpineHandles.BoneMaterial.SetPass(0); + SpineHandles.GetBoneMaterial().SetPass(0); Graphics.DrawMeshNow(SpineHandles.BoneMesh, transform.localToWorldMatrix * Matrix4x4.TRS(pos, rot, scale)); } else { var wp = transform.TransformPoint(pos); @@ -1669,6 +1682,23 @@ namespace Spine.Unity.Editor { } } + public static void DrawBone (Transform transform, Bone b, float boneScale, Color color) { + var pos = new Vector3(b.WorldX, b.WorldY, 0); + float length = b.Data.Length; + if (length > 0) { + Quaternion rot = Quaternion.Euler(0, 0, b.WorldRotationX); + Vector3 scale = Vector3.one * length * b.WorldScaleX; + const float my = 1.5f; + scale.y *= (SpineHandles.handleScale + 1f) * 0.5f; + scale.y = Mathf.Clamp(scale.x, -my, my); + SpineHandles.GetBoneMaterial(color).SetPass(0); + Graphics.DrawMeshNow(SpineHandles.BoneMesh, transform.localToWorldMatrix * Matrix4x4.TRS(pos, rot, scale)); + } else { + var wp = transform.TransformPoint(pos); + DrawBoneCircle(wp, color, transform.forward, boneScale); + } + } + public static void DrawPaths (Transform transform, Skeleton skeleton) { foreach (Slot s in skeleton.DrawOrder) { var p = s.Attachment as PathAttachment; diff --git a/spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs b/spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs index 58fb47aaf..8f5dd6242 100644 --- a/spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs +++ b/spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs @@ -48,25 +48,37 @@ namespace Spine.Unity.Editor { get { return "\u2014"; } } + static GUIContent tempContent; + internal static GUIContent TempContent (string text, Texture2D image = null, string tooltip = null) { + if (tempContent == null) tempContent = new GUIContent(); + tempContent.text = text; + tempContent.image = image; + tempContent.tooltip = tooltip; + return tempContent; + } + public static void PropertyFieldWideLabel (SerializedProperty property, GUIContent label = null, float minimumLabelWidth = 150) { EditorGUIUtility.labelWidth = minimumLabelWidth; - EditorGUILayout.PropertyField(property, label ?? new GUIContent(property.displayName, property.tooltip)); + EditorGUILayout.PropertyField(property, label ?? TempContent(property.displayName, null, property.tooltip)); EditorGUIUtility.labelWidth = 0; // Resets to default } public static void PropertyFieldFitLabel (SerializedProperty property, GUIContent label = null, float extraSpace = 5f) { - label = label ?? new GUIContent(property.displayName, property.tooltip); - float width = GUI.skin.label.CalcSize(new GUIContent(label.text)).x + extraSpace; + label = label ?? TempContent(property.displayName, null, property.tooltip); + float width = GUI.skin.label.CalcSize(TempContent(label.text)).x + extraSpace; if (label.image != null) width += EditorGUIUtility.singleLineHeight; PropertyFieldWideLabel(property, label, width); - } public static bool UndoRedoPerformed (UnityEngine.Event current) { return current.type == EventType.ValidateCommand && current.commandName == "UndoRedoPerformed"; } + public static Texture2D UnityIcon (System.Type type) { + return EditorGUIUtility.ObjectContent(null, type).image as Texture2D; + } + #region Layout Scopes static GUIStyle grayMiniLabel; public static GUIStyle GrayMiniLabel { diff --git a/spine-unity/Assets/spine-unity/Modules/CustomMaterials/Editor/SkeletonRendererCustomMaterialsInspector.cs b/spine-unity/Assets/spine-unity/Modules/CustomMaterials/Editor/SkeletonRendererCustomMaterialsInspector.cs index e30e0b9c1..47d532d12 100644 --- a/spine-unity/Assets/spine-unity/Modules/CustomMaterials/Editor/SkeletonRendererCustomMaterialsInspector.cs +++ b/spine-unity/Assets/spine-unity/Modules/CustomMaterials/Editor/SkeletonRendererCustomMaterialsInspector.cs @@ -136,7 +136,7 @@ namespace Spine.Unity.Editor { _customMaterialOverridesPrev = CopyList(componentCustomMaterialOverrides); _customSlotMaterialsPrev = CopyList(componentCustomSlotMaterials); - if (SpineInspectorUtility.LargeCenteredButton(new GUIContent("Clear and Reapply Changes", "Removes all non-serialized overrides in the SkeletonRenderer and reapplies the overrides on this component."))) { + if (SpineInspectorUtility.LargeCenteredButton(SpineInspectorUtility.TempContent("Clear and Reapply Changes", tooltip: "Removes all non-serialized overrides in the SkeletonRenderer and reapplies the overrides on this component."))) { if (skeletonRenderer != null) { #if SPINE_OPTIONAL_MATERIALOVERRIDE skeletonRenderer.CustomMaterialOverride.Clear(); diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs index 7e114cc7a..13a97b2e3 100644 --- a/spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs +++ b/spine-unity/Assets/spine-unity/Modules/SkeletonGraphic/Editor/SkeletonGraphicInspector.cs @@ -84,7 +84,7 @@ namespace Spine.Unity.Editor { return; } using (new SpineInspectorUtility.BoxScope()) { - EditorGUILayout.PropertyField(meshGeneratorSettings_, new GUIContent("Advanced..."), includeChildren: true); + EditorGUILayout.PropertyField(meshGeneratorSettings_, SpineInspectorUtility.TempContent("Advanced..."), includeChildren: true); } EditorGUILayout.Space(); @@ -94,7 +94,7 @@ namespace Spine.Unity.Editor { EditorGUILayout.PropertyField(startingAnimation_); EditorGUILayout.PropertyField(startingLoop_); EditorGUILayout.PropertyField(timeScale_); - EditorGUILayout.PropertyField(unscaledTime_, new GUIContent(unscaledTime_.displayName, "If checked, this will use Time.unscaledDeltaTime to make this update independent of game Time.timeScale. Instance SkeletonGraphic.timeScale will still be applied.")); + EditorGUILayout.PropertyField(unscaledTime_, SpineInspectorUtility.TempContent(unscaledTime_.displayName, tooltip: "If checked, this will use Time.unscaledDeltaTime to make this update independent of game Time.timeScale. Instance SkeletonGraphic.timeScale will still be applied.")); EditorGUILayout.Space(); EditorGUILayout.PropertyField(freeze_); EditorGUILayout.Space(); diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs index 9b213d8ed..30dbe4f21 100644 --- a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs +++ b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs @@ -43,6 +43,13 @@ namespace Spine.Unity.Modules { public override void OnInspectorGUI () { SpineInspectorUtility.SortingPropertyFields(sortingProperties, true); + EditorGUILayout.Space(); + if (SpineInspectorUtility.LargeCenteredButton(new GUIContent("Select SkeletonRenderer", SpineEditorUtilities.Icons.spine))) { + var thisSkeletonPartsRenderer = target as SkeletonPartsRenderer; + var srs = thisSkeletonPartsRenderer.GetComponentInParent(); + if (srs != null && srs.partsRenderers.Contains(thisSkeletonPartsRenderer) && srs.SkeletonRenderer != null) + Selection.activeGameObject = srs.SkeletonRenderer.gameObject; + } } } diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs index a7fe321d3..2653a3978 100644 --- a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs +++ b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs @@ -85,6 +85,8 @@ namespace Spine.Unity.Modules { bool checkBox = EditorGUILayout.Toggle("Enable Separator", componentEnabled); if (checkBox != componentEnabled) component.enabled = checkBox; + if (component.SkeletonRenderer.disableRenderingOnOverride && !component.enabled) + EditorGUILayout.HelpBox("By default, SkeletonRenderer's MeshRenderer is disabled while the SkeletonRenderSeparator takes over rendering. It is re-enabled when SkeletonRenderSeparator is disabled.", MessageType.Info); EditorGUILayout.PropertyField(copyPropertyBlock_); EditorGUILayout.PropertyField(copyMeshRendererFlags_); diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs index 3c4915baa..ba211dc70 100644 --- a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs +++ b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs @@ -58,9 +58,9 @@ namespace Spine.Unity.Modules { } MeshRenderer mainMeshRenderer; - public bool copyPropertyBlock = false; + public bool copyPropertyBlock = true; [Tooltip("Copies MeshRenderer flags into each parts renderer")] - public bool copyMeshRendererFlags = false; + public bool copyMeshRendererFlags = true; public List partsRenderers = new List(); #if UNITY_EDITOR @@ -117,6 +117,13 @@ namespace Spine.Unity.Modules { var lightProbeUsage = mainMeshRenderer.lightProbeUsage; bool receiveShadows = mainMeshRenderer.receiveShadows; + #if UNITY_5_5_OR_NEWER + var reflectionProbeUsage = mainMeshRenderer.reflectionProbeUsage; + var shadowCastingMode = mainMeshRenderer.shadowCastingMode; + var motionVectorGenerationMode = mainMeshRenderer.motionVectorGenerationMode; + var probeAnchor = mainMeshRenderer.probeAnchor; + #endif + for (int i = 0; i < partsRenderers.Count; i++) { var currentRenderer = partsRenderers[i]; if (currentRenderer == null) continue; // skip null items. @@ -124,6 +131,13 @@ namespace Spine.Unity.Modules { var mr = currentRenderer.MeshRenderer; mr.lightProbeUsage = lightProbeUsage; mr.receiveShadows = receiveShadows; + + #if UNITY_5_5_OR_NEWER + mr.reflectionProbeUsage = reflectionProbeUsage; + mr.shadowCastingMode = shadowCastingMode; + mr.motionVectorGenerationMode = motionVectorGenerationMode; + mr.probeAnchor = probeAnchor; + #endif } } #else diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs index e6acd6227..7ea4eba81 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs @@ -164,11 +164,11 @@ namespace Spine.Unity.Editor { using (new GUILayout.HorizontalScope()) { EditorGUILayout.Space(); using (new EditorGUI.DisabledGroupScope(multiObject || !utilityBone.valid || utilityBone.bone == null || utilityBone.bone.Children.Count == 0)) { - if (GUILayout.Button(new GUIContent("Add Child", Icons.bone), GUILayout.MinWidth(120), GUILayout.Height(24))) + if (GUILayout.Button(SpineInspectorUtility.TempContent("Add Child", Icons.bone), GUILayout.MinWidth(120), GUILayout.Height(24))) BoneSelectorContextMenu("", utilityBone.bone.Children, "", SpawnChildBoneSelected); } using (new EditorGUI.DisabledGroupScope(multiObject || !utilityBone.valid || utilityBone.bone == null || containsOverrides)) { - if (GUILayout.Button(new GUIContent("Add Override", Icons.poseBones), GUILayout.MinWidth(120), GUILayout.Height(24))) + if (GUILayout.Button(SpineInspectorUtility.TempContent("Add Override", Icons.poseBones), GUILayout.MinWidth(120), GUILayout.Height(24))) SpawnOverride(); } EditorGUILayout.Space(); @@ -177,14 +177,14 @@ namespace Spine.Unity.Editor { using (new GUILayout.HorizontalScope()) { EditorGUILayout.Space(); using (new EditorGUI.DisabledGroupScope(multiObject || !utilityBone.valid || !canCreateHingeChain)) { - if (GUILayout.Button(new GUIContent("Create Hinge Chain", Icons.hingeChain), GUILayout.Width(150), GUILayout.Height(24))) + if (GUILayout.Button(SpineInspectorUtility.TempContent("Create Hinge Chain", Icons.hingeChain), GUILayout.Width(150), GUILayout.Height(24))) CreateHingeChain(); } EditorGUILayout.Space(); } using (new EditorGUI.DisabledGroupScope(multiObject || boundingBoxTable.Count == 0)) { - EditorGUILayout.LabelField(new GUIContent("Bounding Boxes", Icons.boundingBox), EditorStyles.boldLabel); + EditorGUILayout.LabelField(SpineInspectorUtility.TempContent("Bounding Boxes", Icons.boundingBox), EditorStyles.boldLabel); foreach (var entry in boundingBoxTable){ Slot slot = entry.Key; diff --git a/spine-unity/Assets/spine-unity/SpineAttributes.cs b/spine-unity/Assets/spine-unity/SpineAttributes.cs index a100b734e..7e41bc3f2 100644 --- a/spine-unity/Assets/spine-unity/SpineAttributes.cs +++ b/spine-unity/Assets/spine-unity/SpineAttributes.cs @@ -31,9 +31,12 @@ // Contributed by: Mitch Thompson using UnityEngine; +using System; using System.Collections; namespace Spine.Unity { + + [AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = false)] public abstract class SpineAttributeBase : PropertyAttribute { public string dataField = ""; public string startsWith = "";