Browse Source

All scripts now in Spine.Unity and Spine.Unity.Modules namespace

pharan 9 years ago
parent
commit
cc95db8e6c
36 changed files with 4325 additions and 4039 deletions
  1. 121 119
      spine-unity/Assets/spine-unity/Asset Types/AtlasAsset.cs
  2. 7 25
      spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs
  3. 114 112
      spine-unity/Assets/spine-unity/Asset Types/SkeletonDataAsset.cs
  4. 86 87
      spine-unity/Assets/spine-unity/BoneFollower.cs
  5. 0 2
      spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs
  6. 31 31
      spine-unity/Assets/spine-unity/Modules/AtlasRegionAttacher.cs
  7. 109 117
      spine-unity/Assets/spine-unity/Modules/BoundingBoxFollower/BoundingBoxFollower.cs
  8. 37 35
      spine-unity/Assets/spine-unity/Modules/CustomSkin.cs
  9. 120 117
      spine-unity/Assets/spine-unity/Modules/Ghost/SkeletonGhost.cs
  10. 42 41
      spine-unity/Assets/spine-unity/Modules/Ragdoll/Editor/SkeletonRagdoll2DInspector.cs
  11. 40 37
      spine-unity/Assets/spine-unity/Modules/Ragdoll/Editor/SkeletonRagdollInspector.cs
  12. 327 325
      spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll.cs
  13. 336 341
      spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs
  14. 33 5
      spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs
  15. 33 2
      spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs
  16. 32 3
      spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonPartsRenderer.cs
  17. 33 4
      spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs
  18. 41 40
      spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityEyeConstraint.cs
  19. 104 101
      spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityGroundConstraint.cs
  20. 58 57
      spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityKinematicShadow.cs
  21. 159 131
      spine-unity/Assets/spine-unity/Modules/SpriteAttacher.cs
  22. 119 118
      spine-unity/Assets/spine-unity/Modules/TK2D/SpriteCollectionAttachmentLoader.cs
  23. 129 127
      spine-unity/Assets/spine-unity/SkeletonAnimation.cs
  24. 149 149
      spine-unity/Assets/spine-unity/SkeletonAnimator.cs
  25. 121 149
      spine-unity/Assets/spine-unity/SkeletonExtensions.cs
  26. 686 664
      spine-unity/Assets/spine-unity/SkeletonRenderer.cs
  27. 272 269
      spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs
  28. 196 192
      spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs
  29. 49 0
      spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilitySubmeshRendererInspector.cs
  30. 8 0
      spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilitySubmeshRendererInspector.cs.meta
  31. 264 261
      spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs
  32. 226 224
      spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs
  33. 14 13
      spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityConstraint.cs
  34. 71 0
      spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs
  35. 14 0
      spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs.meta
  36. 144 141
      spine-unity/Assets/spine-unity/SpineAttributes.cs

+ 121 - 119
spine-unity/Assets/spine-unity/Asset Types/AtlasAsset.cs

@@ -34,148 +34,150 @@ using System.IO;
 using UnityEngine;
 using Spine;
 
-/// <summary>Loads and stores a Spine atlas and list of materials.</summary>
-public class AtlasAsset : ScriptableObject {
-	public TextAsset atlasFile;
-	public Material[] materials;
-	private Atlas atlas;
-
-	public void Reset () {
-		atlas = null;
-	}
-
-	/// <returns>The atlas or null if it could not be loaded.</returns>
-	public Atlas GetAtlas () {
-		if (atlasFile == null) {
-			Debug.LogError("Atlas file not set for atlas asset: " + name, this);
-			Reset();
-			return null;
-		}
-
-		if (materials == null || materials.Length == 0) {
-			Debug.LogError("Materials not set for atlas asset: " + name, this);
-			Reset();
-			return null;
+namespace Spine.Unity {
+	/// <summary>Loads and stores a Spine atlas and list of materials.</summary>
+	public class AtlasAsset : ScriptableObject {
+		public TextAsset atlasFile;
+		public Material[] materials;
+		private Atlas atlas;
+
+		public void Reset () {
+			atlas = null;
 		}
 
-		if (atlas != null)
-			return atlas;
-
-		try {
-			atlas = new Atlas(new StringReader(atlasFile.text), "", new MaterialsTextureLoader(this));
-			atlas.FlipV();
-			return atlas;
-		} catch (Exception ex) {
-			Debug.LogError("Error reading atlas file for atlas asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, this);
-			return null;
-		}
-	}
+		/// <returns>The atlas or null if it could not be loaded.</returns>
+		public Atlas GetAtlas () {
+			if (atlasFile == null) {
+				Debug.LogError("Atlas file not set for atlas asset: " + name, this);
+				Reset();
+				return null;
+			}
 
-	public Sprite GenerateSprite (string name, out Material material) {
-		AtlasRegion region = atlas.FindRegion(name);
+			if (materials == null || materials.Length == 0) {
+				Debug.LogError("Materials not set for atlas asset: " + name, this);
+				Reset();
+				return null;
+			}
 
-		Sprite sprite = null;
-		material = null;
+			if (atlas != null)
+				return atlas;
 
-		if (region != null) {
-			//sprite.rect
+			try {
+				atlas = new Atlas(new StringReader(atlasFile.text), "", new MaterialsTextureLoader(this));
+				atlas.FlipV();
+				return atlas;
+			} catch (Exception ex) {
+				Debug.LogError("Error reading atlas file for atlas asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, this);
+				return null;
+			}
 		}
 
-		return sprite;
-	}
+		public Sprite GenerateSprite (string name, out Material material) {
+			AtlasRegion region = atlas.FindRegion(name);
+
+			Sprite sprite = null;
+			material = null;
 
-	public Mesh GenerateMesh (string name, Mesh mesh, out Material material, float scale = 0.01f) {
-		AtlasRegion region = atlas.FindRegion(name);
-		material = null;
-		if (region != null) {
-			if (mesh == null) {
-				mesh = new Mesh();
-				mesh.name = name;
+			if (region != null) {
+				//sprite.rect
 			}
 
-			Vector3[] verts = new Vector3[4];
-			Vector2[] uvs = new Vector2[4];
-			Color[] colors = new Color[4] { Color.white, Color.white, Color.white, Color.white };
-			int[] triangles = new int[6] { 0, 1, 2, 2, 3, 0 };
-
-			float left, right, top, bottom;
-			left = region.width / -2f;
-			right = left * -1f;
-			top = region.height / 2f;
-			bottom = top * -1;
-
-			verts[0] = new Vector3(left, bottom, 0) * scale;
-			verts[1] = new Vector3(left, top, 0) * scale;
-			verts[2] = new Vector3(right, top, 0) * scale;
-			verts[3] = new Vector3(right, bottom, 0) * scale;
-			float u, v, u2, v2;
-			u = region.u;
-			v = region.v;
-			u2 = region.u2;
-			v2 = region.v2;
-
-			if (!region.rotate) {
-				uvs[0] = new Vector2(u, v2);
-				uvs[1] = new Vector2(u, v);
-				uvs[2] = new Vector2(u2, v);
-				uvs[3] = new Vector2(u2, v2);
+			return sprite;
+		}
+
+		public Mesh GenerateMesh (string name, Mesh mesh, out Material material, float scale = 0.01f) {
+			AtlasRegion region = atlas.FindRegion(name);
+			material = null;
+			if (region != null) {
+				if (mesh == null) {
+					mesh = new Mesh();
+					mesh.name = name;
+				}
+
+				Vector3[] verts = new Vector3[4];
+				Vector2[] uvs = new Vector2[4];
+				Color[] colors = new Color[4] { Color.white, Color.white, Color.white, Color.white };
+				int[] triangles = new int[6] { 0, 1, 2, 2, 3, 0 };
+
+				float left, right, top, bottom;
+				left = region.width / -2f;
+				right = left * -1f;
+				top = region.height / 2f;
+				bottom = top * -1;
+
+				verts[0] = new Vector3(left, bottom, 0) * scale;
+				verts[1] = new Vector3(left, top, 0) * scale;
+				verts[2] = new Vector3(right, top, 0) * scale;
+				verts[3] = new Vector3(right, bottom, 0) * scale;
+				float u, v, u2, v2;
+				u = region.u;
+				v = region.v;
+				u2 = region.u2;
+				v2 = region.v2;
+
+				if (!region.rotate) {
+					uvs[0] = new Vector2(u, v2);
+					uvs[1] = new Vector2(u, v);
+					uvs[2] = new Vector2(u2, v);
+					uvs[3] = new Vector2(u2, v2);
+				} else {
+					uvs[0] = new Vector2(u2, v2);
+					uvs[1] = new Vector2(u, v2);
+					uvs[2] = new Vector2(u, v);
+					uvs[3] = new Vector2(u2, v);
+				}
+
+				mesh.triangles = new int[0];
+				mesh.vertices = verts;
+				mesh.uv = uvs;
+				mesh.colors = colors;
+				mesh.triangles = triangles;
+				mesh.RecalculateNormals();
+				mesh.RecalculateBounds();
+
+				material = (Material)region.page.rendererObject;
 			} else {
-				uvs[0] = new Vector2(u2, v2);
-				uvs[1] = new Vector2(u, v2);
-				uvs[2] = new Vector2(u, v);
-				uvs[3] = new Vector2(u2, v);
+				mesh = null;
 			}
 
-			mesh.triangles = new int[0];
-			mesh.vertices = verts;
-			mesh.uv = uvs;
-			mesh.colors = colors;
-			mesh.triangles = triangles;
-			mesh.RecalculateNormals();
-			mesh.RecalculateBounds();
-
-			material = (Material)region.page.rendererObject;
-		} else {
-			mesh = null;
+			return mesh;
 		}
-
-		return mesh;
 	}
-}
 
-public class MaterialsTextureLoader : TextureLoader {
-	AtlasAsset atlasAsset;
+	public class MaterialsTextureLoader : TextureLoader {
+		AtlasAsset atlasAsset;
 
-	public MaterialsTextureLoader (AtlasAsset atlasAsset) {
-		this.atlasAsset = atlasAsset;
-	}
+		public MaterialsTextureLoader (AtlasAsset atlasAsset) {
+			this.atlasAsset = atlasAsset;
+		}
 
-	public void Load (AtlasPage page, String path) {
-		String name = Path.GetFileNameWithoutExtension(path);
-		Material material = null;
-		foreach (Material other in atlasAsset.materials) {
-			if (other.mainTexture == null) {
-				Debug.LogError("Material is missing texture: " + other.name, other);
+		public void Load (AtlasPage page, String path) {
+			String name = Path.GetFileNameWithoutExtension(path);
+			Material material = null;
+			foreach (Material other in atlasAsset.materials) {
+				if (other.mainTexture == null) {
+					Debug.LogError("Material is missing texture: " + other.name, other);
+					return;
+				}
+				if (other.mainTexture.name == name) {
+					material = other;
+					break;
+				}
+			}
+			if (material == null) {
+				Debug.LogError("Material with texture name \"" + name + "\" not found for atlas asset: " + atlasAsset.name, atlasAsset);
 				return;
 			}
-			if (other.mainTexture.name == name) {
-				material = other;
-				break;
+			page.rendererObject = material;
+
+			// Very old atlas files expected the texture's actual size to be used at runtime.
+			if (page.width == 0 || page.height == 0) {
+				page.width = material.mainTexture.width;
+				page.height = material.mainTexture.height;
 			}
 		}
-		if (material == null) {
-			Debug.LogError("Material with texture name \"" + name + "\" not found for atlas asset: " + atlasAsset.name, atlasAsset);
-			return;
-		}
-		page.rendererObject = material;
 
-		// Very old atlas files expected the texture's actual size to be used at runtime.
-		if (page.width == 0 || page.height == 0) {
-			page.width = material.mainTexture.width;
-			page.height = material.mainTexture.height;
+		public void Unload (object texture) {
 		}
 	}
-
-	public void Unload (object texture) {
-	}
 }

+ 7 - 25
spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs

@@ -182,10 +182,7 @@ namespace Spine.Unity.Editor {
 				EditorGUI.EndDisabledGroup();
 
 				EditorGUI.indentLevel++;
-				GUILayout.BeginHorizontal();
-				{
-
-
+				using (new EditorGUILayout.HorizontalScope()) {
 					if (GUILayout.Button(new GUIContent("Bake All Skins", SpineEditorUtilities.Icons.unityIcon), GUILayout.Height(32), GUILayout.Width(150)))
 						SkeletonBaker.BakeToPrefab(m_skeletonDataAsset, m_skeletonData.Skins, "", bakeAnimations, bakeIK, bakeEventOptions);
 
@@ -200,35 +197,20 @@ namespace Spine.Unity.Editor {
 						} else
 							skinName = m_skeletonAnimation.skeleton.Skin.Name;
 
-						bool oops = false;
-
-						try {
-							GUILayout.BeginVertical();
+						using (var m = new EditorGUILayout.VerticalScope()) {
 							if (GUILayout.Button(new GUIContent("Bake " + skinName, SpineEditorUtilities.Icons.unityIcon), GUILayout.Height(32), GUILayout.Width(250)))
 								SkeletonBaker.BakeToPrefab(m_skeletonDataAsset, new ExposedList<Skin>(new [] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions);
-
-							GUILayout.BeginHorizontal();
-							GUILayout.Label(new GUIContent("Skins", SpineEditorUtilities.Icons.skinsRoot), GUILayout.Width(50));
-							if (GUILayout.Button(skinName, EditorStyles.popup, GUILayout.Width(196))) {
-								SelectSkinContext();
+							using (new EditorGUILayout.HorizontalScope()) {
+								GUILayout.Label(new GUIContent("Skins", SpineEditorUtilities.Icons.skinsRoot), GUILayout.Width(50));
+								if (GUILayout.Button(skinName, EditorStyles.popup, GUILayout.Width(196))) {
+									SelectSkinContext();
+								}
 							}
-							GUILayout.EndHorizontal();
 
-
-
-						} catch {
-							oops = true;
-							//GUILayout.BeginVertical();
 						}
-
-
-
-						if (!oops)
-							GUILayout.EndVertical();
 					}
 
 				}
-				GUILayout.EndHorizontal();
 				EditorGUI.indentLevel--;
 				EditorGUI.indentLevel--;
 			}

+ 114 - 112
spine-unity/Assets/spine-unity/Asset Types/SkeletonDataAsset.cs

@@ -31,145 +31,147 @@
 
 using System;
 using System.IO;
-using System.Collections.Generic;
 using UnityEngine;
 using Spine;
 
-public class SkeletonDataAsset : ScriptableObject {
-	public AtlasAsset[] atlasAssets;
-#if SPINE_TK2D
-	public tk2dSpriteCollectionData spriteCollection;
-#endif
-	public TextAsset skeletonJSON;
-	public float scale = 0.01f;
-	public String[] fromAnimation;
-	public String[] toAnimation;
-	public float[] duration;
-	public float defaultMix;
-	public RuntimeAnimatorController controller;
-	private SkeletonData skeletonData;
-	private AnimationStateData stateData;
-
-	void OnEnable () {
-		if (atlasAssets == null)
-			atlasAssets = new AtlasAsset[0];
-	}
-
-	public void Reset () {
-		skeletonData = null;
-		stateData = null;
-	}
-
-	public SkeletonData GetSkeletonData (bool quiet) {
-		if (atlasAssets == null) {
-			atlasAssets = new AtlasAsset[0];
-			if (!quiet)
-				Debug.LogError("Atlas not set for SkeletonData asset: " + name, this);
-			Reset();
-			return null;
+namespace Spine.Unity {
+	public class SkeletonDataAsset : ScriptableObject {
+		public AtlasAsset[] atlasAssets;
+		#if SPINE_TK2D
+		public tk2dSpriteCollectionData spriteCollection;
+		#endif
+		public TextAsset skeletonJSON;
+		public float scale = 0.01f;
+		public String[] fromAnimation;
+		public String[] toAnimation;
+		public float[] duration;
+		public float defaultMix;
+		public RuntimeAnimatorController controller;
+		private SkeletonData skeletonData;
+		private AnimationStateData stateData;
+
+		void OnEnable () {
+			if (atlasAssets == null)
+				atlasAssets = new AtlasAsset[0];
 		}
 
-		if (skeletonJSON == null) {
-			if (!quiet)
-				Debug.LogError("Skeleton JSON file not set for SkeletonData asset: " + name, this);
-			Reset();
-			return null;
+		public void Reset () {
+			skeletonData = null;
+			stateData = null;
 		}
 
-#if !SPINE_TK2D
-		if (atlasAssets.Length == 0) {
-			Reset();
-			return null;
-		}
-#else
-		if (atlasAssets.Length == 0 && spriteCollection == null) {
-			Reset();
-			return null;
-		}
-#endif
-
-		Atlas[] atlasArr = new Atlas[atlasAssets.Length];
-		for (int i = 0; i < atlasAssets.Length; i++) {
-			if (atlasAssets[i] == null) {
+		public SkeletonData GetSkeletonData (bool quiet) {
+			if (atlasAssets == null) {
+				atlasAssets = new AtlasAsset[0];
+				if (!quiet)
+					Debug.LogError("Atlas not set for SkeletonData asset: " + name, this);
 				Reset();
 				return null;
 			}
-			atlasArr[i] = atlasAssets[i].GetAtlas();
-			if (atlasArr[i] == null) {
+
+			if (skeletonJSON == null) {
+				if (!quiet)
+					Debug.LogError("Skeleton JSON file not set for SkeletonData asset: " + name, this);
 				Reset();
 				return null;
 			}
-		}
-
-		if (skeletonData != null)
-			return skeletonData;
 
-		AttachmentLoader attachmentLoader;
-		float skeletonDataScale;
-
-#if !SPINE_TK2D
-		attachmentLoader = new AtlasAttachmentLoader(atlasArr);
-		skeletonDataScale = scale;
-#else
-		if (spriteCollection != null) {
-			attachmentLoader = new SpriteCollectionAttachmentLoader(spriteCollection);
-			skeletonDataScale = (1.0f / (spriteCollection.invOrthoSize * spriteCollection.halfTargetHeight) * scale);
-		} else {
-			if (atlasArr.Length == 0) {
+			#if !SPINE_TK2D
+			if (atlasAssets.Length == 0) {
 				Reset();
-				if (!quiet) Debug.LogError("Atlas not set for SkeletonData asset: " + name, this);
 				return null;
 			}
+			#else
+			if (atlasAssets.Length == 0 && spriteCollection == null) {
+				Reset();
+				return null;
+			}
+			#endif
+
+			Atlas[] atlasArr = new Atlas[atlasAssets.Length];
+			for (int i = 0; i < atlasAssets.Length; i++) {
+				if (atlasAssets[i] == null) {
+					Reset();
+					return null;
+				}
+				atlasArr[i] = atlasAssets[i].GetAtlas();
+				if (atlasArr[i] == null) {
+					Reset();
+					return null;
+				}
+			}
+
+			if (skeletonData != null)
+				return skeletonData;
+
+			AttachmentLoader attachmentLoader;
+			float skeletonDataScale;
+
+			#if !SPINE_TK2D
 			attachmentLoader = new AtlasAttachmentLoader(atlasArr);
 			skeletonDataScale = scale;
-		}
-#endif
-
-		try {
-			//var stopwatch = new System.Diagnostics.Stopwatch();
-			if (skeletonJSON.name.ToLower().Contains(".skel")) {
-				var input = new MemoryStream(skeletonJSON.bytes);
-				var binary = new SkeletonBinary(attachmentLoader);
-				binary.Scale = skeletonDataScale;
-				//stopwatch.Start();
-				skeletonData = binary.ReadSkeletonData(input);
+			#else
+			if (spriteCollection != null) {
+				attachmentLoader = new Spine.Unity.TK2D.SpriteCollectionAttachmentLoader(spriteCollection);
+				skeletonDataScale = (1.0f / (spriteCollection.invOrthoSize * spriteCollection.halfTargetHeight) * scale);
 			} else {
-				var input = new StringReader(skeletonJSON.text);
-				var json = new SkeletonJson(attachmentLoader);
-				json.Scale = skeletonDataScale;
-				//stopwatch.Start();
-				skeletonData = json.ReadSkeletonData(input);
+				if (atlasArr.Length == 0) {
+					Reset();
+					if (!quiet) Debug.LogError("Atlas not set for SkeletonData asset: " + name, this);
+					return null;
+				}
+				attachmentLoader = new AtlasAttachmentLoader(atlasArr);
+				skeletonDataScale = scale;
+			}
+			#endif
+
+			try {
+				//var stopwatch = new System.Diagnostics.Stopwatch();
+				if (skeletonJSON.name.ToLower().Contains(".skel")) {
+					var input = new MemoryStream(skeletonJSON.bytes);
+					var binary = new SkeletonBinary(attachmentLoader);
+					binary.Scale = skeletonDataScale;
+					//stopwatch.Start();
+					skeletonData = binary.ReadSkeletonData(input);
+				} else {
+					var input = new StringReader(skeletonJSON.text);
+					var json = new SkeletonJson(attachmentLoader);
+					json.Scale = skeletonDataScale;
+					//stopwatch.Start();
+					skeletonData = json.ReadSkeletonData(input);
+				}
+				//stopwatch.Stop();
+				//Debug.Log(stopwatch.Elapsed);
+			} catch (Exception ex) {
+				if (!quiet)
+					Debug.LogError("Error reading skeleton JSON file for SkeletonData asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, this);
+				return null;
 			}
-			//stopwatch.Stop();
-			//Debug.Log(stopwatch.Elapsed);
-		} catch (Exception ex) {
-			if (!quiet)
-				Debug.LogError("Error reading skeleton JSON file for SkeletonData asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, this);
-			return null;
-		}
 
-		stateData = new AnimationStateData(skeletonData);
-		FillStateData();
+			stateData = new AnimationStateData(skeletonData);
+			FillStateData();
 
-		return skeletonData;
-	}
+			return skeletonData;
+		}
 
-	public void FillStateData () {
-		if (stateData == null)
-			return;
+		public void FillStateData () {
+			if (stateData == null)
+				return;
 
-		stateData.DefaultMix = defaultMix;
-		for (int i = 0, n = fromAnimation.Length; i < n; i++) {
-			if (fromAnimation[i].Length == 0 || toAnimation[i].Length == 0)
-				continue;
-			stateData.SetMix(fromAnimation[i], toAnimation[i], duration[i]);
+			stateData.DefaultMix = defaultMix;
+			for (int i = 0, n = fromAnimation.Length; i < n; i++) {
+				if (fromAnimation[i].Length == 0 || toAnimation[i].Length == 0)
+					continue;
+				stateData.SetMix(fromAnimation[i], toAnimation[i], duration[i]);
+			}
 		}
-	}
 
-	public AnimationStateData GetAnimationStateData () {
-		if (stateData != null)
+		public AnimationStateData GetAnimationStateData () {
+			if (stateData != null)
+				return stateData;
+			GetSkeletonData(false);
 			return stateData;
-		GetSkeletonData(false);
-		return stateData;
+		}
 	}
+
 }

+ 86 - 87
spine-unity/Assets/spine-unity/BoneFollower.cs

@@ -28,119 +28,118 @@
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
-
 using System;
-using System.IO;
-using System.Collections.Generic;
 using UnityEngine;
-using Spine;
-
-/// <summary>Sets a GameObject's transform to match a bone on a Spine skeleton.</summary>
-[ExecuteInEditMode]
-[AddComponentMenu("Spine/BoneFollower")]
-public class BoneFollower : MonoBehaviour {
-
-	#region Inspector
-	public SkeletonRenderer skeletonRenderer;
-	public SkeletonRenderer SkeletonRenderer {
-		get { return skeletonRenderer; }
-		set {
-			skeletonRenderer = value;
-			Reset();
-		}
-	}
-	/// <summary>If a bone isn't set, boneName is used to find the bone.</summary>
-	[SpineBone(dataField: "skeletonRenderer")]
-	public String boneName;
 
-	public bool followZPosition = true;
-	public bool followBoneRotation = true;
-	public bool resetOnAwake = true;
-	#endregion
-
-	[NonSerialized]
-	public bool valid;
+namespace Spine.Unity {
+	/// <summary>Sets a GameObject's transform to match a bone on a Spine skeleton.</summary>
+	[ExecuteInEditMode]
+	[AddComponentMenu("Spine/BoneFollower")]
+	public class BoneFollower : MonoBehaviour {
+
+		#region Inspector
+		public SkeletonRenderer skeletonRenderer;
+		public SkeletonRenderer SkeletonRenderer {
+			get { return skeletonRenderer; }
+			set {
+				skeletonRenderer = value;
+				Reset();
+			}
+		}
+		/// <summary>If a bone isn't set, boneName is used to find the bone.</summary>
+		[SpineBone(dataField: "skeletonRenderer")]
+		public String boneName;
 
-	[NonSerialized]
-	public Bone bone;
-	Transform skeletonTransform;
+		public bool followZPosition = true;
+		public bool followBoneRotation = true;
+		public bool resetOnAwake = true;
+		#endregion
 
-	public void HandleResetRenderer (SkeletonRenderer skeletonRenderer) {
-		Reset();
-	}
+		[NonSerialized]
+		public bool valid;
 
-	public void Reset () {
-		bone = null;
-		valid = skeletonRenderer != null && skeletonRenderer.valid;
+		[NonSerialized]
+		public Bone bone;
+		Transform skeletonTransform;
 
-		if (!valid) return;
+		public void HandleResetRenderer (SkeletonRenderer skeletonRenderer) {
+			Reset();
+		}
 
-		skeletonTransform = skeletonRenderer.transform;
-		skeletonRenderer.OnRebuild -= HandleResetRenderer;
-		skeletonRenderer.OnRebuild += HandleResetRenderer;
+		public void Reset () {
+			bone = null;
+			valid = skeletonRenderer != null && skeletonRenderer.valid;
 
-		#if UNITY_EDITOR
-		if (Application.isEditor)
-			DoUpdate();
-		#endif
-	}
+			if (!valid) return;
 
-	void OnDestroy () {
-		if (skeletonRenderer != null)
+			skeletonTransform = skeletonRenderer.transform;
 			skeletonRenderer.OnRebuild -= HandleResetRenderer;
-	}
+			skeletonRenderer.OnRebuild += HandleResetRenderer;
 
-	public void Awake () {
-		if (resetOnAwake)
-			Reset();
-	}
+			#if UNITY_EDITOR
+			if (Application.isEditor)
+				DoUpdate();
+			#endif
+		}
 
-	void LateUpdate () {
-		DoUpdate();
-	}
+		void OnDestroy () {
+			if (skeletonRenderer != null)
+				skeletonRenderer.OnRebuild -= HandleResetRenderer;
+		}
 
-	public void DoUpdate () {
-		if (!valid) {
-			Reset();
-			return;
+		public void Awake () {
+			if (resetOnAwake)
+				Reset();
 		}
 
-		if (bone == null) {
-			if (boneName == null || boneName.Length == 0)
+		void LateUpdate () {
+			DoUpdate();
+		}
+
+		public void DoUpdate () {
+			if (!valid) {
+				Reset();
 				return;
-			bone = skeletonRenderer.skeleton.FindBone(boneName);
+			}
+
 			if (bone == null) {
-				Debug.LogError("Bone not found: " + boneName, this);
-				return;
+				if (boneName == null || boneName.Length == 0)
+					return;
+				bone = skeletonRenderer.skeleton.FindBone(boneName);
+				if (bone == null) {
+					Debug.LogError("Bone not found: " + boneName, this);
+					return;
+				}
 			}
-		}
 
-		Skeleton skeleton = skeletonRenderer.skeleton;
-		float flipRotation = (skeleton.flipX ^ skeleton.flipY) ? -1f : 1f;
-		Transform thisTransform = this.transform;
+			Skeleton skeleton = skeletonRenderer.skeleton;
+			float flipRotation = (skeleton.flipX ^ skeleton.flipY) ? -1f : 1f;
+			Transform thisTransform = this.transform;
 
-		// Recommended setup: Use local transform properties if Spine GameObject is parent
-		if (thisTransform.parent == skeletonTransform) {
-			thisTransform.localPosition = new Vector3(bone.worldX, bone.worldY, followZPosition ? 0f : thisTransform.localPosition.z);
+			// Recommended setup: Use local transform properties if Spine GameObject is parent
+			if (thisTransform.parent == skeletonTransform) {
+				thisTransform.localPosition = new Vector3(bone.worldX, bone.worldY, followZPosition ? 0f : thisTransform.localPosition.z);
 
-			if (followBoneRotation) {
-				Vector3 rotation = thisTransform.localRotation.eulerAngles;
-				thisTransform.localRotation = Quaternion.Euler(rotation.x, rotation.y, bone.WorldRotationX * flipRotation);
-			}
+				if (followBoneRotation) {
+					Vector3 rotation = thisTransform.localRotation.eulerAngles;
+					thisTransform.localRotation = Quaternion.Euler(rotation.x, rotation.y, bone.WorldRotationX * flipRotation);
+				}
 
-		// For special cases: Use transform world properties if transform relationship is complicated
-		} else {
-			Vector3 targetWorldPosition = skeletonTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY, 0f));
-			if (!followZPosition)
-				targetWorldPosition.z = thisTransform.position.z;
+				// For special cases: Use transform world properties if transform relationship is complicated
+			} else {
+				Vector3 targetWorldPosition = skeletonTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY, 0f));
+				if (!followZPosition)
+					targetWorldPosition.z = thisTransform.position.z;
 
-			thisTransform.position = targetWorldPosition;
+				thisTransform.position = targetWorldPosition;
 
-			if (followBoneRotation) {
-				Vector3 worldRotation = skeletonTransform.rotation.eulerAngles;
-				thisTransform.rotation = Quaternion.Euler(worldRotation.x, worldRotation.y, skeletonTransform.rotation.eulerAngles.z + (bone.WorldRotationX * flipRotation));
+				if (followBoneRotation) {
+					Vector3 worldRotation = skeletonTransform.rotation.eulerAngles;
+					thisTransform.rotation = Quaternion.Euler(worldRotation.x, worldRotation.y, skeletonTransform.rotation.eulerAngles.z + (bone.WorldRotationX * flipRotation));
+				}
 			}
-		}
 
+		}
 	}
+
 }

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

@@ -30,10 +30,8 @@
  *****************************************************************************/
 
 using UnityEngine;
-using System.Collections;
 using UnityEditor;
 using System.Reflection;
-using System;
 
 namespace Spine.Unity.Editor {
 	public static class SpineInspectorUtility {

+ 31 - 31
spine-unity/Assets/spine-unity/Modules/AtlasRegionAttacher.cs

@@ -28,53 +28,53 @@
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
-
 using UnityEngine;
 using System.Collections;
 using Spine;
 
+namespace Spine.Unity.Modules {
+	public class AtlasRegionAttacher : MonoBehaviour {
 
-public class AtlasRegionAttacher : MonoBehaviour {
-
-	[System.Serializable]
-	public class SlotRegionPair {
-		[SpineSlot]
-		public string slot;
+		[System.Serializable]
+		public class SlotRegionPair {
+			[SpineSlot]
+			public string slot;
 
-		[SpineAtlasRegion]
-		public string region;
-	}
+			[SpineAtlasRegion]
+			public string region;
+		}
 
-	public AtlasAsset atlasAsset;
-	public SlotRegionPair[] attachments;
+		public AtlasAsset atlasAsset;
+		public SlotRegionPair[] attachments;
 
-	Atlas atlas;
+		Atlas atlas;
 
-	void Awake () {
-		GetComponent<SkeletonRenderer>().OnRebuild += Apply;
-	}
+		void Awake () {
+			GetComponent<SkeletonRenderer>().OnRebuild += Apply;
+		}
 
 
-	void Apply (SkeletonRenderer skeletonRenderer) {
-		atlas = atlasAsset.GetAtlas();
+		void Apply (SkeletonRenderer skeletonRenderer) {
+			atlas = atlasAsset.GetAtlas();
 
-		AtlasAttachmentLoader loader = new AtlasAttachmentLoader(atlas);
+			AtlasAttachmentLoader loader = new AtlasAttachmentLoader(atlas);
 
-		float scaleMultiplier = skeletonRenderer.skeletonDataAsset.scale;
+			float scaleMultiplier = skeletonRenderer.skeletonDataAsset.scale;
 
-		var enumerator = attachments.GetEnumerator();
-		while (enumerator.MoveNext()) {
-			var entry = (SlotRegionPair)enumerator.Current;
-			var regionAttachment = loader.NewRegionAttachment(null, entry.region, entry.region);
-			regionAttachment.Width = regionAttachment.RegionOriginalWidth * scaleMultiplier;
-			regionAttachment.Height = regionAttachment.RegionOriginalHeight * scaleMultiplier;
+			var enumerator = attachments.GetEnumerator();
+			while (enumerator.MoveNext()) {
+				var entry = (SlotRegionPair)enumerator.Current;
+				var regionAttachment = loader.NewRegionAttachment(null, entry.region, entry.region);
+				regionAttachment.Width = regionAttachment.RegionOriginalWidth * scaleMultiplier;
+				regionAttachment.Height = regionAttachment.RegionOriginalHeight * scaleMultiplier;
 
-			regionAttachment.SetColor(new Color(1, 1, 1, 1));
-			regionAttachment.UpdateOffset();
+				regionAttachment.SetColor(new Color(1, 1, 1, 1));
+				regionAttachment.UpdateOffset();
 
-			var slot = skeletonRenderer.skeleton.FindSlot(entry.slot);
-			slot.Attachment = regionAttachment;
+				var slot = skeletonRenderer.skeleton.FindSlot(entry.slot);
+				slot.Attachment = regionAttachment;
+			}
 		}
-	}
 
+	}
 }

+ 109 - 117
spine-unity/Assets/spine-unity/Modules/BoundingBoxFollower/BoundingBoxFollower.cs

@@ -28,167 +28,159 @@
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
-
 using UnityEngine;
-using System.Collections;
 using System.Collections.Generic;
-using Spine;
-
-[ExecuteInEditMode]
-public class BoundingBoxFollower : MonoBehaviour {
 
-	public SkeletonRenderer skeletonRenderer;
+namespace Spine.Unity {
+	[ExecuteInEditMode]
+	public class BoundingBoxFollower : MonoBehaviour {
+		
+		public SkeletonRenderer skeletonRenderer;
 
-	[SpineSlot(dataField: "skeletonRenderer", containsBoundingBoxes: true)]
-	public string slotName;
+		[SpineSlot(dataField: "skeletonRenderer", containsBoundingBoxes: true)]
+		public string slotName;
 
-	//TODO:  not this
-	[Tooltip("LOL JK, Someone else do it!")]
-	public bool use3DMeshCollider;
+		//TODO:  not this
+		[Tooltip("LOL JK, Someone else do it!")]
+		public bool use3DMeshCollider;
 
-	private Slot slot;
-	private BoundingBoxAttachment currentAttachment;
-	private PolygonCollider2D currentCollider;
-	private string currentAttachmentName;
-	private bool valid = false;
-	private bool hasReset;
+		private Slot slot;
+		private BoundingBoxAttachment currentAttachment;
+		private PolygonCollider2D currentCollider;
+		private string currentAttachmentName;
+		private bool valid = false;
+		private bool hasReset;
 
-	public Dictionary<BoundingBoxAttachment, PolygonCollider2D> colliderTable = new Dictionary<BoundingBoxAttachment, PolygonCollider2D>();
-	public Dictionary<BoundingBoxAttachment, string> attachmentNameTable = new Dictionary<BoundingBoxAttachment, string>();
+		public Dictionary<BoundingBoxAttachment, PolygonCollider2D> colliderTable = new Dictionary<BoundingBoxAttachment, PolygonCollider2D>();
+		public Dictionary<BoundingBoxAttachment, string> attachmentNameTable = new Dictionary<BoundingBoxAttachment, string>();
 
-	public string CurrentAttachmentName {
-		get {
-			return currentAttachmentName;
+		public string CurrentAttachmentName {
+			get { return currentAttachmentName;	}
 		}
-	}
 
-	public BoundingBoxAttachment CurrentAttachment {
-		get {
-			return currentAttachment;
+		public BoundingBoxAttachment CurrentAttachment {
+			get { return currentAttachment;	}
 		}
-	}
 
-	public PolygonCollider2D CurrentCollider {
-		get {
-			return currentCollider;
+		public PolygonCollider2D CurrentCollider {
+			get { return currentCollider; }
 		}
-	}
 
-	public Slot Slot {
-		get {
-			return slot;
+		public Slot Slot {
+			get { return slot; }
 		}
-	}
 
 
-	void OnEnable () {
-		ClearColliders();
+		void OnEnable () {
+			ClearColliders();
 
-		if (skeletonRenderer == null)
-			skeletonRenderer = GetComponentInParent<SkeletonRenderer>();
+			if (skeletonRenderer == null)
+				skeletonRenderer = GetComponentInParent<SkeletonRenderer>();
 
-		if (skeletonRenderer != null) {
-			skeletonRenderer.OnRebuild -= HandleReset;
-			skeletonRenderer.OnRebuild += HandleReset;
+			if (skeletonRenderer != null) {
+				skeletonRenderer.OnRebuild -= HandleReset;
+				skeletonRenderer.OnRebuild += HandleReset;
 
-			if (hasReset)
-				HandleReset(skeletonRenderer);
+				if (hasReset)
+					HandleReset(skeletonRenderer);
+			}
 		}
-	}
 
-	void OnDisable () {
-		skeletonRenderer.OnRebuild -= HandleReset;
-	}
+		void OnDisable () {
+			skeletonRenderer.OnRebuild -= HandleReset;
+		}
 
-	void Start () {
-		if (!hasReset && skeletonRenderer != null)
-			HandleReset(skeletonRenderer);
-	}
+		void Start () {
+			if (!hasReset && skeletonRenderer != null)
+				HandleReset(skeletonRenderer);
+		}
 
-	public void HandleReset (SkeletonRenderer renderer) {
-		if (slotName == null || slotName == "")
-			return;
+		public void HandleReset (SkeletonRenderer renderer) {
+			if (slotName == null || slotName == "")
+				return;
 
-		hasReset = true;
+			hasReset = true;
 
-		ClearColliders();
-		colliderTable.Clear();
+			ClearColliders();
+			colliderTable.Clear();
 
-		if (skeletonRenderer.skeleton == null) {
-			skeletonRenderer.OnRebuild -= HandleReset;
-			skeletonRenderer.Initialize(false);
-			skeletonRenderer.OnRebuild += HandleReset;
-		}
+			if (skeletonRenderer.skeleton == null) {
+				skeletonRenderer.OnRebuild -= HandleReset;
+				skeletonRenderer.Initialize(false);
+				skeletonRenderer.OnRebuild += HandleReset;
+			}
 
 
-		var skeleton = skeletonRenderer.skeleton;
-		slot = skeleton.FindSlot(slotName);
-		int slotIndex = skeleton.FindSlotIndex(slotName);
+			var skeleton = skeletonRenderer.skeleton;
+			slot = skeleton.FindSlot(slotName);
+			int slotIndex = skeleton.FindSlotIndex(slotName);
 
-		foreach (var skin in skeleton.Data.Skins) {
-			List<string> attachmentNames = new List<string>();
-			skin.FindNamesForSlot(slotIndex, attachmentNames);
+			foreach (var skin in skeleton.Data.Skins) {
+				List<string> attachmentNames = new List<string>();
+				skin.FindNamesForSlot(slotIndex, attachmentNames);
 
-			foreach (var name in attachmentNames) {
-				var attachment = skin.GetAttachment(slotIndex, name);
-				if (attachment is BoundingBoxAttachment) {
-					var collider = SkeletonUtility.AddBoundingBoxAsComponent((BoundingBoxAttachment)attachment, gameObject, true);
-					collider.enabled = false;
-					collider.hideFlags = HideFlags.HideInInspector;
-					colliderTable.Add((BoundingBoxAttachment)attachment, collider);
-					attachmentNameTable.Add((BoundingBoxAttachment)attachment, name);
+				foreach (var name in attachmentNames) {
+					var attachment = skin.GetAttachment(slotIndex, name);
+					if (attachment is BoundingBoxAttachment) {
+						var collider = SkeletonUtility.AddBoundingBoxAsComponent((BoundingBoxAttachment)attachment, gameObject, true);
+						collider.enabled = false;
+						collider.hideFlags = HideFlags.HideInInspector;
+						colliderTable.Add((BoundingBoxAttachment)attachment, collider);
+						attachmentNameTable.Add((BoundingBoxAttachment)attachment, name);
+					}
 				}
 			}
-		}
 
-		if (colliderTable.Count == 0)
-			valid = false;
-		else
-			valid = true;
+			if (colliderTable.Count == 0)
+				valid = false;
+			else
+				valid = true;
 
-		if (!valid)
-			Debug.LogWarning("Bounding Box Follower not valid! Slot [" + slotName + "] does not contain any Bounding Box Attachments!");
-	}
+			if (!valid)
+				Debug.LogWarning("Bounding Box Follower not valid! Slot [" + slotName + "] does not contain any Bounding Box Attachments!");
+		}
 
-	void ClearColliders () {
-		var colliders = GetComponents<PolygonCollider2D>();
-		if (Application.isPlaying) {
-			foreach (var c in colliders) {
-				Destroy(c);
-			}
-		} else {
-			foreach (var c in colliders) {
-				DestroyImmediate(c);
+		void ClearColliders () {
+			var colliders = GetComponents<PolygonCollider2D>();
+			if (Application.isPlaying) {
+				foreach (var c in colliders) {
+					Destroy(c);
+				}
+			} else {
+				foreach (var c in colliders) {
+					DestroyImmediate(c);
+				}
 			}
-		}
 
-		colliderTable.Clear();
-		attachmentNameTable.Clear();
-	}
+			colliderTable.Clear();
+			attachmentNameTable.Clear();
+		}
 
-	void LateUpdate () {
-		if (!skeletonRenderer.valid)
-			return;
+		void LateUpdate () {
+			if (!skeletonRenderer.valid)
+				return;
 
-		if (slot != null) {
-			if (slot.Attachment != currentAttachment)
-				SetCurrent((BoundingBoxAttachment)slot.Attachment);
+			if (slot != null) {
+				if (slot.Attachment != currentAttachment)
+					SetCurrent((BoundingBoxAttachment)slot.Attachment);
+			}
 		}
-	}
 
-	void SetCurrent (BoundingBoxAttachment attachment) {
-		if (currentCollider)
-			currentCollider.enabled = false;
+		void SetCurrent (BoundingBoxAttachment attachment) {
+			if (currentCollider)
+				currentCollider.enabled = false;
 
-		if (attachment != null) {
-			currentCollider = colliderTable[attachment];
-			currentCollider.enabled = true;
-		} else {
-			currentCollider = null;
-		}
+			if (attachment != null) {
+				currentCollider = colliderTable[attachment];
+				currentCollider.enabled = true;
+			} else {
+				currentCollider = null;
+			}
 
-		currentAttachment = attachment;
+			currentAttachment = attachment;
 
-		currentAttachmentName = currentAttachment == null ? null : attachmentNameTable[attachment];
+			currentAttachmentName = currentAttachment == null ? null : attachmentNameTable[attachment];
+		}
 	}
+
 }

+ 37 - 35
spine-unity/Assets/spine-unity/Modules/CustomSkin.cs

@@ -28,54 +28,56 @@
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
-
 using UnityEngine;
-using System.Collections;
 using Spine;
+using Spine.Unity;
 
-public class CustomSkin : MonoBehaviour {
+namespace Spine.Unity.Modules {
+	public class CustomSkin : MonoBehaviour {
 
-	[System.Serializable]
-	public class SkinPair {
-		/// <summary>SpineAttachment attachment path to help find the attachment.</summary>
-		/// <remarks>This use of SpineAttachment generates an attachment path string that can only be used by SpineAttachment.GetAttachment.</remarks>
-		[SpineAttachment(currentSkinOnly: false, returnAttachmentPath: true, dataField: "skinSource")]
-		[UnityEngine.Serialization.FormerlySerializedAs("sourceAttachment")]
-		public string sourceAttachmentPath;
+		[System.Serializable]
+		public class SkinPair {
+			/// <summary>SpineAttachment attachment path to help find the attachment.</summary>
+			/// <remarks>This use of SpineAttachment generates an attachment path string that can only be used by SpineAttachment.GetAttachment.</remarks>
+			[SpineAttachment(currentSkinOnly: false, returnAttachmentPath: true, dataField: "skinSource")]
+			[UnityEngine.Serialization.FormerlySerializedAs("sourceAttachment")]
+			public string sourceAttachmentPath;
 
-		[SpineSlot]
-		public string targetSlot;
+			[SpineSlot]
+			public string targetSlot;
 
-		/// <summary>The name of the skin placeholder/skin dictionary entry this attachment should be associated with.</summary>
-		/// <remarks>This name is used by the skin dictionary, used in the method Skin.AddAttachment as well as setting a slot attachment</remarks>
-		[SpineAttachment(currentSkinOnly: true, placeholdersOnly: true)]
-		public string targetAttachment;
-	}
+			/// <summary>The name of the skin placeholder/skin dictionary entry this attachment should be associated with.</summary>
+			/// <remarks>This name is used by the skin dictionary, used in the method Skin.AddAttachment as well as setting a slot attachment</remarks>
+			[SpineAttachment(currentSkinOnly: true, placeholdersOnly: true)]
+			public string targetAttachment;
+		}
 
-	#region Inspector
-	public SkeletonDataAsset skinSource;
+		#region Inspector
+		public SkeletonDataAsset skinSource;
 
-	[UnityEngine.Serialization.FormerlySerializedAs("skinning")]
-	public SkinPair[] skinItems;
+		[UnityEngine.Serialization.FormerlySerializedAs("skinning")]
+		public SkinPair[] skinItems;
 
-	public Skin customSkin;
-	#endregion
+		public Skin customSkin;
+		#endregion
 
-	SkeletonRenderer skeletonRenderer;
+		SkeletonRenderer skeletonRenderer;
 
-	void Start () {
-		skeletonRenderer = GetComponent<SkeletonRenderer>();
-		Skeleton skeleton = skeletonRenderer.skeleton;
+		void Start () {
+			skeletonRenderer = GetComponent<SkeletonRenderer>();
+			Skeleton skeleton = skeletonRenderer.skeleton;
 
-		customSkin = new Skin("CustomSkin");
+			customSkin = new Skin("CustomSkin");
 
-		foreach (var pair in skinItems) {
-			var attachment = SpineAttachment.GetAttachment(pair.sourceAttachmentPath, skinSource);
-			customSkin.AddAttachment(skeleton.FindSlotIndex(pair.targetSlot), pair.targetAttachment, attachment);
-		}
+			foreach (var pair in skinItems) {
+				var attachment = SpineAttachment.GetAttachment(pair.sourceAttachmentPath, skinSource);
+				customSkin.AddAttachment(skeleton.FindSlotIndex(pair.targetSlot), pair.targetAttachment, attachment);
+			}
 
-		// The custom skin does not need to be added to the skeleton data for it to work.
-		// But it's useful for your script to keep a reference to it.
-		skeleton.SetSkin(customSkin);
+			// The custom skin does not need to be added to the skeleton data for it to work.
+			// But it's useful for your script to keep a reference to it.
+			skeleton.SetSkin(customSkin);
+		}
 	}
+
 }

+ 120 - 117
spine-unity/Assets/spine-unity/Modules/Ghost/SkeletonGhost.cs

@@ -4,150 +4,153 @@
 *****************************************************************************/
 
 using UnityEngine;
-using System.Collections;
 using System.Collections.Generic;
 
-[RequireComponent(typeof(SkeletonRenderer))]
-public class SkeletonGhost : MonoBehaviour {
-	public bool ghostingEnabled = true;
-	public float spawnRate = 0.05f;
-	public Color32 color = new Color32(0xFF, 0xFF, 0xFF, 0x00); // default for additive.
-	[Tooltip("Remember to set color alpha to 0 if Additive is true")]
-	public bool additive = true;
-	public int maximumGhosts = 10;
-	public float fadeSpeed = 10;
-	public Shader ghostShader;
-	[Tooltip("0 is Color and Alpha, 1 is Alpha only.")]
-	[Range(0, 1)]
-	public float textureFade = 1;
-
-	[Header("Sorting")]
-	public bool sortWithDistanceOnly;
-	public float zOffset = 0f;
-
-	float nextSpawnTime;
-	SkeletonGhostRenderer[] pool;
-	int poolIndex = 0;
-	SkeletonRenderer skeletonRenderer;
-	MeshRenderer meshRenderer;
-	MeshFilter meshFilter;
-
-
-	Dictionary<Material, Material> materialTable = new Dictionary<Material, Material>();
-
-	void Start () {
-		if (ghostShader == null)
-			ghostShader = Shader.Find("Spine/SkeletonGhost");
-
-		skeletonRenderer = GetComponent<SkeletonRenderer>();
-		meshFilter = GetComponent<MeshFilter>();
-		meshRenderer = GetComponent<MeshRenderer>();
-		nextSpawnTime = Time.time + spawnRate;
-		pool = new SkeletonGhostRenderer[maximumGhosts];
-		for (int i = 0; i < maximumGhosts; i++) {
-			GameObject go = new GameObject(gameObject.name + " Ghost", typeof(SkeletonGhostRenderer));
-			pool[i] = go.GetComponent<SkeletonGhostRenderer>();
-			go.SetActive(false);
-			go.hideFlags = HideFlags.HideInHierarchy;
-		}
+namespace Spine.Unity.Modules {
+	
+	[RequireComponent(typeof(SkeletonRenderer))]
+	public class SkeletonGhost : MonoBehaviour {
+		public bool ghostingEnabled = true;
+		public float spawnRate = 0.05f;
+		public Color32 color = new Color32(0xFF, 0xFF, 0xFF, 0x00); // default for additive.
+		[Tooltip("Remember to set color alpha to 0 if Additive is true")]
+		public bool additive = true;
+		public int maximumGhosts = 10;
+		public float fadeSpeed = 10;
+		public Shader ghostShader;
+		[Tooltip("0 is Color and Alpha, 1 is Alpha only.")]
+		[Range(0, 1)]
+		public float textureFade = 1;
+
+		[Header("Sorting")]
+		public bool sortWithDistanceOnly;
+		public float zOffset = 0f;
+
+		float nextSpawnTime;
+		SkeletonGhostRenderer[] pool;
+		int poolIndex = 0;
+		SkeletonRenderer skeletonRenderer;
+		MeshRenderer meshRenderer;
+		MeshFilter meshFilter;
+
+
+		Dictionary<Material, Material> materialTable = new Dictionary<Material, Material>();
+
+		void Start () {
+			if (ghostShader == null)
+				ghostShader = Shader.Find("Spine/SkeletonGhost");
+
+			skeletonRenderer = GetComponent<SkeletonRenderer>();
+			meshFilter = GetComponent<MeshFilter>();
+			meshRenderer = GetComponent<MeshRenderer>();
+			nextSpawnTime = Time.time + spawnRate;
+			pool = new SkeletonGhostRenderer[maximumGhosts];
+			for (int i = 0; i < maximumGhosts; i++) {
+				GameObject go = new GameObject(gameObject.name + " Ghost", typeof(SkeletonGhostRenderer));
+				pool[i] = go.GetComponent<SkeletonGhostRenderer>();
+				go.SetActive(false);
+				go.hideFlags = HideFlags.HideInHierarchy;
+			}
 
-		if (skeletonRenderer is SkeletonAnimation)
-			((SkeletonAnimation)skeletonRenderer).state.Event += OnEvent;
+			if (skeletonRenderer is SkeletonAnimation)
+				((SkeletonAnimation)skeletonRenderer).state.Event += OnEvent;
 
-	}
+		}
 
-	//SkeletonAnimation
-	/*
+		//SkeletonAnimation
+		/*
 	 *	Int Value:		0 sets ghostingEnabled to false, 1 sets ghostingEnabled to true
 	 *	Float Value:	Values greater than 0 set the spawnRate equal the float value
 	 *	String Value:	Pass RGBA hex color values in to set the color property.  IE:   "A0FF8BFF"
 	 */
-	void OnEvent (Spine.AnimationState state, int trackIndex, Spine.Event e) {
-		if (e.Data.Name == "Ghosting") {
-			ghostingEnabled = e.Int > 0;
-			if (e.Float > 0)
-				spawnRate = e.Float;
-			if (e.String != null) {
-				this.color = HexToColor(e.String);
+		void OnEvent (Spine.AnimationState state, int trackIndex, Spine.Event e) {
+			if (e.Data.Name == "Ghosting") {
+				ghostingEnabled = e.Int > 0;
+				if (e.Float > 0)
+					spawnRate = e.Float;
+				if (e.String != null) {
+					this.color = HexToColor(e.String);
+				}
 			}
 		}
-	}
 
-	//SkeletonAnimator
-	//SkeletonAnimator or Mecanim based animations only support toggling ghostingEnabled.  Be sure not to set anything other than the Int param in Spine or String will take priority.
-	void Ghosting (float val) {
-		ghostingEnabled = val > 0;
-	}
+		//SkeletonAnimator
+		//SkeletonAnimator or Mecanim based animations only support toggling ghostingEnabled.  Be sure not to set anything other than the Int param in Spine or String will take priority.
+		void Ghosting (float val) {
+			ghostingEnabled = val > 0;
+		}
 
-	void Update () {
-		if (!ghostingEnabled)
-			return;
-
-		if (Time.time >= nextSpawnTime) {
-			GameObject go = pool[poolIndex].gameObject;
-
-			Material[] materials = meshRenderer.sharedMaterials;
-			for (int i = 0; i < materials.Length; i++) {
-				var originalMat = materials[i];
-				Material ghostMat;
-				if (!materialTable.ContainsKey(originalMat)) {
-					ghostMat = new Material(originalMat);
-					ghostMat.shader = ghostShader;
-					ghostMat.color = Color.white;
-					if (ghostMat.HasProperty("_TextureFade"))
-						ghostMat.SetFloat("_TextureFade", textureFade);
-					materialTable.Add(originalMat, ghostMat);
-				} else {
-					ghostMat = materialTable[originalMat];
+		void Update () {
+			if (!ghostingEnabled)
+				return;
+
+			if (Time.time >= nextSpawnTime) {
+				GameObject go = pool[poolIndex].gameObject;
+
+				Material[] materials = meshRenderer.sharedMaterials;
+				for (int i = 0; i < materials.Length; i++) {
+					var originalMat = materials[i];
+					Material ghostMat;
+					if (!materialTable.ContainsKey(originalMat)) {
+						ghostMat = new Material(originalMat);
+						ghostMat.shader = ghostShader;
+						ghostMat.color = Color.white;
+						if (ghostMat.HasProperty("_TextureFade"))
+							ghostMat.SetFloat("_TextureFade", textureFade);
+						materialTable.Add(originalMat, ghostMat);
+					} else {
+						ghostMat = materialTable[originalMat];
+					}
+
+					materials[i] = ghostMat;
 				}
 
-				materials[i] = ghostMat;
-			}
-
-			var goTransform = go.transform;
-			goTransform.parent = transform;
+				var goTransform = go.transform;
+				goTransform.parent = transform;
 
-			pool[poolIndex].Initialize(meshFilter.sharedMesh, materials, color, additive, fadeSpeed, meshRenderer.sortingLayerID, (sortWithDistanceOnly) ? meshRenderer.sortingOrder : meshRenderer.sortingOrder - 1);
+				pool[poolIndex].Initialize(meshFilter.sharedMesh, materials, color, additive, fadeSpeed, meshRenderer.sortingLayerID, (sortWithDistanceOnly) ? meshRenderer.sortingOrder : meshRenderer.sortingOrder - 1);
 
-			goTransform.localPosition = new Vector3(0f, 0f, zOffset);
-			goTransform.localRotation = Quaternion.identity;
-			goTransform.localScale = Vector3.one;
+				goTransform.localPosition = new Vector3(0f, 0f, zOffset);
+				goTransform.localRotation = Quaternion.identity;
+				goTransform.localScale = Vector3.one;
 
-			goTransform.parent = null;
+				goTransform.parent = null;
 
-			poolIndex++;
+				poolIndex++;
 
-			if (poolIndex == pool.Length)
-				poolIndex = 0;
+				if (poolIndex == pool.Length)
+					poolIndex = 0;
 
-			nextSpawnTime = Time.time + spawnRate;
+				nextSpawnTime = Time.time + spawnRate;
+			}
 		}
-	}
 
-	void OnDestroy () {
-		for (int i = 0; i < maximumGhosts; i++) {
-			if (pool[i] != null)
-				pool[i].Cleanup();
-		}
+		void OnDestroy () {
+			for (int i = 0; i < maximumGhosts; i++) {
+				if (pool[i] != null)
+					pool[i].Cleanup();
+			}
 
-		foreach (var mat in materialTable.Values)
-			Destroy(mat);
-	}
+			foreach (var mat in materialTable.Values)
+				Destroy(mat);
+		}
 
 
-	//based on UnifyWiki  http://wiki.unity3d.com/index.php?title=HexConverter
-	static Color32 HexToColor (string hex) {
-		if (hex.Length < 6)
-			return Color.magenta;
+		//based on UnifyWiki  http://wiki.unity3d.com/index.php?title=HexConverter
+		static Color32 HexToColor (string hex) {
+			if (hex.Length < 6)
+				return Color.magenta;
 
-		hex = hex.Replace("#", "");
-		byte r = byte.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
-		byte g = byte.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
-		byte b = byte.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
-		byte a = 0xFF;
-		if (hex.Length == 8)
-			a = byte.Parse(hex.Substring(6, 2), System.Globalization.NumberStyles.HexNumber);
+			hex = hex.Replace("#", "");
+			byte r = byte.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
+			byte g = byte.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
+			byte b = byte.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
+			byte a = 0xFF;
+			if (hex.Length == 8)
+				a = byte.Parse(hex.Substring(6, 2), System.Globalization.NumberStyles.HexNumber);
 
-		return new Color32(r, g, b, a);
+			return new Color32(r, g, b, a);
+		}
 	}
+
 }

+ 42 - 41
spine-unity/Assets/spine-unity/Modules/Ragdoll/Editor/SkeletonRagdoll2DInspector.cs

@@ -5,48 +5,49 @@
 
 using UnityEngine;
 using UnityEditor;
-using System.Collections;
-using System.Collections.Generic;
-
-[CustomEditor(typeof(SkeletonRagdoll2D))]
-public class SkeletonRagdoll2DInspector : Editor {
-	SerializedProperty startingBoneName, stopBoneNames, applyOnStart, pinStartBone, enableJointCollision, gravityScale, disableIK, thickness, rotationLimit, colliderLayer, mix, rootMass, massFalloffFactor;
-
-	void OnEnable () {
-		startingBoneName = serializedObject.FindProperty("startingBoneName");
-		stopBoneNames = serializedObject.FindProperty("stopBoneNames");
-		applyOnStart = serializedObject.FindProperty("applyOnStart");
-		pinStartBone = serializedObject.FindProperty("pinStartBone");
-		gravityScale = serializedObject.FindProperty("gravityScale");
-		disableIK = serializedObject.FindProperty("disableIK");
-		thickness = serializedObject.FindProperty("thickness");
-		rotationLimit = serializedObject.FindProperty("rotationLimit");
-		colliderLayer = serializedObject.FindProperty("colliderLayer");
-		mix = serializedObject.FindProperty("mix");
-		rootMass = serializedObject.FindProperty("rootMass");
-		massFalloffFactor = serializedObject.FindProperty("massFalloffFactor");
-	}
 
-	public override void OnInspectorGUI () {
-		EditorGUILayout.PropertyField(startingBoneName);
-		EditorGUILayout.PropertyField(stopBoneNames, true);
-		EditorGUILayout.PropertyField(applyOnStart);
-		EditorGUILayout.PropertyField(pinStartBone);
-		EditorGUILayout.PropertyField(gravityScale);
-		EditorGUILayout.PropertyField(disableIK);
-		EditorGUILayout.PropertyField(thickness);
-		EditorGUILayout.PropertyField(rotationLimit);
-		EditorGUILayout.PropertyField(rootMass);
-		EditorGUILayout.PropertyField(massFalloffFactor);
-		colliderLayer.intValue = EditorGUILayout.LayerField(colliderLayer.displayName, colliderLayer.intValue);
-		EditorGUILayout.PropertyField(mix);
-		
-
-		serializedObject.ApplyModifiedProperties();
-	}
+namespace Spine.Unity.Modules {
+	[CustomEditor(typeof(SkeletonRagdoll2D))]
+	public class SkeletonRagdoll2DInspector : UnityEditor.Editor {
+		SerializedProperty startingBoneName, stopBoneNames, applyOnStart, pinStartBone, enableJointCollision, gravityScale, disableIK, thickness, rotationLimit, colliderLayer, mix, rootMass, massFalloffFactor;
+
+		void OnEnable () {
+			startingBoneName = serializedObject.FindProperty("startingBoneName");
+			stopBoneNames = serializedObject.FindProperty("stopBoneNames");
+			applyOnStart = serializedObject.FindProperty("applyOnStart");
+			pinStartBone = serializedObject.FindProperty("pinStartBone");
+			gravityScale = serializedObject.FindProperty("gravityScale");
+			disableIK = serializedObject.FindProperty("disableIK");
+			thickness = serializedObject.FindProperty("thickness");
+			rotationLimit = serializedObject.FindProperty("rotationLimit");
+			colliderLayer = serializedObject.FindProperty("colliderLayer");
+			mix = serializedObject.FindProperty("mix");
+			rootMass = serializedObject.FindProperty("rootMass");
+			massFalloffFactor = serializedObject.FindProperty("massFalloffFactor");
+		}
+
+		public override void OnInspectorGUI () {
+			EditorGUILayout.PropertyField(startingBoneName);
+			EditorGUILayout.PropertyField(stopBoneNames, true);
+			EditorGUILayout.PropertyField(applyOnStart);
+			EditorGUILayout.PropertyField(pinStartBone);
+			EditorGUILayout.PropertyField(gravityScale);
+			EditorGUILayout.PropertyField(disableIK);
+			EditorGUILayout.PropertyField(thickness);
+			EditorGUILayout.PropertyField(rotationLimit);
+			EditorGUILayout.PropertyField(rootMass);
+			EditorGUILayout.PropertyField(massFalloffFactor);
+			colliderLayer.intValue = EditorGUILayout.LayerField(colliderLayer.displayName, colliderLayer.intValue);
+			EditorGUILayout.PropertyField(mix);
 
-	void Header (string name) {
-		GUILayout.Space(20);
-		EditorGUILayout.LabelField(name, EditorStyles.boldLabel);
+
+			serializedObject.ApplyModifiedProperties();
+		}
+
+		void Header (string name) {
+			GUILayout.Space(20);
+			EditorGUILayout.LabelField(name, EditorStyles.boldLabel);
+		}
 	}
+
 }

+ 40 - 37
spine-unity/Assets/spine-unity/Modules/Ragdoll/Editor/SkeletonRagdollInspector.cs

@@ -8,46 +8,49 @@ using UnityEditor;
 using System.Collections;
 using System.Collections.Generic;
 
-[CustomEditor(typeof(SkeletonRagdoll))]
-public class SkeletonRagdollInspector : Editor {
-	SerializedProperty startingBoneName, stopBoneNames, applyOnStart, pinStartBone, enableJointCollision, useGravity, disableIK, thickness, rotationLimit, colliderLayer, mix, rootMass, massFalloffFactor;
+namespace Spine.Unity.Modules {
+	[CustomEditor(typeof(SkeletonRagdoll))]
+	public class SkeletonRagdollInspector : UnityEditor.Editor {
+		SerializedProperty startingBoneName, stopBoneNames, applyOnStart, pinStartBone, enableJointCollision, useGravity, disableIK, thickness, rotationLimit, colliderLayer, mix, rootMass, massFalloffFactor;
 
-	void OnEnable () {
-		startingBoneName = serializedObject.FindProperty("startingBoneName");
-		stopBoneNames = serializedObject.FindProperty("stopBoneNames");
-		applyOnStart = serializedObject.FindProperty("applyOnStart");
-		pinStartBone = serializedObject.FindProperty("pinStartBone");
-		enableJointCollision = serializedObject.FindProperty("enableJointCollision");
-		useGravity = serializedObject.FindProperty("useGravity");
-		disableIK = serializedObject.FindProperty("disableIK");
-		thickness = serializedObject.FindProperty("thickness");
-		rotationLimit = serializedObject.FindProperty("rotationLimit");
-		colliderLayer = serializedObject.FindProperty("colliderLayer");
-		mix = serializedObject.FindProperty("mix");
-		rootMass = serializedObject.FindProperty("rootMass");
-		massFalloffFactor = serializedObject.FindProperty("massFalloffFactor");
-	}
+		void OnEnable () {
+			startingBoneName = serializedObject.FindProperty("startingBoneName");
+			stopBoneNames = serializedObject.FindProperty("stopBoneNames");
+			applyOnStart = serializedObject.FindProperty("applyOnStart");
+			pinStartBone = serializedObject.FindProperty("pinStartBone");
+			enableJointCollision = serializedObject.FindProperty("enableJointCollision");
+			useGravity = serializedObject.FindProperty("useGravity");
+			disableIK = serializedObject.FindProperty("disableIK");
+			thickness = serializedObject.FindProperty("thickness");
+			rotationLimit = serializedObject.FindProperty("rotationLimit");
+			colliderLayer = serializedObject.FindProperty("colliderLayer");
+			mix = serializedObject.FindProperty("mix");
+			rootMass = serializedObject.FindProperty("rootMass");
+			massFalloffFactor = serializedObject.FindProperty("massFalloffFactor");
+		}
 
-	public override void OnInspectorGUI () {
-		EditorGUILayout.PropertyField(startingBoneName);
-		EditorGUILayout.PropertyField(stopBoneNames, true);
-		EditorGUILayout.PropertyField(applyOnStart);
-		EditorGUILayout.PropertyField(pinStartBone);
-		EditorGUILayout.PropertyField(enableJointCollision);
-		EditorGUILayout.PropertyField(useGravity);
-		EditorGUILayout.PropertyField(disableIK);
-		EditorGUILayout.PropertyField(thickness);
-		EditorGUILayout.PropertyField(rotationLimit);
-		EditorGUILayout.PropertyField(rootMass);
-		EditorGUILayout.PropertyField(massFalloffFactor);
-		colliderLayer.intValue = EditorGUILayout.LayerField(colliderLayer.displayName, colliderLayer.intValue);
-		EditorGUILayout.PropertyField(mix);
+		public override void OnInspectorGUI () {
+			EditorGUILayout.PropertyField(startingBoneName);
+			EditorGUILayout.PropertyField(stopBoneNames, true);
+			EditorGUILayout.PropertyField(applyOnStart);
+			EditorGUILayout.PropertyField(pinStartBone);
+			EditorGUILayout.PropertyField(enableJointCollision);
+			EditorGUILayout.PropertyField(useGravity);
+			EditorGUILayout.PropertyField(disableIK);
+			EditorGUILayout.PropertyField(thickness);
+			EditorGUILayout.PropertyField(rotationLimit);
+			EditorGUILayout.PropertyField(rootMass);
+			EditorGUILayout.PropertyField(massFalloffFactor);
+			colliderLayer.intValue = EditorGUILayout.LayerField(colliderLayer.displayName, colliderLayer.intValue);
+			EditorGUILayout.PropertyField(mix);
 
-		serializedObject.ApplyModifiedProperties();
-	}
+			serializedObject.ApplyModifiedProperties();
+		}
 
-	void Header (string name) {
-		GUILayout.Space(20);
-		EditorGUILayout.LabelField(name, EditorStyles.boldLabel);
+		void Header (string name) {
+			GUILayout.Space(20);
+			EditorGUILayout.LabelField(name, EditorStyles.boldLabel);
+		}
 	}
+
 }

+ 327 - 325
spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll.cs

@@ -6,421 +6,423 @@
 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
-using Spine;
-
-[RequireComponent(typeof(SkeletonRenderer))]
-public class SkeletonRagdoll : MonoBehaviour {
-	private static Transform helper;
-
-	[Header("Hierarchy")]
-	[SpineBone]
-	public string startingBoneName = "";
-	[SpineBone]
-	public List<string> stopBoneNames = new List<string>();
-
-	[Header("Parameters")]
-	public bool applyOnStart;
-	[Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
-	public bool pinStartBone;
-	[Tooltip("Enable Collision between adjacent ragdoll elements (IE: Neck and Head)")]
-	public bool enableJointCollision;
-	public bool useGravity = true;
-	[Tooltip("Warning!  You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
-	public bool disableIK = true;
-	[Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
-	public float thickness = 0.125f;
-	[Tooltip("Default rotational limit value.  Min is negative this value, Max is this value.")]
-	public float rotationLimit = 20;
-	public float rootMass = 20;
-	[Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
-	[Range(0.01f, 1f)]
-	public float massFalloffFactor = 0.4f;
-	[Tooltip("The layer assigned to all of the rigidbody parts.")]
-	public int colliderLayer = 0;
-	[Range(0, 1)]
-	public float mix = 1;
-
-	public Rigidbody RootRigidbody {
-		get {
-			return this.rootRigidbody;
-		}
-	}
-
-	public Vector3 RootOffset {
-		get {
-			return this.rootOffset;
-		}
-	}
 
-	public Vector3 EstimatedSkeletonPosition {
-		get {
-			return rootRigidbody.position - rootOffset;
+namespace Spine.Unity.Modules {
+	[RequireComponent(typeof(SkeletonRenderer))]
+	public class SkeletonRagdoll : MonoBehaviour {
+		private static Transform helper;
+
+		[Header("Hierarchy")]
+		[SpineBone]
+		public string startingBoneName = "";
+		[SpineBone]
+		public List<string> stopBoneNames = new List<string>();
+
+		[Header("Parameters")]
+		public bool applyOnStart;
+		[Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
+		public bool pinStartBone;
+		[Tooltip("Enable Collision between adjacent ragdoll elements (IE: Neck and Head)")]
+		public bool enableJointCollision;
+		public bool useGravity = true;
+		[Tooltip("Warning!  You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
+		public bool disableIK = true;
+		[Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
+		public float thickness = 0.125f;
+		[Tooltip("Default rotational limit value.  Min is negative this value, Max is this value.")]
+		public float rotationLimit = 20;
+		public float rootMass = 20;
+		[Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
+		[Range(0.01f, 1f)]
+		public float massFalloffFactor = 0.4f;
+		[Tooltip("The layer assigned to all of the rigidbody parts.")]
+		public int colliderLayer = 0;
+		[Range(0, 1)]
+		public float mix = 1;
+
+		public Rigidbody RootRigidbody {
+			get {
+				return this.rootRigidbody;
+			}
 		}
-	}
 
-	public bool IsActive {
-		get {
-			return this.isActive;
+		public Vector3 RootOffset {
+			get {
+				return this.rootOffset;
+			}
 		}
-	}
 
-	private Rigidbody rootRigidbody;
-	private ISkeletonAnimation skeletonAnim;
-	private Skeleton skeleton;
-	private Dictionary<Bone, Transform> boneTable = new Dictionary<Bone, Transform>();
-	private Bone startingBone;
-	private Transform ragdollRoot;
-	private Vector3 rootOffset;
-	private bool isActive;
-
-	IEnumerator Start () {
-		skeletonAnim = (ISkeletonAnimation)GetComponent<SkeletonRenderer>();
-		if (helper == null) {
-			helper = (Transform)(new GameObject("Helper")).transform;
-			helper.hideFlags = HideFlags.HideInHierarchy;
+		public Vector3 EstimatedSkeletonPosition {
+			get {
+				return rootRigidbody.position - rootOffset;
+			}
 		}
 
-		if (applyOnStart) {
-			yield return null;
-			Apply();
+		public bool IsActive {
+			get {
+				return this.isActive;
+			}
 		}
-	}
 
-	public Coroutine SmoothMix (float target, float duration) {
-		return StartCoroutine(SmoothMixCoroutine(target, duration));
-	}
+		private Rigidbody rootRigidbody;
+		private ISkeletonAnimation skeletonAnim;
+		private Skeleton skeleton;
+		private Dictionary<Bone, Transform> boneTable = new Dictionary<Bone, Transform>();
+		private Bone startingBone;
+		private Transform ragdollRoot;
+		private Vector3 rootOffset;
+		private bool isActive;
+
+		IEnumerator Start () {
+			skeletonAnim = (ISkeletonAnimation)GetComponent<SkeletonRenderer>();
+			if (helper == null) {
+				helper = (Transform)(new GameObject("Helper")).transform;
+				helper.hideFlags = HideFlags.HideInHierarchy;
+			}
 
-	IEnumerator SmoothMixCoroutine (float target, float duration) {
-		float startTime = Time.time;
-		float startMix = mix;
-		while (mix > 0) {
-			mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
-			yield return null;
+			if (applyOnStart) {
+				yield return null;
+				Apply();
+			}
 		}
-	}
 
-	public void SetSkeletonPosition (Vector3 worldPosition) {
-		if (!isActive) {
-			Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
-			return;
+		public Coroutine SmoothMix (float target, float duration) {
+			return StartCoroutine(SmoothMixCoroutine(target, duration));
 		}
 
-		Vector3 offset = worldPosition - transform.position;
-		transform.position = worldPosition;
-		foreach (Transform t in boneTable.Values) {
-			t.position -= offset;
+		IEnumerator SmoothMixCoroutine (float target, float duration) {
+			float startTime = Time.time;
+			float startMix = mix;
+			while (mix > 0) {
+				mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
+				yield return null;
+			}
 		}
 
-		UpdateWorld(null);
-		skeleton.UpdateWorldTransform();
-	}
+		public void SetSkeletonPosition (Vector3 worldPosition) {
+			if (!isActive) {
+				Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
+				return;
+			}
 
-	public Rigidbody[] GetRigidbodyArray () {
-		if (!isActive)
-			return new Rigidbody[0];
+			Vector3 offset = worldPosition - transform.position;
+			transform.position = worldPosition;
+			foreach (Transform t in boneTable.Values) {
+				t.position -= offset;
+			}
 
-		Rigidbody[] arr = new Rigidbody[boneTable.Count];
-		int i = 0;
-		foreach (Transform t in boneTable.Values) {
-			arr[i] = t.GetComponent<Rigidbody>();
-			i++;
+			UpdateWorld(null);
+			skeleton.UpdateWorldTransform();
 		}
 
-		return arr;
-	}
+		public Rigidbody[] GetRigidbodyArray () {
+			if (!isActive)
+				return new Rigidbody[0];
 
-	public Rigidbody GetRigidbody (string boneName) {
-		var bone = skeleton.FindBone(boneName);
-		if (bone == null)
-			return null;
+			Rigidbody[] arr = new Rigidbody[boneTable.Count];
+			int i = 0;
+			foreach (Transform t in boneTable.Values) {
+				arr[i] = t.GetComponent<Rigidbody>();
+				i++;
+			}
 
-		if (boneTable.ContainsKey(bone))
-			return boneTable[bone].GetComponent<Rigidbody>();
+			return arr;
+		}
 
-		return null;
-	}
+		public Rigidbody GetRigidbody (string boneName) {
+			var bone = skeleton.FindBone(boneName);
+			if (bone == null)
+				return null;
 
-	public void Remove () {
-		isActive = false;
-		foreach (var t in boneTable.Values) {
-			Destroy(t.gameObject);
+			if (boneTable.ContainsKey(bone))
+				return boneTable[bone].GetComponent<Rigidbody>();
+
+			return null;
 		}
-		Destroy(ragdollRoot.gameObject);
 
-		boneTable.Clear();
-		skeletonAnim.UpdateWorld -= UpdateWorld;
-	}
+		public void Remove () {
+			isActive = false;
+			foreach (var t in boneTable.Values) {
+				Destroy(t.gameObject);
+			}
+			Destroy(ragdollRoot.gameObject);
 
-	public void Apply () {
-		isActive = true;
-		skeleton = skeletonAnim.Skeleton;
-		mix = 1;
+			boneTable.Clear();
+			skeletonAnim.UpdateWorld -= UpdateWorld;
+		}
 
-		var ragdollRootBone = skeleton.FindBone(startingBoneName);
-		startingBone = ragdollRootBone;
-		RecursivelyCreateBoneProxies(ragdollRootBone);
+		public void Apply () {
+			isActive = true;
+			skeleton = skeletonAnim.Skeleton;
+			mix = 1;
 
-		rootRigidbody = boneTable[ragdollRootBone].GetComponent<Rigidbody>();
-		rootRigidbody.isKinematic = pinStartBone;
+			var ragdollRootBone = skeleton.FindBone(startingBoneName);
+			startingBone = ragdollRootBone;
+			RecursivelyCreateBoneProxies(ragdollRootBone);
 
-		rootRigidbody.mass = rootMass;
+			rootRigidbody = boneTable[ragdollRootBone].GetComponent<Rigidbody>();
+			rootRigidbody.isKinematic = pinStartBone;
 
-		List<Collider> boneColliders = new List<Collider>();
+			rootRigidbody.mass = rootMass;
 
-		foreach (var pair in boneTable) {
-			var b = pair.Key;
-			var t = pair.Value;
-			Bone parentBone = null;
-			Transform parentTransform = transform;
+			List<Collider> boneColliders = new List<Collider>();
 
-			boneColliders.Add(t.GetComponent<Collider>());
+			foreach (var pair in boneTable) {
+				var b = pair.Key;
+				var t = pair.Value;
+				Bone parentBone = null;
+				Transform parentTransform = transform;
 
-			if (b != startingBone) {
-				parentBone = b.Parent;
-				parentTransform = boneTable[parentBone];
-			} else {
-				ragdollRoot = new GameObject("RagdollRoot").transform;
-				ragdollRoot.parent = transform;
+				boneColliders.Add(t.GetComponent<Collider>());
 
-				if (b == skeleton.RootBone) {
-					ragdollRoot.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
-					ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b));
-					parentTransform = ragdollRoot;
+				if (b != startingBone) {
+					parentBone = b.Parent;
+					parentTransform = boneTable[parentBone];
 				} else {
-					ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
-					ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b.Parent));
-					parentTransform = ragdollRoot;
-				}
+					ragdollRoot = new GameObject("RagdollRoot").transform;
+					ragdollRoot.parent = transform;
+
+					if (b == skeleton.RootBone) {
+						ragdollRoot.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
+						ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b));
+						parentTransform = ragdollRoot;
+					} else {
+						ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
+						ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b.Parent));
+						parentTransform = ragdollRoot;
+					}
 
-				rootOffset = t.position - transform.position;
-			}
+					rootOffset = t.position - transform.position;
+				}
 
-			var rbParent = parentTransform.GetComponent<Rigidbody>();
-
-			if (rbParent != null) {
-				var joint = t.gameObject.AddComponent<HingeJoint>();
-				joint.connectedBody = rbParent;
-				Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
-				localPos.x *= 1;
-				joint.connectedAnchor = localPos;
-				joint.axis = Vector3.forward;
-				joint.GetComponent<Rigidbody>().mass = joint.connectedBody.mass * massFalloffFactor;
-				JointLimits limits = new JointLimits();
-				limits.min = -rotationLimit;
-				limits.max = rotationLimit;
-				joint.limits = limits;
-				joint.useLimits = true;
-				joint.enableCollision = enableJointCollision;
+				var rbParent = parentTransform.GetComponent<Rigidbody>();
+
+				if (rbParent != null) {
+					var joint = t.gameObject.AddComponent<HingeJoint>();
+					joint.connectedBody = rbParent;
+					Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
+					localPos.x *= 1;
+					joint.connectedAnchor = localPos;
+					joint.axis = Vector3.forward;
+					joint.GetComponent<Rigidbody>().mass = joint.connectedBody.mass * massFalloffFactor;
+					JointLimits limits = new JointLimits();
+					limits.min = -rotationLimit;
+					limits.max = rotationLimit;
+					joint.limits = limits;
+					joint.useLimits = true;
+					joint.enableCollision = enableJointCollision;
+				}
 			}
-		}
 
-		for (int x = 0; x < boneColliders.Count; x++) {
-			for (int y = 0; y < boneColliders.Count; y++) {
-				if (x == y) continue;
-				Physics.IgnoreCollision(boneColliders[x], boneColliders[y]);
+			for (int x = 0; x < boneColliders.Count; x++) {
+				for (int y = 0; y < boneColliders.Count; y++) {
+					if (x == y) continue;
+					Physics.IgnoreCollision(boneColliders[x], boneColliders[y]);
+				}
 			}
-		}
 
-		var utilityBones = GetComponentsInChildren<SkeletonUtilityBone>();
-		if (utilityBones.Length > 0) {
-			List<string> destroyedUtilityBoneNames = new List<string>();
-			foreach (var ub in utilityBones) {
-				if (ub.mode == SkeletonUtilityBone.Mode.Override) {
-					destroyedUtilityBoneNames.Add(ub.gameObject.name);
-					Destroy(ub.gameObject);
+			var utilityBones = GetComponentsInChildren<SkeletonUtilityBone>();
+			if (utilityBones.Length > 0) {
+				List<string> destroyedUtilityBoneNames = new List<string>();
+				foreach (var ub in utilityBones) {
+					if (ub.mode == SkeletonUtilityBone.Mode.Override) {
+						destroyedUtilityBoneNames.Add(ub.gameObject.name);
+						Destroy(ub.gameObject);
+					}
 				}
-			}
 
-			if (destroyedUtilityBoneNames.Count > 0) {
-				string msg = "Destroyed Utility Bones: ";
-				for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
-					msg += destroyedUtilityBoneNames[i];
-					if (i != destroyedUtilityBoneNames.Count - 1) {
-						msg += ",";
+				if (destroyedUtilityBoneNames.Count > 0) {
+					string msg = "Destroyed Utility Bones: ";
+					for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
+						msg += destroyedUtilityBoneNames[i];
+						if (i != destroyedUtilityBoneNames.Count - 1) {
+							msg += ",";
+						}
 					}
+					Debug.LogWarning(msg);
 				}
-				Debug.LogWarning(msg);
 			}
-		}
 
-		if (disableIK) {
-			foreach (IkConstraint ik in skeleton.IkConstraints) {
-				ik.Mix = 0;
+			if (disableIK) {
+				foreach (IkConstraint ik in skeleton.IkConstraints) {
+					ik.Mix = 0;
+				}
 			}
+
+			skeletonAnim.UpdateWorld += UpdateWorld;
 		}
 
-		skeletonAnim.UpdateWorld += UpdateWorld;
-	}
+		void RecursivelyCreateBoneProxies (Bone b) {
+			if (stopBoneNames.Contains(b.Data.Name))
+				return;
 
-	void RecursivelyCreateBoneProxies (Bone b) {
-		if (stopBoneNames.Contains(b.Data.Name))
-			return;
+			GameObject go = new GameObject(b.Data.Name);
+			go.layer = colliderLayer;
+			Transform t = go.transform;
+			boneTable.Add(b, t);
 
-		GameObject go = new GameObject(b.Data.Name);
-		go.layer = colliderLayer;
-		Transform t = go.transform;
-		boneTable.Add(b, t);
+			t.parent = transform;
 
-		t.parent = transform;
+			t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
+			// MITCH
+			// t.localRotation = Quaternion.Euler(0, 0, b.WorldFlipX ^ b.WorldFlipY ? -b.WorldRotation : b.WorldRotation);
+			t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX);
+			t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 1);
 
-		t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
-        // MITCH
-        // t.localRotation = Quaternion.Euler(0, 0, b.WorldFlipX ^ b.WorldFlipY ? -b.WorldRotation : b.WorldRotation);
-        t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX);
-        t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 1);
+			float length = b.Data.Length;
 
-		float length = b.Data.Length;
+			var colliders = AttachBoundingBoxRagdollColliders(b);
 
-		var colliders = AttachBoundingBoxRagdollColliders(b);
+			if (length == 0) {
+				//physics
+				if (colliders.Count == 0) {
+					var ball = go.AddComponent<SphereCollider>();
+					ball.radius = thickness / 2f;
+				}
+			} else {
+				//physics
+				if (colliders.Count == 0) {
+					var box = go.AddComponent<BoxCollider>();
+					box.size = new Vector3(length, thickness, thickness);
+					// MITCH
+					// box.center = new Vector3((b.WorldFlipX ? -length : length) / 2, 0);
+					box.center = new Vector3(length / 2, 0);
+				}
+			}
 
-		if (length == 0) {
-			//physics
-			if (colliders.Count == 0) {
-				var ball = go.AddComponent<SphereCollider>();
-				ball.radius = thickness / 2f;
+			var rb = go.AddComponent<Rigidbody>();
+			rb.constraints = RigidbodyConstraints.FreezePositionZ;
+			foreach (Bone child in b.Children) {
+				RecursivelyCreateBoneProxies(child);
 			}
-		} else {
-			//physics
-			if (colliders.Count == 0) {
-				var box = go.AddComponent<BoxCollider>();
-				box.size = new Vector3(length, thickness, thickness);
-                // MITCH
-                // box.center = new Vector3((b.WorldFlipX ? -length : length) / 2, 0);
-                box.center = new Vector3(length / 2, 0);
-            }
 		}
 
-		var rb = go.AddComponent<Rigidbody>();
-		rb.constraints = RigidbodyConstraints.FreezePositionZ;
-		foreach (Bone child in b.Children) {
-			RecursivelyCreateBoneProxies(child);
-		}
-	}
+		List<Collider> AttachBoundingBoxRagdollColliders (Bone b) {
+			List<Collider> colliders = new List<Collider>();
 
-	List<Collider> AttachBoundingBoxRagdollColliders (Bone b) {
-		List<Collider> colliders = new List<Collider>();
+			Transform t = boneTable[b];
+			GameObject go = t.gameObject;
+			var skin = skeleton.Skin;
+			if (skin == null)
+				skin = skeleton.Data.DefaultSkin;
 
-		Transform t = boneTable[b];
-		GameObject go = t.gameObject;
-		var skin = skeleton.Skin;
-		if (skin == null)
-			skin = skeleton.Data.DefaultSkin;
+			// MITCH
+			// bool flipX = b.WorldFlipX;
+			// bool flipY = b.WorldFlipY;
+			bool flipX = false;
+			bool flipY = false;
 
-        // MITCH
-        // bool flipX = b.WorldFlipX;
-        // bool flipY = b.WorldFlipY;
-        bool flipX = false;
-        bool flipY = false;
+			List<Attachment> attachments = new List<Attachment>();
+			foreach (Slot s in skeleton.Slots) {
+				if (s.Bone == b) {
+					skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(s), attachments);
+					foreach (var a in attachments) {
+						if (a is BoundingBoxAttachment) {
+							if (!a.Name.ToLower().Contains("ragdoll"))
+								continue;
 
-        List<Attachment> attachments = new List<Attachment>();
-		foreach (Slot s in skeleton.Slots) {
-			if (s.Bone == b) {
-				skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(s), attachments);
-				foreach (var a in attachments) {
-					if (a is BoundingBoxAttachment) {
-						if (!a.Name.ToLower().Contains("ragdoll"))
-							continue;
+							var collider = go.AddComponent<BoxCollider>();
+							var bounds = SkeletonUtility.GetBoundingBoxBounds((BoundingBoxAttachment)a, thickness);
 
-						var collider = go.AddComponent<BoxCollider>();
-						var bounds = SkeletonUtility.GetBoundingBoxBounds((BoundingBoxAttachment)a, thickness);
+							collider.center = bounds.center;
+							collider.size = bounds.size;
 
-						collider.center = bounds.center;
-						collider.size = bounds.size;
+							if (flipX || flipY) {
+								Vector3 center = collider.center;
 
-						if (flipX || flipY) {
-							Vector3 center = collider.center;
+								if (flipX)
+									center.x *= -1;
 
-							if (flipX)
-								center.x *= -1;
+								if (flipY)
+									center.y *= -1;
 
-							if (flipY)
-								center.y *= -1;
+								collider.center = center;
+							}
 
-							collider.center = center;
+							colliders.Add(collider);
 						}
-
-						colliders.Add(collider);
 					}
 				}
 			}
+
+			return colliders;
 		}
 
-		return colliders;
-	}
+		void UpdateWorld (ISkeletonAnimation skeletonRenderer) {
+			foreach (var pair in boneTable) {
+				var b = pair.Key;
+				var t = pair.Value;
+				// bool flip = false;
+				bool flipX = false;  //TODO:  deal with negative scale instead of Flip Key for Spine 3.0
+				bool flipY = false;  //TODO:  deal with negative scale instead of Flip Key for Spine 3.0
+				Bone parentBone = null;
+				Transform parentTransform = transform;
+
+				if (b != startingBone) {
+					parentBone = b.Parent;
+					parentTransform = boneTable[parentBone];
+					// MITCH
+					// flipX = parentBone.WorldFlipX;
+					// flipY = parentBone.WorldFlipY;
 
-	void UpdateWorld (ISkeletonAnimation skeletonRenderer) {
-		foreach (var pair in boneTable) {
-			var b = pair.Key;
-			var t = pair.Value;
-			// bool flip = false;
-			bool flipX = false;  //TODO:  deal with negative scale instead of Flip Key for Spine 3.0
-			bool flipY = false;  //TODO:  deal with negative scale instead of Flip Key for Spine 3.0
-			Bone parentBone = null;
-			Transform parentTransform = transform;
-
-			if (b != startingBone) {
-				parentBone = b.Parent;
-				parentTransform = boneTable[parentBone];
-                // MITCH
-                // flipX = parentBone.WorldFlipX;
-                // flipY = parentBone.WorldFlipY;
-
-            } else {
-				parentBone = b.Parent;
-				parentTransform = ragdollRoot;
-				if (b.Parent != null) {
-                    // MITCH
-                    // flipX = b.worldFlipX;
-                    // flipY = b.WorldFlipY;
-                } else {
-					flipX = b.Skeleton.FlipX;
-					flipY = b.Skeleton.FlipY;
+				} else {
+					parentBone = b.Parent;
+					parentTransform = ragdollRoot;
+					if (b.Parent != null) {
+						// MITCH
+						// flipX = b.worldFlipX;
+						// flipY = b.WorldFlipY;
+					} else {
+						flipX = b.Skeleton.FlipX;
+						flipY = b.Skeleton.FlipY;
+					}
 				}
-			}
 
-			//flip = flipX ^ flipY;
+				//flip = flipX ^ flipY;
 
-			helper.position = parentTransform.position;
-			helper.rotation = parentTransform.rotation;
-			helper.localScale = new Vector3(flipX ? -parentTransform.localScale.x : parentTransform.localScale.x, flipY ? -parentTransform.localScale.y : parentTransform.localScale.y, 1);
+				helper.position = parentTransform.position;
+				helper.rotation = parentTransform.rotation;
+				helper.localScale = new Vector3(flipX ? -parentTransform.localScale.x : parentTransform.localScale.x, flipY ? -parentTransform.localScale.y : parentTransform.localScale.y, 1);
 
 
-			Vector3 pos = t.position;
-			pos = helper.InverseTransformPoint(pos);
-			b.X = Mathf.Lerp(b.X, pos.x, mix);
-			b.Y = Mathf.Lerp(b.Y, pos.y, mix);
+				Vector3 pos = t.position;
+				pos = helper.InverseTransformPoint(pos);
+				b.X = Mathf.Lerp(b.X, pos.x, mix);
+				b.Y = Mathf.Lerp(b.Y, pos.y, mix);
 
-			Vector3 right = helper.InverseTransformDirection(t.right);
+				Vector3 right = helper.InverseTransformDirection(t.right);
 
-			float a = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
+				float a = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
 
-            // MITCH
-			//if (b.WorldFlipX ^ b.WorldFlipY) {
-			//	a *= -1;
-			//}
-
-			if (parentBone != null) {
-                // MITCH
-				//if ((b.WorldFlipX ^ b.WorldFlipY) != flip) {
-				//	a -= GetCompensatedRotationIK(parentBone) * 2;
+				// MITCH
+				//if (b.WorldFlipX ^ b.WorldFlipY) {
+				//	a *= -1;
 				//}
-			}
 
-			b.Rotation = Mathf.Lerp(b.Rotation, a, mix);
-            // MITCH
-			// b.RotationIK = Mathf.Lerp(b.rotationIK, a, mix);
-		}
-	}
+				if (parentBone != null) {
+					// MITCH
+					//if ((b.WorldFlipX ^ b.WorldFlipY) != flip) {
+					//	a -= GetCompensatedRotationIK(parentBone) * 2;
+					//}
+				}
 
-	float GetCompensatedRotationIK (Bone b) {
-		Bone parent = b.Parent;
-        // MITCH
-		float a = b.AppliedRotation;
-		while (parent != null) {
-			a += parent.AppliedRotation;
-			parent = parent.parent;
+				b.Rotation = Mathf.Lerp(b.Rotation, a, mix);
+				// MITCH
+				// b.RotationIK = Mathf.Lerp(b.rotationIK, a, mix);
+			}
 		}
 
-		return a;
+		float GetCompensatedRotationIK (Bone b) {
+			Bone parent = b.Parent;
+			// MITCH
+			float a = b.AppliedRotation;
+			while (parent != null) {
+				a += parent.AppliedRotation;
+				parent = parent.parent;
+			}
+
+			return a;
+		}
 	}
+
 }

+ 336 - 341
spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs

@@ -6,432 +6,427 @@
 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
-using Spine;
-
-[RequireComponent(typeof(SkeletonRenderer))]
-public class SkeletonRagdoll2D : MonoBehaviour {
-	private static Transform helper;
-
-	[Header("Hierarchy")]
-	[SpineBone]
-	public string startingBoneName = "";
-	[SpineBone]
-	public List<string> stopBoneNames = new List<string>();
-
-	[Header("Parameters")]
-	public bool applyOnStart;
-	[Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
-	public bool pinStartBone;
-	public float gravityScale = 1;
-	[Tooltip("Warning!  You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
-	public bool disableIK = true;
-	[Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
-	public float thickness = 0.125f;
-	[Tooltip("Default rotational limit value.  Min is negative this value, Max is this value.")]
-	public float rotationLimit = 20;
-	public float rootMass = 20;
-	[Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
-	[Range(0.01f, 1f)]
-	public float massFalloffFactor = 0.4f;
-	[Tooltip("The layer assigned to all of the rigidbody parts.")]
-	public int colliderLayer = 0;
-	[Range(0, 1)]
-	public float mix = 1;
-
-	public Rigidbody2D RootRigidbody {
-		get {
-			return this.rootRigidbody;
+using Spine.Unity;
+
+namespace Spine.Unity.Modules {
+	[RequireComponent(typeof(SkeletonRenderer))]
+	public class SkeletonRagdoll2D : MonoBehaviour {
+		private static Transform helper;
+
+		[Header("Hierarchy")]
+		[SpineBone]
+		public string startingBoneName = "";
+		[SpineBone]
+		public List<string> stopBoneNames = new List<string>();
+
+		[Header("Parameters")]
+		public bool applyOnStart;
+		[Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
+		public bool pinStartBone;
+		public float gravityScale = 1;
+		[Tooltip("Warning!  You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
+		public bool disableIK = true;
+		[Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
+		public float thickness = 0.125f;
+		[Tooltip("Default rotational limit value.  Min is negative this value, Max is this value.")]
+		public float rotationLimit = 20;
+		public float rootMass = 20;
+		[Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
+		[Range(0.01f, 1f)]
+		public float massFalloffFactor = 0.4f;
+		[Tooltip("The layer assigned to all of the rigidbody parts.")]
+		public int colliderLayer = 0;
+		[Range(0, 1)]
+		public float mix = 1;
+
+		public Rigidbody2D RootRigidbody {
+			get { return this.rootRigidbody; }
 		}
-	}
-
-	public Vector3 RootOffset {
-		get {
-			return this.rootOffset;
-		}
-	}
-
-	public Vector3 EstimatedSkeletonPosition {
-		get {
-			return this.rootRigidbody.position - rootOffset;
-		}
-	}
 
-	public bool IsActive {
-		get {
-			return this.isActive;
+		public Vector3 RootOffset {
+			get { return this.rootOffset; }
 		}
-	}
 
-	private Rigidbody2D rootRigidbody;
-	private ISkeletonAnimation skeletonAnim;
-	private Skeleton skeleton;
-	private Dictionary<Bone, Transform> boneTable = new Dictionary<Bone, Transform>();
-	private Bone startingBone;
-	private Transform ragdollRoot;
-	private Vector2 rootOffset;
-	private bool isActive;
-
-
-	IEnumerator Start () {
-		skeletonAnim = (ISkeletonAnimation)GetComponent<SkeletonRenderer>();
-		if (helper == null) {
-			helper = (Transform)(new GameObject("Helper")).transform;
-			helper.hideFlags = HideFlags.HideInHierarchy;
+		public Vector3 EstimatedSkeletonPosition {
+			get { return this.rootRigidbody.position - rootOffset; }
 		}
 
-		if (applyOnStart) {
-			yield return null;
-			Apply();
+		public bool IsActive {
+			get { return this.isActive; }
 		}
-	}
 
-	public Coroutine SmoothMix (float target, float duration) {
-		return StartCoroutine(SmoothMixCoroutine(target, duration));
-	}
+		private Rigidbody2D rootRigidbody;
+		private ISkeletonAnimation skeletonAnim;
+		private Skeleton skeleton;
+		private Dictionary<Bone, Transform> boneTable = new Dictionary<Bone, Transform>();
+		private Bone startingBone;
+		private Transform ragdollRoot;
+		private Vector2 rootOffset;
+		private bool isActive;
+
+
+		IEnumerator Start () {
+			skeletonAnim = (ISkeletonAnimation)GetComponent<SkeletonRenderer>();
+			if (helper == null) {
+				helper = (Transform)(new GameObject("Helper")).transform;
+				helper.hideFlags = HideFlags.HideInHierarchy;
+			}
 
-	IEnumerator SmoothMixCoroutine (float target, float duration) {
-		float startTime = Time.time;
-		float startMix = mix;
-		while (mix > 0) {
-			mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
-			yield return null;
+			if (applyOnStart) {
+				yield return null;
+				Apply();
+			}
 		}
-	}
 
-	public void SetSkeletonPosition (Vector3 worldPosition) {
-		if (!isActive) {
-			Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
-			return;
+		public Coroutine SmoothMix (float target, float duration) {
+			return StartCoroutine(SmoothMixCoroutine(target, duration));
 		}
 
-		Vector3 offset = worldPosition - transform.position;
-		transform.position = worldPosition;
-		foreach (Transform t in boneTable.Values) {
-			t.position -= offset;
+		IEnumerator SmoothMixCoroutine (float target, float duration) {
+			float startTime = Time.time;
+			float startMix = mix;
+			while (mix > 0) {
+				mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
+				yield return null;
+			}
 		}
 
-		UpdateWorld(null);
-		skeleton.UpdateWorldTransform();
-	}
+		public void SetSkeletonPosition (Vector3 worldPosition) {
+			if (!isActive) {
+				Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
+				return;
+			}
 
-	public Rigidbody2D[] GetRigidbodyArray () {
-		if (!isActive)
-			return new Rigidbody2D[0];
+			Vector3 offset = worldPosition - transform.position;
+			transform.position = worldPosition;
+			foreach (Transform t in boneTable.Values) {
+				t.position -= offset;
+			}
 
-		Rigidbody2D[] arr = new Rigidbody2D[boneTable.Count];
-		int i = 0;
-		foreach (Transform t in boneTable.Values) {
-			arr[i] = t.GetComponent<Rigidbody2D>();
-			i++;
+			UpdateWorld(null);
+			skeleton.UpdateWorldTransform();
 		}
 
-		return arr;
-	}
+		public Rigidbody2D[] GetRigidbodyArray () {
+			if (!isActive)
+				return new Rigidbody2D[0];
 
-	public Rigidbody2D GetRigidbody (string boneName) {
-		var bone = skeleton.FindBone(boneName);
-		if (bone == null)
-			return null;
+			Rigidbody2D[] arr = new Rigidbody2D[boneTable.Count];
+			int i = 0;
+			foreach (Transform t in boneTable.Values) {
+				arr[i] = t.GetComponent<Rigidbody2D>();
+				i++;
+			}
 
-		if (boneTable.ContainsKey(bone))
-			return boneTable[bone].GetComponent<Rigidbody2D>();
+			return arr;
+		}
 
-		return null;
-	}
+		public Rigidbody2D GetRigidbody (string boneName) {
+			var bone = skeleton.FindBone(boneName);
+			if (bone == null)
+				return null;
 
-	public void Remove () {
-		isActive = false;
-		foreach (var t in boneTable.Values) {
-			Destroy(t.gameObject);
+			if (boneTable.ContainsKey(bone))
+				return boneTable[bone].GetComponent<Rigidbody2D>();
+
+			return null;
 		}
-		Destroy(ragdollRoot.gameObject);
 
-		boneTable.Clear();
-		skeletonAnim.UpdateWorld -= UpdateWorld;
-	}
+		public void Remove () {
+			isActive = false;
+			foreach (var t in boneTable.Values) {
+				Destroy(t.gameObject);
+			}
+			Destroy(ragdollRoot.gameObject);
 
-	public void Apply () {
-		isActive = true;
-		skeleton = skeletonAnim.Skeleton;
-		mix = 1;
+			boneTable.Clear();
+			skeletonAnim.UpdateWorld -= UpdateWorld;
+		}
 
-		var ragdollRootBone = skeleton.FindBone(startingBoneName);
-		startingBone = ragdollRootBone;
-		RecursivelyCreateBoneProxies(ragdollRootBone);
+		public void Apply () {
+			isActive = true;
+			skeleton = skeletonAnim.Skeleton;
+			mix = 1;
 
-		rootRigidbody = boneTable[ragdollRootBone].GetComponent<Rigidbody2D>();
-		rootRigidbody.isKinematic = pinStartBone;
-		rootRigidbody.mass = rootMass;
+			var ragdollRootBone = skeleton.FindBone(startingBoneName);
+			startingBone = ragdollRootBone;
+			RecursivelyCreateBoneProxies(ragdollRootBone);
 
-		List<Collider2D> boneColliders = new List<Collider2D>();
+			rootRigidbody = boneTable[ragdollRootBone].GetComponent<Rigidbody2D>();
+			rootRigidbody.isKinematic = pinStartBone;
+			rootRigidbody.mass = rootMass;
 
-		foreach (var pair in boneTable) {
-			var b = pair.Key;
-			var t = pair.Value;
-			Bone parentBone = null;
-			Transform parentTransform = transform;
+			List<Collider2D> boneColliders = new List<Collider2D>();
 
-			boneColliders.Add(t.GetComponent<Collider2D>());
+			foreach (var pair in boneTable) {
+				var b = pair.Key;
+				var t = pair.Value;
+				Bone parentBone = null;
+				Transform parentTransform = transform;
 
-			if (b != startingBone) {
-				parentBone = b.Parent;
-				parentTransform = boneTable[parentBone];
-			} else {
-				ragdollRoot = new GameObject("RagdollRoot").transform;
-				ragdollRoot.parent = transform;
+				boneColliders.Add(t.GetComponent<Collider2D>());
 
-				if (b == skeleton.RootBone) {
-					ragdollRoot.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
-					ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b));
-					parentTransform = ragdollRoot;
+				if (b != startingBone) {
+					parentBone = b.Parent;
+					parentTransform = boneTable[parentBone];
 				} else {
-					ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
-					ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b.Parent));
-					parentTransform = ragdollRoot;
+					ragdollRoot = new GameObject("RagdollRoot").transform;
+					ragdollRoot.parent = transform;
+
+					if (b == skeleton.RootBone) {
+						ragdollRoot.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
+						ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b));
+						parentTransform = ragdollRoot;
+					} else {
+						ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
+						ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b.Parent));
+						parentTransform = ragdollRoot;
+					}
+
+					rootOffset = t.position - transform.position;
 				}
 
-				rootOffset = t.position - transform.position;
+				var rbParent = parentTransform.GetComponent<Rigidbody2D>();
+
+				if (rbParent != null) {
+					var joint = t.gameObject.AddComponent<HingeJoint2D>();
+					joint.connectedBody = rbParent;
+					Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
+					localPos.x *= 1;
+					joint.connectedAnchor = localPos;
+					joint.GetComponent<Rigidbody2D>().mass = joint.connectedBody.mass * massFalloffFactor;
+					JointAngleLimits2D limits = new JointAngleLimits2D();
+					limits.min = -rotationLimit;
+					limits.max = rotationLimit;
+					joint.limits = limits;
+					joint.useLimits = true;
+				}
 			}
 
-			var rbParent = parentTransform.GetComponent<Rigidbody2D>();
-
-			if (rbParent != null) {
-				var joint = t.gameObject.AddComponent<HingeJoint2D>();
-				joint.connectedBody = rbParent;
-				Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
-				localPos.x *= 1;
-				joint.connectedAnchor = localPos;
-				joint.GetComponent<Rigidbody2D>().mass = joint.connectedBody.mass * massFalloffFactor;
-				JointAngleLimits2D limits = new JointAngleLimits2D();
-				limits.min = -rotationLimit;
-				limits.max = rotationLimit;
-				joint.limits = limits;
-				joint.useLimits = true;
+			for (int x = 0; x < boneColliders.Count; x++) {
+				for (int y = 0; y < boneColliders.Count; y++) {
+					if (x == y) continue;
+					Physics2D.IgnoreCollision(boneColliders[x], boneColliders[y]);
+				}
 			}
-		}
 
-		for (int x = 0; x < boneColliders.Count; x++) {
-			for (int y = 0; y < boneColliders.Count; y++) {
-				if (x == y) continue;
-				Physics2D.IgnoreCollision(boneColliders[x], boneColliders[y]);
-			}
-		}
-
-		var utilityBones = GetComponentsInChildren<SkeletonUtilityBone>();
-		if (utilityBones.Length > 0) {
-			List<string> destroyedUtilityBoneNames = new List<string>();
-			foreach (var ub in utilityBones) {
-				if (ub.mode == SkeletonUtilityBone.Mode.Override) {
-					destroyedUtilityBoneNames.Add(ub.gameObject.name);
-					Destroy(ub.gameObject);
+			var utilityBones = GetComponentsInChildren<SkeletonUtilityBone>();
+			if (utilityBones.Length > 0) {
+				List<string> destroyedUtilityBoneNames = new List<string>();
+				foreach (var ub in utilityBones) {
+					if (ub.mode == SkeletonUtilityBone.Mode.Override) {
+						destroyedUtilityBoneNames.Add(ub.gameObject.name);
+						Destroy(ub.gameObject);
+					}
 				}
-			}
 
-			if (destroyedUtilityBoneNames.Count > 0) {
-				string msg = "Destroyed Utility Bones: ";
-				for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
-					msg += destroyedUtilityBoneNames[i];
-					if (i != destroyedUtilityBoneNames.Count - 1) {
-						msg += ",";
+				if (destroyedUtilityBoneNames.Count > 0) {
+					string msg = "Destroyed Utility Bones: ";
+					for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
+						msg += destroyedUtilityBoneNames[i];
+						if (i != destroyedUtilityBoneNames.Count - 1) {
+							msg += ",";
+						}
 					}
+					Debug.LogWarning(msg);
 				}
-				Debug.LogWarning(msg);
 			}
-		}
 
-		if (disableIK) {
-			foreach (IkConstraint ik in skeleton.IkConstraints) {
-				ik.Mix = 0;
+			if (disableIK) {
+				foreach (IkConstraint ik in skeleton.IkConstraints) {
+					ik.Mix = 0;
+				}
 			}
-		}
 
-		skeletonAnim.UpdateWorld += UpdateWorld;
-	}
+			skeletonAnim.UpdateWorld += UpdateWorld;
+		}
 
-	void RecursivelyCreateBoneProxies (Bone b) {
-		if (stopBoneNames.Contains(b.Data.Name))
-			return;
+		void RecursivelyCreateBoneProxies (Bone b) {
+			if (stopBoneNames.Contains(b.Data.Name))
+				return;
 
-		GameObject go = new GameObject(b.Data.Name);
-		go.layer = colliderLayer;
-		Transform t = go.transform;
-		boneTable.Add(b, t);
+			GameObject go = new GameObject(b.Data.Name);
+			go.layer = colliderLayer;
+			Transform t = go.transform;
+			boneTable.Add(b, t);
 
-		t.parent = transform;
+			t.parent = transform;
 
-		t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
-		//TODO: deal with WorldFlipY
-        // MITCH
-		// t.localRotation = Quaternion.Euler(0, 0, b.WorldFlipX ? -b.WorldRotation : b.WorldRotation);
-        t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX);
-		t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 0);
+			t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
+			//TODO: deal with WorldFlipY
+			// MITCH
+			// t.localRotation = Quaternion.Euler(0, 0, b.WorldFlipX ? -b.WorldRotation : b.WorldRotation);
+			t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX);
+			t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 0);
 
-		float length = b.Data.Length;
+			float length = b.Data.Length;
 
-		//TODO proper ragdoll branching
-		var colliders = AttachBoundingBoxRagdollColliders(b);
+			//TODO proper ragdoll branching
+			var colliders = AttachBoundingBoxRagdollColliders(b);
 
-		if (length == 0) {
-			//physics
-			if (colliders.Count == 0) {
-				var circle = go.AddComponent<CircleCollider2D>();
-				circle.radius = thickness / 2f;
-			}
-		} else {
-			//physics
-			if (colliders.Count == 0) {
-				var box = go.AddComponent<BoxCollider2D>();
-				box.size = new Vector2(length, thickness);
-#if UNITY_5
-                // MITCH
-				// box.offset = new Vector2((b.WorldFlipX ? -length : length) / 2, 0);
-                box.offset = new Vector2(length / 2, 0);
-#else
-				//box.center = new Vector2((b.WorldFlipX ? -length : length) / 2, 0);
-				box.center = new Vector2(length/2, 0);
-#endif
+			if (length == 0) {
+				//physics
+				if (colliders.Count == 0) {
+					var circle = go.AddComponent<CircleCollider2D>();
+					circle.radius = thickness / 2f;
+				}
+			} else {
+				//physics
+				if (colliders.Count == 0) {
+					var box = go.AddComponent<BoxCollider2D>();
+					box.size = new Vector2(length, thickness);
+					#if UNITY_5
+					// MITCH
+					// box.offset = new Vector2((b.WorldFlipX ? -length : length) / 2, 0);
+					box.offset = new Vector2(length / 2, 0);
+					#else
+					//box.center = new Vector2((b.WorldFlipX ? -length : length) / 2, 0);
+					box.center = new Vector2(length/2, 0);
+					#endif
+				}
 			}
-		}
 
-		var rb = go.AddComponent<Rigidbody2D>();
-		rb.gravityScale = gravityScale;
+			var rb = go.AddComponent<Rigidbody2D>();
+			rb.gravityScale = gravityScale;
 
-		foreach (Bone child in b.Children) {
-			RecursivelyCreateBoneProxies(child);
+			foreach (Bone child in b.Children) {
+				RecursivelyCreateBoneProxies(child);
+			}
 		}
-	}
 
-	List<Collider2D> AttachBoundingBoxRagdollColliders (Bone b) {
-		List<Collider2D> colliders = new List<Collider2D>();
-		Transform t = boneTable[b];
-		GameObject go = t.gameObject;
-		var skin = skeleton.Skin;
-		if (skin == null)
-			skin = skeleton.Data.DefaultSkin;
-
-        // MITCH
-		// bool flipX = b.WorldFlipX;
-		// bool flipY = b.WorldFlipY;
-        bool flipX = false;
-		bool flipY = false;
-
-		List<Attachment> attachments = new List<Attachment>();
-		foreach (Slot s in skeleton.Slots) {
-			if (s.Bone == b) {
-				skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(s), attachments);
-				foreach (var a in attachments) {
-					if (a is BoundingBoxAttachment) {
-						if (!a.Name.ToLower().Contains("ragdoll"))
-							continue;
-
-						var collider = SkeletonUtility.AddBoundingBoxAsComponent((BoundingBoxAttachment)a, go, false);
-
-						if (flipX || flipY) {
-							Vector2[] points = collider.points;
-
-							for (int i = 0; i < points.Length; i++) {
-								if (flipX)
-									points[i].x *= -1;
-
-								if (flipY)
-									points[i].y *= -1;
+		List<Collider2D> AttachBoundingBoxRagdollColliders (Bone b) {
+			List<Collider2D> colliders = new List<Collider2D>();
+			Transform t = boneTable[b];
+			GameObject go = t.gameObject;
+			var skin = skeleton.Skin;
+			if (skin == null)
+				skin = skeleton.Data.DefaultSkin;
+
+			// MITCH
+			// bool flipX = b.WorldFlipX;
+			// bool flipY = b.WorldFlipY;
+			bool flipX = false;
+			bool flipY = false;
+
+			List<Attachment> attachments = new List<Attachment>();
+			foreach (Slot s in skeleton.Slots) {
+				if (s.Bone == b) {
+					skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(s), attachments);
+					foreach (var a in attachments) {
+						if (a is BoundingBoxAttachment) {
+							if (!a.Name.ToLower().Contains("ragdoll"))
+								continue;
+
+							var collider = SkeletonUtility.AddBoundingBoxAsComponent((BoundingBoxAttachment)a, go, false);
+
+							if (flipX || flipY) {
+								Vector2[] points = collider.points;
+
+								for (int i = 0; i < points.Length; i++) {
+									if (flipX)
+										points[i].x *= -1;
+
+									if (flipY)
+										points[i].y *= -1;
+								}
+
+								collider.points = points;
 							}
 
-							collider.points = points;
+							colliders.Add(collider);
 						}
-
-						colliders.Add(collider);
 					}
 				}
 			}
-		}
 
-		return colliders;
-	}
+			return colliders;
+		}
 
-	void UpdateWorld (ISkeletonAnimation skeletonRenderer) {
-		foreach (var pair in boneTable) {
-			var b = pair.Key;
-			var t = pair.Value;
-			//bool flip = false;
-			bool flipX = false;  //TODO:  deal with negative scale instead of Flip Key
-			bool flipY = false;  //TODO:  deal with negative scale instead of Flip Key
-			Bone parentBone = null;
-			Transform parentTransform = transform;
-
-			if (b != startingBone) {
-				parentBone = b.Parent;
-				parentTransform = boneTable[parentBone];
-                // MITCH
-				// flipX = parentBone.WorldFlipX;
-				// flipY = parentBone.WorldFlipY;
+		void UpdateWorld (ISkeletonAnimation skeletonRenderer) {
+			foreach (var pair in boneTable) {
+				var b = pair.Key;
+				var t = pair.Value;
+				//bool flip = false;
+				bool flipX = false;  //TODO:  deal with negative scale instead of Flip Key
+				bool flipY = false;  //TODO:  deal with negative scale instead of Flip Key
+				Bone parentBone = null;
+				Transform parentTransform = transform;
+
+				if (b != startingBone) {
+					parentBone = b.Parent;
+					parentTransform = boneTable[parentBone];
+					// MITCH
+					// flipX = parentBone.WorldFlipX;
+					// flipY = parentBone.WorldFlipY;
 
-			} else {
-				parentBone = b.Parent;
-				parentTransform = ragdollRoot;
-				if (b.Parent != null) {
-                    // MITCH
-					// flipX = b.worldFlipX;
-					// flipY = b.WorldFlipY;
 				} else {
-					flipX = b.Skeleton.FlipX;
-					flipY = b.Skeleton.FlipY;
+					parentBone = b.Parent;
+					parentTransform = ragdollRoot;
+					if (b.Parent != null) {
+						// MITCH
+						// flipX = b.worldFlipX;
+						// flipY = b.WorldFlipY;
+					} else {
+						flipX = b.Skeleton.FlipX;
+						flipY = b.Skeleton.FlipY;
+					}
 				}
-			}
-
-			//flip = flipX ^ flipY;
 
-			helper.position = parentTransform.position;
-			helper.rotation = parentTransform.rotation;
-			helper.localScale = new Vector3(flipX ? -parentTransform.localScale.x : parentTransform.localScale.x, flipY ? -parentTransform.localScale.y : parentTransform.localScale.y, 1);
+				//flip = flipX ^ flipY;
 
+				helper.position = parentTransform.position;
+				helper.rotation = parentTransform.rotation;
+				helper.localScale = new Vector3(flipX ? -parentTransform.localScale.x : parentTransform.localScale.x, flipY ? -parentTransform.localScale.y : parentTransform.localScale.y, 1);
 
-			Vector3 pos = t.position;
-			pos = helper.InverseTransformPoint(pos);
-			b.X = Mathf.Lerp(b.X, pos.x, mix);
-			b.Y = Mathf.Lerp(b.Y, pos.y, mix);
 
-			Vector3 right = helper.InverseTransformDirection(t.right);
+				Vector3 pos = t.position;
+				pos = helper.InverseTransformPoint(pos);
+				b.X = Mathf.Lerp(b.X, pos.x, mix);
+				b.Y = Mathf.Lerp(b.Y, pos.y, mix);
 
-			float a = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
+				Vector3 right = helper.InverseTransformDirection(t.right);
 
-            // MITCH
-			//if (b.WorldFlipX ^ b.WorldFlipY) {
-			//	a *= -1;
-			//}
+				float a = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
 
-			if (parentBone != null) {
-                // MITCH
-				//if ((b.WorldFlipX ^ b.WorldFlipY) != flip) {
-				//	a -= GetCompensatedRotationIK(parentBone) * 2;
+				// MITCH
+				//if (b.WorldFlipX ^ b.WorldFlipY) {
+				//	a *= -1;
 				//}
-			}
 
-			b.Rotation = Mathf.Lerp(b.Rotation, a, mix);
-            // MITCH
-			// b.RotationIK = Mathf.Lerp(b.rotationIK, a, mix);
-		}
-	}
+				if (parentBone != null) {
+					// MITCH
+					//if ((b.WorldFlipX ^ b.WorldFlipY) != flip) {
+					//	a -= GetCompensatedRotationIK(parentBone) * 2;
+					//}
+				}
 
-	float GetCompensatedRotationIK (Bone b) {
-		Bone parent = b.Parent;
-        // MITCH
-		float a = b.AppliedRotation;
-		while (parent != null) {
-			a += parent.AppliedRotation;
-			parent = parent.parent;
+				b.Rotation = Mathf.Lerp(b.Rotation, a, mix);
+				// MITCH
+				// b.RotationIK = Mathf.Lerp(b.rotationIK, a, mix);
+			}
 		}
 
-		return a;
-	}
+		float GetCompensatedRotationIK (Bone b) {
+			Bone parent = b.Parent;
+			// MITCH
+			float a = b.AppliedRotation;
+			while (parent != null) {
+				a += parent.AppliedRotation;
+				parent = parent.parent;
+			}
 
-	void OnDrawGizmosSelected () {
-		if (isActive) {
-			Gizmos.DrawWireSphere(transform.position, thickness * 1.2f);
-			Vector3 newTransformPos = rootRigidbody.position - rootOffset;
-			Gizmos.DrawLine(transform.position, newTransformPos);
-			Gizmos.DrawWireSphere(newTransformPos, thickness * 1.2f);
+			return a;
 		}
+
+		void OnDrawGizmosSelected () {
+			if (isActive) {
+				Gizmos.DrawWireSphere(transform.position, thickness * 1.2f);
+				Vector3 newTransformPos = rootRigidbody.position - rootOffset;
+				Gizmos.DrawLine(transform.position, newTransformPos);
+				Gizmos.DrawWireSphere(newTransformPos, thickness * 1.2f);
+			}
+		}
+
 	}
 
 }

+ 33 - 5
spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs

@@ -1,9 +1,38 @@
-using UnityEngine;
-using System.Collections;
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ * 
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ * 
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+using UnityEngine;
 using UnityEditor;
-using Spine.Unity;
+using Spine.Unity.Editor;
 
-namespace Spine.Unity.Editor {
+namespace Spine.Unity.Modules {
 	[CustomEditor(typeof(SkeletonPartsRenderer))]
 	public class SkeletonRenderPartInspector : UnityEditor.Editor {
 		SpineInspectorUtility.SerializedSortingProperties sortingProperties;
@@ -13,7 +42,6 @@ namespace Spine.Unity.Editor {
 		}
 
 		public override void OnInspectorGUI () {
-			DrawDefaultInspector();
 			SpineInspectorUtility.SortingPropertyFields(sortingProperties, true);
 		}
 	}

+ 33 - 2
spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs

@@ -1,9 +1,40 @@
-using UnityEngine;
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ * 
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ * 
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+using UnityEngine;
 using UnityEditor;
 
 using Spine.Unity;
+using Spine.Unity.Editor;
 
-namespace Spine.Unity.Editor {
+namespace Spine.Unity.Modules {
 	
 	[CustomEditor(typeof(SkeletonRenderSeparator))]
 	public class SkeletonRenderSeparatorInspector : UnityEditor.Editor {

+ 32 - 3
spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonPartsRenderer.cs

@@ -1,8 +1,37 @@
-using UnityEngine;
-using System.Collections;
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ * 
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ * 
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+using UnityEngine;
 using Spine.Unity.MeshGeneration;
 
-namespace Spine.Unity {
+namespace Spine.Unity.Modules {
 	[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
 	public class SkeletonPartsRenderer : MonoBehaviour {
 

+ 33 - 4
spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs

@@ -1,9 +1,38 @@
-using UnityEngine;
-using System.Collections;
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ * 
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ * 
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+using UnityEngine;
 using System.Collections.Generic;
 using Spine.Unity;
 
-namespace Spine.Unity {
+namespace Spine.Unity.Modules {
 	
 	[ExecuteInEditMode]
 	[HelpURL("https://github.com/pharan/spine-unity-docs/blob/master/SkeletonRenderSeparator.md")]
@@ -28,7 +57,7 @@ namespace Spine.Unity {
 		public bool copyPropertyBlock = false;
 		[Tooltip("Copies MeshRenderer flags into ")]
 		public bool copyMeshRendererFlags = false;
-		public List<Spine.Unity.SkeletonPartsRenderer> partsRenderers = new List<SkeletonPartsRenderer>();
+		public List<Spine.Unity.Modules.SkeletonPartsRenderer> partsRenderers = new List<SkeletonPartsRenderer>();
 
 		#if UNITY_EDITOR
 		void Reset () {

+ 41 - 40
spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityEyeConstraint.cs

@@ -32,56 +32,57 @@
 using UnityEngine;
 using System.Collections;
 
-public class SkeletonUtilityEyeConstraint : SkeletonUtilityConstraint {
-
-	public Transform[] eyes;
-	public float radius = 0.5f;
-	public Transform target;
-	public Vector3 targetPosition;
-	public float speed = 10;
-	Vector3[] origins;
-	Vector3 centerPoint;
-
-	protected override void OnEnable () {
-		if (!Application.isPlaying)
-			return;
-
-		base.OnEnable();
-
-		Bounds centerBounds = new Bounds(eyes[0].localPosition, Vector3.zero);
-		origins = new Vector3[eyes.Length];
-		for (int i = 0; i < eyes.Length; i++) {
-			origins[i] = eyes[i].localPosition;
-			centerBounds.Encapsulate(origins[i]);
+namespace Spine.Unity.Modules {
+	public class SkeletonUtilityEyeConstraint : SkeletonUtilityConstraint {
+		public Transform[] eyes;
+		public float radius = 0.5f;
+		public Transform target;
+		public Vector3 targetPosition;
+		public float speed = 10;
+		Vector3[] origins;
+		Vector3 centerPoint;
+
+		protected override void OnEnable () {
+			if (!Application.isPlaying)
+				return;
+
+			base.OnEnable();
+
+			Bounds centerBounds = new Bounds(eyes[0].localPosition, Vector3.zero);
+			origins = new Vector3[eyes.Length];
+			for (int i = 0; i < eyes.Length; i++) {
+				origins[i] = eyes[i].localPosition;
+				centerBounds.Encapsulate(origins[i]);
+			}
+
+			centerPoint = centerBounds.center;
 		}
 
-		centerPoint = centerBounds.center;
-	}
+		protected override void OnDisable () {
+			if (!Application.isPlaying)
+				return;
 
-	protected override void OnDisable () {
-		if (!Application.isPlaying)
-			return;
+			base.OnDisable();
+		}
 
-		base.OnDisable();
-	}
+		public override void DoUpdate () {
 
-	public override void DoUpdate () {
+			if (target != null)
+				targetPosition = target.position;
 
-		if (target != null)
-			targetPosition = target.position;
+			Vector3 goal = targetPosition;
 
-		Vector3 goal = targetPosition;
+			Vector3 center = transform.TransformPoint(centerPoint);
+			Vector3 dir = goal - center;
 
-		Vector3 center = transform.TransformPoint(centerPoint);
-		Vector3 dir = goal - center;
+			if (dir.magnitude > 1)
+				dir.Normalize();
 
-		if (dir.magnitude > 1)
-			dir.Normalize();
+			for (int i = 0; i < eyes.Length; i++) {
+				center = transform.TransformPoint(origins[i]);
+				eyes[i].position = Vector3.MoveTowards(eyes[i].position, center + (dir * radius), speed * Time.deltaTime);
+			}
 
-		for (int i = 0; i < eyes.Length; i++) {
-			center = transform.TransformPoint(origins[i]);
-			eyes[i].position = Vector3.MoveTowards(eyes[i].position, center + (dir * radius), speed * Time.deltaTime);
 		}
-
 	}
 }

+ 104 - 101
spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityGroundConstraint.cs

@@ -32,121 +32,124 @@
 using UnityEngine;
 using System.Collections;
 
-[RequireComponent(typeof(SkeletonUtilityBone)), ExecuteInEditMode]
-public class SkeletonUtilityGroundConstraint : SkeletonUtilityConstraint {
-
-#if UNITY_4_3
-	public LayerMask groundMask;
-	public bool use2D = false;
-	public bool useRadius = false;
-	public float castRadius = 0.1f;
-	public float castDistance = 5f;
-	public float castOffset = 0;
-	public float groundOffset = 0;
-	public float adjustSpeed = 5;
-#else
-	[Tooltip("LayerMask for what objects to raycast against")]
-	public LayerMask groundMask;
-	[Tooltip("The 2D")]
-	public bool use2D = false;
-	[Tooltip("Uses SphereCast for 3D mode and CircleCast for 2D mode")]
-	public bool useRadius = false;
-	[Tooltip("The Radius")]
-	public float castRadius = 0.1f;
-	[Tooltip("How high above the target bone to begin casting from")]
-	public float castDistance = 5f;
-	[Tooltip("X-Axis adjustment")]
-	public float castOffset = 0;
-	[Tooltip("Y-Axis adjustment")]
-	public float groundOffset = 0;
-	[Tooltip("How fast the target IK position adjusts to the ground.  Use smaller values to prevent snapping")]
-	public float adjustSpeed = 5;
-#endif
-
-
-	Vector3 rayOrigin;
-	Vector3 rayDir = new Vector3(0, -1, 0);
-	float hitY;
-	float lastHitY;
-
-	protected override void OnEnable () {
-		base.OnEnable();
-		lastHitY = transform.position.y;
-	}
-
-	protected override void OnDisable () {
-		base.OnDisable();
-	}
-
-	public override void DoUpdate () {
-		rayOrigin = transform.position + new Vector3(castOffset, castDistance, 0);
+namespace Spine.Unity.Modules {
+	[RequireComponent(typeof(SkeletonUtilityBone)), ExecuteInEditMode]
+	public class SkeletonUtilityGroundConstraint : SkeletonUtilityConstraint {
+
+		#if UNITY_4_3
+		public LayerMask groundMask;
+		public bool use2D = false;
+		public bool useRadius = false;
+		public float castRadius = 0.1f;
+		public float castDistance = 5f;
+		public float castOffset = 0;
+		public float groundOffset = 0;
+		public float adjustSpeed = 5;
+		#else
+		[Tooltip("LayerMask for what objects to raycast against")]
+		public LayerMask groundMask;
+		[Tooltip("The 2D")]
+		public bool use2D = false;
+		[Tooltip("Uses SphereCast for 3D mode and CircleCast for 2D mode")]
+		public bool useRadius = false;
+		[Tooltip("The Radius")]
+		public float castRadius = 0.1f;
+		[Tooltip("How high above the target bone to begin casting from")]
+		public float castDistance = 5f;
+		[Tooltip("X-Axis adjustment")]
+		public float castOffset = 0;
+		[Tooltip("Y-Axis adjustment")]
+		public float groundOffset = 0;
+		[Tooltip("How fast the target IK position adjusts to the ground.  Use smaller values to prevent snapping")]
+		public float adjustSpeed = 5;
+		#endif
+
+
+		Vector3 rayOrigin;
+		Vector3 rayDir = new Vector3(0, -1, 0);
+		float hitY;
+		float lastHitY;
+
+		protected override void OnEnable () {
+			base.OnEnable();
+			lastHitY = transform.position.y;
+		}
 
-		hitY = float.MinValue;
-		if (use2D) {
-			RaycastHit2D hit;
+		protected override void OnDisable () {
+			base.OnDisable();
+		}
 
-			if (useRadius) {
-#if UNITY_4_3
-				//NOTE:  Unity 4.3.x does not have CircleCast
-				hit = Physics2D.Raycast(rayOrigin , rayDir, castDistance + groundOffset, groundMask);
-#else
-				hit = Physics2D.CircleCast(rayOrigin, castRadius, rayDir, castDistance + groundOffset, groundMask);
-#endif
-			} else {
-				hit = Physics2D.Raycast(rayOrigin, rayDir, castDistance + groundOffset, groundMask);
-			}
+		public override void DoUpdate () {
+			rayOrigin = transform.position + new Vector3(castOffset, castDistance, 0);
+
+			hitY = float.MinValue;
+			if (use2D) {
+				RaycastHit2D hit;
+
+				if (useRadius) {
+					#if UNITY_4_3
+					//NOTE:  Unity 4.3.x does not have CircleCast
+					hit = Physics2D.Raycast(rayOrigin , rayDir, castDistance + groundOffset, groundMask);
+					#else
+					hit = Physics2D.CircleCast(rayOrigin, castRadius, rayDir, castDistance + groundOffset, groundMask);
+					#endif
+				} else {
+					hit = Physics2D.Raycast(rayOrigin, rayDir, castDistance + groundOffset, groundMask);
+				}
 
-			if (hit.collider != null) {
-				hitY = hit.point.y + groundOffset;
-				if (Application.isPlaying) {
-					hitY = Mathf.MoveTowards(lastHitY, hitY, adjustSpeed * Time.deltaTime);
+				if (hit.collider != null) {
+					hitY = hit.point.y + groundOffset;
+					if (Application.isPlaying) {
+						hitY = Mathf.MoveTowards(lastHitY, hitY, adjustSpeed * Time.deltaTime);
+					}
+				} else {
+					if (Application.isPlaying)
+						hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustSpeed * Time.deltaTime);
 				}
 			} else {
-				if (Application.isPlaying)
-					hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustSpeed * Time.deltaTime);
-			}
-		} else {
-			RaycastHit hit;
-			bool validHit = false;
+				RaycastHit hit;
+				bool validHit = false;
 
-			if (useRadius) {
-				validHit = Physics.SphereCast(rayOrigin, castRadius, rayDir, out hit, castDistance + groundOffset, groundMask);
-			} else {
-				validHit = Physics.Raycast(rayOrigin, rayDir, out hit, castDistance + groundOffset, groundMask);
-			}
+				if (useRadius) {
+					validHit = Physics.SphereCast(rayOrigin, castRadius, rayDir, out hit, castDistance + groundOffset, groundMask);
+				} else {
+					validHit = Physics.Raycast(rayOrigin, rayDir, out hit, castDistance + groundOffset, groundMask);
+				}
 
-			if (validHit) {
-				hitY = hit.point.y + groundOffset;
-				if (Application.isPlaying) {
-					hitY = Mathf.MoveTowards(lastHitY, hitY, adjustSpeed * Time.deltaTime);
+				if (validHit) {
+					hitY = hit.point.y + groundOffset;
+					if (Application.isPlaying) {
+						hitY = Mathf.MoveTowards(lastHitY, hitY, adjustSpeed * Time.deltaTime);
+					}
+				} else {
+					if (Application.isPlaying)
+						hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustSpeed * Time.deltaTime);
 				}
-			} else {
-				if (Application.isPlaying)
-					hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustSpeed * Time.deltaTime);
 			}
-		}
 
-		Vector3 v = transform.position;
-		v.y = Mathf.Clamp(v.y, Mathf.Min(lastHitY, hitY), float.MaxValue);
-		transform.position = v;
+			Vector3 v = transform.position;
+			v.y = Mathf.Clamp(v.y, Mathf.Min(lastHitY, hitY), float.MaxValue);
+			transform.position = v;
 
-		utilBone.bone.X = transform.localPosition.x;
-		utilBone.bone.Y = transform.localPosition.y;
+			utilBone.bone.X = transform.localPosition.x;
+			utilBone.bone.Y = transform.localPosition.y;
 
-		lastHitY = hitY;
-	}
+			lastHitY = hitY;
+		}
 
-	void OnDrawGizmos () {
-		Vector3 hitEnd = rayOrigin + (rayDir * Mathf.Min(castDistance, rayOrigin.y - hitY));
-		Vector3 clearEnd = rayOrigin + (rayDir * castDistance);
-		Gizmos.DrawLine(rayOrigin, hitEnd);
+		void OnDrawGizmos () {
+			Vector3 hitEnd = rayOrigin + (rayDir * Mathf.Min(castDistance, rayOrigin.y - hitY));
+			Vector3 clearEnd = rayOrigin + (rayDir * castDistance);
+			Gizmos.DrawLine(rayOrigin, hitEnd);
 
-		if (useRadius) {
-			Gizmos.DrawLine(new Vector3(hitEnd.x - castRadius, hitEnd.y - groundOffset, hitEnd.z), new Vector3(hitEnd.x + castRadius, hitEnd.y - groundOffset, hitEnd.z));
-			Gizmos.DrawLine(new Vector3(clearEnd.x - castRadius, clearEnd.y, clearEnd.z), new Vector3(clearEnd.x + castRadius, clearEnd.y, clearEnd.z));
-		}
+			if (useRadius) {
+				Gizmos.DrawLine(new Vector3(hitEnd.x - castRadius, hitEnd.y - groundOffset, hitEnd.z), new Vector3(hitEnd.x + castRadius, hitEnd.y - groundOffset, hitEnd.z));
+				Gizmos.DrawLine(new Vector3(clearEnd.x - castRadius, clearEnd.y, clearEnd.z), new Vector3(clearEnd.x + castRadius, clearEnd.y, clearEnd.z));
+			}
 
-		Gizmos.color = Color.red;
-		Gizmos.DrawLine(hitEnd, clearEnd);
+			Gizmos.color = Color.red;
+			Gizmos.DrawLine(hitEnd, clearEnd);
+		}
 	}
+
 }

+ 58 - 57
spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityKinematicShadow.cs

@@ -30,85 +30,86 @@
  *****************************************************************************/
 
 using UnityEngine;
-using System.Collections;
 using System.Collections.Generic;
 
-public class SkeletonUtilityKinematicShadow : MonoBehaviour {
-	public bool hideShadow = true;
-	public Transform parent;
-	Dictionary<Transform, Transform> shadowTable;
-	GameObject shadowRoot;
+namespace Spine.Unity.Modules {
+	public class SkeletonUtilityKinematicShadow : MonoBehaviour {
+		public bool hideShadow = true;
+		public Transform parent;
+		Dictionary<Transform, Transform> shadowTable;
+		GameObject shadowRoot;
 
-	void Start () {
-		shadowRoot = (GameObject)Instantiate(gameObject);
-		if (hideShadow)
-			shadowRoot.hideFlags = HideFlags.HideInHierarchy;
+		void Start () {
+			shadowRoot = (GameObject)Instantiate(gameObject);
+			if (hideShadow)
+				shadowRoot.hideFlags = HideFlags.HideInHierarchy;
 
-		if (parent == null)
-			shadowRoot.transform.parent = transform.root;
-		else
-			shadowRoot.transform.parent = parent;
+			if (parent == null)
+				shadowRoot.transform.parent = transform.root;
+			else
+				shadowRoot.transform.parent = parent;
 
-		shadowTable = new Dictionary<Transform, Transform>();
+			shadowTable = new Dictionary<Transform, Transform>();
 
-		Destroy(shadowRoot.GetComponent<SkeletonUtilityKinematicShadow>());
+			Destroy(shadowRoot.GetComponent<SkeletonUtilityKinematicShadow>());
 
-		shadowRoot.transform.position = transform.position;
-		shadowRoot.transform.rotation = transform.rotation;
+			shadowRoot.transform.position = transform.position;
+			shadowRoot.transform.rotation = transform.rotation;
 
-		Vector3 scaleRef = transform.TransformPoint(Vector3.right);
-		float scale = Vector3.Distance(transform.position, scaleRef);
-		shadowRoot.transform.localScale = Vector3.one;
+			Vector3 scaleRef = transform.TransformPoint(Vector3.right);
+			float scale = Vector3.Distance(transform.position, scaleRef);
+			shadowRoot.transform.localScale = Vector3.one;
 
-		var shadowJoints = shadowRoot.GetComponentsInChildren<Joint>();
-		foreach (Joint j in shadowJoints) {
-			j.connectedAnchor *= scale;
-		}
-
-		var joints = GetComponentsInChildren<Joint>();
-		foreach (var j in joints)
-			Destroy(j);
+			var shadowJoints = shadowRoot.GetComponentsInChildren<Joint>();
+			foreach (Joint j in shadowJoints) {
+				j.connectedAnchor *= scale;
+			}
 
-		var rbs = GetComponentsInChildren<Rigidbody>();
-		foreach (var rb in rbs)
-			Destroy(rb);
+			var joints = GetComponentsInChildren<Joint>();
+			foreach (var j in joints)
+				Destroy(j);
 
-		var colliders = GetComponentsInChildren<Collider>();
-		foreach (var c in colliders)
-			Destroy(c);
+			var rbs = GetComponentsInChildren<Rigidbody>();
+			foreach (var rb in rbs)
+				Destroy(rb);
 
+			var colliders = GetComponentsInChildren<Collider>();
+			foreach (var c in colliders)
+				Destroy(c);
 
-		//match by bone name
-		var shadowBones = shadowRoot.GetComponentsInChildren<SkeletonUtilityBone>();
-		var bones = GetComponentsInChildren<SkeletonUtilityBone>();
 
-		//build bone lookup
-		foreach (var b in bones) {
-			if (b.gameObject == gameObject)
-				continue;
+			//match by bone name
+			var shadowBones = shadowRoot.GetComponentsInChildren<SkeletonUtilityBone>();
+			var bones = GetComponentsInChildren<SkeletonUtilityBone>();
 
-			foreach (var sb in shadowBones) {
-				if (sb.GetComponent<Rigidbody>() == null)
+			//build bone lookup
+			foreach (var b in bones) {
+				if (b.gameObject == gameObject)
 					continue;
 
-				if (sb.boneName == b.boneName) {
-					shadowTable.Add(sb.transform, b.transform);
-					break;
+				foreach (var sb in shadowBones) {
+					if (sb.GetComponent<Rigidbody>() == null)
+						continue;
+
+					if (sb.boneName == b.boneName) {
+						shadowTable.Add(sb.transform, b.transform);
+						break;
+					}
 				}
 			}
-		}
 
-		foreach (var b in shadowBones)
-			Destroy(b);
-	}
+			foreach (var b in shadowBones)
+				Destroy(b);
+		}
 
-	void FixedUpdate () {
-		shadowRoot.GetComponent<Rigidbody>().MovePosition(transform.position);
-		shadowRoot.GetComponent<Rigidbody>().MoveRotation(transform.rotation);
+		void FixedUpdate () {
+			shadowRoot.GetComponent<Rigidbody>().MovePosition(transform.position);
+			shadowRoot.GetComponent<Rigidbody>().MoveRotation(transform.rotation);
 
-		foreach (var pair in shadowTable) {
-			pair.Value.localPosition = pair.Key.localPosition;
-			pair.Value.localRotation = pair.Key.localRotation;
+			foreach (var pair in shadowTable) {
+				pair.Value.localPosition = pair.Key.localPosition;
+				pair.Value.localRotation = pair.Key.localRotation;
+			}
 		}
 	}
 }

+ 159 - 131
spine-unity/Assets/spine-unity/Modules/SpriteAttacher.cs

@@ -30,170 +30,198 @@
  *****************************************************************************/
 
 using UnityEngine;
-using System.Collections;
 using System.Collections.Generic;
 using Spine;
 
-public class SpriteAttacher : MonoBehaviour {
+namespace Spine.Unity.Modules {
+	public class SpriteAttacher : MonoBehaviour {
+		public bool attachOnStart = true;
+		public bool keepLoaderInMemory = true;
 
+		public Sprite sprite;
 
-	public bool attachOnStart = true;
-	public bool keepLoaderInMemory = true;
+		[SpineSlot]
+		public string slot;
 
-	public Sprite sprite;
+		private SpriteAttachmentLoader loader;
+		private RegionAttachment attachment;
 
-	[SpineSlot]
-	public string slot;
-
-	private SpriteAttachmentLoader loader;
-	private RegionAttachment attachment;
-
-	void Start () {
-		if (attachOnStart)
-			Attach();
-	}
+		void Start () {
+			if (attachOnStart)
+				Attach();
+		}
 
-	public void Attach () {
-		var skeletonRenderer = GetComponent<SkeletonRenderer>();
+		public void Attach () {
+			var skeletonRenderer = GetComponent<SkeletonRenderer>();
 
-		if (loader == null)
-			//create loader instance, tell it what sprite and shader to use
-			loader = new SpriteAttachmentLoader(sprite, Shader.Find("Spine/Skeleton"));
+			if (loader == null)
+				//create loader instance, tell it what sprite and shader to use
+				loader = new SpriteAttachmentLoader(sprite, Shader.Find("Spine/Skeleton"));
 
-		if (attachment == null)
-			attachment = loader.NewRegionAttachment(null, sprite.name, "");
+			if (attachment == null)
+				attachment = loader.NewRegionAttachment(null, sprite.name, "");
 
-		skeletonRenderer.skeleton.FindSlot(slot).Attachment = attachment;
+			skeletonRenderer.skeleton.FindSlot(slot).Attachment = attachment;
 
-		if (!keepLoaderInMemory)
-			loader = null;
+			if (!keepLoaderInMemory)
+				loader = null;
+		}
 	}
-}
 
-public class SpriteAttachmentLoader : AttachmentLoader {
+	public class SpriteAttachmentLoader : AttachmentLoader {
 
-	//TODO:  Memory cleanup functions
+		//TODO:  Memory cleanup functions
 
-	//IMPORTANT:  Make sure you clear this when you don't need it anymore. Goodluck.
-	public static Dictionary<int, AtlasRegion> atlasTable = new Dictionary<int, AtlasRegion>();
+		//IMPORTANT:  Make sure you clear this when you don't need it anymore. Goodluck.
+		public static Dictionary<int, AtlasRegion> atlasTable = new Dictionary<int, AtlasRegion>();
 
-	//Shouldn't need to clear this, should just prevent redoing premultiply alpha pass on packed atlases
-	public static List<int> premultipliedAtlasIds = new List<int>();
+		//Shouldn't need to clear this, should just prevent redoing premultiply alpha pass on packed atlases
+		public static List<int> premultipliedAtlasIds = new List<int>();
 
-	Sprite sprite;
-	Shader shader;
+		Sprite sprite;
+		Shader shader;
 
-	public SpriteAttachmentLoader (Sprite sprite, Shader shader) {
+		public SpriteAttachmentLoader (Sprite sprite, Shader shader) {
 
-		if (sprite.packed && sprite.packingMode == SpritePackingMode.Tight) {
-			Debug.LogError("Tight Packer Policy not supported yet!");
-			return;
-		}
+			if (sprite.packed && sprite.packingMode == SpritePackingMode.Tight) {
+				Debug.LogError("Tight Packer Policy not supported yet!");
+				return;
+			}
 
-		this.sprite = sprite;
-		this.shader = shader;
-
-		Texture2D tex = sprite.texture;
-		//premultiply texture if it hasn't been yet
-		int instanceId = tex.GetInstanceID();
-		if (!premultipliedAtlasIds.Contains(instanceId)) {
-			try {
-				var colors = tex.GetPixels();
-				Color c;
-				float a;
-				for (int i = 0; i < colors.Length; i++) {
-					c = colors[i];
-					a = c.a;
-					c.r *= a;
-					c.g *= a;
-					c.b *= a;
-					colors[i] = c;
+			this.sprite = sprite;
+			this.shader = shader;
+
+			Texture2D tex = sprite.texture;
+			//premultiply texture if it hasn't been yet
+			int instanceId = tex.GetInstanceID();
+			if (!premultipliedAtlasIds.Contains(instanceId)) {
+				try {
+					var colors = tex.GetPixels();
+					Color c;
+					float a;
+					for (int i = 0; i < colors.Length; i++) {
+						c = colors[i];
+						a = c.a;
+						c.r *= a;
+						c.g *= a;
+						c.b *= a;
+						colors[i] = c;
+					}
+
+					tex.SetPixels(colors);
+					tex.Apply();
+
+					premultipliedAtlasIds.Add(instanceId);
+				} catch {
+					//texture is not readable!  Can't pre-multiply it, you're on your own.
 				}
-
-				tex.SetPixels(colors);
-				tex.Apply();
-
-				premultipliedAtlasIds.Add(instanceId);
-			} catch {
-				//texture is not readable!  Can't pre-multiply it, you're on your own.
 			}
 		}
-	}
 
-	public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) {
-		RegionAttachment attachment = new RegionAttachment(name);
+		public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) {
+			RegionAttachment attachment = new RegionAttachment(name);
+
+			Texture2D tex = sprite.texture;
+			int instanceId = tex.GetInstanceID();
+			AtlasRegion atlasRegion;
+
+			//check cache first
+			if (atlasTable.ContainsKey(instanceId)) {
+				atlasRegion = atlasTable[instanceId];
+			} else {
+				//Setup new material
+				Material mat = new Material(shader);
+				if (sprite.packed)
+					mat.name = "Unity Packed Sprite Material";
+				else
+					mat.name = sprite.name + " Sprite Material";
+				mat.mainTexture = tex;
+
+				//create faux-region to play nice with SkeletonRenderer
+				atlasRegion = new AtlasRegion();
+				AtlasPage page = new AtlasPage();
+				page.rendererObject = mat;
+				atlasRegion.page = page;
+
+				//cache it
+				atlasTable[instanceId] = atlasRegion;
+			}
+
+			Rect texRect = sprite.textureRect;
+
+			//normalize rect to UV space of packed atlas
+			texRect.x = Mathf.InverseLerp(0, tex.width, texRect.x);
+			texRect.y = Mathf.InverseLerp(0, tex.height, texRect.y);
+			texRect.width = Mathf.InverseLerp(0, tex.width, texRect.width);
+			texRect.height = Mathf.InverseLerp(0, tex.height, texRect.height);
 
-		Texture2D tex = sprite.texture;
-		int instanceId = tex.GetInstanceID();
-		AtlasRegion atlasRegion;
+			Bounds bounds = sprite.bounds;
+			Vector3 size = bounds.size;
 
-		//check cache first
-		if (atlasTable.ContainsKey(instanceId)) {
-			atlasRegion = atlasTable[instanceId];
-		} else {
-			//Setup new material
-			Material mat = new Material(shader);
+			//TODO: make sure this rotation thing actually works
+			bool rotated = false;
 			if (sprite.packed)
-				mat.name = "Unity Packed Sprite Material";
-			else
-				mat.name = sprite.name + " Sprite Material";
-			mat.mainTexture = tex;
-
-			//create faux-region to play nice with SkeletonRenderer
-			atlasRegion = new AtlasRegion();
-			AtlasPage page = new AtlasPage();
-			page.rendererObject = mat;
-			atlasRegion.page = page;
-
-			//cache it
-			atlasTable[instanceId] = atlasRegion;
+				rotated = sprite.packingRotation == SpritePackingRotation.Any;
+
+			//do some math and assign UVs and sizes
+			attachment.SetUVs(texRect.xMin, texRect.yMax, texRect.xMax, texRect.yMin, rotated);
+			attachment.RendererObject = atlasRegion;
+			attachment.SetColor(Color.white);
+			attachment.ScaleX = 1;
+			attachment.ScaleY = 1;
+			attachment.RegionOffsetX = sprite.rect.width * (0.5f - Mathf.InverseLerp(bounds.min.x, bounds.max.x, 0)) / sprite.pixelsPerUnit;
+			attachment.RegionOffsetY = sprite.rect.height * (0.5f - Mathf.InverseLerp(bounds.min.y, bounds.max.y, 0)) / sprite.pixelsPerUnit;
+			attachment.Width = size.x;
+			attachment.Height = size.y;
+			attachment.RegionWidth = size.x;
+			attachment.RegionHeight = size.y;
+			attachment.RegionOriginalWidth = size.x;
+			attachment.RegionOriginalHeight = size.y;
+			attachment.UpdateOffset();
+
+			return attachment;
 		}
 
-		Rect texRect = sprite.textureRect;
-
-		//normalize rect to UV space of packed atlas
-		texRect.x = Mathf.InverseLerp(0, tex.width, texRect.x);
-		texRect.y = Mathf.InverseLerp(0, tex.height, texRect.y);
-		texRect.width = Mathf.InverseLerp(0, tex.width, texRect.width);
-		texRect.height = Mathf.InverseLerp(0, tex.height, texRect.height);
-
-		Bounds bounds = sprite.bounds;
-		Vector3 size = bounds.size;
-
-		//TODO: make sure this rotation thing actually works
-		bool rotated = false;
-		if (sprite.packed)
-			rotated = sprite.packingRotation == SpritePackingRotation.Any;
-
-		//do some math and assign UVs and sizes
-		attachment.SetUVs(texRect.xMin, texRect.yMax, texRect.xMax, texRect.yMin, rotated);
-		attachment.RendererObject = atlasRegion;
-		attachment.SetColor(Color.white);
-		attachment.ScaleX = 1;
-		attachment.ScaleY = 1;
-		attachment.RegionOffsetX = sprite.rect.width * (0.5f - Mathf.InverseLerp(bounds.min.x, bounds.max.x, 0)) / sprite.pixelsPerUnit;
-		attachment.RegionOffsetY = sprite.rect.height * (0.5f - Mathf.InverseLerp(bounds.min.y, bounds.max.y, 0)) / sprite.pixelsPerUnit;
-		attachment.Width = size.x;
-		attachment.Height = size.y;
-		attachment.RegionWidth = size.x;
-		attachment.RegionHeight = size.y;
-		attachment.RegionOriginalWidth = size.x;
-		attachment.RegionOriginalHeight = size.y;
-		attachment.UpdateOffset();
-
-		return attachment;
-	}
+		public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) {
+			//TODO:  Unity 5 only
+			throw new System.NotImplementedException();
+		}
 
-	public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) {
-		//TODO:  Unity 5 only
-		throw new System.NotImplementedException();
-	}
+		public WeightedMeshAttachment NewWeightedMeshAttachment(Skin skin, string name, string path) {
+			throw new System.NotImplementedException();
+		}
 
-	public WeightedMeshAttachment NewWeightedMeshAttachment(Skin skin, string name, string path) {
-		throw new System.NotImplementedException();
+		public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name) {
+			throw new System.NotImplementedException();
+		}
 	}
 
-	public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name) {
-		throw new System.NotImplementedException();
+	public static class SpriteAttachmentExtensions {
+		public static Attachment AttachUnitySprite (this Skeleton skeleton, string slotName, Sprite sprite, string shaderName = "Spine/Skeleton") {
+			var att = sprite.ToRegionAttachment(shaderName);
+			skeleton.FindSlot(slotName).Attachment = att;
+			return att;
+		}
+
+		public static Attachment AddUnitySprite (this SkeletonData skeletonData, string slotName, Sprite sprite, string skinName = "", string shaderName = "Spine/Skeleton") {
+			var att = sprite.ToRegionAttachment(shaderName);
+
+			var slotIndex = skeletonData.FindSlotIndex(slotName);
+			Skin skin = skeletonData.defaultSkin;
+			if (skinName != "")
+				skin = skeletonData.FindSkin(skinName);
+
+			skin.AddAttachment(slotIndex, att.Name, att);
+
+			return att;
+		}
+
+		public static RegionAttachment ToRegionAttachment (this Sprite sprite, string shaderName = "Spine/Skeleton") {
+			var loader = new SpriteAttachmentLoader(sprite, Shader.Find(shaderName));
+			var att = loader.NewRegionAttachment(null, sprite.name, "");
+			loader = null;
+			return att;
+		}
 	}
 }
+

+ 119 - 118
spine-unity/Assets/spine-unity/Modules/TK2D/SpriteCollectionAttachmentLoader.cs

@@ -35,131 +35,132 @@ using UnityEngine;
 using Spine;
 
 // TODO: handle TPackerCW flip mode (probably not swap uv horizontaly)
+namespace Spine.Unity.TK2D {
+	public class SpriteCollectionAttachmentLoader : AttachmentLoader {
+		private tk2dSpriteCollectionData sprites;
+		private float u, v, u2, v2;
+		private bool regionRotated;
+		private float regionOriginalWidth, regionOriginalHeight;
+		private float regionWidth, regionHeight;
+		private float regionOffsetX, regionOffsetY;
+		private Material material;
 
-public class SpriteCollectionAttachmentLoader : AttachmentLoader {
-	private tk2dSpriteCollectionData sprites;
-	private float u, v, u2, v2;
-	private bool regionRotated;
-	private float regionOriginalWidth, regionOriginalHeight;
-	private float regionWidth, regionHeight;
-	private float regionOffsetX, regionOffsetY;
-	private Material material;
-
-	public SpriteCollectionAttachmentLoader (tk2dSpriteCollectionData sprites) {
-		if (sprites == null)
-			throw new ArgumentNullException("sprites cannot be null.");
-		this.sprites = sprites;
-	}
+		public SpriteCollectionAttachmentLoader (tk2dSpriteCollectionData sprites) {
+			if (sprites == null)
+				throw new ArgumentNullException("sprites cannot be null.");
+			this.sprites = sprites;
+		}
+
+		private void ProcessSpriteDefinition (String name) {
+			// Strip folder names.
+			int index = name.LastIndexOfAny(new char[] {'/', '\\'});
+			if (index != -1)
+				name = name.Substring(index + 1);
+
+			tk2dSpriteDefinition def = sprites.inst.GetSpriteDefinition(name);
+
+			if (def == null) {
+				Debug.Log("Sprite not found in atlas: " + name, sprites);
+				throw new Exception("Sprite not found in atlas: " + name);
+			}
+			if (def.complexGeometry)
+				throw new NotImplementedException("Complex geometry is not supported: " + name);
+			if (def.flipped == tk2dSpriteDefinition.FlipMode.TPackerCW)
+				throw new NotImplementedException("Only 2D Toolkit atlases are supported: " + name);
+
+			Vector2 minTexCoords = Vector2.one, maxTexCoords = Vector2.zero;
+			for (int i = 0; i < def.uvs.Length; ++i) {
+				Vector2 uv = def.uvs[i];
+				minTexCoords = Vector2.Min(minTexCoords, uv);
+				maxTexCoords = Vector2.Max(maxTexCoords, uv);
+			}
+			regionRotated = def.flipped == tk2dSpriteDefinition.FlipMode.Tk2d;
+			if (regionRotated) {
+				float temp = minTexCoords.x;
+				minTexCoords.x = maxTexCoords.x;
+				maxTexCoords.x = temp;
+			}
+			u = minTexCoords.x;
+			v = maxTexCoords.y;
+			u2 = maxTexCoords.x;
+			v2 = minTexCoords.y;
 
-	private void ProcessSpriteDefinition (String name) {
-		// Strip folder names.
-		int index = name.LastIndexOfAny(new char[] {'/', '\\'});
-		if (index != -1)
-			name = name.Substring(index + 1);
-		
-		tk2dSpriteDefinition def = sprites.inst.GetSpriteDefinition(name);
-		
-		if (def == null) {
-			Debug.Log("Sprite not found in atlas: " + name, sprites);
-			throw new Exception("Sprite not found in atlas: " + name);
+			regionOriginalWidth = (int)(def.untrimmedBoundsData[1].x / def.texelSize.x);
+			regionOriginalHeight = (int)(def.untrimmedBoundsData[1].y / def.texelSize.y);
+
+			regionWidth = (int)(def.boundsData[1].x / def.texelSize.x);
+			regionHeight = (int)(def.boundsData[1].y / def.texelSize.y);
+
+			float x0 = def.untrimmedBoundsData[0].x - def.untrimmedBoundsData[1].x / 2;
+			float x1 = def.boundsData[0].x - def.boundsData[1].x / 2;
+			regionOffsetX = (int)((x1 - x0) / def.texelSize.x);
+
+			float y0 = def.untrimmedBoundsData[0].y - def.untrimmedBoundsData[1].y / 2;
+			float y1 = def.boundsData[0].y - def.boundsData[1].y / 2;
+			regionOffsetY = (int)((y1 - y0) / def.texelSize.y);
+
+			material = def.materialInst;
 		}
-		if (def.complexGeometry)
-			throw new NotImplementedException("Complex geometry is not supported: " + name);
-		if (def.flipped == tk2dSpriteDefinition.FlipMode.TPackerCW)
-			throw new NotImplementedException("Only 2D Toolkit atlases are supported: " + name);
-
-		Vector2 minTexCoords = Vector2.one, maxTexCoords = Vector2.zero;
-		for (int i = 0; i < def.uvs.Length; ++i) {
-			Vector2 uv = def.uvs[i];
-			minTexCoords = Vector2.Min(minTexCoords, uv);
-			maxTexCoords = Vector2.Max(maxTexCoords, uv);
+
+		public RegionAttachment NewRegionAttachment (Skin skin, String name, String path) {
+			ProcessSpriteDefinition(path);
+
+			RegionAttachment region = new RegionAttachment(name);
+			region.Path = path;
+			region.RendererObject = material;
+			region.SetUVs(u, v, u2, v2, regionRotated);
+			region.RegionOriginalWidth = regionOriginalWidth;
+			region.RegionOriginalHeight = regionOriginalHeight;
+			region.RegionWidth = regionWidth;
+			region.RegionHeight = regionHeight;
+			region.RegionOffsetX = regionOffsetX;
+			region.RegionOffsetY = regionOffsetY;
+			return region;
 		}
-		regionRotated = def.flipped == tk2dSpriteDefinition.FlipMode.Tk2d;
-		if (regionRotated) {
-			float temp = minTexCoords.x;
-			minTexCoords.x = maxTexCoords.x;
-			maxTexCoords.x = temp;
+
+		public MeshAttachment NewMeshAttachment (Skin skin, String name, String path) {
+			ProcessSpriteDefinition(path);
+
+			MeshAttachment mesh = new MeshAttachment(name);
+			mesh.Path = path;
+			mesh.RendererObject = material;
+			mesh.RegionU = u;
+			mesh.RegionV = v;
+			mesh.RegionU2 = u2;
+			mesh.RegionV2 = v2;
+			mesh.RegionRotate = regionRotated;
+			mesh.RegionOriginalWidth = regionOriginalWidth;
+			mesh.RegionOriginalHeight = regionOriginalHeight;
+			mesh.RegionWidth = regionWidth;
+			mesh.RegionHeight = regionHeight;
+			mesh.RegionOffsetX = regionOffsetX;
+			mesh.RegionOffsetY = regionOffsetY;
+			return mesh;
 		}
-		u = minTexCoords.x;
-		v = maxTexCoords.y;
-		u2 = maxTexCoords.x;
-		v2 = minTexCoords.y;
-
-		regionOriginalWidth = (int)(def.untrimmedBoundsData[1].x / def.texelSize.x);
-		regionOriginalHeight = (int)(def.untrimmedBoundsData[1].y / def.texelSize.y);
-		
-		regionWidth = (int)(def.boundsData[1].x / def.texelSize.x);
-		regionHeight = (int)(def.boundsData[1].y / def.texelSize.y);
-		
-		float x0 = def.untrimmedBoundsData[0].x - def.untrimmedBoundsData[1].x / 2;
-		float x1 = def.boundsData[0].x - def.boundsData[1].x / 2;
-		regionOffsetX = (int)((x1 - x0) / def.texelSize.x);
-		
-		float y0 = def.untrimmedBoundsData[0].y - def.untrimmedBoundsData[1].y / 2;
-		float y1 = def.boundsData[0].y - def.boundsData[1].y / 2;
-		regionOffsetY = (int)((y1 - y0) / def.texelSize.y);
-
-		material = def.materialInst;
-	}
 
-	public RegionAttachment NewRegionAttachment (Skin skin, String name, String path) {
-		ProcessSpriteDefinition(path);
-		
-		RegionAttachment region = new RegionAttachment(name);
-		region.Path = path;
-		region.RendererObject = material;
-		region.SetUVs(u, v, u2, v2, regionRotated);
-		region.RegionOriginalWidth = regionOriginalWidth;
-		region.RegionOriginalHeight = regionOriginalHeight;
-		region.RegionWidth = regionWidth;
-		region.RegionHeight = regionHeight;
-		region.RegionOffsetX = regionOffsetX;
-		region.RegionOffsetY = regionOffsetY;
-		return region;
-	}
-	
-	public MeshAttachment NewMeshAttachment (Skin skin, String name, String path) {
-		ProcessSpriteDefinition(path);
-		
-		MeshAttachment mesh = new MeshAttachment(name);
-		mesh.Path = path;
-		mesh.RendererObject = material;
-		mesh.RegionU = u;
-		mesh.RegionV = v;
-		mesh.RegionU2 = u2;
-		mesh.RegionV2 = v2;
-		mesh.RegionRotate = regionRotated;
-		mesh.RegionOriginalWidth = regionOriginalWidth;
-		mesh.RegionOriginalHeight = regionOriginalHeight;
-		mesh.RegionWidth = regionWidth;
-		mesh.RegionHeight = regionHeight;
-		mesh.RegionOffsetX = regionOffsetX;
-		mesh.RegionOffsetY = regionOffsetY;
-		return mesh;
-	}
-	
-	public WeightedMeshAttachment NewWeightedMeshAttachment (Skin skin, String name, String path) {
-		ProcessSpriteDefinition(path);
-		
-		WeightedMeshAttachment mesh = new WeightedMeshAttachment(name);
-		mesh.Path = path;
-		mesh.RendererObject = material;
-		mesh.RegionU = u;
-		mesh.RegionV = v;
-		mesh.RegionU2 = u2;
-		mesh.RegionV2 = v2;
-		mesh.RegionRotate = regionRotated;
-		mesh.RegionOriginalWidth = regionOriginalWidth;
-		mesh.RegionOriginalHeight = regionOriginalHeight;
-		mesh.RegionWidth = regionWidth;
-		mesh.RegionHeight = regionHeight;
-		mesh.RegionOffsetX = regionOffsetX;
-		mesh.RegionOffsetY = regionOffsetY;
-		return mesh;
-	}
+		public WeightedMeshAttachment NewWeightedMeshAttachment (Skin skin, String name, String path) {
+			ProcessSpriteDefinition(path);
 
-	public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, String name) {
-		return new BoundingBoxAttachment(name);
+			WeightedMeshAttachment mesh = new WeightedMeshAttachment(name);
+			mesh.Path = path;
+			mesh.RendererObject = material;
+			mesh.RegionU = u;
+			mesh.RegionV = v;
+			mesh.RegionU2 = u2;
+			mesh.RegionV2 = v2;
+			mesh.RegionRotate = regionRotated;
+			mesh.RegionOriginalWidth = regionOriginalWidth;
+			mesh.RegionOriginalHeight = regionOriginalHeight;
+			mesh.RegionWidth = regionWidth;
+			mesh.RegionHeight = regionHeight;
+			mesh.RegionOffsetX = regionOffsetX;
+			mesh.RegionOffsetY = regionOffsetY;
+			return mesh;
+		}
+
+		public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, String name) {
+			return new BoundingBoxAttachment(name);
+		}
 	}
 }
 #endif

+ 129 - 127
spine-unity/Assets/spine-unity/SkeletonAnimation.cs

@@ -30,163 +30,165 @@
  *****************************************************************************/
 
 using System;
-using System.Collections.Generic;
 using UnityEngine;
-using Spine;
 
-[ExecuteInEditMode]
-[AddComponentMenu("Spine/SkeletonAnimation")]
-[HelpURL("http://esotericsoftware.com/spine-unity-documentation#Controlling-Animation")]
-public class SkeletonAnimation : SkeletonRenderer, ISkeletonAnimation {
-
-	/// <summary>
-	/// This is the Spine.AnimationState object of this SkeletonAnimation. You can control animations through it. 
-	/// Note that this object, like .skeleton, is not guaranteed to exist in Awake. Do all accesses and caching to it in Start</summary>
-	public Spine.AnimationState state;
-
-	public event UpdateBonesDelegate UpdateLocal {
-		add { _UpdateLocal += value; }
-		remove { _UpdateLocal -= value; }
-	}
+namespace Spine.Unity {
+	
+	[ExecuteInEditMode]
+	[AddComponentMenu("Spine/SkeletonAnimation")]
+	[HelpURL("http://esotericsoftware.com/spine-unity-documentation#Controlling-Animation")]
+	public class SkeletonAnimation : SkeletonRenderer, ISkeletonAnimation {
+
+		/// <summary>
+		/// This is the Spine.AnimationState object of this SkeletonAnimation. You can control animations through it. 
+		/// Note that this object, like .skeleton, is not guaranteed to exist in Awake. Do all accesses and caching to it in Start</summary>
+		public Spine.AnimationState state;
+
+		public event UpdateBonesDelegate UpdateLocal {
+			add { _UpdateLocal += value; }
+			remove { _UpdateLocal -= value; }
+		}
 
-	public event UpdateBonesDelegate UpdateWorld {
-		add { _UpdateWorld += value; }
-		remove { _UpdateWorld -= value; }
-	}
+		public event UpdateBonesDelegate UpdateWorld {
+			add { _UpdateWorld += value; }
+			remove { _UpdateWorld -= value; }
+		}
 
-	public event UpdateBonesDelegate UpdateComplete {
-		add { _UpdateComplete += value; }
-		remove { _UpdateComplete -= value; }
-	}
+		public event UpdateBonesDelegate UpdateComplete {
+			add { _UpdateComplete += value; }
+			remove { _UpdateComplete -= value; }
+		}
 
-	protected event UpdateBonesDelegate _UpdateLocal;
-	protected event UpdateBonesDelegate _UpdateWorld;
-	protected event UpdateBonesDelegate _UpdateComplete;
+		protected event UpdateBonesDelegate _UpdateLocal;
+		protected event UpdateBonesDelegate _UpdateWorld;
+		protected event UpdateBonesDelegate _UpdateComplete;
 
-	/// <summary>Gets the skeleton.</summary>
-	public Skeleton Skeleton {
-		get {
-			this.Initialize(false);
-			return this.skeleton;
+		/// <summary>Gets the skeleton.</summary>
+		public Skeleton Skeleton {
+			get {
+				this.Initialize(false);
+				return this.skeleton;
+			}
 		}
-	}
 
-	[SerializeField]
-	[SpineAnimation]
-	private String _animationName;
+		[SerializeField]
+		[SpineAnimation]
+		private String _animationName;
 
-	public String AnimationName {
-		get {
-			if (!valid) {
-				Debug.LogWarning("You tried access AnimationName but the SkeletonAnimation was not valid. Try checking your Skeleton Data for errors.");
-				return null;
+		public String AnimationName {
+			get {
+				if (!valid) {
+					Debug.LogWarning("You tried access AnimationName but the SkeletonAnimation was not valid. Try checking your Skeleton Data for errors.");
+					return null;
+				}
+
+				TrackEntry entry = state.GetCurrent(0);
+				return entry == null ? null : entry.Animation.Name;
 			}
-			
-			TrackEntry entry = state.GetCurrent(0);
-			return entry == null ? null : entry.Animation.Name;
-		}
-		set {
-			if (_animationName == value)
-				return;
-			_animationName = value;
-			
-			if (!valid) {
-				Debug.LogWarning("You tried to change AnimationName but the SkeletonAnimation was not valid. Try checking your Skeleton Data for errors.");
-				return;
+			set {
+				if (_animationName == value)
+					return;
+				_animationName = value;
+
+				if (!valid) {
+					Debug.LogWarning("You tried to change AnimationName but the SkeletonAnimation was not valid. Try checking your Skeleton Data for errors.");
+					return;
+				}
+
+				if (value == null || value.Length == 0)
+					state.ClearTrack(0);
+				else
+					state.SetAnimation(0, value, loop);
 			}
-			
-			if (value == null || value.Length == 0)
-				state.ClearTrack(0);
-			else
-				state.SetAnimation(0, value, loop);
 		}
-	}
 
-	/// <summary>Whether or not an animation should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.</summary>
-	#if UNITY_5
-	[Tooltip("Whether or not an animation should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.")]
-	#endif
-	public bool loop;
-
-	/// <summary>
-	/// The rate at which animations progress over time. 1 means 100%. 0.5 means 50%.</summary>
-	/// <remarks>AnimationState and TrackEntry also have their own timeScale. These are combined multiplicatively.</remarks>
-	#if UNITY_5
-	[Tooltip("The rate at which animations progress over time. 1 means 100%. 0.5 means 50%.")]
-	#endif
-	public float timeScale = 1;
-
-	#region Runtime Instantiation
-	/// <summary>Adds and prepares a SkeletonAnimation component to a GameObject at runtime.</summary>
-	/// <returns>The newly instantiated SkeletonAnimation</returns>
-	public static SkeletonAnimation AddToGameObject (GameObject gameObject, SkeletonDataAsset skeletonDataAsset) {
-		return SkeletonRenderer.AddSpineComponent<SkeletonAnimation>(gameObject, skeletonDataAsset);
-	}
+		/// <summary>Whether or not an animation should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.</summary>
+		#if UNITY_5
+		[Tooltip("Whether or not an animation should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.")]
+		#endif
+		public bool loop;
 
-	/// <summary>Instantiates a new UnityEngine.GameObject and adds a prepared SkeletonAnimation component to it.</summary>
-	/// <returns>The newly instantiated SkeletonAnimation component.</returns>
-	public static SkeletonAnimation NewSkeletonAnimationGameObject (SkeletonDataAsset skeletonDataAsset) {
-		return SkeletonRenderer.NewSpineGameObject<SkeletonAnimation>(skeletonDataAsset);
-	}
-	#endregion
+		/// <summary>
+		/// The rate at which animations progress over time. 1 means 100%. 0.5 means 50%.</summary>
+		/// <remarks>AnimationState and TrackEntry also have their own timeScale. These are combined multiplicatively.</remarks>
+		#if UNITY_5
+		[Tooltip("The rate at which animations progress over time. 1 means 100%. 0.5 means 50%.")]
+		#endif
+		public float timeScale = 1;
 
-	public override void Initialize (bool overwrite) {
-		if (valid && !overwrite)
-			return;
+		#region Runtime Instantiation
+		/// <summary>Adds and prepares a SkeletonAnimation component to a GameObject at runtime.</summary>
+		/// <returns>The newly instantiated SkeletonAnimation</returns>
+		public static SkeletonAnimation AddToGameObject (GameObject gameObject, SkeletonDataAsset skeletonDataAsset) {
+			return SkeletonRenderer.AddSpineComponent<SkeletonAnimation>(gameObject, skeletonDataAsset);
+		}
 
-		base.Initialize(overwrite);
+		/// <summary>Instantiates a new UnityEngine.GameObject and adds a prepared SkeletonAnimation component to it.</summary>
+		/// <returns>The newly instantiated SkeletonAnimation component.</returns>
+		public static SkeletonAnimation NewSkeletonAnimationGameObject (SkeletonDataAsset skeletonDataAsset) {
+			return SkeletonRenderer.NewSpineGameObject<SkeletonAnimation>(skeletonDataAsset);
+		}
+		#endregion
 
-		if (!valid)
-			return;
+		public override void Initialize (bool overwrite) {
+			if (valid && !overwrite)
+				return;
 
-		state = new Spine.AnimationState(skeletonDataAsset.GetAnimationStateData());
+			base.Initialize(overwrite);
 
-		#if UNITY_EDITOR
-		if (!string.IsNullOrEmpty(_animationName)) {
-			if (Application.isPlaying) {
-				state.SetAnimation(0, _animationName, loop);
-			} else {
-				// Assume SkeletonAnimation is valid for skeletonData and skeleton. Checked above.
-				var animationObject = skeletonDataAsset.GetSkeletonData(false).FindAnimation(_animationName);
-				if (animationObject != null)
-					animationObject.Apply(skeleton, 0f, 0f, false, null);
+			if (!valid)
+				return;
+
+			state = new Spine.AnimationState(skeletonDataAsset.GetAnimationStateData());
+
+			#if UNITY_EDITOR
+			if (!string.IsNullOrEmpty(_animationName)) {
+				if (Application.isPlaying) {
+					state.SetAnimation(0, _animationName, loop);
+				} else {
+					// Assume SkeletonAnimation is valid for skeletonData and skeleton. Checked above.
+					var animationObject = skeletonDataAsset.GetSkeletonData(false).FindAnimation(_animationName);
+					if (animationObject != null)
+						animationObject.Apply(skeleton, 0f, 0f, false, null);
+				}
+				Update(0);
 			}
-			Update(0);
-		}
-		#else
-		if (!string.IsNullOrEmpty(_animationName)) {
+			#else
+			if (!string.IsNullOrEmpty(_animationName)) {
 			state.SetAnimation(0, _animationName, loop);
 			Update(0);
+			}
+			#endif
 		}
-		#endif
-	}
 
-	public virtual void Update () {
-		Update(Time.deltaTime);
-	}
-
-	public virtual void Update (float deltaTime) {
-		if (!valid)
-			return;
+		public virtual void Update () {
+			Update(Time.deltaTime);
+		}
 
-		deltaTime *= timeScale;
-		skeleton.Update(deltaTime);
-		state.Update(deltaTime);
-		state.Apply(skeleton);
+		public virtual void Update (float deltaTime) {
+			if (!valid)
+				return;
 
-		if (_UpdateLocal != null)
-			_UpdateLocal(this);
+			deltaTime *= timeScale;
+			skeleton.Update(deltaTime);
+			state.Update(deltaTime);
+			state.Apply(skeleton);
 
-		skeleton.UpdateWorldTransform();
+			if (_UpdateLocal != null)
+				_UpdateLocal(this);
 
-		if (_UpdateWorld != null) {
-			_UpdateWorld(this);
 			skeleton.UpdateWorldTransform();
-		}
 
-		if (_UpdateComplete != null) {
-			_UpdateComplete(this);
+			if (_UpdateWorld != null) {
+				_UpdateWorld(this);
+				skeleton.UpdateWorldTransform();
+			}
+
+			if (_UpdateComplete != null) {
+				_UpdateComplete(this);
+			}
 		}
+
 	}
-		
+
 }

+ 149 - 149
spine-unity/Assets/spine-unity/SkeletonAnimator.cs

@@ -5,211 +5,211 @@
  * Full irrevocable rights and permissions granted to Esoteric Software
 *****************************************************************************/
 using UnityEngine;
-using System.Collections;
 using System.Collections.Generic;
-using Spine;
 
-[RequireComponent(typeof(Animator))]
-public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation {
+namespace Spine.Unity {
+	[RequireComponent(typeof(Animator))]
+	public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation {
 
-	public enum MixMode { AlwaysMix, MixNext, SpineStyle }
-	public MixMode[] layerMixModes = new MixMode[0];
+		public enum MixMode { AlwaysMix, MixNext, SpineStyle }
+		public MixMode[] layerMixModes = new MixMode[0];
 
-	public event UpdateBonesDelegate UpdateLocal {
-		add { _UpdateLocal += value; }
-		remove { _UpdateLocal -= value; }
-	}
+		public event UpdateBonesDelegate UpdateLocal {
+			add { _UpdateLocal += value; }
+			remove { _UpdateLocal -= value; }
+		}
 
-	public event UpdateBonesDelegate UpdateWorld {
-		add { _UpdateWorld += value; }
-		remove { _UpdateWorld -= value; }
-	}
+		public event UpdateBonesDelegate UpdateWorld {
+			add { _UpdateWorld += value; }
+			remove { _UpdateWorld -= value; }
+		}
 
-	public event UpdateBonesDelegate UpdateComplete {
-		add { _UpdateComplete += value; }
-		remove { _UpdateComplete -= value; }
-	}
+		public event UpdateBonesDelegate UpdateComplete {
+			add { _UpdateComplete += value; }
+			remove { _UpdateComplete -= value; }
+		}
 
-	protected event UpdateBonesDelegate _UpdateLocal;
-	protected event UpdateBonesDelegate _UpdateWorld;
-	protected event UpdateBonesDelegate _UpdateComplete;
+		protected event UpdateBonesDelegate _UpdateLocal;
+		protected event UpdateBonesDelegate _UpdateWorld;
+		protected event UpdateBonesDelegate _UpdateComplete;
 
-	public Skeleton Skeleton {
-		get {
-			return this.skeleton;
+		public Skeleton Skeleton {
+			get {
+				return this.skeleton;
+			}
 		}
-	}
-
-	readonly Dictionary<int, Spine.Animation> animationTable = new Dictionary<int, Spine.Animation>();
-	readonly Dictionary<AnimationClip, int> clipNameHashCodeTable = new Dictionary<AnimationClip, int>();
-	Animator animator;
-	float lastTime;
 
-	public override void Initialize (bool overwrite) {
-		if (valid && !overwrite)
-			return;
-		
-		base.Initialize(overwrite);
+		readonly Dictionary<int, Spine.Animation> animationTable = new Dictionary<int, Spine.Animation>();
+		readonly Dictionary<AnimationClip, int> clipNameHashCodeTable = new Dictionary<AnimationClip, int>();
+		Animator animator;
+		float lastTime;
 
-		if (!valid)
-			return;
+		public override void Initialize (bool overwrite) {
+			if (valid && !overwrite)
+				return;
 
-		animationTable.Clear();
-		clipNameHashCodeTable.Clear();
+			base.Initialize(overwrite);
 
-		var data = skeletonDataAsset.GetSkeletonData(true);
+			if (!valid)
+				return;
 
-		foreach (var a in data.Animations) {
-			animationTable.Add(a.Name.GetHashCode(), a);
-		}
+			animationTable.Clear();
+			clipNameHashCodeTable.Clear();
 
-		animator = GetComponent<Animator>();
+			var data = skeletonDataAsset.GetSkeletonData(true);
 
-		lastTime = Time.time;
-	}
+			foreach (var a in data.Animations) {
+				animationTable.Add(a.Name.GetHashCode(), a);
+			}
 
-	void Update () {
-		if (!valid)
-			return;
+			animator = GetComponent<Animator>();
 
-		if (layerMixModes.Length != animator.layerCount) {
-			System.Array.Resize<MixMode>(ref layerMixModes, animator.layerCount);
+			lastTime = Time.time;
 		}
-		float deltaTime = Time.time - lastTime;
 
-		skeleton.Update(Time.deltaTime);
+		void Update () {
+			if (!valid)
+				return;
 
-		//apply
-		int layerCount = animator.layerCount;
+			if (layerMixModes.Length != animator.layerCount) {
+				System.Array.Resize<MixMode>(ref layerMixModes, animator.layerCount);
+			}
+			float deltaTime = Time.time - lastTime;
 
-		for (int i = 0; i < layerCount; i++) {
+			skeleton.Update(Time.deltaTime);
 
-			float layerWeight = animator.GetLayerWeight(i);
-			if (i == 0)
-				layerWeight = 1;
+			//apply
+			int layerCount = animator.layerCount;
 
-			var stateInfo = animator.GetCurrentAnimatorStateInfo(i);
-			var nextStateInfo = animator.GetNextAnimatorStateInfo(i);
+			for (int i = 0; i < layerCount; i++) {
 
-#if UNITY_5
-			var clipInfo = animator.GetCurrentAnimatorClipInfo(i);
-			var nextClipInfo = animator.GetNextAnimatorClipInfo(i);
-#else
-			var clipInfo = animator.GetCurrentAnimationClipState(i);
-			var nextClipInfo = animator.GetNextAnimationClipState(i);
-#endif
-			MixMode mode = layerMixModes[i];
+				float layerWeight = animator.GetLayerWeight(i);
+				if (i == 0)
+					layerWeight = 1;
 
-			if (mode == MixMode.AlwaysMix) {
-				//always use Mix instead of Applying the first non-zero weighted clip
-				for (int c = 0; c < clipInfo.Length; c++) {
-					var info = clipInfo[c];
-					float weight = info.weight * layerWeight;
-					if (weight == 0)
-						continue;
+				var stateInfo = animator.GetCurrentAnimatorStateInfo(i);
+				var nextStateInfo = animator.GetNextAnimatorStateInfo(i);
 
-					float time = stateInfo.normalizedTime * info.clip.length;
-					animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight);
-				}
-#if UNITY_5
-				if (nextStateInfo.fullPathHash != 0) {
-#else
-				if (nextStateInfo.nameHash != 0) {
-#endif
-					for (int c = 0; c < nextClipInfo.Length; c++) {
-						var info = nextClipInfo[c];
+				#if UNITY_5
+				var clipInfo = animator.GetCurrentAnimatorClipInfo(i);
+				var nextClipInfo = animator.GetNextAnimatorClipInfo(i);
+				#else
+				var clipInfo = animator.GetCurrentAnimationClipState(i);
+				var nextClipInfo = animator.GetNextAnimationClipState(i);
+				#endif
+				MixMode mode = layerMixModes[i];
+
+				if (mode == MixMode.AlwaysMix) {
+					//always use Mix instead of Applying the first non-zero weighted clip
+					for (int c = 0; c < clipInfo.Length; c++) {
+						var info = clipInfo[c];
 						float weight = info.weight * layerWeight;
 						if (weight == 0)
 							continue;
 
-						float time = nextStateInfo.normalizedTime * info.clip.length;
-						animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight);
+						float time = stateInfo.normalizedTime * info.clip.length;
+						animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight);
 					}
-				}
-			} else if (mode >= MixMode.MixNext) {
-				//apply first non-zero weighted clip
-				int c = 0;
-
-				for (; c < clipInfo.Length; c++) {
-					var info = clipInfo[c];
-					float weight = info.weight * layerWeight;
-					if (weight == 0)
-						continue;
-
-					float time = stateInfo.normalizedTime * info.clip.length;
-					animationTable[GetAnimationClipNameHashCode(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null);
-					break;
-				}
-
-				//mix the rest
-				for (; c < clipInfo.Length; c++) {
-					var info = clipInfo[c];
-					float weight = info.weight * layerWeight;
-					if (weight == 0)
-						continue;
-
-					float time = stateInfo.normalizedTime * info.clip.length;
-					animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight);
-				}
-
-				c = 0;
-#if UNITY_5
-				if (nextStateInfo.fullPathHash != 0) {
-#else
-				if (nextStateInfo.nameHash != 0) {
-#endif
-					//apply next clip directly instead of mixing (ie:  no crossfade, ignores mecanim transition weights)
-					if (mode == MixMode.SpineStyle) {
-						for (; c < nextClipInfo.Length; c++) {
+					#if UNITY_5
+					if (nextStateInfo.fullPathHash != 0) {
+					#else
+					if (nextStateInfo.nameHash != 0) {
+					#endif
+						for (int c = 0; c < nextClipInfo.Length; c++) {
 							var info = nextClipInfo[c];
 							float weight = info.weight * layerWeight;
 							if (weight == 0)
 								continue;
 
 							float time = nextStateInfo.normalizedTime * info.clip.length;
-							animationTable[GetAnimationClipNameHashCode(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null);
-							break;
+							animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight);
 						}
 					}
+				} else if (mode >= MixMode.MixNext) {
+					//apply first non-zero weighted clip
+					int c = 0;
+
+					for (; c < clipInfo.Length; c++) {
+						var info = clipInfo[c];
+						float weight = info.weight * layerWeight;
+						if (weight == 0)
+							continue;
+
+						float time = stateInfo.normalizedTime * info.clip.length;
+						animationTable[GetAnimationClipNameHashCode(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null);
+						break;
+					}
 
 					//mix the rest
-					for (; c < nextClipInfo.Length; c++) {
-						var info = nextClipInfo[c];
+					for (; c < clipInfo.Length; c++) {
+						var info = clipInfo[c];
 						float weight = info.weight * layerWeight;
 						if (weight == 0)
 							continue;
 
-						float time = nextStateInfo.normalizedTime * info.clip.length;
-						animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight);
+						float time = stateInfo.normalizedTime * info.clip.length;
+						animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight);
+					}
+
+					c = 0;
+					#if UNITY_5
+					if (nextStateInfo.fullPathHash != 0) {
+					#else
+					if (nextStateInfo.nameHash != 0) {
+					#endif
+						//apply next clip directly instead of mixing (ie:  no crossfade, ignores mecanim transition weights)
+						if (mode == MixMode.SpineStyle) {
+							for (; c < nextClipInfo.Length; c++) {
+								var info = nextClipInfo[c];
+								float weight = info.weight * layerWeight;
+								if (weight == 0)
+									continue;
+
+								float time = nextStateInfo.normalizedTime * info.clip.length;
+								animationTable[GetAnimationClipNameHashCode(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null);
+								break;
+							}
+						}
+
+						//mix the rest
+						for (; c < nextClipInfo.Length; c++) {
+							var info = nextClipInfo[c];
+							float weight = info.weight * layerWeight;
+							if (weight == 0)
+								continue;
+
+							float time = nextStateInfo.normalizedTime * info.clip.length;
+							animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight);
+						}
 					}
 				}
 			}
-		}
 
-		if (_UpdateLocal != null)
-			_UpdateLocal(this);
+			if (_UpdateLocal != null)
+				_UpdateLocal(this);
 
-		skeleton.UpdateWorldTransform();
-
-		if (_UpdateWorld != null) {
-			_UpdateWorld(this);
 			skeleton.UpdateWorldTransform();
-		}
 
-		if (_UpdateComplete != null) {
-			_UpdateComplete(this);
-		}
+			if (_UpdateWorld != null) {
+				_UpdateWorld(this);
+				skeleton.UpdateWorldTransform();
+			}
 
-		lastTime = Time.time;
-	}
+			if (_UpdateComplete != null) {
+				_UpdateComplete(this);
+			}
 
-	private int GetAnimationClipNameHashCode (AnimationClip clip) {
-		int clipNameHashCode;
-		if (!clipNameHashCodeTable.TryGetValue(clip, out clipNameHashCode)) {
-			clipNameHashCode = clip.name.GetHashCode();
-			clipNameHashCodeTable.Add(clip, clipNameHashCode);
+			lastTime = Time.time;
 		}
 
-		return clipNameHashCode;
+		private int GetAnimationClipNameHashCode (AnimationClip clip) {
+			int clipNameHashCode;
+			if (!clipNameHashCodeTable.TryGetValue(clip, out clipNameHashCode)) {
+				clipNameHashCode = clip.name.GetHashCode();
+				clipNameHashCodeTable.Add(clip, clipNameHashCode);
+			}
+
+			return clipNameHashCode;
+		}
 	}
 }

+ 121 - 149
spine-unity/Assets/spine-unity/SkeletonExtensions.cs

@@ -6,153 +6,125 @@
 *****************************************************************************/
 
 using UnityEngine;
-using System.Collections;
 using Spine;
-
-public static class SkeletonExtensions {
-
-	const float ByteToFloat = 1f / 255f;
-
-	#region Colors
-	public static Color GetColor (this Skeleton s) { return new Color(s.r, s.g, s.b, s.a); }
-	public static Color GetColor (this RegionAttachment a) { return new Color(a.r, a.g, a.b, a.a); }
-	public static Color GetColor (this MeshAttachment a) { return new Color(a.r, a.g, a.b, a.a); }
-	public static Color GetColor (this WeightedMeshAttachment a) { return new Color(a.r, a.g, a.b, a.a);	}
-
-	public static void SetColor (this Skeleton skeleton, Color color) {
-		skeleton.A = color.a;
-		skeleton.R = color.r;
-		skeleton.G = color.g;
-		skeleton.B = color.b;
-	}
-
-	public static void SetColor (this Skeleton skeleton, Color32 color) {
-		skeleton.A = color.a * ByteToFloat;
-		skeleton.R = color.r * ByteToFloat;
-		skeleton.G = color.g * ByteToFloat;
-		skeleton.B = color.b * ByteToFloat;
-	}
-
-	public static void SetColor (this Slot slot, Color color) {
-		slot.A = color.a;
-		slot.R = color.r;
-		slot.G = color.g;
-		slot.B = color.b;
-	}
-
-	public static void SetColor (this Slot slot, Color32 color) {
-		slot.A = color.a * ByteToFloat;
-		slot.R = color.r * ByteToFloat;
-		slot.G = color.g * ByteToFloat;
-		slot.B = color.b * ByteToFloat;
-	}
-
-	public static void SetColor (this RegionAttachment attachment, Color color) {
-		attachment.A = color.a;
-		attachment.R = color.r;
-		attachment.G = color.g;
-		attachment.B = color.b;
-	}
-
-	public static void SetColor (this RegionAttachment attachment, Color32 color) {
-		attachment.A = color.a * ByteToFloat;
-		attachment.R = color.r * ByteToFloat;
-		attachment.G = color.g * ByteToFloat;
-		attachment.B = color.b * ByteToFloat;
-	}
-
-	public static void SetColor (this MeshAttachment attachment, Color color) {
-		attachment.A = color.a;
-		attachment.R = color.r;
-		attachment.G = color.g;
-		attachment.B = color.b;
-	}
-
-	public static void SetColor (this MeshAttachment attachment, Color32 color) {
-		attachment.A = color.a * ByteToFloat;
-		attachment.R = color.r * ByteToFloat;
-		attachment.G = color.g * ByteToFloat;
-		attachment.B = color.b * ByteToFloat;
-	}
-
-	public static void SetColor (this WeightedMeshAttachment attachment, Color color) {
-		attachment.A = color.a;
-		attachment.R = color.r;
-		attachment.G = color.g;
-		attachment.B = color.b;
-	}
-
-	public static void SetColor (this WeightedMeshAttachment attachment, Color32 color) {
-		attachment.A = color.a * ByteToFloat;
-		attachment.R = color.r * ByteToFloat;
-		attachment.G = color.g * ByteToFloat;
-		attachment.B = color.b * ByteToFloat;
-	}
-	#endregion
-
-	#region Bone Position
-	public static void SetPosition (this Bone bone, Vector2 position) {
-		bone.X = position.x;
-		bone.Y = position.y;
-	}
-
-	public static void SetPosition (this Bone bone, Vector3 position) {
-		bone.X = position.x;
-		bone.Y = position.y;
-	}
-
-	public static Vector2 GetSkeletonSpacePosition (this Bone bone) {
-		// TODO: This changes in v3.0
-		return new Vector2(bone.worldX, bone.worldY);
-	}
-
-	public static Vector3 GetWorldPosition (this Bone bone, UnityEngine.Transform parentTransform) {		
-		return parentTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY));
-	}
-	#endregion
-
-	#region Posing
-	/// <summary>
-	/// Shortcut for posing a skeleton at a specific time. Time is in seconds. (frameNumber / 30f) will give you seconds.
-	/// If you need to do this often, you should get the Animation object yourself using skeleton.data.FindAnimation. and call Apply on that.</summary>
-	/// <param name = "skeleton">The skeleton to pose.</param>
-	/// <param name="animationName">The name of the animation to use.</param>
-	/// <param name = "time">The time of the pose within the animation.</param>
-	/// <param name = "loop">Wraps the time around if it is longer than the duration of the animation.</param>
-	public static void PoseWithAnimation (this Skeleton skeleton, string animationName, float time, bool loop) {
-		// Fail loud when skeleton.data is null.
-		Spine.Animation animation = skeleton.data.FindAnimation(animationName);
-		if (animation == null) return;
-		animation.Apply(skeleton, 0, time, loop, null);
-	}
-	#endregion
-
-	#region Unity Sprite To Attachments
-	public static Attachment AttachUnitySprite (this Skeleton skeleton, string slotName, Sprite sprite, string shaderName = "Spine/Skeleton") {
-		var att = sprite.ToRegionAttachment(shaderName);
-		skeleton.FindSlot(slotName).Attachment = att;
-		return att;
-	}
-
-	public static Attachment AddUnitySprite (this SkeletonData skeletonData, string slotName, Sprite sprite, string skinName = "", string shaderName = "Spine/Skeleton") {
-		var att = sprite.ToRegionAttachment(shaderName);
-
-		var slotIndex = skeletonData.FindSlotIndex(slotName);
-		Skin skin = skeletonData.defaultSkin;
-		if (skinName != "")
-			skin = skeletonData.FindSkin(skinName);
-
-		skin.AddAttachment(slotIndex, att.Name, att);
-
-		return att;
-	}
-
-	public static RegionAttachment ToRegionAttachment (this Sprite sprite, string shaderName = "Spine/Skeleton") {
-		var loader = new SpriteAttachmentLoader(sprite, Shader.Find(shaderName));
-		var att = loader.NewRegionAttachment(null, sprite.name, "");
-		loader = null;
-		return att;
-	}
-	#endregion
-
-}
+using Spine.Unity;
+
+namespace Spine.Unity {
+	public static class SkeletonExtensions {
+
+		const float ByteToFloat = 1f / 255f;
+
+		#region Colors
+		public static Color GetColor (this Skeleton s) { return new Color(s.r, s.g, s.b, s.a); }
+		public static Color GetColor (this RegionAttachment a) { return new Color(a.r, a.g, a.b, a.a); }
+		public static Color GetColor (this MeshAttachment a) { return new Color(a.r, a.g, a.b, a.a); }
+		public static Color GetColor (this WeightedMeshAttachment a) { return new Color(a.r, a.g, a.b, a.a);	}
+
+		public static void SetColor (this Skeleton skeleton, Color color) {
+			skeleton.A = color.a;
+			skeleton.R = color.r;
+			skeleton.G = color.g;
+			skeleton.B = color.b;
+		}
+
+		public static void SetColor (this Skeleton skeleton, Color32 color) {
+			skeleton.A = color.a * ByteToFloat;
+			skeleton.R = color.r * ByteToFloat;
+			skeleton.G = color.g * ByteToFloat;
+			skeleton.B = color.b * ByteToFloat;
+		}
+
+		public static void SetColor (this Slot slot, Color color) {
+			slot.A = color.a;
+			slot.R = color.r;
+			slot.G = color.g;
+			slot.B = color.b;
+		}
+
+		public static void SetColor (this Slot slot, Color32 color) {
+			slot.A = color.a * ByteToFloat;
+			slot.R = color.r * ByteToFloat;
+			slot.G = color.g * ByteToFloat;
+			slot.B = color.b * ByteToFloat;
+		}
+
+		public static void SetColor (this RegionAttachment attachment, Color color) {
+			attachment.A = color.a;
+			attachment.R = color.r;
+			attachment.G = color.g;
+			attachment.B = color.b;
+		}
+
+		public static void SetColor (this RegionAttachment attachment, Color32 color) {
+			attachment.A = color.a * ByteToFloat;
+			attachment.R = color.r * ByteToFloat;
+			attachment.G = color.g * ByteToFloat;
+			attachment.B = color.b * ByteToFloat;
+		}
+
+		public static void SetColor (this MeshAttachment attachment, Color color) {
+			attachment.A = color.a;
+			attachment.R = color.r;
+			attachment.G = color.g;
+			attachment.B = color.b;
+		}
+
+		public static void SetColor (this MeshAttachment attachment, Color32 color) {
+			attachment.A = color.a * ByteToFloat;
+			attachment.R = color.r * ByteToFloat;
+			attachment.G = color.g * ByteToFloat;
+			attachment.B = color.b * ByteToFloat;
+		}
+
+		public static void SetColor (this WeightedMeshAttachment attachment, Color color) {
+			attachment.A = color.a;
+			attachment.R = color.r;
+			attachment.G = color.g;
+			attachment.B = color.b;
+		}
+
+		public static void SetColor (this WeightedMeshAttachment attachment, Color32 color) {
+			attachment.A = color.a * ByteToFloat;
+			attachment.R = color.r * ByteToFloat;
+			attachment.G = color.g * ByteToFloat;
+			attachment.B = color.b * ByteToFloat;
+		}
+		#endregion
+
+		#region Bone Position
+		public static void SetPosition (this Bone bone, Vector2 position) {
+			bone.X = position.x;
+			bone.Y = position.y;
+		}
+
+		public static void SetPosition (this Bone bone, Vector3 position) {
+			bone.X = position.x;
+			bone.Y = position.y;
+		}
+
+		public static Vector2 GetSkeletonSpacePosition (this Bone bone) {
+			return new Vector2(bone.worldX, bone.worldY);
+		}
+
+		public static Vector3 GetWorldPosition (this Bone bone, UnityEngine.Transform parentTransform) {		
+			return parentTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY));
+		}
+		#endregion
+
+		#region Posing
+		/// <summary>
+		/// Shortcut for posing a skeleton at a specific time. Time is in seconds. (frameNumber / 30f) will give you seconds.
+		/// If you need to do this often, you should get the Animation object yourself using skeleton.data.FindAnimation. and call Apply on that.</summary>
+		/// <param name = "skeleton">The skeleton to pose.</param>
+		/// <param name="animationName">The name of the animation to use.</param>
+		/// <param name = "time">The time of the pose within the animation.</param>
+		/// <param name = "loop">Wraps the time around if it is longer than the duration of the animation.</param>
+		public static void PoseWithAnimation (this Skeleton skeleton, string animationName, float time, bool loop) {
+			// Fail loud when skeleton.data is null.
+			Spine.Animation animation = skeleton.data.FindAnimation(animationName);
+			if (animation == null) return;
+			animation.Apply(skeleton, 0, time, loop, null);
+		}
+		#endregion
+	}
+}

File diff suppressed because it is too large
+ 686 - 664
spine-unity/Assets/spine-unity/SkeletonRenderer.cs


+ 272 - 269
spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs

@@ -10,345 +10,348 @@ using System.Collections;
 using System.Collections.Generic;
 using Spine;
 
-[CustomEditor(typeof(SkeletonUtilityBone)), CanEditMultipleObjects]
-public class SkeletonUtilityBoneInspector : Editor {
-	SerializedProperty mode, boneName, zPosition, position, rotation, scale, overrideAlpha, parentReference;
-	// MITCH
-//	SerializedProperty flip, flipX;
-
-	//multi selected flags
-	bool containsFollows, containsOverrides, multiObject;
-	
-	//single selected helpers
-	SkeletonUtilityBone utilityBone;
-	SkeletonUtility skeletonUtility;
-	bool canCreateHingeChain = false;
-
-	Dictionary<Slot, List<BoundingBoxAttachment>> boundingBoxTable = new Dictionary<Slot, List<BoundingBoxAttachment>>();
-	string currentSkinName = "";
-
-	void OnEnable () {
-		mode = this.serializedObject.FindProperty("mode");
-		boneName = this.serializedObject.FindProperty("boneName");
-		zPosition = this.serializedObject.FindProperty("zPosition");
-		position = this.serializedObject.FindProperty("position");
-		rotation = this.serializedObject.FindProperty("rotation");
-		scale = this.serializedObject.FindProperty("scale");
-		overrideAlpha = this.serializedObject.FindProperty("overrideAlpha");
-		parentReference = this.serializedObject.FindProperty("parentReference");
-
+namespace Spine.Unity.Editor {
+	[CustomEditor(typeof(SkeletonUtilityBone)), CanEditMultipleObjects]
+	public class SkeletonUtilityBoneInspector : UnityEditor.Editor {
+		SerializedProperty mode, boneName, zPosition, position, rotation, scale, overrideAlpha, parentReference;
 		// MITCH
-//		flip = this.serializedObject.FindProperty("flip");
-//		flipX = this.serializedObject.FindProperty("flipX");
+		//	SerializedProperty flip, flipX;
 
-		EvaluateFlags();
+		//multi selected flags
+		bool containsFollows, containsOverrides, multiObject;
 
-		if (utilityBone.valid == false && skeletonUtility != null && skeletonUtility.skeletonRenderer != null) {
-			skeletonUtility.skeletonRenderer.Initialize(false);
-		}
+		//single selected helpers
+		SkeletonUtilityBone utilityBone;
+		SkeletonUtility skeletonUtility;
+		bool canCreateHingeChain = false;
 
-		canCreateHingeChain = CanCreateHingeChain();
+		Dictionary<Slot, List<BoundingBoxAttachment>> boundingBoxTable = new Dictionary<Slot, List<BoundingBoxAttachment>>();
+		string currentSkinName = "";
 
-		boundingBoxTable.Clear();
+		void OnEnable () {
+			mode = this.serializedObject.FindProperty("mode");
+			boneName = this.serializedObject.FindProperty("boneName");
+			zPosition = this.serializedObject.FindProperty("zPosition");
+			position = this.serializedObject.FindProperty("position");
+			rotation = this.serializedObject.FindProperty("rotation");
+			scale = this.serializedObject.FindProperty("scale");
+			overrideAlpha = this.serializedObject.FindProperty("overrideAlpha");
+			parentReference = this.serializedObject.FindProperty("parentReference");
 
-		if (multiObject)
-			return;
+			// MITCH
+			//		flip = this.serializedObject.FindProperty("flip");
+			//		flipX = this.serializedObject.FindProperty("flipX");
 
-		if (utilityBone.bone == null)
-			return;
+			EvaluateFlags();
 
-		var skeleton = utilityBone.bone.Skeleton;
-		int slotCount = skeleton.Slots.Count;
-		Skin skin = skeleton.Skin;
-		if (skeleton.Skin == null)
-			skin = skeleton.Data.DefaultSkin;
+			if (utilityBone.valid == false && skeletonUtility != null && skeletonUtility.skeletonRenderer != null) {
+				skeletonUtility.skeletonRenderer.Initialize(false);
+			}
 
-		currentSkinName = skin.Name;
-		for(int i = 0; i < slotCount; i++){
-			Slot slot = skeletonUtility.skeletonRenderer.skeleton.Slots.Items[i];
-			if (slot.Bone == utilityBone.bone) {
-				List<Attachment> attachments = new List<Attachment>();
-				
-					
-				skin.FindAttachmentsForSlot(skeleton.FindSlotIndex(slot.Data.Name), attachments);
+			canCreateHingeChain = CanCreateHingeChain();
 
-				List<BoundingBoxAttachment> boundingBoxes = new List<BoundingBoxAttachment>();
-				foreach (var att in attachments) {
-					if (att is BoundingBoxAttachment) {
-						boundingBoxes.Add((BoundingBoxAttachment)att);
-					}
-				}
+			boundingBoxTable.Clear();
 
-				if (boundingBoxes.Count > 0) {
-					boundingBoxTable.Add(slot, boundingBoxes);
-				}
-			}
-		}
-		
-	}
+			if (multiObject)
+				return;
 
-	void EvaluateFlags () {
-		utilityBone = (SkeletonUtilityBone)target;
-		skeletonUtility = utilityBone.skeletonUtility;
-
-		if (Selection.objects.Length == 1) {
-			containsFollows = utilityBone.mode == SkeletonUtilityBone.Mode.Follow;
-			containsOverrides = utilityBone.mode == SkeletonUtilityBone.Mode.Override;
-		} else {
-			int boneCount = 0;
-			foreach (Object o in Selection.objects) {
-				if (o is GameObject) {
-					GameObject go = (GameObject)o;
-					SkeletonUtilityBone sub = go.GetComponent<SkeletonUtilityBone>();
-					if (sub != null) {
-						boneCount++;
-						if (sub.mode == SkeletonUtilityBone.Mode.Follow)
-							containsFollows = true;
-						if (sub.mode == SkeletonUtilityBone.Mode.Override)
-							containsOverrides = true;
+			if (utilityBone.bone == null)
+				return;
+
+			var skeleton = utilityBone.bone.Skeleton;
+			int slotCount = skeleton.Slots.Count;
+			Skin skin = skeleton.Skin;
+			if (skeleton.Skin == null)
+				skin = skeleton.Data.DefaultSkin;
+
+			currentSkinName = skin.Name;
+			for(int i = 0; i < slotCount; i++){
+				Slot slot = skeletonUtility.skeletonRenderer.skeleton.Slots.Items[i];
+				if (slot.Bone == utilityBone.bone) {
+					List<Attachment> attachments = new List<Attachment>();
+
+
+					skin.FindAttachmentsForSlot(skeleton.FindSlotIndex(slot.Data.Name), attachments);
+
+					List<BoundingBoxAttachment> boundingBoxes = new List<BoundingBoxAttachment>();
+					foreach (var att in attachments) {
+						if (att is BoundingBoxAttachment) {
+							boundingBoxes.Add((BoundingBoxAttachment)att);
+						}
+					}
+
+					if (boundingBoxes.Count > 0) {
+						boundingBoxTable.Add(slot, boundingBoxes);
 					}
 				}
 			}
-			
-			if (boneCount > 1)
-				multiObject = true;
-		}
-	}
-	
-	public override void OnInspectorGUI () {
-		serializedObject.Update();
-
-		EditorGUI.BeginChangeCheck();
-		EditorGUILayout.PropertyField(mode);
-		if (EditorGUI.EndChangeCheck()) {
-			containsOverrides = mode.enumValueIndex == 1;
-			containsFollows = mode.enumValueIndex == 0;
+
 		}
 
-		EditorGUI.BeginDisabledGroup(multiObject);
-		{
-			string str = boneName.stringValue;
-			if (str == "")
-				str = "<None>";
-			if (multiObject)
-				str = "<Multiple>";
+		void EvaluateFlags () {
+			utilityBone = (SkeletonUtilityBone)target;
+			skeletonUtility = utilityBone.skeletonUtility;
 
-			GUILayout.BeginHorizontal();
-			EditorGUILayout.PrefixLabel("Bone");
+			if (Selection.objects.Length == 1) {
+				containsFollows = utilityBone.mode == SkeletonUtilityBone.Mode.Follow;
+				containsOverrides = utilityBone.mode == SkeletonUtilityBone.Mode.Override;
+			} else {
+				int boneCount = 0;
+				foreach (Object o in Selection.objects) {
+					if (o is GameObject) {
+						GameObject go = (GameObject)o;
+						SkeletonUtilityBone sub = go.GetComponent<SkeletonUtilityBone>();
+						if (sub != null) {
+							boneCount++;
+							if (sub.mode == SkeletonUtilityBone.Mode.Follow)
+								containsFollows = true;
+							if (sub.mode == SkeletonUtilityBone.Mode.Override)
+								containsOverrides = true;
+						}
+					}
+				}
 
-			if (GUILayout.Button(str, EditorStyles.popup)) {
-				BoneSelectorContextMenu(str, ((SkeletonUtilityBone)target).skeletonUtility.skeletonRenderer.skeleton.Bones, "<None>", TargetBoneSelected);
+				if (boneCount > 1)
+					multiObject = true;
 			}
-
-			GUILayout.EndHorizontal();
 		}
-		EditorGUI.EndDisabledGroup();
 
-		EditorGUILayout.PropertyField(zPosition);
-		EditorGUILayout.PropertyField(position);
-		EditorGUILayout.PropertyField(rotation);
-		EditorGUILayout.PropertyField(scale);
-		// MITCH
-//		EditorGUILayout.PropertyField(flip);
+		public override void OnInspectorGUI () {
+			serializedObject.Update();
 
-		EditorGUI.BeginDisabledGroup(containsFollows);
-		{
-			EditorGUILayout.PropertyField(overrideAlpha);
-			EditorGUILayout.PropertyField(parentReference);
+			EditorGUI.BeginChangeCheck();
+			EditorGUILayout.PropertyField(mode);
+			if (EditorGUI.EndChangeCheck()) {
+				containsOverrides = mode.enumValueIndex == 1;
+				containsFollows = mode.enumValueIndex == 0;
+			}
 
-			// MITCH
-//			EditorGUI.BeginDisabledGroup(multiObject || !flip.boolValue);
-//			{
-//				EditorGUI.BeginChangeCheck();
-//				EditorGUILayout.PropertyField(flipX);
-//				if (EditorGUI.EndChangeCheck()) {
-//					FlipX(flipX.boolValue);
-//				}
-//			}
-//			EditorGUI.EndDisabledGroup();
+			EditorGUI.BeginDisabledGroup(multiObject);
+			{
+				string str = boneName.stringValue;
+				if (str == "")
+					str = "<None>";
+				if (multiObject)
+					str = "<Multiple>";
 
-		}
-		EditorGUI.EndDisabledGroup();
+				GUILayout.BeginHorizontal();
+				EditorGUILayout.PrefixLabel("Bone");
 
-		EditorGUILayout.Space();
+				if (GUILayout.Button(str, EditorStyles.popup)) {
+					BoneSelectorContextMenu(str, ((SkeletonUtilityBone)target).skeletonUtility.skeletonRenderer.skeleton.Bones, "<None>", TargetBoneSelected);
+				}
 
-		GUILayout.BeginHorizontal();
-		{
-			EditorGUI.BeginDisabledGroup(multiObject || !utilityBone.valid || utilityBone.bone == null || utilityBone.bone.Children.Count == 0);
-			{
-				if (GUILayout.Button(new GUIContent("Add Child", SpineEditorUtilities.Icons.bone), GUILayout.Width(150), GUILayout.Height(24)))
-					BoneSelectorContextMenu("", utilityBone.bone.Children, "<Recursively>", SpawnChildBoneSelected);
+				GUILayout.EndHorizontal();
 			}
 			EditorGUI.EndDisabledGroup();
 
-			EditorGUI.BeginDisabledGroup(multiObject || !utilityBone.valid || utilityBone.bone == null || containsOverrides);
+			EditorGUILayout.PropertyField(zPosition);
+			EditorGUILayout.PropertyField(position);
+			EditorGUILayout.PropertyField(rotation);
+			EditorGUILayout.PropertyField(scale);
+			// MITCH
+			//		EditorGUILayout.PropertyField(flip);
+
+			EditorGUI.BeginDisabledGroup(containsFollows);
 			{
-				if (GUILayout.Button(new GUIContent("Add Override", SpineEditorUtilities.Icons.poseBones), GUILayout.Width(150), GUILayout.Height(24)))
-					SpawnOverride();
+				EditorGUILayout.PropertyField(overrideAlpha);
+				EditorGUILayout.PropertyField(parentReference);
+
+				// MITCH
+				//			EditorGUI.BeginDisabledGroup(multiObject || !flip.boolValue);
+				//			{
+				//				EditorGUI.BeginChangeCheck();
+				//				EditorGUILayout.PropertyField(flipX);
+				//				if (EditorGUI.EndChangeCheck()) {
+				//					FlipX(flipX.boolValue);
+				//				}
+				//			}
+				//			EditorGUI.EndDisabledGroup();
+
 			}
 			EditorGUI.EndDisabledGroup();
 
-			EditorGUI.BeginDisabledGroup(multiObject || !utilityBone.valid || !canCreateHingeChain);
+			EditorGUILayout.Space();
+
+			GUILayout.BeginHorizontal();
 			{
-				if (GUILayout.Button(new GUIContent("Create Hinge Chain", SpineEditorUtilities.Icons.hingeChain), GUILayout.Width(150), GUILayout.Height(24)))
-					CreateHingeChain();
-			}
-			EditorGUI.EndDisabledGroup();
+				EditorGUI.BeginDisabledGroup(multiObject || !utilityBone.valid || utilityBone.bone == null || utilityBone.bone.Children.Count == 0);
+				{
+					if (GUILayout.Button(new GUIContent("Add Child", SpineEditorUtilities.Icons.bone), GUILayout.Width(150), GUILayout.Height(24)))
+						BoneSelectorContextMenu("", utilityBone.bone.Children, "<Recursively>", SpawnChildBoneSelected);
+				}
+				EditorGUI.EndDisabledGroup();
 
-		}
-		GUILayout.EndHorizontal();
+				EditorGUI.BeginDisabledGroup(multiObject || !utilityBone.valid || utilityBone.bone == null || containsOverrides);
+				{
+					if (GUILayout.Button(new GUIContent("Add Override", SpineEditorUtilities.Icons.poseBones), GUILayout.Width(150), GUILayout.Height(24)))
+						SpawnOverride();
+				}
+				EditorGUI.EndDisabledGroup();
 
-		EditorGUI.BeginDisabledGroup(multiObject || boundingBoxTable.Count == 0);
-		EditorGUILayout.LabelField(new GUIContent("Bounding Boxes", SpineEditorUtilities.Icons.boundingBox), EditorStyles.boldLabel);
+				EditorGUI.BeginDisabledGroup(multiObject || !utilityBone.valid || !canCreateHingeChain);
+				{
+					if (GUILayout.Button(new GUIContent("Create Hinge Chain", SpineEditorUtilities.Icons.hingeChain), GUILayout.Width(150), GUILayout.Height(24)))
+						CreateHingeChain();
+				}
+				EditorGUI.EndDisabledGroup();
+
+			}
+			GUILayout.EndHorizontal();
+
+			EditorGUI.BeginDisabledGroup(multiObject || boundingBoxTable.Count == 0);
+			EditorGUILayout.LabelField(new GUIContent("Bounding Boxes", SpineEditorUtilities.Icons.boundingBox), EditorStyles.boldLabel);
+
+			foreach(var entry in boundingBoxTable){
+				EditorGUI.indentLevel++;
+				EditorGUILayout.LabelField(entry.Key.Data.Name);
+				EditorGUI.indentLevel++;
+				foreach (var box in entry.Value) {
+					GUILayout.BeginHorizontal();
+					GUILayout.Space(30);
+					if (GUILayout.Button(box.Name, GUILayout.Width(200))) {
+						var child = utilityBone.transform.FindChild("[BoundingBox]" + box.Name);
+						if (child != null) {
+							var originalCollider = child.GetComponent<PolygonCollider2D>();
+							var updatedCollider = SkeletonUtility.AddBoundingBoxAsComponent(box, child.gameObject, originalCollider.isTrigger);
+							originalCollider.points = updatedCollider.points;
+							if (EditorApplication.isPlaying)
+								Destroy(updatedCollider);
+							else
+								DestroyImmediate(updatedCollider);
+						} else {
+							utilityBone.AddBoundingBox(currentSkinName, entry.Key.Data.Name, box.Name);
+						}
 
-		foreach(var entry in boundingBoxTable){
-			EditorGUI.indentLevel++;
-			EditorGUILayout.LabelField(entry.Key.Data.Name);
-			EditorGUI.indentLevel++;
-			foreach (var box in entry.Value) {
-				GUILayout.BeginHorizontal();
-				GUILayout.Space(30);
-				if (GUILayout.Button(box.Name, GUILayout.Width(200))) {
-					var child = utilityBone.transform.FindChild("[BoundingBox]" + box.Name);
-					if (child != null) {
-						var originalCollider = child.GetComponent<PolygonCollider2D>();
-						var updatedCollider = SkeletonUtility.AddBoundingBoxAsComponent(box, child.gameObject, originalCollider.isTrigger);
-						originalCollider.points = updatedCollider.points;
-						if (EditorApplication.isPlaying)
-							Destroy(updatedCollider);
-						else
-							DestroyImmediate(updatedCollider);
-					} else {
-						utilityBone.AddBoundingBox(currentSkinName, entry.Key.Data.Name, box.Name);
 					}
-					
+					GUILayout.EndHorizontal();
 				}
-				GUILayout.EndHorizontal();
 			}
-		}
 
-		EditorGUI.EndDisabledGroup();
+			EditorGUI.EndDisabledGroup();
 
-		serializedObject.ApplyModifiedProperties();
-	}
+			serializedObject.ApplyModifiedProperties();
+		}
 
-	// MITCH
-//	void FlipX (bool state) {
-//		utilityBone.FlipX(state);
-//		if (Application.isPlaying == false) {
-//			skeletonUtility.skeletonAnimation.LateUpdate();
-//		}
-//	}
+		// MITCH
+		//	void FlipX (bool state) {
+		//		utilityBone.FlipX(state);
+		//		if (Application.isPlaying == false) {
+		//			skeletonUtility.skeletonAnimation.LateUpdate();
+		//		}
+		//	}
 
-	void BoneSelectorContextMenu (string current, ExposedList<Bone> bones, string topValue, GenericMenu.MenuFunction2 callback) {
-		GenericMenu menu = new GenericMenu();
+		void BoneSelectorContextMenu (string current, ExposedList<Bone> bones, string topValue, GenericMenu.MenuFunction2 callback) {
+			GenericMenu menu = new GenericMenu();
 
-		if (topValue != "")
-			menu.AddItem(new GUIContent(topValue), current == topValue, callback, null);
+			if (topValue != "")
+				menu.AddItem(new GUIContent(topValue), current == topValue, callback, null);
 
-		for (int i = 0; i < bones.Count; i++) {
-			menu.AddItem(new GUIContent(bones.Items[i].Data.Name), bones.Items[i].Data.Name == current, callback, bones.Items[i]);
-		}
+			for (int i = 0; i < bones.Count; i++) {
+				menu.AddItem(new GUIContent(bones.Items[i].Data.Name), bones.Items[i].Data.Name == current, callback, bones.Items[i]);
+			}
 
-		menu.ShowAsContext();
+			menu.ShowAsContext();
 
-	}
+		}
 
-	void TargetBoneSelected (object obj) {
-		if (obj == null) {
-			boneName.stringValue = "";
-			serializedObject.ApplyModifiedProperties();
-		} else {
-			Bone bone = (Bone)obj;
-			boneName.stringValue = bone.Data.Name;
-			serializedObject.ApplyModifiedProperties();
+		void TargetBoneSelected (object obj) {
+			if (obj == null) {
+				boneName.stringValue = "";
+				serializedObject.ApplyModifiedProperties();
+			} else {
+				Bone bone = (Bone)obj;
+				boneName.stringValue = bone.Data.Name;
+				serializedObject.ApplyModifiedProperties();
 
-			utilityBone.Reset();
+				utilityBone.Reset();
+			}
 		}
-	}
 
-	void SpawnChildBoneSelected (object obj) {
-		if (obj == null) {
-			//add recursively
-			foreach (var bone in utilityBone.bone.Children) {
-				GameObject go = skeletonUtility.SpawnBoneRecursively(bone, utilityBone.transform, utilityBone.mode, utilityBone.position, utilityBone.rotation, utilityBone.scale);
-				SkeletonUtilityBone[] newUtilityBones = go.GetComponentsInChildren<SkeletonUtilityBone>();
-				foreach (SkeletonUtilityBone utilBone in newUtilityBones)
-					SkeletonUtilityInspector.AttachIcon(utilBone);
+		void SpawnChildBoneSelected (object obj) {
+			if (obj == null) {
+				//add recursively
+				foreach (var bone in utilityBone.bone.Children) {
+					GameObject go = skeletonUtility.SpawnBoneRecursively(bone, utilityBone.transform, utilityBone.mode, utilityBone.position, utilityBone.rotation, utilityBone.scale);
+					SkeletonUtilityBone[] newUtilityBones = go.GetComponentsInChildren<SkeletonUtilityBone>();
+					foreach (SkeletonUtilityBone utilBone in newUtilityBones)
+						SkeletonUtilityInspector.AttachIcon(utilBone);
+				}
+			} else {
+				Bone bone = (Bone)obj;
+				GameObject go = skeletonUtility.SpawnBone(bone, utilityBone.transform, utilityBone.mode, utilityBone.position, utilityBone.rotation, utilityBone.scale);
+				SkeletonUtilityInspector.AttachIcon(go.GetComponent<SkeletonUtilityBone>());
+				Selection.activeGameObject = go;
+				EditorGUIUtility.PingObject(go);
 			}
-		} else {
-			Bone bone = (Bone)obj;
-			GameObject go = skeletonUtility.SpawnBone(bone, utilityBone.transform, utilityBone.mode, utilityBone.position, utilityBone.rotation, utilityBone.scale);
+		}
+
+		void SpawnOverride () {
+			GameObject go = skeletonUtility.SpawnBone(utilityBone.bone, utilityBone.transform.parent, SkeletonUtilityBone.Mode.Override, utilityBone.position, utilityBone.rotation, utilityBone.scale);
+			go.name = go.name + " [Override]";
 			SkeletonUtilityInspector.AttachIcon(go.GetComponent<SkeletonUtilityBone>());
 			Selection.activeGameObject = go;
 			EditorGUIUtility.PingObject(go);
 		}
-	}
 
-	void SpawnOverride () {
-		GameObject go = skeletonUtility.SpawnBone(utilityBone.bone, utilityBone.transform.parent, SkeletonUtilityBone.Mode.Override, utilityBone.position, utilityBone.rotation, utilityBone.scale);
-		go.name = go.name + " [Override]";
-		SkeletonUtilityInspector.AttachIcon(go.GetComponent<SkeletonUtilityBone>());
-		Selection.activeGameObject = go;
-		EditorGUIUtility.PingObject(go);
-	}
+		bool CanCreateHingeChain () {
+			if (utilityBone == null)
+				return false;
+			if (utilityBone.GetComponent<Rigidbody>() != null)
+				return false;
+			if (utilityBone.bone != null && utilityBone.bone.Children.Count == 0)
+				return false;
 
-	bool CanCreateHingeChain () {
-		if (utilityBone == null)
-			return false;
-		if (utilityBone.GetComponent<Rigidbody>() != null)
-			return false;
-		if (utilityBone.bone != null && utilityBone.bone.Children.Count == 0)
-			return false;
+			Rigidbody[] rigidbodies = utilityBone.GetComponentsInChildren<Rigidbody>();
 
-		Rigidbody[] rigidbodies = utilityBone.GetComponentsInChildren<Rigidbody>();
+			if (rigidbodies.Length > 0)
+				return false;
 
-		if (rigidbodies.Length > 0)
-			return false;
-
-		return true;
-	}
+			return true;
+		}
 
-	void CreateHingeChain () {
-		var utilBoneArr = utilityBone.GetComponentsInChildren<SkeletonUtilityBone>();
+		void CreateHingeChain () {
+			var utilBoneArr = utilityBone.GetComponentsInChildren<SkeletonUtilityBone>();
 
-		foreach (var utilBone in utilBoneArr) {
-			AttachRigidbody(utilBone);
-		}
+			foreach (var utilBone in utilBoneArr) {
+				AttachRigidbody(utilBone);
+			}
 
-		utilityBone.GetComponent<Rigidbody>().isKinematic = true;
+			utilityBone.GetComponent<Rigidbody>().isKinematic = true;
 
-		foreach (var utilBone in utilBoneArr) {
-			if (utilBone == utilityBone)
-				continue;
+			foreach (var utilBone in utilBoneArr) {
+				if (utilBone == utilityBone)
+					continue;
 
-			utilBone.mode = SkeletonUtilityBone.Mode.Override;
+				utilBone.mode = SkeletonUtilityBone.Mode.Override;
 
-			HingeJoint joint = utilBone.gameObject.AddComponent<HingeJoint>();
-			joint.axis = Vector3.forward;
-			joint.connectedBody = utilBone.transform.parent.GetComponent<Rigidbody>();
-			joint.useLimits = true;
-			JointLimits limits = new JointLimits();
-			limits.min = -20;
-			limits.max = 20;
-			joint.limits = limits;
-			utilBone.GetComponent<Rigidbody>().mass = utilBone.transform.parent.GetComponent<Rigidbody>().mass * 0.75f;
-		}
-	}
-	
-	static void AttachRigidbody (SkeletonUtilityBone utilBone) {
-		if (utilBone.GetComponent<Collider>() == null) {
-			if (utilBone.bone.Data.Length == 0) {
-				SphereCollider sphere = utilBone.gameObject.AddComponent<SphereCollider>();
-				sphere.radius = 0.1f;
-			} else {
-				float length = utilBone.bone.Data.Length;
-				BoxCollider box = utilBone.gameObject.AddComponent<BoxCollider>();
-				box.size = new Vector3(length, length / 3, 0.2f);
-				box.center = new Vector3(length / 2, 0, 0);
+				HingeJoint joint = utilBone.gameObject.AddComponent<HingeJoint>();
+				joint.axis = Vector3.forward;
+				joint.connectedBody = utilBone.transform.parent.GetComponent<Rigidbody>();
+				joint.useLimits = true;
+				JointLimits limits = new JointLimits();
+				limits.min = -20;
+				limits.max = 20;
+				joint.limits = limits;
+				utilBone.GetComponent<Rigidbody>().mass = utilBone.transform.parent.GetComponent<Rigidbody>().mass * 0.75f;
 			}
 		}
 
-		utilBone.gameObject.AddComponent<Rigidbody>();
+		static void AttachRigidbody (SkeletonUtilityBone utilBone) {
+			if (utilBone.GetComponent<Collider>() == null) {
+				if (utilBone.bone.Data.Length == 0) {
+					SphereCollider sphere = utilBone.gameObject.AddComponent<SphereCollider>();
+					sphere.radius = 0.1f;
+				} else {
+					float length = utilBone.bone.Data.Length;
+					BoxCollider box = utilBone.gameObject.AddComponent<BoxCollider>();
+					box.size = new Vector3(length, length / 3, 0.2f);
+					box.center = new Vector3(length / 2, 0, 0);
+				}
+			}
+
+			utilBone.gameObject.AddComponent<Rigidbody>();
+		}
 	}
+
 }

+ 196 - 192
spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs

@@ -18,264 +18,268 @@ using Spine;
 
 using System.Reflection;
 
-[CustomEditor(typeof(SkeletonUtility))]
-public class SkeletonUtilityInspector : Editor {
-
-	public static void AttachIcon (SkeletonUtilityBone utilityBone) {
-		Skeleton skeleton = utilityBone.skeletonUtility.skeletonRenderer.skeleton;
-		Texture2D icon;
-		if (utilityBone.bone.Data.Length == 0)
-			icon = SpineEditorUtilities.Icons.nullBone;
-		else
-			icon = SpineEditorUtilities.Icons.boneNib;
-		
-		foreach (IkConstraint c in skeleton.IkConstraints) {
-			if (c.Target == utilityBone.bone) {
-				icon = SpineEditorUtilities.Icons.constraintNib;
-				break;
+
+namespace Spine.Unity.Editor {
+	[CustomEditor(typeof(SkeletonUtility))]
+	public class SkeletonUtilityInspector : UnityEditor.Editor {
+
+		public static void AttachIcon (SkeletonUtilityBone utilityBone) {
+			Skeleton skeleton = utilityBone.skeletonUtility.skeletonRenderer.skeleton;
+			Texture2D icon;
+			if (utilityBone.bone.Data.Length == 0)
+				icon = SpineEditorUtilities.Icons.nullBone;
+			else
+				icon = SpineEditorUtilities.Icons.boneNib;
+
+			foreach (IkConstraint c in skeleton.IkConstraints) {
+				if (c.Target == utilityBone.bone) {
+					icon = SpineEditorUtilities.Icons.constraintNib;
+					break;
+				}
 			}
-		}
 
-		typeof(EditorGUIUtility).InvokeMember("SetIconForObject", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic, null, null, new object[2] {
-			utilityBone.gameObject,
-			icon
-		});
-	}
+			typeof(EditorGUIUtility).InvokeMember("SetIconForObject", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic, null, null, new object[2] {
+				utilityBone.gameObject,
+				icon
+			});
+		}
 
-	static void AttachIconsToChildren (Transform root) {
-		if (root != null) {
-			var utilityBones = root.GetComponentsInChildren<SkeletonUtilityBone>();
-			foreach (var utilBone in utilityBones) {
-				AttachIcon(utilBone);
+		static void AttachIconsToChildren (Transform root) {
+			if (root != null) {
+				var utilityBones = root.GetComponentsInChildren<SkeletonUtilityBone>();
+				foreach (var utilBone in utilityBones) {
+					AttachIcon(utilBone);
+				}
 			}
 		}
-	}
 
-	static SkeletonUtilityInspector () {
+		static SkeletonUtilityInspector () {
+			#if UNITY_4_3
+			showSlots = false;
+			#else
+			showSlots = new AnimBool(false);
+			#endif
+		}
+
+		SkeletonUtility skeletonUtility;
+		Skeleton skeleton;
+		SkeletonRenderer skeletonRenderer;
+		Transform transform;
+		bool isPrefab;
+		Dictionary<Slot, List<Attachment>> attachmentTable = new Dictionary<Slot, List<Attachment>>();
+
+
+		//GUI stuff
 		#if UNITY_4_3
-		showSlots = false;
+		static bool showSlots;
 		#else
-		showSlots = new AnimBool(false);
+		static AnimBool showSlots;
 		#endif
-	}
 
-	SkeletonUtility skeletonUtility;
-	Skeleton skeleton;
-	SkeletonRenderer skeletonRenderer;
-	Transform transform;
-	bool isPrefab;
-	Dictionary<Slot, List<Attachment>> attachmentTable = new Dictionary<Slot, List<Attachment>>();
+		void OnEnable () {
+			skeletonUtility = (SkeletonUtility)target;
+			skeletonRenderer = skeletonUtility.GetComponent<SkeletonRenderer>();
+			skeleton = skeletonRenderer.skeleton;
+			transform = skeletonRenderer.transform;
 
+			if (skeleton == null) {
+				skeletonRenderer.Initialize(false);
+				skeletonRenderer.LateUpdate();
 
-	//GUI stuff
-#if UNITY_4_3
-	static bool showSlots;
-#else
-	static AnimBool showSlots;
-#endif
+				skeleton = skeletonRenderer.skeleton;
+			}
 
-	void OnEnable () {
-		skeletonUtility = (SkeletonUtility)target;
-		skeletonRenderer = skeletonUtility.GetComponent<SkeletonRenderer>();
-		skeleton = skeletonRenderer.skeleton;
-		transform = skeletonRenderer.transform;
+			UpdateAttachments();
 
-		if (skeleton == null) {
-			skeletonRenderer.Initialize(false);
-			skeletonRenderer.LateUpdate();
+			if (PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab)
+				isPrefab = true;
 
-			skeleton = skeletonRenderer.skeleton;
 		}
 
-		UpdateAttachments();
+		void OnSceneGUI () {
+			if (skeleton == null) {
+				OnEnable();
+				return;
+			}
 
-		if (PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab)
-			isPrefab = true;
+			// MITCH
+			//float flipRotation = skeleton.FlipX ? -1 : 1;
+			const float flipRotation = 1;
 
-	}
+			foreach (Bone b in skeleton.Bones) {
+				Vector3 vec = transform.TransformPoint(new Vector3(b.WorldX, b.WorldY, 0));
+
+				// MITCH
+				Quaternion rot = Quaternion.Euler(0, 0, b.WorldRotationX * flipRotation);
+				Vector3 forward = transform.TransformDirection(rot * Vector3.right);
+				forward *= flipRotation;
 
-	void OnSceneGUI () {
-		if (skeleton == null) {
-			OnEnable();
-			return;
+				SpineEditorUtilities.Icons.boneMaterial.SetPass(0);
+				Graphics.DrawMeshNow(SpineEditorUtilities.Icons.boneMesh, Matrix4x4.TRS(vec, Quaternion.LookRotation(transform.forward, forward), Vector3.one * b.Data.Length * b.WorldScaleX));
+			}
 		}
 
-		// MITCH
-		//float flipRotation = skeleton.FlipX ? -1 : 1;
-		const float flipRotation = 1;
+		void UpdateAttachments () {
+			attachmentTable = new Dictionary<Slot, List<Attachment>>();
+			Skin skin = skeleton.Skin;
 
-		foreach (Bone b in skeleton.Bones) {
-			Vector3 vec = transform.TransformPoint(new Vector3(b.WorldX, b.WorldY, 0));
+			if (skin == null) {
+				skin = skeletonRenderer.skeletonDataAsset.GetSkeletonData(true).DefaultSkin;
+			}
 
-			// MITCH
-			Quaternion rot = Quaternion.Euler(0, 0, b.WorldRotationX * flipRotation);
-			Vector3 forward = transform.TransformDirection(rot * Vector3.right);
-			forward *= flipRotation;
+			for (int i = skeleton.Slots.Count-1; i >= 0; i--) {
+				List<Attachment> attachments = new List<Attachment>();
+				skin.FindAttachmentsForSlot(i, attachments);
 
-			SpineEditorUtilities.Icons.boneMaterial.SetPass(0);
-			Graphics.DrawMeshNow(SpineEditorUtilities.Icons.boneMesh, Matrix4x4.TRS(vec, Quaternion.LookRotation(transform.forward, forward), Vector3.one * b.Data.Length * b.WorldScaleX));
+				attachmentTable.Add(skeleton.Slots.Items[i], attachments);
+			}
 		}
-	}
 
-	void UpdateAttachments () {
-		attachmentTable = new Dictionary<Slot, List<Attachment>>();
-		Skin skin = skeleton.Skin;
+		void SpawnHierarchyButton (string label, string tooltip, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca, params GUILayoutOption[] options) {
+			GUIContent content = new GUIContent(label, tooltip);
+			if (GUILayout.Button(content, options)) {
+				if (skeletonUtility.skeletonRenderer == null)
+					skeletonUtility.skeletonRenderer = skeletonUtility.GetComponent<SkeletonRenderer>();
 
-		if (skin == null) {
-			skin = skeletonRenderer.skeletonDataAsset.GetSkeletonData(true).DefaultSkin;
-		}
+				if (skeletonUtility.boneRoot != null) {
+					return;
+				}
 
-		for (int i = skeleton.Slots.Count-1; i >= 0; i--) {
-			List<Attachment> attachments = new List<Attachment>();
-			skin.FindAttachmentsForSlot(i, attachments);
+				skeletonUtility.SpawnHierarchy(mode, pos, rot, sca);
 
-			attachmentTable.Add(skeleton.Slots.Items[i], attachments);
+				SkeletonUtilityBone[] boneComps = skeletonUtility.GetComponentsInChildren<SkeletonUtilityBone>();
+				foreach (SkeletonUtilityBone b in boneComps) 
+					AttachIcon(b);
+			}
 		}
-	}
-
-	void SpawnHierarchyButton (string label, string tooltip, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca, params GUILayoutOption[] options) {
-		GUIContent content = new GUIContent(label, tooltip);
-		if (GUILayout.Button(content, options)) {
-			if (skeletonUtility.skeletonRenderer == null)
-				skeletonUtility.skeletonRenderer = skeletonUtility.GetComponent<SkeletonRenderer>();
 
-			if (skeletonUtility.boneRoot != null) {
+		public override void OnInspectorGUI () {
+			if (isPrefab) {
+				GUILayout.Label(new GUIContent("Cannot edit Prefabs", SpineEditorUtilities.Icons.warning));
 				return;
 			}
 
-			skeletonUtility.SpawnHierarchy(mode, pos, rot, sca);
+			skeletonUtility.boneRoot = (Transform)EditorGUILayout.ObjectField("Bone Root", skeletonUtility.boneRoot, typeof(Transform), true);
 
-			SkeletonUtilityBone[] boneComps = skeletonUtility.GetComponentsInChildren<SkeletonUtilityBone>();
-			foreach (SkeletonUtilityBone b in boneComps) 
-				AttachIcon(b);
-		}
-	}
-
-	public override void OnInspectorGUI () {
-		if (isPrefab) {
-			GUILayout.Label(new GUIContent("Cannot edit Prefabs", SpineEditorUtilities.Icons.warning));
-			return;
-		}
-
-		skeletonUtility.boneRoot = (Transform)EditorGUILayout.ObjectField("Bone Root", skeletonUtility.boneRoot, typeof(Transform), true);
-
-		GUILayout.BeginHorizontal();
-		EditorGUI.BeginDisabledGroup(skeletonUtility.boneRoot != null);
-		{
-			if (GUILayout.Button(new GUIContent("Spawn Hierarchy", SpineEditorUtilities.Icons.skeleton), GUILayout.Width(150), GUILayout.Height(24)))
-				SpawnHierarchyContextMenu();
-		}
-		EditorGUI.EndDisabledGroup();
+			GUILayout.BeginHorizontal();
+			EditorGUI.BeginDisabledGroup(skeletonUtility.boneRoot != null);
+			{
+				if (GUILayout.Button(new GUIContent("Spawn Hierarchy", SpineEditorUtilities.Icons.skeleton), GUILayout.Width(150), GUILayout.Height(24)))
+					SpawnHierarchyContextMenu();
+			}
+			EditorGUI.EndDisabledGroup();
 
-//		if (GUILayout.Button(new GUIContent("Spawn Submeshes", SpineEditorUtilities.Icons.subMeshRenderer), GUILayout.Width(150), GUILayout.Height(24)))
-//			skeletonUtility.SpawnSubRenderers(true);
+			//		if (GUILayout.Button(new GUIContent("Spawn Submeshes", SpineEditorUtilities.Icons.subMeshRenderer), GUILayout.Width(150), GUILayout.Height(24)))
+			//			skeletonUtility.SpawnSubRenderers(true);
 
-		GUILayout.EndHorizontal();
+			GUILayout.EndHorizontal();
 
-		EditorGUI.BeginChangeCheck();
-		skeleton.FlipX = EditorGUILayout.ToggleLeft("Flip X", skeleton.FlipX);
-		skeleton.FlipY = EditorGUILayout.ToggleLeft("Flip Y", skeleton.FlipY);
-		if (EditorGUI.EndChangeCheck()) {
-			skeletonRenderer.LateUpdate();
-			SceneView.RepaintAll();
-		}
+			EditorGUI.BeginChangeCheck();
+			skeleton.FlipX = EditorGUILayout.ToggleLeft("Flip X", skeleton.FlipX);
+			skeleton.FlipY = EditorGUILayout.ToggleLeft("Flip Y", skeleton.FlipY);
+			if (EditorGUI.EndChangeCheck()) {
+				skeletonRenderer.LateUpdate();
+				SceneView.RepaintAll();
+			}
 
-#if UNITY_4_3
-		showSlots = EditorGUILayout.Foldout(showSlots, "Slots");
-#else
-		showSlots.target = EditorGUILayout.Foldout(showSlots.target, "Slots");
-		if (EditorGUILayout.BeginFadeGroup(showSlots.faded)) {
-#endif
-			foreach (KeyValuePair<Slot, List<Attachment>> pair in attachmentTable) {
+			#if UNITY_4_3
+			showSlots = EditorGUILayout.Foldout(showSlots, "Slots");
+			#else
+			showSlots.target = EditorGUILayout.Foldout(showSlots.target, "Slots");
+			if (EditorGUILayout.BeginFadeGroup(showSlots.faded)) {
+			#endif
+				foreach (KeyValuePair<Slot, List<Attachment>> pair in attachmentTable) {
 
-				Slot slot = pair.Key;
+					Slot slot = pair.Key;
 
-				EditorGUILayout.BeginHorizontal();
-				EditorGUI.indentLevel = 1;
-				EditorGUILayout.LabelField(new GUIContent(slot.Data.Name, SpineEditorUtilities.Icons.slot), GUILayout.ExpandWidth(false));
+					EditorGUILayout.BeginHorizontal();
+					EditorGUI.indentLevel = 1;
+					EditorGUILayout.LabelField(new GUIContent(slot.Data.Name, SpineEditorUtilities.Icons.slot), GUILayout.ExpandWidth(false));
 
-				EditorGUI.BeginChangeCheck();
-				Color c = EditorGUILayout.ColorField(new Color(slot.R, slot.G, slot.B, slot.A), GUILayout.Width(60));
+					EditorGUI.BeginChangeCheck();
+					Color c = EditorGUILayout.ColorField(new Color(slot.R, slot.G, slot.B, slot.A), GUILayout.Width(60));
 
-				if (EditorGUI.EndChangeCheck()) {
-					slot.SetColor(c);
-					skeletonRenderer.LateUpdate();
-				}
+					if (EditorGUI.EndChangeCheck()) {
+						slot.SetColor(c);
+						skeletonRenderer.LateUpdate();
+					}
 
-				EditorGUILayout.EndHorizontal();
+					EditorGUILayout.EndHorizontal();
 
 
 
-				foreach (Attachment attachment in pair.Value) {
+					foreach (Attachment attachment in pair.Value) {
 
-					if (slot.Attachment == attachment) {
-						GUI.contentColor = Color.white;
-					} else {
-						GUI.contentColor = Color.grey;
-					}
+						if (slot.Attachment == attachment) {
+							GUI.contentColor = Color.white;
+						} else {
+							GUI.contentColor = Color.grey;
+						}
 
-					EditorGUI.indentLevel = 2;
-					bool isAttached = attachment == slot.Attachment;
+						EditorGUI.indentLevel = 2;
+						bool isAttached = attachment == slot.Attachment;
 
-					Texture2D icon = null;
+						Texture2D icon = null;
 
-					if (attachment is MeshAttachment || attachment is WeightedMeshAttachment)
-						icon = SpineEditorUtilities.Icons.mesh;
-					else
-						icon = SpineEditorUtilities.Icons.image;
+						if (attachment is MeshAttachment || attachment is WeightedMeshAttachment)
+							icon = SpineEditorUtilities.Icons.mesh;
+						else
+							icon = SpineEditorUtilities.Icons.image;
 
-					bool swap = EditorGUILayout.ToggleLeft(new GUIContent(attachment.Name, icon), attachment == slot.Attachment);
+						bool swap = EditorGUILayout.ToggleLeft(new GUIContent(attachment.Name, icon), attachment == slot.Attachment);
 
-					if (!isAttached && swap) {
-						slot.Attachment = attachment;
-						skeletonRenderer.LateUpdate();
-					} else if (isAttached && !swap) {
+						if (!isAttached && swap) {
+							slot.Attachment = attachment;
+							skeletonRenderer.LateUpdate();
+						} else if (isAttached && !swap) {
 							slot.Attachment = null;
 							skeletonRenderer.LateUpdate();
 						}
 
-					GUI.contentColor = Color.white;
+						GUI.contentColor = Color.white;
+					}
 				}
-			}
-			#if UNITY_4_3
+				#if UNITY_4_3
 
-#else
+				#else
+			}
+			EditorGUILayout.EndFadeGroup();
+			if (showSlots.isAnimating)
+				Repaint();
+				#endif
 		}
-		EditorGUILayout.EndFadeGroup();
-		if (showSlots.isAnimating)
-			Repaint();
-#endif
-	}
 
-	void SpawnHierarchyContextMenu () {
-		GenericMenu menu = new GenericMenu();
+		void SpawnHierarchyContextMenu () {
+			GenericMenu menu = new GenericMenu();
 
-		menu.AddItem(new GUIContent("Follow"), false, SpawnFollowHierarchy);
-		menu.AddItem(new GUIContent("Follow (Root Only)"), false, SpawnFollowHierarchyRootOnly);
-		menu.AddSeparator("");
-		menu.AddItem(new GUIContent("Override"), false, SpawnOverrideHierarchy);
-		menu.AddItem(new GUIContent("Override (Root Only)"), false, SpawnOverrideHierarchyRootOnly);
+			menu.AddItem(new GUIContent("Follow"), false, SpawnFollowHierarchy);
+			menu.AddItem(new GUIContent("Follow (Root Only)"), false, SpawnFollowHierarchyRootOnly);
+			menu.AddSeparator("");
+			menu.AddItem(new GUIContent("Override"), false, SpawnOverrideHierarchy);
+			menu.AddItem(new GUIContent("Override (Root Only)"), false, SpawnOverrideHierarchyRootOnly);
 
-		menu.ShowAsContext();
-	}
+			menu.ShowAsContext();
+		}
 
-	void SpawnFollowHierarchy () {
-		Selection.activeGameObject = skeletonUtility.SpawnHierarchy(SkeletonUtilityBone.Mode.Follow, true, true, true);
-		AttachIconsToChildren(skeletonUtility.boneRoot);
-	}
+		void SpawnFollowHierarchy () {
+			Selection.activeGameObject = skeletonUtility.SpawnHierarchy(SkeletonUtilityBone.Mode.Follow, true, true, true);
+			AttachIconsToChildren(skeletonUtility.boneRoot);
+		}
 
-	void SpawnFollowHierarchyRootOnly () {
-		Selection.activeGameObject = skeletonUtility.SpawnRoot(SkeletonUtilityBone.Mode.Follow, true, true, true);
-		AttachIconsToChildren(skeletonUtility.boneRoot);
-	}
+		void SpawnFollowHierarchyRootOnly () {
+			Selection.activeGameObject = skeletonUtility.SpawnRoot(SkeletonUtilityBone.Mode.Follow, true, true, true);
+			AttachIconsToChildren(skeletonUtility.boneRoot);
+		}
 
-	void SpawnOverrideHierarchy () {
-		Selection.activeGameObject = skeletonUtility.SpawnHierarchy(SkeletonUtilityBone.Mode.Override, true, true, true);
-		AttachIconsToChildren(skeletonUtility.boneRoot);
-	}
-	
-	void SpawnOverrideHierarchyRootOnly () {
-		Selection.activeGameObject = skeletonUtility.SpawnRoot(SkeletonUtilityBone.Mode.Override, true, true, true);
-		AttachIconsToChildren(skeletonUtility.boneRoot);
+		void SpawnOverrideHierarchy () {
+			Selection.activeGameObject = skeletonUtility.SpawnHierarchy(SkeletonUtilityBone.Mode.Override, true, true, true);
+			AttachIconsToChildren(skeletonUtility.boneRoot);
+		}
+
+		void SpawnOverrideHierarchyRootOnly () {
+			Selection.activeGameObject = skeletonUtility.SpawnRoot(SkeletonUtilityBone.Mode.Override, true, true, true);
+			AttachIconsToChildren(skeletonUtility.boneRoot);
+		}
 	}
+
 }

+ 49 - 0
spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilitySubmeshRendererInspector.cs

@@ -0,0 +1,49 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ * 
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ * 
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+using UnityEngine;
+using UnityEditor;
+using Spine.Unity.Editor;
+
+namespace Spine.Unity.Modules {
+	[CustomEditor(typeof(SkeletonUtilitySubmeshRenderer))]
+	public class SkeletonUtilitySubmeshRendererInspector : UnityEditor.Editor {
+		public SpineInspectorUtility.SerializedSortingProperties sorting;
+
+		void OnEnable () {			
+			sorting = new SpineInspectorUtility.SerializedSortingProperties((target as Component).GetComponent<Renderer>());
+		}
+
+		public override void OnInspectorGUI () {
+			EditorGUILayout.HelpBox("SkeletonUtilitySubmeshRenderer is now obsolete. We recommend using SkeletonRenderSeparator.", MessageType.Info);
+			SpineInspectorUtility.SortingPropertyFields(sorting, true);
+		}
+	}
+}

+ 8 - 0
spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilitySubmeshRendererInspector.cs.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 67418e462bd4dc24e8c234b92f1d4d9b
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 

+ 264 - 261
spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs

@@ -10,49 +10,76 @@ using System.Collections;
 using System.Collections.Generic;
 using Spine;
 
-[RequireComponent(typeof(ISkeletonAnimation))]
-[ExecuteInEditMode]
-public class SkeletonUtility : MonoBehaviour {
-
-	public static T GetInParent<T> (Transform origin) where T : Component {
-#if UNITY_4_3
-		Transform parent = origin.parent;
-		while(parent.GetComponent<T>() == null){
+namespace Spine.Unity {
+	[RequireComponent(typeof(ISkeletonAnimation))]
+	[ExecuteInEditMode]
+	public class SkeletonUtility : MonoBehaviour {
+
+		public static T GetInParent<T> (Transform origin) where T : Component {
+			#if UNITY_4_3
+			Transform parent = origin.parent;
+			while(parent.GetComponent<T>() == null){
 			parent = parent.parent;
 			if(parent == null)
-				return default(T);
+			return default(T);
+			}
+
+			return parent.GetComponent<T>();
+			#else
+			return origin.GetComponentInParent<T>();
+			#endif
 		}
 
-		return parent.GetComponent<T>();
-#else
-		return origin.GetComponentInParent<T>();
-#endif
-	}
+		public static PolygonCollider2D AddBoundingBox (Skeleton skeleton, string skinName, string slotName, string attachmentName, Transform parent, bool isTrigger = true) {
+			// List<Attachment> attachments = new List<Attachment>();
+			Skin skin;
 
-	public static PolygonCollider2D AddBoundingBox (Skeleton skeleton, string skinName, string slotName, string attachmentName, Transform parent, bool isTrigger = true) {
-		// List<Attachment> attachments = new List<Attachment>();
-		Skin skin;
+			if (skinName == "")
+				skinName = skeleton.Data.DefaultSkin.Name;
 
-		if (skinName == "")
-			skinName = skeleton.Data.DefaultSkin.Name;
+			skin = skeleton.Data.FindSkin(skinName);
 
-		skin = skeleton.Data.FindSkin(skinName);
+			if (skin == null) {
+				Debug.LogError("Skin " + skinName + " not found!");
+				return null;
+			}
+
+			var attachment = skin.GetAttachment(skeleton.FindSlotIndex(slotName), attachmentName);
+			if (attachment is BoundingBoxAttachment) {
+				GameObject go = new GameObject("[BoundingBox]" + attachmentName);
+				go.transform.parent = parent;
+				go.transform.localPosition = Vector3.zero;
+				go.transform.localRotation = Quaternion.identity;
+				go.transform.localScale = Vector3.one;
+				var collider = go.AddComponent<PolygonCollider2D>();
+				collider.isTrigger = isTrigger;
+				var boundingBox = (BoundingBoxAttachment)attachment;
+				float[] floats = boundingBox.Vertices;
+				int floatCount = floats.Length;
+				int vertCount = floatCount / 2;
+
+				Vector2[] verts = new Vector2[vertCount];
+				int v = 0;
+				for (int i = 0; i < floatCount; i += 2, v++) {
+					verts[v].x = floats[i];
+					verts[v].y = floats[i + 1];
+				}
+
+				collider.SetPath(0, verts);
+
+				return collider;
+
+			}
 
-		if (skin == null) {
-			Debug.LogError("Skin " + skinName + " not found!");
 			return null;
 		}
 
-		var attachment = skin.GetAttachment(skeleton.FindSlotIndex(slotName), attachmentName);
-		if (attachment is BoundingBoxAttachment) {
-			GameObject go = new GameObject("[BoundingBox]" + attachmentName);
-			go.transform.parent = parent;
-			go.transform.localPosition = Vector3.zero;
-			go.transform.localRotation = Quaternion.identity;
-			go.transform.localScale = Vector3.one;
-			var collider = go.AddComponent<PolygonCollider2D>();
+		public static PolygonCollider2D AddBoundingBoxAsComponent (BoundingBoxAttachment boundingBox, GameObject gameObject, bool isTrigger = true) {
+			if (boundingBox == null)
+				return null;
+
+			var collider = gameObject.AddComponent<PolygonCollider2D>();
 			collider.isTrigger = isTrigger;
-			var boundingBox = (BoundingBoxAttachment)attachment;
 			float[] floats = boundingBox.Vertices;
 			int floatCount = floats.Length;
 			int vertCount = floatCount / 2;
@@ -67,318 +94,294 @@ public class SkeletonUtility : MonoBehaviour {
 			collider.SetPath(0, verts);
 
 			return collider;
-
 		}
 
-		return null;
-	}
+		public static Bounds GetBoundingBoxBounds (BoundingBoxAttachment boundingBox, float depth = 0) {
+			float[] floats = boundingBox.Vertices;
+			int floatCount = floats.Length;
 
-	public static PolygonCollider2D AddBoundingBoxAsComponent (BoundingBoxAttachment boundingBox, GameObject gameObject, bool isTrigger = true) {
-		if (boundingBox == null)
-			return null;
+			Bounds bounds = new Bounds();
 
-		var collider = gameObject.AddComponent<PolygonCollider2D>();
-		collider.isTrigger = isTrigger;
-		float[] floats = boundingBox.Vertices;
-		int floatCount = floats.Length;
-		int vertCount = floatCount / 2;
-
-		Vector2[] verts = new Vector2[vertCount];
-		int v = 0;
-		for (int i = 0; i < floatCount; i += 2, v++) {
-			verts[v].x = floats[i];
-			verts[v].y = floats[i + 1];
+			bounds.center = new Vector3(floats[0], floats[1], 0);
+			for (int i = 2; i < floatCount; i += 2) {
+				bounds.Encapsulate(new Vector3(floats[i], floats[i + 1], 0));
+			}
+			Vector3 size = bounds.size;
+			size.z = depth;
+			bounds.size = size;
+
+			return bounds;
 		}
 
-		collider.SetPath(0, verts);
+		public delegate void SkeletonUtilityDelegate ();
 
-		return collider;
-	}
+		public event SkeletonUtilityDelegate OnReset;
 
-	public static Bounds GetBoundingBoxBounds (BoundingBoxAttachment boundingBox, float depth = 0) {
-		float[] floats = boundingBox.Vertices;
-		int floatCount = floats.Length;
+		public Transform boneRoot;
 
-		Bounds bounds = new Bounds();
-
-		bounds.center = new Vector3(floats[0], floats[1], 0);
-		for (int i = 2; i < floatCount; i += 2) {
-			bounds.Encapsulate(new Vector3(floats[i], floats[i + 1], 0));
-		}
-		Vector3 size = bounds.size;
-		size.z = depth;
-		bounds.size = size;
+		void Update () {
+			if (boneRoot != null && skeletonRenderer.skeleton != null) {
+				Vector3 flipScale = Vector3.one;
+				if (skeletonRenderer.skeleton.FlipX)
+					flipScale.x = -1;
 
-		return bounds;
-	}
+				if (skeletonRenderer.skeleton.FlipY)
+					flipScale.y = -1;
 
-	public delegate void SkeletonUtilityDelegate ();
+				boneRoot.localScale = flipScale;
+			}
+		}
 
-	public event SkeletonUtilityDelegate OnReset;
+		[HideInInspector]
+		public SkeletonRenderer skeletonRenderer;
+		[HideInInspector]
+		public ISkeletonAnimation skeletonAnimation;
+		[System.NonSerialized]
+		public List<SkeletonUtilityBone> utilityBones = new List<SkeletonUtilityBone>();
+		[System.NonSerialized]
+		public List<SkeletonUtilityConstraint> utilityConstraints = new List<SkeletonUtilityConstraint>();
+		//	Dictionary<Bone, SkeletonUtilityBone> utilityBoneTable;
+
+		protected bool hasTransformBones;
+		protected bool hasUtilityConstraints;
+		protected bool needToReprocessBones;
+
+		void OnEnable () {
+			if (skeletonRenderer == null) {
+				skeletonRenderer = GetComponent<SkeletonRenderer>();
+			}
 
-	public Transform boneRoot;
+			if (skeletonAnimation == null) {
+				skeletonAnimation = GetComponent<SkeletonAnimation>();
+				if (skeletonAnimation == null)
+					skeletonAnimation = GetComponent<SkeletonAnimator>();
+			}
 
-	void Update () {
-		if (boneRoot != null && skeletonRenderer.skeleton != null) {
-			Vector3 flipScale = Vector3.one;
-			if (skeletonRenderer.skeleton.FlipX)
-				flipScale.x = -1;
+			skeletonRenderer.OnRebuild -= HandleRendererReset;
+			skeletonRenderer.OnRebuild += HandleRendererReset;
 
-			if (skeletonRenderer.skeleton.FlipY)
-				flipScale.y = -1;
+			if (skeletonAnimation != null) {
+				skeletonAnimation.UpdateLocal -= UpdateLocal;
+				skeletonAnimation.UpdateLocal += UpdateLocal;
+			}
 
-			boneRoot.localScale = flipScale;
-		}
-	}
 
-	[HideInInspector]
-	public SkeletonRenderer skeletonRenderer;
-	[HideInInspector]
-	public ISkeletonAnimation skeletonAnimation;
-	[System.NonSerialized]
-	public List<SkeletonUtilityBone> utilityBones = new List<SkeletonUtilityBone>();
-	[System.NonSerialized]
-	public List<SkeletonUtilityConstraint> utilityConstraints = new List<SkeletonUtilityConstraint>();
-	//	Dictionary<Bone, SkeletonUtilityBone> utilityBoneTable;
-
-	protected bool hasTransformBones;
-	protected bool hasUtilityConstraints;
-	protected bool needToReprocessBones;
-
-	void OnEnable () {
-		if (skeletonRenderer == null) {
-			skeletonRenderer = GetComponent<SkeletonRenderer>();
+			CollectBones();
 		}
 
-		if (skeletonAnimation == null) {
-			skeletonAnimation = GetComponent<SkeletonAnimation>();
-			if (skeletonAnimation == null)
-				skeletonAnimation = GetComponent<SkeletonAnimator>();
+		void Start () {
+			//recollect because order of operations failure when switching between game mode and edit mode...
+			//		CollectBones();
 		}
 
-		skeletonRenderer.OnRebuild -= HandleRendererReset;
-		skeletonRenderer.OnRebuild += HandleRendererReset;
+		void OnDisable () {
+			skeletonRenderer.OnRebuild -= HandleRendererReset;
 
-		if (skeletonAnimation != null) {
-			skeletonAnimation.UpdateLocal -= UpdateLocal;
-			skeletonAnimation.UpdateLocal += UpdateLocal;
+			if (skeletonAnimation != null) {
+				skeletonAnimation.UpdateLocal -= UpdateLocal;
+				skeletonAnimation.UpdateWorld -= UpdateWorld;
+				skeletonAnimation.UpdateComplete -= UpdateComplete;
+			}
 		}
 
+		void HandleRendererReset (SkeletonRenderer r) {
+			if (OnReset != null)
+				OnReset();
 
-		CollectBones();
-	}
-
-	void Start () {
-		//recollect because order of operations failure when switching between game mode and edit mode...
-		//		CollectBones();
-	}
-
-	void OnDisable () {
-		skeletonRenderer.OnRebuild -= HandleRendererReset;
-
-		if (skeletonAnimation != null) {
-			skeletonAnimation.UpdateLocal -= UpdateLocal;
-			skeletonAnimation.UpdateWorld -= UpdateWorld;
-			skeletonAnimation.UpdateComplete -= UpdateComplete;
+			CollectBones();
 		}
-	}
-
-	void HandleRendererReset (SkeletonRenderer r) {
-		if (OnReset != null)
-			OnReset();
 
-		CollectBones();
-	}
+		public void RegisterBone (SkeletonUtilityBone bone) {
+			if (utilityBones.Contains(bone))
+				return;
+			else {
+				utilityBones.Add(bone);
+				needToReprocessBones = true;
+			}
+		}
 
-	public void RegisterBone (SkeletonUtilityBone bone) {
-		if (utilityBones.Contains(bone))
-			return;
-		else {
-			utilityBones.Add(bone);
-			needToReprocessBones = true;
+		public void UnregisterBone (SkeletonUtilityBone bone) {
+			utilityBones.Remove(bone);
 		}
-	}
 
-	public void UnregisterBone (SkeletonUtilityBone bone) {
-		utilityBones.Remove(bone);
-	}
+		public void RegisterConstraint (SkeletonUtilityConstraint constraint) {
 
-	public void RegisterConstraint (SkeletonUtilityConstraint constraint) {
+			if (utilityConstraints.Contains(constraint))
+				return;
+			else {
+				utilityConstraints.Add(constraint);
+				needToReprocessBones = true;
+			}
+		}
 
-		if (utilityConstraints.Contains(constraint))
-			return;
-		else {
-			utilityConstraints.Add(constraint);
-			needToReprocessBones = true;
+		public void UnregisterConstraint (SkeletonUtilityConstraint constraint) {
+			utilityConstraints.Remove(constraint);
 		}
-	}
 
-	public void UnregisterConstraint (SkeletonUtilityConstraint constraint) {
-		utilityConstraints.Remove(constraint);
-	}
+		public void CollectBones () {
+			if (skeletonRenderer.skeleton == null)
+				return;
 
-	public void CollectBones () {
-		if (skeletonRenderer.skeleton == null)
-			return;
+			if (boneRoot != null) {
+				List<string> constraintTargetNames = new List<string>();
 
-		if (boneRoot != null) {
-			List<string> constraintTargetNames = new List<string>();
+				ExposedList<IkConstraint> ikConstraints = skeletonRenderer.skeleton.IkConstraints;
+				for (int i = 0, n = ikConstraints.Count; i < n; i++)
+					constraintTargetNames.Add(ikConstraints.Items[i].Target.Data.Name);
 
-			ExposedList<IkConstraint> ikConstraints = skeletonRenderer.skeleton.IkConstraints;
-			for (int i = 0, n = ikConstraints.Count; i < n; i++)
-				constraintTargetNames.Add(ikConstraints.Items[i].Target.Data.Name);
+				foreach (var b in utilityBones) {
+					if (b.bone == null) {
+						return;
+					}
+					if (b.mode == SkeletonUtilityBone.Mode.Override) {
+						hasTransformBones = true;
+					}
 
-			foreach (var b in utilityBones) {
-				if (b.bone == null) {
-					return;
-				}
-				if (b.mode == SkeletonUtilityBone.Mode.Override) {
-					hasTransformBones = true;
+					if (constraintTargetNames.Contains(b.bone.Data.Name)) {
+						hasUtilityConstraints = true;
+					}
 				}
 
-				if (constraintTargetNames.Contains(b.bone.Data.Name)) {
+				if (utilityConstraints.Count > 0)
 					hasUtilityConstraints = true;
-				}
-			}
 
-			if (utilityConstraints.Count > 0)
-				hasUtilityConstraints = true;
+				if (skeletonAnimation != null) {
+					skeletonAnimation.UpdateWorld -= UpdateWorld;
+					skeletonAnimation.UpdateComplete -= UpdateComplete;
 
-			if (skeletonAnimation != null) {
-				skeletonAnimation.UpdateWorld -= UpdateWorld;
-				skeletonAnimation.UpdateComplete -= UpdateComplete;
+					if (hasTransformBones || hasUtilityConstraints) {
+						skeletonAnimation.UpdateWorld += UpdateWorld;
+					}
 
-				if (hasTransformBones || hasUtilityConstraints) {
-					skeletonAnimation.UpdateWorld += UpdateWorld;
+					if (hasUtilityConstraints) {
+						skeletonAnimation.UpdateComplete += UpdateComplete;
+					}
 				}
 
-				if (hasUtilityConstraints) {
-					skeletonAnimation.UpdateComplete += UpdateComplete;
-				}
+				needToReprocessBones = false;
+			} else {
+				utilityBones.Clear();
+				utilityConstraints.Clear();
 			}
 
-			needToReprocessBones = false;
-		} else {
-			utilityBones.Clear();
-			utilityConstraints.Clear();
 		}
 
-	}
+		void UpdateLocal (ISkeletonAnimation anim) {
 
-	void UpdateLocal (ISkeletonAnimation anim) {
+			if (needToReprocessBones)
+				CollectBones();
 
-		if (needToReprocessBones)
-			CollectBones();
+			if (utilityBones == null)
+				return;
 
-		if (utilityBones == null)
-			return;
+			foreach (SkeletonUtilityBone b in utilityBones) {
+				b.transformLerpComplete = false;
+			}
 
-		foreach (SkeletonUtilityBone b in utilityBones) {
-			b.transformLerpComplete = false;
+			UpdateAllBones();
 		}
 
-		UpdateAllBones();
-	}
+		void UpdateWorld (ISkeletonAnimation anim) {
+			UpdateAllBones();
 
-	void UpdateWorld (ISkeletonAnimation anim) {
-		UpdateAllBones();
+			foreach (SkeletonUtilityConstraint c in utilityConstraints)
+				c.DoUpdate();
+		}
 
-		foreach (SkeletonUtilityConstraint c in utilityConstraints)
-			c.DoUpdate();
-	}
+		void UpdateComplete (ISkeletonAnimation anim) {
+			UpdateAllBones();
+		}
 
-	void UpdateComplete (ISkeletonAnimation anim) {
-		UpdateAllBones();
-	}
+		void UpdateAllBones () {
+			if (boneRoot == null) {
+				CollectBones();
+			}
 
-	void UpdateAllBones () {
-		if (boneRoot == null) {
-			CollectBones();
+			if (utilityBones == null)
+				return;
+
+			foreach (SkeletonUtilityBone b in utilityBones) {
+				b.DoUpdate();
+			}
 		}
 
-		if (utilityBones == null)
-			return;
+		public Transform GetBoneRoot () {
+			if (boneRoot != null)
+				return boneRoot;
 
-		foreach (SkeletonUtilityBone b in utilityBones) {
-			b.DoUpdate();
-		}
-	}
+			boneRoot = new GameObject("SkeletonUtility-Root").transform;
+			boneRoot.parent = transform;
+			boneRoot.localPosition = Vector3.zero;
+			boneRoot.localRotation = Quaternion.identity;
+			boneRoot.localScale = Vector3.one;
 
-	public Transform GetBoneRoot () {
-		if (boneRoot != null)
 			return boneRoot;
+		}
 
-		boneRoot = new GameObject("SkeletonUtility-Root").transform;
-		boneRoot.parent = transform;
-		boneRoot.localPosition = Vector3.zero;
-		boneRoot.localRotation = Quaternion.identity;
-		boneRoot.localScale = Vector3.one;
-
-		return boneRoot;
-	}
+		public GameObject SpawnRoot (SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca) {
+			GetBoneRoot();
+			Skeleton skeleton = this.skeletonRenderer.skeleton;
 
-	public GameObject SpawnRoot (SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca) {
-		GetBoneRoot();
-		Skeleton skeleton = this.skeletonRenderer.skeleton;
+			GameObject go = SpawnBone(skeleton.RootBone, boneRoot, mode, pos, rot, sca);
 
-		GameObject go = SpawnBone(skeleton.RootBone, boneRoot, mode, pos, rot, sca);
+			CollectBones();
 
-		CollectBones();
+			return go;
+		}
 
-		return go;
-	}
+		public GameObject SpawnHierarchy (SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca) {
+			GetBoneRoot();
 
-	public GameObject SpawnHierarchy (SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca) {
-		GetBoneRoot();
+			Skeleton skeleton = this.skeletonRenderer.skeleton;
 
-		Skeleton skeleton = this.skeletonRenderer.skeleton;
+			GameObject go = SpawnBoneRecursively(skeleton.RootBone, boneRoot, mode, pos, rot, sca);
 
-		GameObject go = SpawnBoneRecursively(skeleton.RootBone, boneRoot, mode, pos, rot, sca);
+			CollectBones();
 
-		CollectBones();
+			return go;
+		}
 
-		return go;
-	}
+		public GameObject SpawnBoneRecursively (Bone bone, Transform parent, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca) {
+			GameObject go = SpawnBone(bone, parent, mode, pos, rot, sca);
 
-	public GameObject SpawnBoneRecursively (Bone bone, Transform parent, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca) {
-		GameObject go = SpawnBone(bone, parent, mode, pos, rot, sca);
+			ExposedList<Bone> childrenBones = bone.Children;
+			for (int i = 0, n = childrenBones.Count; i < n; i++) {
+				Bone child = childrenBones.Items[i];
+				SpawnBoneRecursively(child, go.transform, mode, pos, rot, sca);
+			}
 
-		ExposedList<Bone> childrenBones = bone.Children;
-		for (int i = 0, n = childrenBones.Count; i < n; i++) {
-			Bone child = childrenBones.Items[i];
-			SpawnBoneRecursively(child, go.transform, mode, pos, rot, sca);
+			return go;
 		}
 
-		return go;
-	}
+		public GameObject SpawnBone (Bone bone, Transform parent, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca) {
+			GameObject go = new GameObject(bone.Data.Name);
+			go.transform.parent = parent;
+
+			SkeletonUtilityBone b = go.AddComponent<SkeletonUtilityBone>();
+			b.skeletonUtility = this;
+			b.position = pos;
+			b.rotation = rot;
+			b.scale = sca;
+			b.mode = mode;
+			b.zPosition = true;
+			b.Reset();
+			b.bone = bone;
+			b.boneName = bone.Data.Name;
+			b.valid = true;
+
+			if (mode == SkeletonUtilityBone.Mode.Override) {
+				if (rot)
+					go.transform.localRotation = Quaternion.Euler(0, 0, b.bone.AppliedRotation);
+
+				if (pos)
+					go.transform.localPosition = new Vector3(b.bone.X, b.bone.Y, 0);
+
+				go.transform.localScale = new Vector3(b.bone.scaleX, b.bone.scaleY, 0);
+			}
 
-	public GameObject SpawnBone (Bone bone, Transform parent, SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca) {
-		GameObject go = new GameObject(bone.Data.Name);
-		go.transform.parent = parent;
-
-		SkeletonUtilityBone b = go.AddComponent<SkeletonUtilityBone>();
-		b.skeletonUtility = this;
-		b.position = pos;
-		b.rotation = rot;
-		b.scale = sca;
-		b.mode = mode;
-		b.zPosition = true;
-		b.Reset();
-		b.bone = bone;
-		b.boneName = bone.Data.Name;
-		b.valid = true;
-
-		if (mode == SkeletonUtilityBone.Mode.Override) {
-			if (rot)
-				go.transform.localRotation = Quaternion.Euler(0, 0, b.bone.AppliedRotation);
-
-			if (pos)
-				go.transform.localPosition = new Vector3(b.bone.X, b.bone.Y, 0);
-
-			go.transform.localScale = new Vector3(b.bone.scaleX, b.bone.scaleY, 0);
+			return go;
 		}
 
-		return go;
 	}
 
 }

+ 226 - 224
spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs

@@ -11,274 +11,276 @@ using System.Collections.Generic;
 using UnityEngine;
 using Spine;
 
-/// <summary>Sets a GameObject's transform to match a bone on a Spine skeleton.</summary>
-[ExecuteInEditMode]
-[AddComponentMenu("Spine/SkeletonUtilityBone")]
-public class SkeletonUtilityBone : MonoBehaviour {
-
-	public enum Mode {
-		Follow,
-		Override
-	}
-
-	[System.NonSerialized]
-	public bool valid;
-	[System.NonSerialized]
-	public SkeletonUtility skeletonUtility;
-	[System.NonSerialized]
-	public Bone bone;
-	public Mode mode;
-	public bool zPosition = true;
-	public bool position;
-	public bool rotation;
-	public bool scale;
-	// MITCH : remove flipX
-	// Kept these fields public to retain serialization. Probably remove eventually?
-	public bool flip;
-	public bool flipX;
-	[Range(0f, 1f)]
-	public float overrideAlpha = 1;
-
-	/// <summary>If a bone isn't set, boneName is used to find the bone.</summary>
-	public String boneName;
-	public Transform parentReference;
-
-	[System.NonSerialized]
-	public bool transformLerpComplete;
-
-	protected Transform cachedTransform;
-	protected Transform skeletonTransform;
-
-	// MITCH : nonuniform scale
-//	private bool nonUniformScaleWarning;
-//	public bool NonUniformScaleWarning {
-//		get { return nonUniformScaleWarning; }
-//	}
-
-	private bool disableInheritScaleWarning;
-	public bool DisableInheritScaleWarning {
-		get { return disableInheritScaleWarning; }
-	}
+namespace Spine.Unity {
+	/// <summary>Sets a GameObject's transform to match a bone on a Spine skeleton.</summary>
+	[ExecuteInEditMode]
+	[AddComponentMenu("Spine/SkeletonUtilityBone")]
+	public class SkeletonUtilityBone : MonoBehaviour {
+
+		public enum Mode {
+			Follow,
+			Override
+		}
 
-	public void Reset () {
-		bone = null;
-		cachedTransform = transform;
-		valid = skeletonUtility != null && skeletonUtility.skeletonRenderer != null && skeletonUtility.skeletonRenderer.valid;
-		if (!valid)
-			return;
-		skeletonTransform = skeletonUtility.transform;
-		skeletonUtility.OnReset -= HandleOnReset;
-		skeletonUtility.OnReset += HandleOnReset;
-		DoUpdate();
-	}
+		[System.NonSerialized]
+		public bool valid;
+		[System.NonSerialized]
+		public SkeletonUtility skeletonUtility;
+		[System.NonSerialized]
+		public Bone bone;
+		public Mode mode;
+		public bool zPosition = true;
+		public bool position;
+		public bool rotation;
+		public bool scale;
+		// MITCH : remove flipX
+		// Kept these fields public to retain serialization. Probably remove eventually?
+		public bool flip;
+		public bool flipX;
+		[Range(0f, 1f)]
+		public float overrideAlpha = 1;
 
-	void OnEnable () {
-		skeletonUtility = SkeletonUtility.GetInParent<SkeletonUtility>(transform);
+		/// <summary>If a bone isn't set, boneName is used to find the bone.</summary>
+		public String boneName;
+		public Transform parentReference;
 
-		if (skeletonUtility == null)
-			return;
+		[System.NonSerialized]
+		public bool transformLerpComplete;
 
-		skeletonUtility.RegisterBone(this);
-		skeletonUtility.OnReset += HandleOnReset;
-	}
+		protected Transform cachedTransform;
+		protected Transform skeletonTransform;
 
-	void HandleOnReset () {
-		Reset();
-	}
+		// MITCH : nonuniform scale
+		//	private bool nonUniformScaleWarning;
+		//	public bool NonUniformScaleWarning {
+		//		get { return nonUniformScaleWarning; }
+		//	}
+
+		private bool disableInheritScaleWarning;
+		public bool DisableInheritScaleWarning {
+			get { return disableInheritScaleWarning; }
+		}
 
-	void OnDisable () {
-		if (skeletonUtility != null) {
+		public void Reset () {
+			bone = null;
+			cachedTransform = transform;
+			valid = skeletonUtility != null && skeletonUtility.skeletonRenderer != null && skeletonUtility.skeletonRenderer.valid;
+			if (!valid)
+				return;
+			skeletonTransform = skeletonUtility.transform;
 			skeletonUtility.OnReset -= HandleOnReset;
-			skeletonUtility.UnregisterBone(this);
+			skeletonUtility.OnReset += HandleOnReset;
+			DoUpdate();
 		}
-	}
 
-	public void DoUpdate () {
-		if (!valid) {
-			Reset();
-			return;
+		void OnEnable () {
+			skeletonUtility = SkeletonUtility.GetInParent<SkeletonUtility>(transform);
+
+			if (skeletonUtility == null)
+				return;
+
+			skeletonUtility.RegisterBone(this);
+			skeletonUtility.OnReset += HandleOnReset;
 		}
 
-		Spine.Skeleton skeleton = skeletonUtility.skeletonRenderer.skeleton;
+		void HandleOnReset () {
+			Reset();
+		}
 
-		if (bone == null) {
-			if (boneName == null || boneName.Length == 0)
-				return;
-			
-			bone = skeleton.FindBone(boneName);
+		void OnDisable () {
+			if (skeletonUtility != null) {
+				skeletonUtility.OnReset -= HandleOnReset;
+				skeletonUtility.UnregisterBone(this);
+			}
+		}
 
-			if (bone == null) {
-				Debug.LogError("Bone not found: " + boneName, this);
+		public void DoUpdate () {
+			if (!valid) {
+				Reset();
 				return;
 			}
-		}
 
-		float skeletonFlipRotation = (skeleton.flipX ^ skeleton.flipY) ? -1f : 1f;
+			Spine.Skeleton skeleton = skeletonUtility.skeletonRenderer.skeleton;
 
-		// MITCH : remove flipX
-//		float flipCompensation = 0;
-//		if (flip && (flipX || (flipX != bone.flipX)) && bone.parent != null) {
-//			flipCompensation = bone.parent.WorldRotation * -2;
-//		}
+			if (bone == null) {
+				if (boneName == null || boneName.Length == 0)
+					return;
 
-		if (mode == Mode.Follow) {
-			// MITCH : remove flipX
-//			if (flip)
-//				flipX = bone.flipX;
-				
-			if (position)
-				cachedTransform.localPosition = new Vector3(bone.x, bone.y, 0);
-
-			if (rotation) {
-				if (bone.Data.InheritRotation) {
-					// MITCH : remove flipX
-					//if (bone.FlipX) {
-					//	cachedTransform.localRotation = Quaternion.Euler(0, 180, bone.rotationIK - flipCompensation);
-					//} else {
-						cachedTransform.localRotation = Quaternion.Euler(0, 0, bone.AppliedRotation);
-					//}
-				} else {
-					Vector3 euler = skeletonTransform.rotation.eulerAngles;
-					cachedTransform.rotation = Quaternion.Euler(euler.x, euler.y, euler.z + (bone.WorldRotationX * skeletonFlipRotation));
+				bone = skeleton.FindBone(boneName);
+
+				if (bone == null) {
+					Debug.LogError("Bone not found: " + boneName, this);
+					return;
 				}
 			}
 
-			if (scale) {
-				cachedTransform.localScale = new Vector3(bone.scaleX, bone.scaleY, bone.WorldSignX);
-				// MITCH : nonuniform scale
-				//nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
-				disableInheritScaleWarning = !bone.data.inheritScale;
-			}
+			float skeletonFlipRotation = (skeleton.flipX ^ skeleton.flipY) ? -1f : 1f;
 
-		} else if (mode == Mode.Override) {
-			if (transformLerpComplete)
-				return;
+			// MITCH : remove flipX
+			//		float flipCompensation = 0;
+			//		if (flip && (flipX || (flipX != bone.flipX)) && bone.parent != null) {
+			//			flipCompensation = bone.parent.WorldRotation * -2;
+			//		}
 
-			if (parentReference == null) {
-				if (position) {
-					bone.x = Mathf.Lerp(bone.x, cachedTransform.localPosition.x, overrideAlpha);
-					bone.y = Mathf.Lerp(bone.y, cachedTransform.localPosition.y, overrideAlpha);
-				}
+			if (mode == Mode.Follow) {
+				// MITCH : remove flipX
+				//			if (flip)
+				//				flipX = bone.flipX;
 
-				if (rotation) {
-					float angle = Mathf.LerpAngle(bone.Rotation, cachedTransform.localRotation.eulerAngles.z, overrideAlpha);
+				if (position)
+					cachedTransform.localPosition = new Vector3(bone.x, bone.y, 0);
 
-					// MITCH : remove flipX
-//					float angle = Mathf.LerpAngle(bone.Rotation, cachedTransform.localRotation.eulerAngles.z, overrideAlpha) + flipCompensation;
-//					if (flip) {
-//                        
-//						if ((!flipX && bone.flipX)) {
-//							angle -= flipCompensation;
-//						}
-//
-//						//TODO fix this...
-//						if (angle >= 360)
-//							angle -= 360;
-//						else if (angle <= -360)
-//							angle += 360;
-//					}
-					bone.Rotation = angle;
-					bone.AppliedRotation = angle;
+				if (rotation) {
+					if (bone.Data.InheritRotation) {
+						// MITCH : remove flipX
+						//if (bone.FlipX) {
+						//	cachedTransform.localRotation = Quaternion.Euler(0, 180, bone.rotationIK - flipCompensation);
+						//} else {
+						cachedTransform.localRotation = Quaternion.Euler(0, 0, bone.AppliedRotation);
+						//}
+					} else {
+						Vector3 euler = skeletonTransform.rotation.eulerAngles;
+						cachedTransform.rotation = Quaternion.Euler(euler.x, euler.y, euler.z + (bone.WorldRotationX * skeletonFlipRotation));
+					}
 				}
 
 				if (scale) {
-					bone.scaleX = Mathf.Lerp(bone.scaleX, cachedTransform.localScale.x, overrideAlpha);
-					bone.scaleY = Mathf.Lerp(bone.scaleY, cachedTransform.localScale.y, overrideAlpha);
+					cachedTransform.localScale = new Vector3(bone.scaleX, bone.scaleY, bone.WorldSignX);
 					// MITCH : nonuniform scale
 					//nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
+					disableInheritScaleWarning = !bone.data.inheritScale;
 				}
 
-				// MITCH : remove flipX
-				//if (flip)
-				//	bone.flipX = flipX;
-			} else {
+			} else if (mode == Mode.Override) {
 				if (transformLerpComplete)
 					return;
 
-				if (position) {
-					Vector3 pos = parentReference.InverseTransformPoint(cachedTransform.position);
-					bone.x = Mathf.Lerp(bone.x, pos.x, overrideAlpha);
-					bone.y = Mathf.Lerp(bone.y, pos.y, overrideAlpha);
-				}
+				if (parentReference == null) {
+					if (position) {
+						bone.x = Mathf.Lerp(bone.x, cachedTransform.localPosition.x, overrideAlpha);
+						bone.y = Mathf.Lerp(bone.y, cachedTransform.localPosition.y, overrideAlpha);
+					}
+
+					if (rotation) {
+						float angle = Mathf.LerpAngle(bone.Rotation, cachedTransform.localRotation.eulerAngles.z, overrideAlpha);
+
+						// MITCH : remove flipX
+						//					float angle = Mathf.LerpAngle(bone.Rotation, cachedTransform.localRotation.eulerAngles.z, overrideAlpha) + flipCompensation;
+						//					if (flip) {
+						//                        
+						//						if ((!flipX && bone.flipX)) {
+						//							angle -= flipCompensation;
+						//						}
+						//
+						//						//TODO fix this...
+						//						if (angle >= 360)
+						//							angle -= 360;
+						//						else if (angle <= -360)
+						//							angle += 360;
+						//					}
+						bone.Rotation = angle;
+						bone.AppliedRotation = angle;
+					}
+
+					if (scale) {
+						bone.scaleX = Mathf.Lerp(bone.scaleX, cachedTransform.localScale.x, overrideAlpha);
+						bone.scaleY = Mathf.Lerp(bone.scaleY, cachedTransform.localScale.y, overrideAlpha);
+						// MITCH : nonuniform scale
+						//nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
+					}
 
-				// MITCH
-				if (rotation) {
-					float angle = Mathf.LerpAngle(bone.Rotation, Quaternion.LookRotation(flipX ? Vector3.forward * -1 : Vector3.forward, parentReference.InverseTransformDirection(cachedTransform.up)).eulerAngles.z, overrideAlpha);
+					// MITCH : remove flipX
+					//if (flip)
+					//	bone.flipX = flipX;
+				} else {
+					if (transformLerpComplete)
+						return;
+
+					if (position) {
+						Vector3 pos = parentReference.InverseTransformPoint(cachedTransform.position);
+						bone.x = Mathf.Lerp(bone.x, pos.x, overrideAlpha);
+						bone.y = Mathf.Lerp(bone.y, pos.y, overrideAlpha);
+					}
+
+					// MITCH
+					if (rotation) {
+						float angle = Mathf.LerpAngle(bone.Rotation, Quaternion.LookRotation(flipX ? Vector3.forward * -1 : Vector3.forward, parentReference.InverseTransformDirection(cachedTransform.up)).eulerAngles.z, overrideAlpha);
+
+						// MITCH : remove flipX
+						//					float angle = Mathf.LerpAngle(bone.Rotation, Quaternion.LookRotation(flipX ? Vector3.forward * -1 : Vector3.forward, parentReference.InverseTransformDirection(cachedTransform.up)).eulerAngles.z, overrideAlpha) + flipCompensation;
+						//					if (flip) {
+						//                        
+						//						if ((!flipX && bone.flipX)) {
+						//							angle -= flipCompensation;
+						//						}
+						//
+						//						//TODO fix this...
+						//						if (angle >= 360)
+						//							angle -= 360;
+						//						else if (angle <= -360)
+						//							angle += 360;
+						//					}
+						bone.Rotation = angle;
+						bone.AppliedRotation = angle;
+					}
+
+					if (scale) {
+						bone.scaleX = Mathf.Lerp(bone.scaleX, cachedTransform.localScale.x, overrideAlpha);
+						bone.scaleY = Mathf.Lerp(bone.scaleY, cachedTransform.localScale.y, overrideAlpha);
+						// MITCH : nonuniform scale
+						//nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
+					}
+
+					disableInheritScaleWarning = !bone.data.inheritScale;
 
 					// MITCH : remove flipX
-//					float angle = Mathf.LerpAngle(bone.Rotation, Quaternion.LookRotation(flipX ? Vector3.forward * -1 : Vector3.forward, parentReference.InverseTransformDirection(cachedTransform.up)).eulerAngles.z, overrideAlpha) + flipCompensation;
-//					if (flip) {
-//                        
-//						if ((!flipX && bone.flipX)) {
-//							angle -= flipCompensation;
-//						}
-//
-//						//TODO fix this...
-//						if (angle >= 360)
-//							angle -= 360;
-//						else if (angle <= -360)
-//							angle += 360;
-//					}
-					bone.Rotation = angle;
-					bone.AppliedRotation = angle;
+					//if (flip)
+					//	bone.flipX = flipX;
 				}
-					
-				if (scale) {
-					bone.scaleX = Mathf.Lerp(bone.scaleX, cachedTransform.localScale.x, overrideAlpha);
-					bone.scaleY = Mathf.Lerp(bone.scaleY, cachedTransform.localScale.y, overrideAlpha);
-					// MITCH : nonuniform scale
-					//nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
-				}
-
-				disableInheritScaleWarning = !bone.data.inheritScale;
 
-				// MITCH : remove flipX
-				//if (flip)
-				//	bone.flipX = flipX;
+				transformLerpComplete = true;
 			}
-
-			transformLerpComplete = true;
 		}
-	}
 
-	// MITCH : remove flipX
-//	public void FlipX (bool state) {
-//		if (state != flipX) {
-//			flipX = state;
-//			if (flipX && Mathf.Abs(transform.localRotation.eulerAngles.y) > 90) {
-//				skeletonUtility.skeletonAnimation.LateUpdate();
-//				return;
-//			} else if (!flipX && Mathf.Abs(transform.localRotation.eulerAngles.y) < 90) {
-//				skeletonUtility.skeletonAnimation.LateUpdate();
-//				return;
-//			}
-//		}
-//
-//        
-//		bone.FlipX = state;
-//		transform.RotateAround(transform.position, skeletonUtility.transform.up, 180);
-//		Vector3 euler = transform.localRotation.eulerAngles;
-//		euler.x = 0;
-//        
-//		euler.y = bone.FlipX ? 180 : 0;
-//        euler.y = 0;
-//		transform.localRotation = Quaternion.Euler(euler);
-//	}
-
-	public void AddBoundingBox (string skinName, string slotName, string attachmentName) {
-		SkeletonUtility.AddBoundingBox(bone.skeleton, skinName, slotName, attachmentName, transform);
-	}
+		// MITCH : remove flipX
+		//	public void FlipX (bool state) {
+		//		if (state != flipX) {
+		//			flipX = state;
+		//			if (flipX && Mathf.Abs(transform.localRotation.eulerAngles.y) > 90) {
+		//				skeletonUtility.skeletonAnimation.LateUpdate();
+		//				return;
+		//			} else if (!flipX && Mathf.Abs(transform.localRotation.eulerAngles.y) < 90) {
+		//				skeletonUtility.skeletonAnimation.LateUpdate();
+		//				return;
+		//			}
+		//		}
+		//
+		//        
+		//		bone.FlipX = state;
+		//		transform.RotateAround(transform.position, skeletonUtility.transform.up, 180);
+		//		Vector3 euler = transform.localRotation.eulerAngles;
+		//		euler.x = 0;
+		//        
+		//		euler.y = bone.FlipX ? 180 : 0;
+		//        euler.y = 0;
+		//		transform.localRotation = Quaternion.Euler(euler);
+		//	}
+
+		public void AddBoundingBox (string skinName, string slotName, string attachmentName) {
+			SkeletonUtility.AddBoundingBox(bone.skeleton, skinName, slotName, attachmentName, transform);
+		}
 
 
-	#if UNITY_EDITOR
-	void OnDrawGizmos () {
-		// MITCH : nonuniform scale
-//		if (NonUniformScaleWarning) {
-//			Gizmos.DrawIcon(transform.position + new Vector3(0, 0.128f, 0), "icon-warning");
-//		}
+		#if UNITY_EDITOR
+		void OnDrawGizmos () {
+			// MITCH : nonuniform scale
+			//		if (NonUniformScaleWarning) {
+			//			Gizmos.DrawIcon(transform.position + new Vector3(0, 0.128f, 0), "icon-warning");
+			//		}
 
-		if (DisableInheritScaleWarning)
-			Gizmos.DrawIcon(transform.position + new Vector3(0, 0.128f, 0), "icon-warning");		
+			if (DisableInheritScaleWarning)
+				Gizmos.DrawIcon(transform.position + new Vector3(0, 0.128f, 0), "icon-warning");		
+		}
+		#endif
 	}
-	#endif
-}
+}

+ 14 - 13
spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityConstraint.cs

@@ -32,22 +32,23 @@
 using UnityEngine;
 using System.Collections;
 
-[RequireComponent(typeof(SkeletonUtilityBone)), ExecuteInEditMode]
+namespace Spine.Unity {
+	[RequireComponent(typeof(SkeletonUtilityBone)), ExecuteInEditMode]
+	public abstract class SkeletonUtilityConstraint : MonoBehaviour {
 
-public abstract class SkeletonUtilityConstraint : MonoBehaviour {
+		protected SkeletonUtilityBone utilBone;
+		protected SkeletonUtility skeletonUtility;
 
-	protected SkeletonUtilityBone utilBone;
-	protected SkeletonUtility skeletonUtility;
+		protected virtual void OnEnable () {
+			utilBone = GetComponent<SkeletonUtilityBone>();
+			skeletonUtility = SkeletonUtility.GetInParent<SkeletonUtility>(transform);
+			skeletonUtility.RegisterConstraint(this);
+		}
 
-	protected virtual void OnEnable () {
-		utilBone = GetComponent<SkeletonUtilityBone>();
-		skeletonUtility = SkeletonUtility.GetInParent<SkeletonUtility>(transform);
-		skeletonUtility.RegisterConstraint(this);
-	}
+		protected virtual void OnDisable () {
+			skeletonUtility.UnregisterConstraint(this);
+		}
 
-	protected virtual void OnDisable () {
-		skeletonUtility.UnregisterConstraint(this);
+		public abstract void DoUpdate ();
 	}
-
-	public abstract void DoUpdate ();
 }

+ 71 - 0
spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs

@@ -0,0 +1,71 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ * 
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ * 
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+using UnityEngine;
+
+namespace Spine.Unity.Modules {
+	[ExecuteInEditMode]
+	public class SkeletonUtilitySubmeshRenderer : MonoBehaviour {
+		[System.NonSerialized]
+		public Mesh mesh;
+		public int submeshIndex = 0;
+		public Material hiddenPassMaterial;
+		Renderer cachedRenderer;
+		MeshFilter filter;
+		Material[] sharedMaterials;
+
+		void Awake () {
+			cachedRenderer = GetComponent<Renderer>();
+			filter = GetComponent<MeshFilter>();
+			sharedMaterials = new Material[0];
+		}
+
+		public void SetMesh (Renderer parentRenderer, Mesh mesh, Material mat) {
+			if (cachedRenderer == null)
+				return;
+
+			cachedRenderer.enabled = true;
+			filter.sharedMesh = mesh;
+			if (cachedRenderer.sharedMaterials.Length != parentRenderer.sharedMaterials.Length) {
+				sharedMaterials = parentRenderer.sharedMaterials;
+			}
+
+			for (int i = 0; i < sharedMaterials.Length; i++) {
+				if (i == submeshIndex)
+					sharedMaterials[i] = mat;
+				else
+					sharedMaterials[i] = hiddenPassMaterial;
+			}
+
+			cachedRenderer.sharedMaterials = sharedMaterials;
+		}
+	}
+
+}

+ 14 - 0
spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs.meta

@@ -0,0 +1,14 @@
+fileFormatVersion: 2
+guid: 7820c1c2b0e52c6408de899d6939996e
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences:
+  - parentRenderer: {instanceID: 0}
+  - mesh: {instanceID: 0}
+  - hiddenPassMaterial: {fileID: 2100000, guid: 43227e5adadc6f24bb4bf74b92a56fb4,
+      type: 2}
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 144 - 141
spine-unity/Assets/spine-unity/SpineAttributes.cs

@@ -7,168 +7,171 @@
 using UnityEngine;
 using System.Collections;
 
-public abstract class SpineAttributeBase : PropertyAttribute {
-	public string dataField = "";
-	public string startsWith = "";
-}
+namespace Spine.Unity {
+	public abstract class SpineAttributeBase : PropertyAttribute {
+		public string dataField = "";
+		public string startsWith = "";
+	}
 
-public class SpineSlot : SpineAttributeBase {
-	public bool containsBoundingBoxes = false;
-
-	/// <summary>
-	/// Smart popup menu for Spine Slots
-	/// </summary>
-	/// <param name="startsWith">Filters popup results to elements that begin with supplied string.</param>
-	/// <param name="dataField">If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
-	/// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives).
-	/// If left empty and the script the attribute is applied to is derived from Component, GetComponent<SkeletonRenderer>() will be called as a fallback.
-	/// </param>
-	/// <param name="containsBoundingBoxes">Disables popup results that don't contain bounding box attachments when true.</param>
-	public SpineSlot(string startsWith = "", string dataField = "", bool containsBoundingBoxes = false) {
-		this.startsWith = startsWith;
-		this.dataField = dataField;
-		this.containsBoundingBoxes = containsBoundingBoxes;
+	public class SpineSlot : SpineAttributeBase {
+		public bool containsBoundingBoxes = false;
+
+		/// <summary>
+		/// Smart popup menu for Spine Slots
+		/// </summary>
+		/// <param name="startsWith">Filters popup results to elements that begin with supplied string.</param>
+		/// <param name="dataField">If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
+		/// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives).
+		/// If left empty and the script the attribute is applied to is derived from Component, GetComponent<SkeletonRenderer>() will be called as a fallback.
+		/// </param>
+		/// <param name="containsBoundingBoxes">Disables popup results that don't contain bounding box attachments when true.</param>
+		public SpineSlot(string startsWith = "", string dataField = "", bool containsBoundingBoxes = false) {
+			this.startsWith = startsWith;
+			this.dataField = dataField;
+			this.containsBoundingBoxes = containsBoundingBoxes;
+		}
 	}
-}
 
-public class SpineEvent : SpineAttributeBase {
-	/// <summary>
-	/// Smart popup menu for Spine Events (Spine.EventData)
-	/// </summary>
-	/// <param name="startsWith">Filters popup results to elements that begin with supplied string.</param>
-	/// <param name="dataField">If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
-	/// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives).
-	/// If left empty and the script the attribute is applied to is derived from Component, GetComponent<SkeletonRenderer>() will be called as a fallback.
-	/// </param>
-	public SpineEvent(string startsWith = "", string dataField = "") {
-		this.startsWith = startsWith;
-		this.dataField = dataField;
+	public class SpineEvent : SpineAttributeBase {
+		/// <summary>
+		/// Smart popup menu for Spine Events (Spine.EventData)
+		/// </summary>
+		/// <param name="startsWith">Filters popup results to elements that begin with supplied string.</param>
+		/// <param name="dataField">If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
+		/// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives).
+		/// If left empty and the script the attribute is applied to is derived from Component, GetComponent<SkeletonRenderer>() will be called as a fallback.
+		/// </param>
+		public SpineEvent(string startsWith = "", string dataField = "") {
+			this.startsWith = startsWith;
+			this.dataField = dataField;
+		}
 	}
-}
 
-public class SpineSkin : SpineAttributeBase {
-	/// <summary>
-	/// Smart popup menu for Spine Skins
-	/// </summary>
-	/// <param name="startsWith">Filters popup results to elements that begin with supplied string.</param>
-	/// <param name="dataField">If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
-	/// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives)
-	/// If left empty and the script the attribute is applied to is derived from Component, GetComponent<SkeletonRenderer>() will be called as a fallback.
-	/// </param>
-	public SpineSkin(string startsWith = "", string dataField = "") {
-		this.startsWith = startsWith;
-		this.dataField = dataField;
+	public class SpineSkin : SpineAttributeBase {
+		/// <summary>
+		/// Smart popup menu for Spine Skins
+		/// </summary>
+		/// <param name="startsWith">Filters popup results to elements that begin with supplied string.</param>
+		/// <param name="dataField">If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
+		/// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives)
+		/// If left empty and the script the attribute is applied to is derived from Component, GetComponent<SkeletonRenderer>() will be called as a fallback.
+		/// </param>
+		public SpineSkin(string startsWith = "", string dataField = "") {
+			this.startsWith = startsWith;
+			this.dataField = dataField;
+		}
 	}
-}
-public class SpineAnimation : SpineAttributeBase {
-	/// <summary>
-	/// Smart popup menu for Spine Animations
-	/// </summary>
-	/// <param name="startsWith">Filters popup results to elements that begin with supplied string.</param>
-	/// <param name="dataField">If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
-	/// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives)
-	/// If left empty and the script the attribute is applied to is derived from Component, GetComponent<SkeletonRenderer>() will be called as a fallback.
-	/// </param>
-	public SpineAnimation(string startsWith = "", string dataField = "") {
-		this.startsWith = startsWith;
-		this.dataField = dataField;
+	public class SpineAnimation : SpineAttributeBase {
+		/// <summary>
+		/// Smart popup menu for Spine Animations
+		/// </summary>
+		/// <param name="startsWith">Filters popup results to elements that begin with supplied string.</param>
+		/// <param name="dataField">If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
+		/// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives)
+		/// If left empty and the script the attribute is applied to is derived from Component, GetComponent<SkeletonRenderer>() will be called as a fallback.
+		/// </param>
+		public SpineAnimation(string startsWith = "", string dataField = "") {
+			this.startsWith = startsWith;
+			this.dataField = dataField;
+		}
 	}
-}
 
-public class SpineAttachment : SpineAttributeBase {
-	public bool returnAttachmentPath = false;
-	public bool currentSkinOnly = false;
-	public bool placeholdersOnly = false;
-	public string slotField = "";
-
-	/// <summary>
-	/// Smart popup menu for Spine Attachments
-	/// </summary>
-	/// <param name="currentSkinOnly">Filters popup results to only include the current Skin.  Only valid when a SkeletonRenderer is the data source.</param>
-	/// <param name="returnAttachmentPath">Returns a fully qualified path for an Attachment in the format "Skin/Slot/AttachmentName". This path format is only used by the SpineAttachment helper methods like SpineAttachment.GetAttachment and .GetHierarchy. Do not use full path anywhere else in Spine's system.</param>
-	/// <param name="placeholdersOnly">Filters popup results to exclude attachments that are not children of Skin Placeholders</param>
-	/// <param name="slotField">If specified, a locally scoped field with the name supplied by in slotField will be used to limit the popup results to children of a named slot</param>
-	/// <param name="dataField">If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
-	/// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives)
-	/// If left empty and the script the attribute is applied to is derived from Component, GetComponent<SkeletonRenderer>() will be called as a fallback.
-	/// </param>
-	public SpineAttachment (bool currentSkinOnly = true, bool returnAttachmentPath = false, bool placeholdersOnly = false, string slotField = "", string dataField = "") {
-		this.currentSkinOnly = currentSkinOnly;
-		this.returnAttachmentPath = returnAttachmentPath;
-		this.placeholdersOnly = placeholdersOnly;
-		this.slotField = slotField;
-		this.dataField = dataField;		
-	}
+	public class SpineAttachment : SpineAttributeBase {
+		public bool returnAttachmentPath = false;
+		public bool currentSkinOnly = false;
+		public bool placeholdersOnly = false;
+		public string slotField = "";
+
+		/// <summary>
+		/// Smart popup menu for Spine Attachments
+		/// </summary>
+		/// <param name="currentSkinOnly">Filters popup results to only include the current Skin.  Only valid when a SkeletonRenderer is the data source.</param>
+		/// <param name="returnAttachmentPath">Returns a fully qualified path for an Attachment in the format "Skin/Slot/AttachmentName". This path format is only used by the SpineAttachment helper methods like SpineAttachment.GetAttachment and .GetHierarchy. Do not use full path anywhere else in Spine's system.</param>
+		/// <param name="placeholdersOnly">Filters popup results to exclude attachments that are not children of Skin Placeholders</param>
+		/// <param name="slotField">If specified, a locally scoped field with the name supplied by in slotField will be used to limit the popup results to children of a named slot</param>
+		/// <param name="dataField">If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
+		/// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives)
+		/// If left empty and the script the attribute is applied to is derived from Component, GetComponent<SkeletonRenderer>() will be called as a fallback.
+		/// </param>
+		public SpineAttachment (bool currentSkinOnly = true, bool returnAttachmentPath = false, bool placeholdersOnly = false, string slotField = "", string dataField = "") {
+			this.currentSkinOnly = currentSkinOnly;
+			this.returnAttachmentPath = returnAttachmentPath;
+			this.placeholdersOnly = placeholdersOnly;
+			this.slotField = slotField;
+			this.dataField = dataField;		
+		}
 
-	public static SpineAttachment.Hierarchy GetHierarchy (string fullPath) {
-		return new SpineAttachment.Hierarchy(fullPath);
-	}
+		public static SpineAttachment.Hierarchy GetHierarchy (string fullPath) {
+			return new SpineAttachment.Hierarchy(fullPath);
+		}
 
-	public static Spine.Attachment GetAttachment (string attachmentPath, Spine.SkeletonData skeletonData) {
-		var hierarchy = SpineAttachment.GetHierarchy(attachmentPath);
-		if (hierarchy.name == "")
-			return null;
+		public static Spine.Attachment GetAttachment (string attachmentPath, Spine.SkeletonData skeletonData) {
+			var hierarchy = SpineAttachment.GetHierarchy(attachmentPath);
+			if (hierarchy.name == "")
+				return null;
 
-		return skeletonData.FindSkin(hierarchy.skin).GetAttachment(skeletonData.FindSlotIndex(hierarchy.slot), hierarchy.name);
-	}
+			return skeletonData.FindSkin(hierarchy.skin).GetAttachment(skeletonData.FindSlotIndex(hierarchy.slot), hierarchy.name);
+		}
 
-	public static Spine.Attachment GetAttachment (string attachmentPath, SkeletonDataAsset skeletonDataAsset) {
-		return GetAttachment(attachmentPath, skeletonDataAsset.GetSkeletonData(true));
-	}
+		public static Spine.Attachment GetAttachment (string attachmentPath, SkeletonDataAsset skeletonDataAsset) {
+			return GetAttachment(attachmentPath, skeletonDataAsset.GetSkeletonData(true));
+		}
 
-	/// <summary>
-	/// A struct that represents 3 strings that help identify and locate an attachment in a skeleton.</summary>
-	public struct Hierarchy {
-		public string skin;
-		public string slot;
-		public string name;
-
-		public Hierarchy (string fullPath) {
-			string[] chunks = fullPath.Split(new char[]{'/'}, System.StringSplitOptions.RemoveEmptyEntries);
-			if (chunks.Length == 0) {
-				skin = "";
-				slot = "";
+		/// <summary>
+		/// A struct that represents 3 strings that help identify and locate an attachment in a skeleton.</summary>
+		public struct Hierarchy {
+			public string skin;
+			public string slot;
+			public string name;
+
+			public Hierarchy (string fullPath) {
+				string[] chunks = fullPath.Split(new char[]{'/'}, System.StringSplitOptions.RemoveEmptyEntries);
+				if (chunks.Length == 0) {
+					skin = "";
+					slot = "";
+					name = "";
+					return;
+				}
+				else if (chunks.Length < 2) {
+					throw new System.Exception("Cannot generate Attachment Hierarchy from string! Not enough components! [" + fullPath + "]");
+				}
+				skin = chunks[0];
+				slot = chunks[1];
 				name = "";
-				return;
-			}
-			else if (chunks.Length < 2) {
-				throw new System.Exception("Cannot generate Attachment Hierarchy from string! Not enough components! [" + fullPath + "]");
-			}
-			skin = chunks[0];
-			slot = chunks[1];
-			name = "";
-			for (int i = 2; i < chunks.Length; i++) {
-				name += chunks[i];
+				for (int i = 2; i < chunks.Length; i++) {
+					name += chunks[i];
+				}
 			}
 		}
 	}
-}
 
-public class SpineBone : SpineAttributeBase {
-	/// <summary>
-	/// Smart popup menu for Spine Bones
-	/// </summary>
-	/// <param name="startsWith">Filters popup results to elements that begin with supplied string.</param>
-	/// <param name="dataField">If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
-	/// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives)
-	/// If left empty and the script the attribute is applied to is derived from Component, GetComponent<SkeletonRenderer>() will be called as a fallback.
-	/// </param>
-	public SpineBone(string startsWith = "", string dataField = "") {
-		this.startsWith = startsWith;
-		this.dataField = dataField;
-	}
+	public class SpineBone : SpineAttributeBase {
+		/// <summary>
+		/// Smart popup menu for Spine Bones
+		/// </summary>
+		/// <param name="startsWith">Filters popup results to elements that begin with supplied string.</param>
+		/// <param name="dataField">If specified, a locally scoped field with the name supplied by in dataField will be used to fill the popup results.
+		/// Valid types are SkeletonDataAsset and SkeletonRenderer (and derivatives)
+		/// If left empty and the script the attribute is applied to is derived from Component, GetComponent<SkeletonRenderer>() will be called as a fallback.
+		/// </param>
+		public SpineBone(string startsWith = "", string dataField = "") {
+			this.startsWith = startsWith;
+			this.dataField = dataField;
+		}
+
+		public static Spine.Bone GetBone(string boneName, SkeletonRenderer renderer) {
+			return renderer.skeleton == null ? null : renderer.skeleton.FindBone(boneName);
+		}
 
-	public static Spine.Bone GetBone(string boneName, SkeletonRenderer renderer) {
-		return renderer.skeleton == null ? null : renderer.skeleton.FindBone(boneName);
+		public static Spine.BoneData GetBoneData(string boneName, SkeletonDataAsset skeletonDataAsset) {
+			var data = skeletonDataAsset.GetSkeletonData(true);
+			return data.FindBone(boneName);
+		}
 	}
 
-	public static Spine.BoneData GetBoneData(string boneName, SkeletonDataAsset skeletonDataAsset) {
-		var data = skeletonDataAsset.GetSkeletonData(true);
-		return data.FindBone(boneName);
+	public class SpineAtlasRegion : PropertyAttribute {
+		//TODO:  Standardize with Skeleton attributes
+		//NOTE:  For now, relies on locally scoped field named "atlasAsset" for source.
 	}
-}
 
-public class SpineAtlasRegion : PropertyAttribute {
-	//TODO:  Standardize with Skeleton attributes
-	//NOTE:  For now, relies on locally scoped field named "atlasAsset" for source.
 }

Some files were not shown because too many files changed in this diff