浏览代码

[unity] Make SkeletonDebug an EditorWindow.

pharan 8 年之前
父节点
当前提交
742ffe5497
共有 24 个文件被更改,包括 697 次插入169 次删除
  1. 二进制
      spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintIK.png
  2. 92 0
      spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintIK.png.meta
  3. 二进制
      spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintPath.png
  4. 92 0
      spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintPath.png.meta
  5. 二进制
      spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintTransform.png
  6. 92 0
      spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintTransform.png.meta
  7. 二进制
      spine-unity/Assets/spine-unity/Editor/GUI/icon-constraints.png
  8. 92 0
      spine-unity/Assets/spine-unity/Editor/GUI/icon-constraints.png.meta
  9. 二进制
      spine-unity/Assets/spine-unity/Editor/GUI/icon-skin.png
  10. 48 9
      spine-unity/Assets/spine-unity/Editor/GUI/icon-skin.png.meta
  11. 二进制
      spine-unity/Assets/spine-unity/Editor/GUI/icon-skinPlaceholder.png
  12. 二进制
      spine-unity/Assets/spine-unity/Editor/GUI/icon-skinsRoot.png
  13. 0 2
      spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs
  14. 0 3
      spine-unity/Assets/spine-unity/Editor/SkeletonAnimatorInspector.cs
  15. 199 83
      spine-unity/Assets/spine-unity/Editor/SkeletonDebugWindow.cs
  16. 2 2
      spine-unity/Assets/spine-unity/Editor/SkeletonDebugWindow.cs.meta
  17. 53 26
      spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs
  18. 10 0
      spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs
  19. 7 7
      spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs
  20. 0 9
      spine-unity/Assets/spine-unity/Modules/SkeletonDebug.meta
  21. 0 9
      spine-unity/Assets/spine-unity/Modules/SkeletonDebug/Editor.meta
  22. 0 12
      spine-unity/Assets/spine-unity/Modules/SkeletonDebug/Editor/SkeletonDebugEditor.cs.meta
  23. 0 6
      spine-unity/Assets/spine-unity/Modules/SkeletonDebug/SkeletonDebug.cs
  24. 10 1
      spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs

二进制
spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintIK.png


+ 92 - 0
spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintIK.png.meta

@@ -0,0 +1,92 @@
+fileFormatVersion: 2
+guid: 02822eb69e09dd947b434ab81e3d938f
+timeCreated: 1494878353
+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: 

二进制
spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintPath.png


+ 92 - 0
spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintPath.png.meta

@@ -0,0 +1,92 @@
+fileFormatVersion: 2
+guid: c1aae98dd56b14c4b8c25360000b7e9e
+timeCreated: 1494878353
+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: 

二进制
spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintTransform.png


+ 92 - 0
spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintTransform.png.meta

@@ -0,0 +1,92 @@
+fileFormatVersion: 2
+guid: 4709175437c21f64bab9b061f98a49fc
+timeCreated: 1494878353
+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: 

二进制
spine-unity/Assets/spine-unity/Editor/GUI/icon-constraints.png


+ 92 - 0
spine-unity/Assets/spine-unity/Editor/GUI/icon-constraints.png.meta

@@ -0,0 +1,92 @@
+fileFormatVersion: 2
+guid: ed0736a1eb519ef42b4892d1db2426b3
+timeCreated: 1494878353
+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: 

二进制
spine-unity/Assets/spine-unity/Editor/GUI/icon-skin.png


+ 48 - 9
spine-unity/Assets/spine-unity/Editor/GUI/icon-skin.png.meta

@@ -1,13 +1,15 @@
 fileFormatVersion: 2
 guid: bfd9f3d2607e9e44c97384d7575a17dc
+timeCreated: 1494878353
+licenseType: Free
 TextureImporter:
   fileIDToRecycleName: {}
-  serializedVersion: 2
+  serializedVersion: 4
   mipmaps:
     mipMapMode: 0
     enableMipMap: 0
+    sRGBTexture: 0
     linearTexture: 1
-    correctGamma: 0
     fadeOut: 0
     borderMipMap: 0
     mipMapFadeDistanceStart: 1
@@ -15,14 +17,12 @@ TextureImporter:
   bumpmap:
     convertToNormalMap: 0
     externalNormalMap: 0
-    heightScale: .25
+    heightScale: 0.25
     normalMapFilter: 0
   isReadable: 0
   grayScaleToAlpha: 0
-  generateCubemap: 0
+  generateCubemap: 6
   cubemapConvolution: 0
-  cubemapConvolutionSteps: 8
-  cubemapConvolutionExponent: 1.5
   seamlessCubemap: 0
   textureFormat: -3
   maxTextureSize: 1024
@@ -33,20 +33,59 @@ TextureImporter:
     wrapMode: 1
   nPOTScale: 0
   lightmap: 0
-  rGBM: 0
   compressionQuality: 50
   spriteMode: 0
   spriteExtrude: 1
   spriteMeshType: 1
   alignment: 0
-  spritePivot: {x: .5, y: .5}
+  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
-  buildTargetSettings: []
+  textureShape: 1
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  platformSettings:
+  - buildTarget: DefaultTexturePlatform
+    maxTextureSize: 1024
+    textureFormat: -1
+    textureCompression: 0
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+  - buildTarget: Standalone
+    maxTextureSize: 1024
+    textureFormat: -1
+    textureCompression: 0
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+  - buildTarget: Android
+    maxTextureSize: 1024
+    textureFormat: -1
+    textureCompression: 0
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+  - buildTarget: WebGL
+    maxTextureSize: 1024
+    textureFormat: -1
+    textureCompression: 0
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
   spriteSheet:
+    serializedVersion: 2
     sprites: []
+    outline: []
   spritePackingTag: 
   userData: 
   assetBundleName: 

二进制
spine-unity/Assets/spine-unity/Editor/GUI/icon-skinPlaceholder.png


二进制
spine-unity/Assets/spine-unity/Editor/GUI/icon-skinsRoot.png


+ 0 - 2
spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs

@@ -95,8 +95,6 @@ namespace Spine.Unity.Editor {
 					SceneView.RepaintAll();
 					requireRepaint = false;
 				}
-
-				DrawSkeletonUtilityButton(multi);
 			}
 		}
 

+ 0 - 3
spine-unity/Assets/spine-unity/Editor/SkeletonAnimatorInspector.cs

@@ -49,9 +49,6 @@ namespace Spine.Unity.Editor {
 			base.DrawInspectorGUI(multi);
 			EditorGUILayout.PropertyField(autoReset);
 			EditorGUILayout.PropertyField(layerMixModes, true);
-			if (!TargetIsValid) return;
-			if (!isInspectingPrefab)
-				DrawSkeletonUtilityButton(multi);
 		}
 	}
 }

+ 199 - 83
spine-unity/Assets/spine-unity/Modules/SkeletonDebug/Editor/SkeletonDebugEditor.cs → spine-unity/Assets/spine-unity/Editor/SkeletonDebugWindow.cs

@@ -33,49 +33,85 @@
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEditor;
-using Spine.Unity.Modules;
 using UnityEditor.AnimatedValues;
 
 namespace Spine.Unity.Editor {
 	using Editor = UnityEditor.Editor;
 	using Icons = SpineEditorUtilities.Icons;
 
-	[CustomEditor(typeof(SkeletonDebug))]
-	public class SkeletonDebugEditor : Editor {
+	public class SkeletonDebugWindow : EditorWindow {
+
+		const bool IsUtilityWindow = true;
+
+		[MenuItem("CONTEXT/SkeletonRenderer/Open Skeleton Debug Window", false, 5000)]
+		public static void Init () {
+			var window = EditorWindow.GetWindow<SkeletonDebugWindow>(IsUtilityWindow);
+			window.minSize = new Vector2(330f, 360f);
+			window.maxSize = new Vector2(600f, 4000f);
+			window.titleContent = new GUIContent("Skeleton Debug", Icons.spine);
+			window.Show();
+			window.OnSelectionChange();
+		}
+
 
-		static AnimBool showSlotsTree = new AnimBool(false);
 		static AnimBool showSkeleton = new AnimBool(true);
+		static AnimBool showSlotsTree = new AnimBool(false);
 		static AnimBool showConstraintsTree = new AnimBool(false);
+		static AnimBool showDrawOrderTree = new AnimBool(false);
+		static AnimBool showEventDataTree = new AnimBool(false);
+		static AnimBool showInspectBoneTree = new AnimBool(false);
 
-		protected static bool showBoneNames, showPaths = true, showShapes = true, showConstraints = true;
+		Vector2 scrollPos;
 
 		GUIContent SlotsRootLabel, SkeletonRootLabel;
 		GUIStyle BoldFoldoutStyle;
 
-		SkeletonDebug skeletonDebug;
-		SkeletonRenderer skeletonRenderer;
+		public SkeletonRenderer skeletonRenderer;
 		Skeleton skeleton;
-
 		Skin activeSkin;
-
 		bool isPrefab;
 
-		readonly Dictionary<Slot, List<Attachment>> attachmentTable = new Dictionary<Slot, List<Attachment>>();
+		SerializedProperty bpo;
+		Bone bone;
 
-		#region Menus
-		[MenuItem("CONTEXT/SkeletonRenderer/Debug with SkeletonDebug", false, 5000)]
-		static void AddSkeletonDebug (MenuCommand command) {
-			var go = ((SkeletonRenderer)command.context).gameObject;
-			go.AddComponent<SkeletonDebug>();
-			Undo.RegisterCreatedObjectUndo(go, "Add SkeletonDebug");
-		}
-		#endregion
+		[SpineBone(dataField:"skeletonRenderer")]
+		public string boneName;
+
+		readonly Dictionary<Slot, List<Attachment>> attachmentTable = new Dictionary<Slot, List<Attachment>>();
 
-		void OnEnable () {
-			Initialize();
+		void OnSelectionChange () {
+			bool noSkeletonRenderer = false;
+
+			var selectedObject = Selection.activeGameObject;
+			if (selectedObject == null) {
+				noSkeletonRenderer = true;
+			} else {
+				var selectedSkeletonRenderer = selectedObject.GetComponent<SkeletonRenderer>();
+				if (selectedSkeletonRenderer == null) {
+					noSkeletonRenderer = true;
+				} else if (skeletonRenderer != selectedSkeletonRenderer) {
+					skeletonRenderer = selectedSkeletonRenderer;
+					skeletonRenderer.Initialize(false);
+					skeletonRenderer.LateUpdate();
+					skeleton = skeletonRenderer.skeleton;
+					isPrefab |= PrefabUtility.GetPrefabType(selectedObject) == PrefabType.Prefab;
+					UpdateAttachments();
+				}
+			} 
+
+			if (noSkeletonRenderer) {
+				skeletonRenderer = null;
+				skeleton = null;
+				attachmentTable.Clear();
+				isPrefab = false;
+				boneName = string.Empty;
+				bone = null;
+			}				
+
+			Repaint();
 		}
 
-		void Initialize () {
+		void OnGUI () {
 			if (SlotsRootLabel == null) {
 				SlotsRootLabel = new GUIContent("Slots", Icons.slotRoot);
 				SkeletonRootLabel = new GUIContent("Skeleton", Icons.skeleton);
@@ -85,39 +121,13 @@ namespace Spine.Unity.Editor {
 				BoldFoldoutStyle.fixedWidth = 0;
 			}
 
-			if (skeleton == null) {
-				skeletonDebug = (SkeletonDebug)target;
-				skeletonRenderer = skeletonDebug.GetComponent<SkeletonRenderer>();
-				skeletonRenderer.Initialize(false);
-				skeletonRenderer.LateUpdate();
-				skeleton = skeletonRenderer.skeleton;
-			}
-
-			if (attachmentTable.Count == 0) UpdateAttachments();
-
-			if (!skeletonRenderer.valid) return;
-			isPrefab |= PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab;
-		}
-
-		public void OnSceneGUI () {
-			var transform = skeletonRenderer.transform;
-			if (skeleton == null) return;
-			if (isPrefab) return;
-
-			if (showPaths) SpineHandles.DrawPaths(transform, skeleton);
-			if (showConstraints) SpineHandles.DrawConstraints(transform, skeleton);
-			if (showBoneNames) SpineHandles.DrawBoneNames(transform, skeleton);
-			if (showShapes) SpineHandles.DrawBoundingBoxes(transform, skeleton);
-		}
-
-		public override void OnInspectorGUI () {
-			Initialize();
-
 			bool requireRepaint = false;
+			EditorGUILayout.Space();
+			EditorGUI.BeginDisabledGroup(true);
+			EditorGUILayout.ObjectField("Debug Selection", skeletonRenderer, typeof(SkeletonRenderer), true);
+			EditorGUI.EndDisabledGroup();
 
-			if (skeletonRenderer.skeleton != skeleton || activeSkin != skeleton.Skin) {
-				UpdateAttachments();
-			}
+			if (skeleton == null || skeletonRenderer == null || !skeletonRenderer.valid) return;
 
 			if (isPrefab) {
 				GUILayout.Label(new GUIContent("Cannot edit Prefabs", Icons.warning));
@@ -129,37 +139,96 @@ namespace Spine.Unity.Editor {
 				return;	
 			}
 
-			EditorGUILayout.HelpBox("This is a debug component. Changes are not serialized.", MessageType.Info);
+			if (activeSkin != skeleton.Skin)
+				UpdateAttachments();
+
+			scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
+
+			using (new SpineInspectorUtility.BoxScope(false)) {
+				if (SpineInspectorUtility.CenteredButton(new GUIContent("Skeleton.SetToSetupPose()"))) {
+					skeleton.SetToSetupPose();
+					requireRepaint = true;
+				}
+
+				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);
+				}
+				requireRepaint |= EditorGUI.EndChangeCheck();
 
-			using (new SpineInspectorUtility.BoxScope()) {
 
 				// Skeleton
 				showSkeleton.target = EditorGUILayout.Foldout(showSkeleton.target, SkeletonRootLabel, BoldFoldoutStyle);
 				if (showSkeleton.faded > 0) {
-					using (new EditorGUILayout.FadeGroupScope(showSkeleton.faded)) {
-						using (new SpineInspectorUtility.IndentScope()) {
+					using (new SpineInspectorUtility.IndentScope()) {
+						using (new EditorGUILayout.FadeGroupScope(showSkeleton.faded)) {
 							EditorGUI.BeginChangeCheck();
+
+							// Flip
+							EditorGUILayout.BeginHorizontal(GUILayout.MaxWidth(160f));
+							EditorGUILayout.LabelField("Flip", GUILayout.MaxWidth(EditorGUIUtility.labelWidth - 20f));
+							skeleton.FlipX = EditorGUILayout.ToggleLeft(".FlipX", skeleton.FlipX, GUILayout.MaxWidth(70f));
+							skeleton.FlipY = EditorGUILayout.ToggleLeft(".FlipY", skeleton.FlipY, GUILayout.MaxWidth(70f));
+							GUILayout.EndHorizontal();
+
+							// Color
 							skeleton.SetColor(EditorGUILayout.ColorField(".R .G .B .A", skeleton.GetColor()));
-							skeleton.FlipX = EditorGUILayout.ToggleLeft(".FlipX", skeleton.FlipX);
-							skeleton.FlipY = EditorGUILayout.ToggleLeft(".FlipY", skeleton.FlipY);
-
-							EditorGUILayout.Space();
-							using (new SpineInspectorUtility.LabelWidthScope()) {
-								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();
 						}
 					}
 				}
 
+				// Bone
+				showInspectBoneTree.target = EditorGUILayout.Foldout(showInspectBoneTree.target, new GUIContent("Bone", Icons.bone), BoldFoldoutStyle);
+				if (showInspectBoneTree.faded > 0) {
+					using (new SpineInspectorUtility.IndentScope()) {
+						using (new EditorGUILayout.FadeGroupScope(showInspectBoneTree.faded)) {
+							if (bpo == null) bpo = new SerializedObject(this).FindProperty("boneName");
+							EditorGUILayout.PropertyField(bpo);
+							if (!string.IsNullOrEmpty(bpo.stringValue)) {
+								if (bone == null || bone.Data.Name != bpo.stringValue) {
+									bone = skeleton.FindBone(bpo.stringValue);
+								}
+
+								if (bone != null) {
+									using (new EditorGUI.DisabledGroupScope(true)) {
+										var boneParent = bone.Parent;
+										if (boneParent != null) EditorGUILayout.TextField("parent", boneParent.Data.Name);
+										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));
+									}
+								}
+								requireRepaint = true;
+							} else {
+								bone = null;
+							}
+						}
+					}
+				}
+
 				// Slots
 				int preSlotsIndent = EditorGUI.indentLevel;
 				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()"))) {
+							skeleton.SetSlotsToSetupPose();
+							requireRepaint = true;
+						}
+
 						int baseIndent = EditorGUI.indentLevel;
 						foreach (KeyValuePair<Slot, List<Attachment>> pair in attachmentTable) {
 							Slot slot = pair.Key;
@@ -194,22 +263,22 @@ namespace Spine.Unity.Editor {
 
 				// Constraints
 				const string NoneText = "<none>";
-				showConstraintsTree.target = EditorGUILayout.Foldout(showConstraintsTree.target, "Constraints", BoldFoldoutStyle);
+				showConstraintsTree.target = EditorGUILayout.Foldout(showConstraintsTree.target, new GUIContent("Constraints", Icons.constraintRoot), BoldFoldoutStyle);
 				if (showConstraintsTree.faded > 0) {
-					using (new EditorGUILayout.FadeGroupScope(showConstraintsTree.faded)) {
-						using (new SpineInspectorUtility.IndentScope()) {
+					using (new SpineInspectorUtility.IndentScope()) {
+						using (new EditorGUILayout.FadeGroupScope(showConstraintsTree.faded)) {
 							const float MixMin = 0f;
 							const float MixMax = 1f;
 
-							EditorGUILayout.LabelField(string.Format("IK Constraints ({0})", skeleton.IkConstraints.Count), EditorStyles.boldLabel);
+							EditorGUILayout.LabelField(new GUIContent(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(c.Data.Name);
+										EditorGUILayout.LabelField(new GUIContent(c.Data.Name, Icons.constraintIK));
 
 										EditorGUI.BeginChangeCheck();
-										c.BendDirection = EditorGUILayout.Toggle("Bend Direction Positive", c.BendDirection > 0) ? 1 : -1;
 										c.Mix = EditorGUILayout.Slider("Mix", c.Mix, MixMin, MixMax);
+										c.BendDirection = EditorGUILayout.Toggle("Bend Direction +", c.BendDirection > 0) ? 1 : -1;
 										if (EditorGUI.EndChangeCheck())	requireRepaint = true;
 
 										EditorGUILayout.Space();
@@ -220,11 +289,11 @@ namespace Spine.Unity.Editor {
 								}
 							}
 
-							EditorGUILayout.LabelField(string.Format("Transform Constraints ({0})", skeleton.TransformConstraints.Count), EditorStyles.boldLabel);
+							EditorGUILayout.LabelField(new GUIContent(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(c.Data.Name);
+										EditorGUILayout.LabelField(new GUIContent(c.Data.Name, Icons.constraintTransform));
 
 										EditorGUI.BeginChangeCheck();
 										c.TranslateMix = EditorGUILayout.Slider("TranslateMix", c.TranslateMix, MixMin, MixMax);
@@ -240,11 +309,11 @@ namespace Spine.Unity.Editor {
 								}
 							}
 
-							EditorGUILayout.LabelField(string.Format("Path Constraints ({0})", skeleton.PathConstraints.Count), EditorStyles.boldLabel);
+							EditorGUILayout.LabelField(new GUIContent(string.Format("Path Constraints ({0})", skeleton.PathConstraints.Count), Icons.constraintPath), EditorStyles.boldLabel);
 							using (new SpineInspectorUtility.IndentScope()) {
 								if (skeleton.PathConstraints.Count > 0) {
 									foreach (var c in skeleton.PathConstraints) {
-										EditorGUILayout.LabelField(c.Data.Name);
+										EditorGUILayout.LabelField(new GUIContent(c.Data.Name, Icons.constraintPath));
 										EditorGUILayout.LabelField("PositionMode." + c.Data.PositionMode);
 										EditorGUILayout.LabelField("SpacingMode." + c.Data.SpacingMode);
 										EditorGUILayout.LabelField("RotateMode." + c.Data.RotateMode);
@@ -267,19 +336,69 @@ namespace Spine.Unity.Editor {
 					}
 				}
 
-				if (showSlotsTree.isAnimating || showSkeleton.isAnimating || showConstraintsTree.isAnimating)
+				showDrawOrderTree.target = EditorGUILayout.Foldout(showDrawOrderTree.target, new GUIContent("Draw Order and Separators", Icons.slotRoot), BoldFoldoutStyle);
+				if (showDrawOrderTree.faded > 0) {
+					using (new SpineInspectorUtility.IndentScope()) {
+						using (new EditorGUILayout.FadeGroupScope(showDrawOrderTree.faded)) {
+
+							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));
+								}
+							} 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("------");
+											break;
+										}
+									}
+									EditorGUILayout.LabelField(new GUIContent(slot.Data.Name, Icons.slot), GUILayout.ExpandWidth(false));
+								}
+							}
+								
+						}
+					}
+				}
+
+				showEventDataTree.target = EditorGUILayout.Foldout(showEventDataTree.target, new GUIContent("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));
+								}
+							} else {
+								EditorGUILayout.LabelField(NoneText);
+							}
+						}
+					}
+				}
+
+				if (IsAnimating(showSlotsTree, showSkeleton, showConstraintsTree, showDrawOrderTree, showEventDataTree, showInspectBoneTree))
 					Repaint();
 			}
 
 			if (requireRepaint) {
 				skeletonRenderer.LateUpdate();
+				Repaint();
 				SceneView.RepaintAll();
 			}
+
+			EditorGUILayout.EndScrollView();
+		}
+
+		static bool IsAnimating (params AnimBool[] animBools) {
+			foreach (var a in animBools)
+				if (a.isAnimating) return true;
+			return false;
 		}
-	
-	
+
 		void UpdateAttachments () {
-			skeleton = skeletonRenderer.skeleton;
+			//skeleton = skeletonRenderer.skeleton;
 			Skin defaultSkin = skeleton.Data.DefaultSkin;
 			Skin skin = skeleton.Skin ?? defaultSkin;
 			bool notDefaultSkin = skin != defaultSkin;
@@ -294,8 +413,5 @@ namespace Spine.Unity.Editor {
 
 			activeSkin = skeleton.Skin;
 		}
-	
-
-
 	}
 }

+ 2 - 2
spine-unity/Assets/spine-unity/Modules/SkeletonDebug/SkeletonDebug.cs.meta → spine-unity/Assets/spine-unity/Editor/SkeletonDebugWindow.cs.meta

@@ -1,6 +1,6 @@
 fileFormatVersion: 2
-guid: 7b337e07bc016684dabf04793dd00ea3
-timeCreated: 1494814889
+guid: 7093e73ff3cf6c543ac5865980070b49
+timeCreated: 1494837950
 licenseType: Free
 MonoImporter:
   serializedVersion: 2

+ 53 - 26
spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs

@@ -36,11 +36,13 @@ using UnityEngine;
 
 namespace Spine.Unity.Editor {
 	using Event = UnityEngine.Event;
+	using Icons = SpineEditorUtilities.Icons;
 
 	[CustomEditor(typeof(SkeletonRenderer))]
 	[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;
@@ -76,8 +78,8 @@ namespace Spine.Unity.Editor {
 			SpineEditorUtilities.ConfirmInitialization();
 
 			// Labels
-			SkeletonDataAssetLabel = new GUIContent("SkeletonData Asset", SpineEditorUtilities.Icons.spine);
-			SkeletonUtilityButtonContent = new GUIContent("Add Skeleton Utility", SpineEditorUtilities.Icons.skeletonUtility);
+			SkeletonDataAssetLabel = new GUIContent("SkeletonData Asset", Icons.spine);
+			SkeletonUtilityButtonContent = new GUIContent("Add Skeleton Utility", Icons.skeletonUtility);
 			MeshesLabel = new GUIContent("Render MeshAttachments", "Disable to optimize rendering for skeletons that don't use Mesh Attachments");
 			ImmubleTrianglesLabel = new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility");
 			PMAVertexColorsLabel = new GUIContent("PMA Vertex Colors", "Use this if you are using the default Spine/Skeleton shader or any premultiply-alpha shader.");
@@ -93,7 +95,7 @@ namespace Spine.Unity.Editor {
 			initialSkinName = so.FindProperty("initialSkinName");
 			initialFlipX = so.FindProperty("initialFlipX");
 			initialFlipY = so.FindProperty("initialFlipY");
-			normals = so.FindProperty("calculateNormals");
+			normals = so.FindProperty("addNormals");
 			tangents = so.FindProperty("calculateTangents");
 			meshes = so.FindProperty("renderMeshes");
 			immutableTriangles = so.FindProperty("immutableTriangles");
@@ -238,7 +240,20 @@ namespace Spine.Unity.Editor {
 			// More Render Options...
 			using (new SpineInspectorUtility.BoxScope()) {
 				EditorGUI.BeginChangeCheck();
-				if (advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced")) {
+
+				EditorGUILayout.BeginHorizontal(GUILayout.Height(EditorGUIUtility.singleLineHeight + 5));
+				advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced");
+				if (advancedFoldout) {
+					EditorGUILayout.Space();
+					if (GUILayout.Button("Debug", EditorStyles.miniButton, GUILayout.Width(65f)))
+						SkeletonDebugWindow.Init();
+				} else {
+					EditorGUILayout.Space();
+				}
+				EditorGUILayout.EndHorizontal();
+
+				if (advancedFoldout) {
+					
 					using (new SpineInspectorUtility.IndentScope()) {
 						using (new EditorGUILayout.HorizontalScope()) {
 							initialFlipX.boolValue = EditorGUILayout.ToggleLeft(initialFlipX.displayName, initialFlipX.boolValue, GUILayout.Width(120f));
@@ -247,7 +262,7 @@ namespace Spine.Unity.Editor {
 						}
 
 						EditorGUILayout.Space();
-
+						EditorGUILayout.LabelField("Renderer Settings", EditorStyles.boldLabel);
 						using (new SpineInspectorUtility.LabelWidthScope()) {
 							// Optimization options
 							if (singleSubmesh != null) EditorGUILayout.PropertyField(singleSubmesh, SingleSubmeshLabel);
@@ -277,8 +292,30 @@ namespace Spine.Unity.Editor {
 						}
 
 						EditorGUILayout.Space();
+
+						if (TargetIsValid && !isInspectingPrefab) {
+							if (multi) {
+								// Support multi-edit SkeletonUtility button.
+								//	EditorGUILayout.Space();
+								//	bool addSkeletonUtility = GUILayout.Button(buttonContent, GUILayout.Height(30));
+								//	foreach (var t in targets) {
+								//		var component = t as Component;
+								//		if (addSkeletonUtility && component.GetComponent<SkeletonUtility>() == null)
+								//			component.gameObject.AddComponent<SkeletonUtility>();
+								//	}
+							} else {
+								var component = (Component)target;
+								if (component.GetComponent<SkeletonUtility>() == null) {						
+									if (SpineInspectorUtility.CenteredButton(SkeletonUtilityButtonContent, 21, true, 200f))
+										component.gameObject.AddComponent<SkeletonUtility>();
+								}
+							}
+						}
+
+						EditorGUILayout.Space();
 					}
 				}
+
 				if (EditorGUI.EndChangeCheck())
 					SceneView.RepaintAll();
 			}
@@ -308,6 +345,13 @@ namespace Spine.Unity.Editor {
 				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);
+					GUILayout.BeginHorizontal();
+					GUILayout.FlexibleSpace();
+					if (GUILayout.Button("+", GUILayout.MaxWidth(28f), GUILayout.MaxHeight(15f))) {
+						separatorSlotNames.arraySize++;
+					}
+					GUILayout.EndHorizontal();
+
 					EditorGUILayout.Space();
 				} else
 					EditorGUILayout.PropertyField(separatorSlotNames, new GUIContent(separatorSlotNames.displayName + string.Format("{0} [{1}]", terminalSlotWarning, separatorSlotNames.arraySize), SeparatorsDescription), true);
@@ -318,30 +362,13 @@ namespace Spine.Unity.Editor {
 			var skeletonRenderer = (SkeletonRenderer)target;
 			var skeleton = skeletonRenderer.skeleton;
 			var transform = skeletonRenderer.transform;
-
 			if (skeleton == null) return;
 
+			if (showPaths) SpineHandles.DrawPaths(transform, skeleton);
 			SpineHandles.DrawBones(transform, skeleton);
-		}
-
-		public void DrawSkeletonUtilityButton (bool multi) {
-			if (multi) {
-				// Support multi-edit SkeletonUtility button.
-				//	EditorGUILayout.Space();
-				//	bool addSkeletonUtility = GUILayout.Button(buttonContent, GUILayout.Height(30));
-				//	foreach (var t in targets) {
-				//		var component = t as Component;
-				//		if (addSkeletonUtility && component.GetComponent<SkeletonUtility>() == null)
-				//			component.gameObject.AddComponent<SkeletonUtility>();
-				//	}
-			} else {
-				EditorGUILayout.Space();
-				var component = (Component)target;
-				if (component.GetComponent<SkeletonUtility>() == null) {						
-					if (SpineInspectorUtility.CenteredButton(SkeletonUtilityButtonContent, 21))
-						component.gameObject.AddComponent<SkeletonUtility>();
-				}
-			}
+			if (showConstraints) SpineHandles.DrawConstraints(transform, skeleton);
+			if (showBoneNames) SpineHandles.DrawBoneNames(transform, skeleton);
+			if (showShapes) SpineHandles.DrawBoundingBoxes(transform, skeleton);
 		}
 
 		override public void OnInspectorGUI () {

+ 10 - 0
spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs

@@ -70,6 +70,10 @@ namespace Spine.Unity.Editor {
 			public static Texture2D spine;
 			public static Texture2D userEvent;
 			public static Texture2D constraintNib;
+			public static Texture2D constraintRoot;
+			public static Texture2D constraintTransform;
+			public static Texture2D constraintPath;
+			public static Texture2D constraintIK;
 			public static Texture2D warning;
 			public static Texture2D skeletonUtility;
 			public static Texture2D hingeChain;
@@ -97,6 +101,12 @@ namespace Spine.Unity.Editor {
 				spine = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-spine.png");
 				userEvent = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-event.png");
 				constraintNib = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-constraintNib.png");
+
+				constraintRoot = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-constraints.png");
+				constraintTransform = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-constraintTransform.png");
+				constraintPath = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-constraintPath.png");
+				constraintIK = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-constraintIK.png");
+
 				warning = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-warning.png");
 				skeletonUtility = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skeletonUtility.png");
 				hingeChain = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-hingeChain.png");

+ 7 - 7
spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs

@@ -140,12 +140,12 @@ namespace Spine.Unity.Editor {
 			}
 		}
 
-		public static bool LargeCenteredButton (string label, bool sideSpace = true) {
+		public static bool LargeCenteredButton (string label, bool sideSpace = true, float maxWidth = CenterButtonMaxWidth) {
 			if (sideSpace) {
 				bool clicked;
 				using (new EditorGUILayout.HorizontalScope()) {
 					EditorGUILayout.Space();
-					clicked = GUILayout.Button(label, SpineButtonStyle, GUILayout.MaxWidth(CenterButtonMaxWidth), GUILayout.Height(CenterButtonHeight));
+					clicked = GUILayout.Button(label, SpineButtonStyle, GUILayout.MaxWidth(maxWidth), GUILayout.Height(CenterButtonHeight));
 					EditorGUILayout.Space();
 				}
 				EditorGUILayout.Space();
@@ -155,12 +155,12 @@ namespace Spine.Unity.Editor {
 			}
 		}
 
-		public static bool LargeCenteredButton (GUIContent content, bool sideSpace = true) {
+		public static bool LargeCenteredButton (GUIContent content, bool sideSpace = true, float maxWidth = CenterButtonMaxWidth) {
 			if (sideSpace) {
 				bool clicked;
 				using (new EditorGUILayout.HorizontalScope()) {
 					EditorGUILayout.Space();
-					clicked = GUILayout.Button(content, SpineButtonStyle, GUILayout.MaxWidth(CenterButtonMaxWidth), GUILayout.Height(CenterButtonHeight));
+					clicked = GUILayout.Button(content, SpineButtonStyle, GUILayout.MaxWidth(maxWidth), GUILayout.Height(CenterButtonHeight));
 					EditorGUILayout.Space();
 				}
 				EditorGUILayout.Space();
@@ -170,18 +170,18 @@ namespace Spine.Unity.Editor {
 			}
 		}
 
-		public static bool CenteredButton (GUIContent content, float height = 20f, bool sideSpace = true) {
+		public static bool CenteredButton (GUIContent content, float height = 20f, bool sideSpace = true, float maxWidth = CenterButtonMaxWidth) {
 			if (sideSpace) {
 				bool clicked;
 				using (new EditorGUILayout.HorizontalScope()) {
 					EditorGUILayout.Space();
-					clicked = GUILayout.Button(content, GUILayout.MaxWidth(CenterButtonMaxWidth), GUILayout.Height(height));
+					clicked = GUILayout.Button(content, GUILayout.MaxWidth(maxWidth), GUILayout.Height(height));
 					EditorGUILayout.Space();
 				}
 				EditorGUILayout.Space();
 				return clicked;
 			} else {
-				return GUILayout.Button(content, GUILayout.MaxWidth(CenterButtonMaxWidth), GUILayout.Height(height));
+				return GUILayout.Button(content, GUILayout.MaxWidth(maxWidth), GUILayout.Height(height));
 			}
 		}
 		#endregion

+ 0 - 9
spine-unity/Assets/spine-unity/Modules/SkeletonDebug.meta

@@ -1,9 +0,0 @@
-fileFormatVersion: 2
-guid: 061893380931ebd4f94376c54cdb60dc
-folderAsset: yes
-timeCreated: 1494814883
-licenseType: Free
-DefaultImporter:
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 

+ 0 - 9
spine-unity/Assets/spine-unity/Modules/SkeletonDebug/Editor.meta

@@ -1,9 +0,0 @@
-fileFormatVersion: 2
-guid: 7e09f6de2e1bcbf4085ca3825dc89489
-folderAsset: yes
-timeCreated: 1494814895
-licenseType: Free
-DefaultImporter:
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 

+ 0 - 12
spine-unity/Assets/spine-unity/Modules/SkeletonDebug/Editor/SkeletonDebugEditor.cs.meta

@@ -1,12 +0,0 @@
-fileFormatVersion: 2
-guid: 3e60ef41778c8e84e958675f00ce83e8
-timeCreated: 1494814901
-licenseType: Free
-MonoImporter:
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 

+ 0 - 6
spine-unity/Assets/spine-unity/Modules/SkeletonDebug/SkeletonDebug.cs

@@ -1,6 +0,0 @@
-using UnityEngine;
-
-namespace Spine.Unity.Modules {
-	[DisallowMultipleComponent]
-	public class SkeletonDebug : MonoBehaviour { }
-}

+ 10 - 1
spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs

@@ -79,10 +79,19 @@ namespace Spine.Unity.Editor {
 
 			skeletonUtility.boneRoot = (Transform)EditorGUILayout.ObjectField("Bone Root", skeletonUtility.boneRoot, typeof(Transform), true);
 
-			using (new EditorGUI.DisabledGroupScope(skeletonUtility.boneRoot != null)) {
+			bool hasRootBone = skeletonUtility.boneRoot != null;
+			using (new EditorGUI.DisabledGroupScope(hasRootBone)) {
 				if (SpineInspectorUtility.LargeCenteredButton(SpawnHierarchyButtonLabel))
 					SpawnHierarchyContextMenu();
 			}
+
+			if (hasRootBone) {
+				if (SpineInspectorUtility.CenteredButton(new GUIContent("Remove Hierarchy"))) {
+					Undo.RegisterCompleteObjectUndo(skeletonUtility, "Remove Hierarchy");
+					Undo.DestroyObjectImmediate(skeletonUtility.boneRoot.gameObject);
+					skeletonUtility.boneRoot = null;
+				}
+			}
 		}
 
 		void SpawnHierarchyContextMenu () {