Browse Source

Merge remote-tracking branch 'origin/master'

NathanSweet 11 years ago
parent
commit
d706590095
87 changed files with 3995 additions and 119 deletions
  1. 5 0
      spine-tk2d/Assets/Gizmos.meta
  2. BIN
      spine-tk2d/Assets/Gizmos/SkeletonDataAsset Icon.png
  3. 46 0
      spine-tk2d/Assets/Gizmos/SkeletonDataAsset Icon.png.meta
  4. 2 2
      spine-tk2d/Assets/examples/goblins/Goblins.cs
  5. 44 22
      spine-tk2d/Assets/spine-tk2d/BoneFollower.cs
  6. 1 1
      spine-tk2d/Assets/spine-tk2d/BoneFollower.cs.meta
  7. 35 7
      spine-tk2d/Assets/spine-tk2d/Editor/BoneFollowerInspector.cs
  8. 1 1
      spine-tk2d/Assets/spine-tk2d/Editor/BoneFollowerInspector.cs.meta
  9. 5 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI.meta
  10. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-animation.png
  11. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-animation.png.meta
  12. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-animationRoot.png
  13. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-animationRoot.png.meta
  14. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-bone.png
  15. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-bone.png.meta
  16. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-boneNib.png
  17. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-boneNib.png.meta
  18. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-boundingBox.png
  19. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-boundingBox.png.meta
  20. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-constraintNib.png
  21. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-constraintNib.png.meta
  22. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-event.png
  23. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-event.png.meta
  24. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-hingeChain.png
  25. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-hingeChain.png.meta
  26. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-image.png
  27. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-image.png.meta
  28. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-mesh.png
  29. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-mesh.png.meta
  30. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-null.png
  31. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-null.png.meta
  32. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-poseBones.png
  33. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-poseBones.png.meta
  34. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skeleton.png
  35. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skeleton.png.meta
  36. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skeletonUtility.png
  37. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skeletonUtility.png.meta
  38. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skin.png
  39. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skin.png.meta
  40. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skinPlaceholder.png
  41. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skinPlaceholder.png.meta
  42. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skinsRoot.png
  43. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skinsRoot.png.meta
  44. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-slot.png
  45. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-slot.png.meta
  46. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-spine.png
  47. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-spine.png.meta
  48. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-subMeshRenderer.png
  49. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-subMeshRenderer.png.meta
  50. BIN
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-warning.png
  51. 47 0
      spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-warning.png.meta
  52. 37 4
      spine-tk2d/Assets/spine-tk2d/Editor/SkeletonAnimationInspector.cs
  53. 522 20
      spine-tk2d/Assets/spine-tk2d/Editor/SkeletonDataAssetInspector.cs
  54. 1 1
      spine-tk2d/Assets/spine-tk2d/Editor/SkeletonDataAssetInspector.cs.meta
  55. 268 0
      spine-tk2d/Assets/spine-tk2d/Editor/SpineEditorUtilities.cs
  56. 8 0
      spine-tk2d/Assets/spine-tk2d/Editor/SpineEditorUtilities.cs.meta
  57. 69 0
      spine-tk2d/Assets/spine-tk2d/Shaders/Bones.shader
  58. 5 0
      spine-tk2d/Assets/spine-tk2d/Shaders/Bones.shader.meta
  59. BIN
      spine-tk2d/Assets/spine-tk2d/Shaders/HiddenPass.mat
  60. 4 0
      spine-tk2d/Assets/spine-tk2d/Shaders/HiddenPass.mat.meta
  61. 21 0
      spine-tk2d/Assets/spine-tk2d/Shaders/HiddenPass.shader
  62. 5 0
      spine-tk2d/Assets/spine-tk2d/Shaders/HiddenPass.shader.meta
  63. 26 7
      spine-tk2d/Assets/spine-tk2d/SkeletonAnimation.cs
  64. 5 4
      spine-tk2d/Assets/spine-tk2d/SkeletonDataAsset.cs
  65. 108 0
      spine-tk2d/Assets/spine-tk2d/SkeletonExtensions.cs
  66. 8 0
      spine-tk2d/Assets/spine-tk2d/SkeletonExtensions.cs.meta
  67. 69 50
      spine-tk2d/Assets/spine-tk2d/SkeletonRenderer.cs
  68. 5 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility.meta
  69. 5 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/Editor.meta
  70. 304 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs
  71. 8 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs.meta
  72. 311 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/Editor/SkeletonUtilityInspector.cs
  73. 8 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/Editor/SkeletonUtilityInspector.cs.meta
  74. 346 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtility.cs
  75. 8 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtility.cs.meta
  76. 293 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityBone.cs
  77. 8 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityBone.cs.meta
  78. 22 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityConstraint.cs
  79. 8 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityConstraint.cs.meta
  80. 56 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityEyeConstraint.cs
  81. 8 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityEyeConstraint.cs.meta
  82. 120 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityGroundConstraint.cs
  83. 8 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityGroundConstraint.cs.meta
  84. 79 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityKinematicShadow.cs
  85. 8 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityKinematicShadow.cs.meta
  86. 96 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs
  87. 12 0
      spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs.meta

+ 5 - 0
spine-tk2d/Assets/Gizmos.meta

@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: a260a1ff5965c2c4f88aea3e7d433965
+folderAsset: yes
+DefaultImporter:
+  userData: 

BIN
spine-tk2d/Assets/Gizmos/SkeletonDataAsset Icon.png


+ 46 - 0
spine-tk2d/Assets/Gizmos/SkeletonDataAsset Icon.png.meta

@@ -0,0 +1,46 @@
+fileFormatVersion: 2
+guid: 68defdbc95b30a74a9ad396bfc9a2277
+TextureImporter:
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

+ 2 - 2
spine-tk2d/Assets/examples/goblins/Goblins.cs

@@ -40,11 +40,11 @@ public class Goblins : MonoBehaviour {
 	public void Start () {
 		skeletonAnimation = GetComponent<SkeletonAnimation>();
 		headBone = skeletonAnimation.skeleton.FindBone("head");
-		skeletonAnimation.UpdateBones += UpdateBones;
+		skeletonAnimation.UpdateLocal += UpdateLocal;
 	}
 
 	// This is called after the animation is applied to the skeleton and can be used to adjust the bones dynamically.
-	public void UpdateBones (SkeletonAnimation skeletonAnimation) {
+	public void UpdateLocal (SkeletonAnimation skeletonAnimation) {
 		headBone.Rotation += 15;
 	}
 	

+ 44 - 22
spine-tk2d/Assets/spine-tk2d/BoneComponent.cs → spine-tk2d/Assets/spine-tk2d/BoneFollower.cs

@@ -36,14 +36,14 @@ using Spine;
 
 /// <summary>Sets a GameObject's transform to match a bone on a Spine skeleton.</summary>
 [ExecuteInEditMode]
-[AddComponentMenu("Spine/BoneComponent")]
-public class BoneComponent : MonoBehaviour {
-	[System.NonSerialized]
-	public bool valid;
+[AddComponentMenu("Spine/BoneFollower")]
+public class BoneFollower : MonoBehaviour {
 
+	[System.NonSerialized]
+	public bool
+		valid;
 	public SkeletonRenderer skeletonRenderer;
 	public Bone bone;
-
 	public bool followZPosition = true;
 	public bool followBoneRotation = true;
 
@@ -51,46 +51,66 @@ public class BoneComponent : MonoBehaviour {
 		get { return skeletonRenderer; }
 		set {
 			skeletonRenderer = value;
-			Reset ();
+			Reset();
 		}
 	}
 
-	// TODO: Make the rotation behavior more customizable
-	// public bool followTransformRotation = false;
-
-	// TODO: Make transform follow bone scale? too specific? This is really useful for shared shadow assets.
-	//public bool followBoneScale = false;
 
 	/// <summary>If a bone isn't set, boneName is used to find the bone.</summary>
 	public String boneName;
-
+	public bool resetOnAwake = true;
 	protected Transform cachedTransform;
 	protected Transform skeletonTransform;
-	
+
+	public void HandleResetRenderer (SkeletonRenderer skeletonRenderer) {
+		Reset();
+	}
+
 	public void Reset () {
 		bone = null;
 		cachedTransform = transform;
 		valid = skeletonRenderer != null && skeletonRenderer.valid;
-		if (!valid) return;
+		if (!valid)
+			return;
 		skeletonTransform = skeletonRenderer.transform;
+
+		skeletonRenderer.OnReset -= HandleResetRenderer;
+		skeletonRenderer.OnReset += HandleResetRenderer;
+
+		if (Application.isEditor)
+			DoUpdate();
+	}
+
+	void OnDestroy () {
+		//cleanup
+		if (skeletonRenderer != null)
+			skeletonRenderer.OnReset -= HandleResetRenderer;
 	}
 
 	public void Awake () {
-		Reset();
+		if (resetOnAwake)
+			Reset();
 	}
 
-	public void LateUpdate () {
+	void LateUpdate () {
+		DoUpdate();
+	}
+
+	public void DoUpdate () {
 		if (!valid) {
 			Reset();
 			return;
 		}
 
 		if (bone == null) {
-			if (boneName == null || boneName.Length == 0) return;
+			if (boneName == null || boneName.Length == 0)
+				return;
 			bone = skeletonRenderer.skeleton.FindBone(boneName);
 			if (bone == null) {
 				Debug.LogError("Bone not found: " + boneName, this);
 				return;
+			} else {
+
 			}
 		}
 
@@ -100,22 +120,24 @@ public class BoneComponent : MonoBehaviour {
 		if (cachedTransform.parent == skeletonTransform) {
 			cachedTransform.localPosition = new Vector3(bone.worldX, bone.worldY, followZPosition ? 0f : cachedTransform.localPosition.z);
 
-			if(followBoneRotation) {
+			if (followBoneRotation) {
 				Vector3 rotation = cachedTransform.localRotation.eulerAngles;
 				cachedTransform.localRotation = Quaternion.Euler(rotation.x, rotation.y, bone.worldRotation * flipRotation);
 			}
 
 		} else {
 			Vector3 targetWorldPosition = skeletonTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY, 0f));
-			if(!followZPosition) targetWorldPosition.z = cachedTransform.position.z;
+			if (!followZPosition)
+				targetWorldPosition.z = cachedTransform.position.z;
 
 			cachedTransform.position = targetWorldPosition;
 
-			if(followBoneRotation) {
+			if (followBoneRotation) {
 				Vector3 rotation = skeletonTransform.rotation.eulerAngles;
-				cachedTransform.rotation = Quaternion.Euler(rotation.x, rotation.y, 
-				                                            skeletonTransform.rotation.eulerAngles.z + (bone.worldRotation * flipRotation) );
+
+				cachedTransform.rotation = Quaternion.Euler(rotation.x, rotation.y, skeletonTransform.rotation.eulerAngles.z + (bone.worldRotation * flipRotation));
 			}
 		}
+
 	}
 }

+ 1 - 1
spine-tk2d/Assets/spine-tk2d/BoneComponent.cs.meta → spine-tk2d/Assets/spine-tk2d/BoneFollower.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: d08aa5caf52eae44ba81cc81ca1dad5d
+guid: a1fd8daaed7b64148a34acb96ba14ce1
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 35 - 7
spine-tk2d/Assets/spine-tk2d/Editor/BoneComponentInspector.cs → spine-tk2d/Assets/spine-tk2d/Editor/BoneFollowerInspector.cs

@@ -27,30 +27,57 @@
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
-
 using System;
 using UnityEditor;
 using UnityEngine;
 
-[CustomEditor(typeof(BoneComponent))]
-public class BoneComponentInspector : Editor {
+[CustomEditor(typeof(BoneFollower))]
+public class BoneFollowerInspector : Editor {
 	private SerializedProperty boneName, skeletonRenderer, followZPosition, followBoneRotation;
+	BoneFollower component;
 
 	void OnEnable () {
 		skeletonRenderer = serializedObject.FindProperty("skeletonRenderer");
 		boneName = serializedObject.FindProperty("boneName");
 		followBoneRotation = serializedObject.FindProperty("followBoneRotation");
 		followZPosition = serializedObject.FindProperty("followZPosition");
+		component = (BoneFollower)target;
+		ForceReload();
+	}
+
+	void FindRenderer () {
+		if (skeletonRenderer.objectReferenceValue == null) {
+			SkeletonRenderer parentRenderer = SkeletonUtility.GetInParent<SkeletonRenderer>(component.transform);
+
+			if (parentRenderer != null) {
+				skeletonRenderer.objectReferenceValue = (UnityEngine.Object)parentRenderer;
+			}
+
+		}
+	}
+
+	void ForceReload () {
+		if (component.skeletonRenderer != null) {
+			if (component.skeletonRenderer.valid == false)
+				component.skeletonRenderer.Reset();
+		}
 	}
 
 	override public void OnInspectorGUI () {
 		serializedObject.Update();
-		BoneComponent component = (BoneComponent)target;
+
+		FindRenderer();
 
 		EditorGUILayout.PropertyField(skeletonRenderer);
 
 		if (component.valid) {
-			String[] bones = new String[component.skeletonRenderer.skeleton.Data.Bones.Count + 1];
+			String[] bones = new String[1];
+			try {
+				bones = new String[component.skeletonRenderer.skeleton.Data.Bones.Count + 1];
+			} catch {
+
+			}
+
 			bones[0] = "<None>";
 			for (int i = 0; i < bones.Length - 1; i++)
 				bones[i + 1] = component.skeletonRenderer.skeleton.Data.Bones[i].Name;
@@ -64,13 +91,14 @@ public class BoneComponentInspector : Editor {
 			EditorGUILayout.EndHorizontal();
 
 			boneName.stringValue = boneIndex == 0 ? null : bones[boneIndex];
-
 			EditorGUILayout.PropertyField(followBoneRotation);
 			EditorGUILayout.PropertyField(followZPosition);
+		} else {
+			GUILayout.Label("INVALID");
 		}
 
 		if (serializedObject.ApplyModifiedProperties() ||
-	    	(Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed")
+			(Event.current.type == EventType.ValidateCommand && Event.current.commandName == "UndoRedoPerformed")
 	    ) {
 			component.Reset();
 		}

+ 1 - 1
spine-tk2d/Assets/spine-tk2d/Editor/BoneComponentInspector.cs.meta → spine-tk2d/Assets/spine-tk2d/Editor/BoneFollowerInspector.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 99e3e8311529bbc48a5c3a5b9714e162
+guid: c71ca35fd6241cb49a0b0756a664fcf7
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 5 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI.meta

@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: bfaea6b7e7f52bc46b8d1c3cb5e9eaa1
+folderAsset: yes
+DefaultImporter:
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-animation.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-animation.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: 52b12ec801461494185a4d3dc66f3d1d
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-animationRoot.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-animationRoot.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: 3d1be4ea889f3a14b864352fe49a1bde
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-bone.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-bone.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: 8322793223a533a4ca8be6f430256dfc
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-boneNib.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-boneNib.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: 97a43f11e00735147a9dc3dff6d68191
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-boundingBox.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-boundingBox.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: 955aed20030d0504b8a9c6934a5cb47a
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-constraintNib.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-constraintNib.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: de1a4f5ad4bdf1a4ea072c4d59ba87d8
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-event.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-event.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: d226a80acc775714aa78b85e16a00e9b
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-hingeChain.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-hingeChain.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: 2c2c6d283dcf3654baf40001c982891c
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-image.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-image.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: 2b3a6f35bbaa8414eb51a344743ee641
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-mesh.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-mesh.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: a309a2e14638a204091b915126910f45
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-null.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-null.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: d1de1604dfe4cb64c9d31246a8e43c78
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-poseBones.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-poseBones.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: da6f6d414e43aac46a57cc5a87208db4
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skeleton.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skeleton.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: f2216037084d99d4481810cb521ed96f
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skeletonUtility.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skeletonUtility.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: 5bb0631368b462047869d8788673cb48
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skin.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skin.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: bfd9f3d2607e9e44c97384d7575a17dc
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skinPlaceholder.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skinPlaceholder.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: 04c82a4acf7b5244e947f2709ec3a6cf
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skinsRoot.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-skinsRoot.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: 8bd14c7643597a74ba2edc10a5e4c4ed
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-slot.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-slot.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: 0338faf3e7d93e2478fcbc022d13e081
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-spine.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-spine.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: 4e7c964fa5e07024c8bf1debecc3b7c8
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-subMeshRenderer.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-subMeshRenderer.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: f31c0c0d608e8ba4f9a1afb032092287
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-warning.png


+ 47 - 0
spine-tk2d/Assets/spine-tk2d/Editor/GUI/icon-warning.png.meta

@@ -0,0 +1,47 @@
+fileFormatVersion: 2
+guid: 754d724c1bd750048852e8cf3d4a05ee
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    linearTexture: 1
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  seamlessCubemap: 0
+  textureFormat: -3
+  maxTextureSize: 1024
+  textureSettings:
+    filterMode: -1
+    aniso: 1
+    mipBias: -1
+    wrapMode: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 1
+  textureType: 2
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 

+ 37 - 4
spine-tk2d/Assets/spine-tk2d/Editor/SkeletonAnimationInspector.cs

@@ -27,28 +27,47 @@
  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
-
 using System;
 using UnityEditor;
 using UnityEngine;
+using Spine;
 
 [CustomEditor(typeof(SkeletonAnimation))]
 public class SkeletonAnimationInspector : SkeletonRendererInspector {
 	protected SerializedProperty animationName, loop, timeScale;
+	protected bool isPrefab;
 
 	protected override void OnEnable () {
 		base.OnEnable();
 		animationName = serializedObject.FindProperty("_animationName");
 		loop = serializedObject.FindProperty("loop");
 		timeScale = serializedObject.FindProperty("timeScale");
+
+		if (PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab)
+			isPrefab = true;
+
+
 	}
 
 	protected override void gui () {
 		base.gui();
 
 		SkeletonAnimation component = (SkeletonAnimation)target;
-		if (!component.valid) return;
+		if (!component.valid)
+			return;
+
+		//catch case where SetAnimation was used to set track 0 without using AnimationName
+		if (Application.isPlaying) {
+			TrackEntry currentState = component.state.GetCurrent(0);
+			if (currentState != null) {
+				if (component.AnimationName != animationName.stringValue) {
+					animationName.stringValue = currentState.Animation.Name;
+				}
+			}
+		}
+
 
+		//TODO:  Refactor this to use GenericMenu and callbacks to avoid interfering with control by other behaviours.
 		// Animation name.
 		{
 			String[] animations = new String[component.skeleton.Data.Animations.Count + 1];
@@ -67,12 +86,26 @@ public class SkeletonAnimationInspector : SkeletonRendererInspector {
 			EditorGUILayout.EndHorizontal();
 
 			String selectedAnimationName = animationIndex == 0 ? null : animations[animationIndex];
-			component.AnimationName = selectedAnimationName;
-			animationName.stringValue = selectedAnimationName;
+			if (component.AnimationName != selectedAnimationName) {
+				component.AnimationName = selectedAnimationName;
+				animationName.stringValue = selectedAnimationName;
+			}
+
+
 		}
 
 		EditorGUILayout.PropertyField(loop);
 		EditorGUILayout.PropertyField(timeScale);
 		component.timeScale = Math.Max(component.timeScale, 0);
+
+		EditorGUILayout.Space();
+
+		if (!isPrefab) {
+			if (component.GetComponent<SkeletonUtility>() == null) {
+				if (GUILayout.Button(new GUIContent("Add Skeleton Utility", SpineEditorUtilities.Icons.skeletonUtility), GUILayout.Height(30))) {
+					component.gameObject.AddComponent<SkeletonUtility>();
+				}
+			}
+		}
 	}
 }

+ 522 - 20
spine-tk2d/Assets/spine-tk2d/Editor/SkeletonDataAssetInspector.cs

@@ -28,8 +28,17 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************************/
 
+/*****************************************************************************
+ * Automatic import and advanced preview added by Mitch Thompson
+ * Full irrevocable rights and permissions granted to Esoteric Software
+*****************************************************************************/
 using System;
+using System.Collections.Generic;
 using UnityEditor;
+
+#if !UNITY_4_3
+using UnityEditor.AnimatedValues;
+#endif
 using UnityEngine;
 using Spine;
 
@@ -37,39 +46,75 @@ using Spine;
 public class SkeletonDataAssetInspector : Editor {
 	private SerializedProperty spriteCollection, skeletonJSON, scale, fromAnimation, toAnimation, duration, defaultMix;
 	private bool showAnimationStateData = true;
-
+	
+	#if UNITY_4_3
+	private bool m_showAnimationList = true;
+	#else
+	private AnimBool m_showAnimationList = new AnimBool(true);
+	#endif
+	
+	private bool m_initialized = false;
+	private SkeletonDataAsset m_skeletonDataAsset;
+	private string m_skeletonDataAssetGUID;
+	
 	void OnEnable () {
-		spriteCollection = serializedObject.FindProperty("spriteCollection");
-		skeletonJSON = serializedObject.FindProperty("skeletonJSON");
-		scale = serializedObject.FindProperty("scale");
-		fromAnimation = serializedObject.FindProperty("fromAnimation");
-		toAnimation = serializedObject.FindProperty("toAnimation");
-		duration = serializedObject.FindProperty("duration");
-		defaultMix = serializedObject.FindProperty("defaultMix");
-	}
+		try {
 
+			spriteCollection = serializedObject.FindProperty("spriteCollection");
+			skeletonJSON = serializedObject.FindProperty("skeletonJSON");
+			scale = serializedObject.FindProperty("scale");
+			fromAnimation = serializedObject.FindProperty("fromAnimation");
+			toAnimation = serializedObject.FindProperty("toAnimation");
+			duration = serializedObject.FindProperty("duration");
+			defaultMix = serializedObject.FindProperty("defaultMix");
+			
+			m_skeletonDataAsset = (SkeletonDataAsset)target;
+			m_skeletonDataAssetGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(m_skeletonDataAsset));
+			
+			EditorApplication.update += Update;
+
+		} catch {
+
+
+		}
+	}
+	
+	void OnDestroy () {
+		m_initialized = false;
+		EditorApplication.update -= Update;
+		this.DestroyPreviewInstances();
+		if (this.m_previewUtility != null) {
+			this.m_previewUtility.Cleanup();
+			this.m_previewUtility = null;
+		}
+	}
+	
 	override public void OnInspectorGUI () {
 		serializedObject.Update();
 		SkeletonDataAsset asset = (SkeletonDataAsset)target;
-
-		tk2dSpriteCollection sprites = EditorGUILayout.ObjectField("Sprite Collection", asset.spriteCollection, typeof(tk2dSpriteCollection), false) as tk2dSpriteCollection;
-		if (sprites != null)
-			spriteCollection.objectReferenceValue = sprites.spriteCollection;
-
+		
+		EditorGUI.BeginChangeCheck();
+		EditorGUILayout.PropertyField(spriteCollection);
 		EditorGUILayout.PropertyField(skeletonJSON);
 		EditorGUILayout.PropertyField(scale);
+		if (EditorGUI.EndChangeCheck()) {
+			if (m_previewUtility != null) {
+				m_previewUtility.Cleanup();
+				m_previewUtility = null;
+			}
+		}
 		
 		SkeletonData skeletonData = asset.GetSkeletonData(asset.spriteCollection == null || asset.skeletonJSON == null);
 		if (skeletonData != null) {
 			showAnimationStateData = EditorGUILayout.Foldout(showAnimationStateData, "Animation State Data");
 			if (showAnimationStateData) {
 				EditorGUILayout.PropertyField(defaultMix);
-
-				// Animation names.
+				
+				// Animation names
 				String[] animations = new String[skeletonData.Animations.Count];
 				for (int i = 0; i < animations.Length; i++)
 					animations[i] = skeletonData.Animations[i].Name;
-			
+				
 				for (int i = 0; i < fromAnimation.arraySize; i++) {
 					SerializedProperty from = fromAnimation.GetArrayElementAtIndex(i);
 					SerializedProperty to = toAnimation.GetArrayElementAtIndex(i);
@@ -95,14 +140,471 @@ public class SkeletonDataAssetInspector : Editor {
 				EditorGUILayout.Space();
 				EditorGUILayout.EndHorizontal();
 			}
+			
+			if (GUILayout.Button(new GUIContent("Setup Pose", SpineEditorUtilities.Icons.skeleton), GUILayout.Width(105), GUILayout.Height(18))) {
+				StopAnimation();
+				m_skeletonAnimation.skeleton.SetToSetupPose();
+				m_requireRefresh = true;
+			}
+			
+			#if UNITY_4_3
+			m_showAnimationList = EditorGUILayout.Foldout(m_showAnimationList, new GUIContent("Animations", SpineEditorUtilities.Icons.animationRoot));
+			if(m_showAnimationList){
+			#else
+			m_showAnimationList.target = EditorGUILayout.Foldout(m_showAnimationList.target, new GUIContent("Animations", SpineEditorUtilities.Icons.animationRoot));
+			if (EditorGUILayout.BeginFadeGroup(m_showAnimationList.faded)) {
+				#endif
+					
+					
+					
+					
+				EditorGUILayout.LabelField("Name", "Duration");
+				foreach (Spine.Animation a in skeletonData.Animations) {
+					GUILayout.BeginHorizontal();
+						
+					if (m_skeletonAnimation != null && m_skeletonAnimation.state != null) {
+						if (m_skeletonAnimation.state.GetCurrent(0) != null && m_skeletonAnimation.state.GetCurrent(0).Animation == a) {
+							GUI.contentColor = Color.black;
+							if (GUILayout.Button("\u25BA", GUILayout.Width(24))) {
+								StopAnimation();
+							}
+							GUI.contentColor = Color.white;
+						} else {
+							if (GUILayout.Button("\u25BA", GUILayout.Width(24))) {
+								PlayAnimation(a.Name, true);
+							}
+						}
+					} else {
+						GUILayout.Label("?", GUILayout.Width(24));
+					}
+					EditorGUILayout.LabelField(new GUIContent(a.Name, SpineEditorUtilities.Icons.animation), new GUIContent(a.Duration.ToString("f3") + "s" + ("(" + (Mathf.RoundToInt(a.Duration * 30)) + ")").PadLeft(12, ' ')));
+					GUILayout.EndHorizontal();
+				}
+			}
+			#if !UNITY_4_3
+			EditorGUILayout.EndFadeGroup();
+			#endif
 		}
-		
+			
 		if (!Application.isPlaying) {
 			if (serializedObject.ApplyModifiedProperties() ||
 				(UnityEngine.Event.current.type == EventType.ValidateCommand && UnityEngine.Event.current.commandName == "UndoRedoPerformed")
-			) {
+				    ) {
 				asset.Reset();
 			}
 		}
 	}
-}
+		
+	//preview window stuff
+	private PreviewRenderUtility m_previewUtility;
+	private GameObject m_previewInstance;
+	private Vector2 previewDir;
+	private SkeletonAnimation m_skeletonAnimation;
+	private SkeletonData m_skeletonData;
+	private static int sliderHash = "Slider".GetHashCode();
+	private float m_lastTime;
+	private bool m_playing;
+	private bool m_requireRefresh;
+	private Color m_originColor = new Color(0.3f, 0.3f, 0.3f, 1);
+		
+	private void StopAnimation () {
+		m_skeletonAnimation.state.ClearTrack(0);
+		m_playing = false;
+	}
+		
+	List<Spine.Event> m_animEvents = new List<Spine.Event>();
+	List<float> m_animEventFrames = new List<float>();
+
+	private void PlayAnimation (string animName, bool loop) {
+		m_animEvents.Clear();
+		m_animEventFrames.Clear();
+			
+		m_skeletonAnimation.state.SetAnimation(0, animName, loop);
+			
+		Spine.Animation a = m_skeletonAnimation.state.GetCurrent(0).Animation;
+		foreach (Timeline t in a.Timelines) {
+			if (t.GetType() == typeof(EventTimeline)) {
+				EventTimeline et = (EventTimeline)t;
+					
+				for (int i = 0; i < et.Events.Length; i++) {
+					m_animEvents.Add(et.Events[i]);
+					m_animEventFrames.Add(et.Frames[i]);
+				}
+					
+			}
+		}
+			
+		m_playing = true;
+	}
+		
+	private void InitPreview () {
+		if (this.m_previewUtility == null) {
+			this.m_lastTime = Time.realtimeSinceStartup;
+			this.m_previewUtility = new PreviewRenderUtility(true);
+			this.m_previewUtility.m_Camera.isOrthoGraphic = true;
+			this.m_previewUtility.m_Camera.orthographicSize = (scale.floatValue * (m_skeletonDataAsset.spriteCollection.invOrthoSize * m_skeletonDataAsset.spriteCollection.halfTargetHeight)) / 100;
+			this.m_previewUtility.m_Camera.cullingMask = -2147483648;
+			this.CreatePreviewInstances();
+		}
+	}
+		
+	private void CreatePreviewInstances () {
+		this.DestroyPreviewInstances();
+		if (this.m_previewInstance == null) {
+			string skinName = EditorPrefs.GetString(m_skeletonDataAssetGUID + "_lastSkin", "");
+				
+			m_previewInstance = SpineEditorUtilities.SpawnAnimatedSkeleton((SkeletonDataAsset)target, skinName).gameObject;
+			//m_previewInstance.transform.localScale = Vector3.one * 0.01f;
+			m_previewInstance.hideFlags = HideFlags.HideAndDontSave;
+			m_previewInstance.layer = 0x1f;
+				
+				
+			m_skeletonAnimation = m_previewInstance.GetComponent<SkeletonAnimation>();
+			m_skeletonAnimation.initialSkinName = skinName;
+			m_skeletonAnimation.LateUpdate();				
+			m_skeletonData = m_skeletonAnimation.skeletonDataAsset.GetSkeletonData(true);
+				
+			m_previewInstance.renderer.enabled = false;
+				
+			m_initialized = true;
+			AdjustCameraGoals(true);
+		}
+	}
+		
+	private void DestroyPreviewInstances () {
+		if (this.m_previewInstance != null) {
+			DestroyImmediate(this.m_previewInstance);
+			m_previewInstance = null;
+		}
+		m_initialized = false;
+	}
+		
+	public override bool HasPreviewGUI () {
+		//TODO: validate json data
+		return skeletonJSON.objectReferenceValue != null;
+	}
+		
+	Texture m_previewTex = new Texture();
+
+	public override void OnInteractivePreviewGUI (Rect r, GUIStyle background) {
+		this.InitPreview();
+			
+		if (UnityEngine.Event.current.type == EventType.Repaint) {
+			if (m_requireRefresh) {
+				this.m_previewUtility.BeginPreview(r, background);
+				this.DoRenderPreview(true);
+				this.m_previewTex = this.m_previewUtility.EndPreview();
+				m_requireRefresh = false;
+			}
+			if (this.m_previewTex != null)
+				GUI.DrawTexture(r, m_previewTex, ScaleMode.StretchToFill, false);
+		}
+			
+		DrawSkinToolbar(r);
+		NormalizedTimeBar(r);
+		//TODO: implement panning
+		//		this.previewDir = Drag2D(this.previewDir, r);
+		MouseScroll(r);
+	}
+		
+	float m_orthoGoal = 1;
+	Vector3 m_posGoal = new Vector3(0, 0, -10);
+	double m_adjustFrameEndTime = 0;
+
+	private void AdjustCameraGoals (bool calculateMixTime) {
+		if (calculateMixTime) {
+			if (m_skeletonAnimation.state.GetCurrent(0) != null) {
+				m_adjustFrameEndTime = EditorApplication.timeSinceStartup + m_skeletonAnimation.state.GetCurrent(0).Mix;
+			}
+		}
+
+		GameObject go = this.m_previewInstance;
+		Bounds bounds = go.renderer.bounds;
+		m_orthoGoal = bounds.size.y;
+		m_posGoal = bounds.center + new Vector3(0, 0, -10);
+	}
+		
+	private void AdjustCameraGoals () {
+		AdjustCameraGoals(false);
+	}
+		
+	private void AdjustCamera () {
+		if (m_previewUtility == null)
+			return;
+			
+			
+		if (EditorApplication.timeSinceStartup < m_adjustFrameEndTime) {
+			AdjustCameraGoals();
+		}
+			
+		float orthoSet = Mathf.Lerp(this.m_previewUtility.m_Camera.orthographicSize, m_orthoGoal, 0.1f);
+			
+		this.m_previewUtility.m_Camera.orthographicSize = orthoSet;
+
+			
+		float dist = Vector3.Distance(m_previewUtility.m_Camera.transform.position, m_posGoal);
+		if (dist > m_skeletonDataAsset.scale) {
+			Vector3 pos = Vector3.Lerp(this.m_previewUtility.m_Camera.transform.position, m_posGoal, 0.1f);
+			pos.x = 0;
+			this.m_previewUtility.m_Camera.transform.position = pos;
+			this.m_previewUtility.m_Camera.transform.rotation = Quaternion.identity;
+			m_requireRefresh = true;
+		}
+	}
+		
+	private void DoRenderPreview (bool drawHandles) {
+		GameObject go = this.m_previewInstance;
+			
+		if (m_requireRefresh) {
+			go.renderer.enabled = true;
+				
+			if (EditorApplication.isPlaying) {
+				//do nothing
+			} else {
+				m_skeletonAnimation.Update((Time.realtimeSinceStartup - m_lastTime));
+			}
+				
+			m_lastTime = Time.realtimeSinceStartup;
+				
+			if (!EditorApplication.isPlaying)
+				m_skeletonAnimation.LateUpdate();
+				
+			if (drawHandles) {
+				Handles.SetCamera(m_previewUtility.m_Camera);
+				Handles.color = m_originColor;
+					
+				Handles.DrawLine(new Vector3(-1000 * m_skeletonDataAsset.scale, 0, 0), new Vector3(1000 * m_skeletonDataAsset.scale, 0, 0));
+				Handles.DrawLine(new Vector3(0, 1000 * m_skeletonDataAsset.scale, 0), new Vector3(0, -1000 * m_skeletonDataAsset.scale, 0));
+			}
+				
+			this.m_previewUtility.m_Camera.Render();
+			go.renderer.enabled = false;
+		}
+			
+			
+	}
+		
+	void Update () {
+		AdjustCamera();
+			
+		if (m_playing) {
+			m_requireRefresh = true;
+			Repaint();
+		} else if (m_requireRefresh) {
+				Repaint();
+			} else {
+				#if !UNITY_4_3
+				if (m_showAnimationList.isAnimating)
+					Repaint();
+				#endif
+			}
+	}
+		
+	void DrawSkinToolbar (Rect r) {
+		if (m_skeletonAnimation == null)
+			return;
+			
+		if (m_skeletonAnimation.skeleton != null) {
+			string label = (m_skeletonAnimation.skeleton != null && m_skeletonAnimation.skeleton.Skin != null) ? m_skeletonAnimation.skeleton.Skin.Name : "default";
+				
+			Rect popRect = new Rect(r);
+			popRect.y += 32;
+			popRect.x += 4;
+			popRect.height = 24;
+			popRect.width = 40;
+			EditorGUI.DropShadowLabel(popRect, new GUIContent("Skin", SpineEditorUtilities.Icons.skinsRoot));
+				
+			popRect.y += 11;
+			popRect.width = 150;
+			popRect.x += 44;
+				
+			if (GUI.Button(popRect, label, EditorStyles.popup)) {
+				SelectSkinContext();
+			}
+		}
+	}
+		
+	void SelectSkinContext () {
+		GenericMenu menu = new GenericMenu();
+			
+		foreach (Skin s in m_skeletonData.Skins) {
+			menu.AddItem(new GUIContent(s.Name), this.m_skeletonAnimation.skeleton.Skin == s, SetSkin, (object)s);
+		}
+			
+		menu.ShowAsContext();
+	}
+		
+	void SetSkin (object o) {
+		Skin skin = (Skin)o;
+			
+		m_skeletonAnimation.initialSkinName = skin.Name;
+		m_skeletonAnimation.Reset();
+		m_requireRefresh = true;
+			
+		EditorPrefs.SetString(m_skeletonDataAssetGUID + "_lastSkin", skin.Name);
+	}
+		
+	void NormalizedTimeBar (Rect r) {
+		Rect barRect = new Rect(r);
+		barRect.height = 32;
+		barRect.x += 4;
+		barRect.width -= 4;
+			
+		GUI.Box(barRect, "");
+			
+		Rect lineRect = new Rect(barRect);
+		float width = lineRect.width;
+		TrackEntry t = m_skeletonAnimation.state.GetCurrent(0);
+			
+		if (t != null) {
+			int loopCount = (int)(t.Time / t.EndTime);
+			float currentTime = t.Time - (t.EndTime * loopCount);
+				
+			float normalizedTime = currentTime / t.Animation.Duration;
+				
+			lineRect.x = barRect.x + (width * normalizedTime) - 0.5f;
+			lineRect.width = 2;
+				
+			GUI.color = Color.red;
+			GUI.DrawTexture(lineRect, EditorGUIUtility.whiteTexture);
+			GUI.color = Color.white;
+				
+			for (int i = 0; i < m_animEvents.Count; i++) {
+				//TODO: Tooltip
+				//Spine.Event spev = animEvents[i];
+					
+				float fr = m_animEventFrames[i];
+					
+				Rect evRect = new Rect(barRect);
+				evRect.x = Mathf.Clamp(((fr / t.Animation.Duration) * width) - (SpineEditorUtilities.Icons._event.width / 2), barRect.x, float.MaxValue);
+				evRect.width = SpineEditorUtilities.Icons._event.width;
+				evRect.height = SpineEditorUtilities.Icons._event.height;
+				evRect.y += SpineEditorUtilities.Icons._event.height;
+				GUI.DrawTexture(evRect, SpineEditorUtilities.Icons._event);
+					
+					
+				//TODO:  Tooltip
+				/*
+				UnityEngine.Event ev = UnityEngine.Event.current;
+				if(ev.isMouse){
+					if(evRect.Contains(ev.mousePosition)){
+						Rect tooltipRect = new Rect(evRect);
+						tooltipRect.width = 500;
+						tooltipRect.y -= 4;
+						tooltipRect.x += 4;
+						GUI.Label(tooltipRect, spev.Data.Name);
+					}
+				}
+				*/
+			}
+		}
+	}
+		
+	void MouseScroll (Rect position) {
+		UnityEngine.Event current = UnityEngine.Event.current;
+		int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
+			
+		switch (current.GetTypeForControl(controlID)) {
+		case EventType.ScrollWheel:
+			if (position.Contains(current.mousePosition)) {
+					
+				m_orthoGoal += current.delta.y * ((SkeletonDataAsset)target).scale * 10;
+				GUIUtility.hotControl = controlID;
+				current.Use();
+			}
+			break;
+		}
+			
+	}
+		
+	//TODO:  Implement preview panning
+	/*
+	static Vector2 Drag2D(Vector2 scrollPosition, Rect position)
+	{
+		int controlID = GUIUtility.GetControlID(sliderHash, FocusType.Passive);
+		UnityEngine.Event current = UnityEngine.Event.current;
+		switch (current.GetTypeForControl(controlID))
+		{
+		case EventType.MouseDown:
+			if (position.Contains(current.mousePosition) && (position.width > 50f))
+			{
+				GUIUtility.hotControl = controlID;
+				current.Use();
+				EditorGUIUtility.SetWantsMouseJumping(1);
+			}
+			return scrollPosition;
+			
+		case EventType.MouseUp:
+			if (GUIUtility.hotControl == controlID)
+			{
+				GUIUtility.hotControl = 0;
+			}
+			EditorGUIUtility.SetWantsMouseJumping(0);
+			return scrollPosition;
+			
+		case EventType.MouseMove:
+			return scrollPosition;
+			
+		case EventType.MouseDrag:
+			if (GUIUtility.hotControl == controlID)
+			{
+				scrollPosition -= (Vector2) (((current.delta * (!current.shift ? ((float) 1) : ((float) 3))) / Mathf.Min(position.width, position.height)) * 140f);
+				scrollPosition.y = Mathf.Clamp(scrollPosition.y, -90f, 90f);
+				current.Use();
+				GUI.changed = true;
+			}
+			return scrollPosition;
+		}
+		return scrollPosition;
+	}
+	*/
+		
+	public override GUIContent GetPreviewTitle () {
+		return new GUIContent("Preview");
+	}
+		
+	public override void OnPreviewSettings () {
+		if (!m_initialized) {
+			GUILayout.HorizontalSlider(0, 0, 2, GUILayout.MaxWidth(64));
+		} else {
+			float speed = GUILayout.HorizontalSlider(m_skeletonAnimation.timeScale, 0, 2, GUILayout.MaxWidth(64));
+				
+			//snap to nearest 0.25
+			float y = speed / 0.25f;
+			int q = Mathf.RoundToInt(y);
+			speed = q * 0.25f;
+				
+			m_skeletonAnimation.timeScale = speed;
+		}
+	}
+		
+	//TODO:  Fix first-import error
+	//TODO:  Update preview without thumbnail
+	public override Texture2D RenderStaticPreview (string assetPath, UnityEngine.Object[] subAssets, int width, int height) {
+		Texture2D tex = new Texture2D(width, height, TextureFormat.ARGB32, false);
+			
+		this.InitPreview();
+			
+		if (this.m_previewUtility.m_Camera == null)
+			return null;
+			
+		m_requireRefresh = true;
+		this.DoRenderPreview(false);
+		AdjustCameraGoals(false);
+			
+		this.m_previewUtility.m_Camera.orthographicSize = m_orthoGoal / 2;
+		this.m_previewUtility.m_Camera.transform.position = m_posGoal;
+		this.m_previewUtility.BeginStaticPreview(new Rect(0, 0, width, height));
+		this.DoRenderPreview(false);
+			
+		//TODO:  Figure out why this is throwing errors on first attempt
+		//		if(m_previewUtility != null){
+		//			Handles.SetCamera(this.m_previewUtility.m_Camera);
+		//			Handles.BeginGUI();
+		//			GUI.DrawTexture(new Rect(40,60,width,height), SpineEditorUtilities.Icons.spine, ScaleMode.StretchToFill);
+		//			Handles.EndGUI();
+		//		}
+		tex = this.m_previewUtility.EndStaticPreview();
+		return tex;
+	}
+}

+ 1 - 1
spine-tk2d/Assets/spine-tk2d/Editor/SkeletonDataAssetInspector.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: cffb121e3cd80644d84c585b9c7448e8
+guid: 01cbef8f24d105f4bafa9668d669e040
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 268 - 0
spine-tk2d/Assets/spine-tk2d/Editor/SpineEditorUtilities.cs

@@ -0,0 +1,268 @@
+#pragma warning disable 0219
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.1
+ * 
+ * Copyright (c) 2013, Esoteric Software
+ * All rights reserved.
+ * 
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to install, execute and perform the Spine Runtimes
+ * Software (the "Software") solely for internal use. Without the written
+ * permission of Esoteric Software (typically granted by licensing Spine), 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 SOFTARE 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Spine Editor Utilities created by Mitch Thompson
+ * Full irrevocable rights and permissions granted to Esoteric Software
+*****************************************************************************/
+using UnityEngine;
+using UnityEditor;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Spine;
+
+[InitializeOnLoad]
+public class SpineEditorUtilities : AssetPostprocessor {
+
+	public static class Icons {
+		public static Texture2D skeleton;
+		public static Texture2D nullBone;
+		public static Texture2D bone;
+		public static Texture2D poseBones;
+		public static Texture2D boneNib;
+		public static Texture2D slot;
+		public static Texture2D skinPlaceholder;
+		public static Texture2D image;
+		public static Texture2D boundingBox;
+		public static Texture2D mesh;
+		public static Texture2D skin;
+		public static Texture2D skinsRoot;
+		public static Texture2D animation;
+		public static Texture2D animationRoot;
+		public static Texture2D spine;
+		public static Texture2D _event;
+		public static Texture2D constraintNib;
+		public static Texture2D warning;
+		public static Texture2D skeletonUtility;
+		public static Texture2D hingeChain;
+		public static Texture2D subMeshRenderer;
+
+		public static Mesh boneMesh {
+			get {
+				if (_boneMesh == null) {
+					_boneMesh = new Mesh();
+					_boneMesh.vertices = new Vector3[4] {
+						Vector3.zero,
+						new Vector3(-0.1f, 0.1f, 0),
+						Vector3.up,
+						new Vector3(0.1f, 0.1f, 0)
+					};
+					_boneMesh.uv = new Vector2[4];
+					_boneMesh.triangles = new int[6]{0,1,2,2,3,0};
+					_boneMesh.RecalculateBounds();
+					_boneMesh.RecalculateNormals();
+				}
+
+				return _boneMesh;
+			}
+		}
+
+		internal static Mesh _boneMesh;
+
+		public static Material boneMaterial {
+			get {
+				if (_boneMaterial == null) {
+#if UNITY_4_3
+					_boneMaterial = new Material(Shader.Find("Particles/Alpha Blended"));
+					_boneMaterial.SetColor("_TintColor", new Color(0.4f, 0.4f, 0.4f, 0.25f));
+#else
+					_boneMaterial = new Material(Shader.Find("Spine/Bones"));
+					_boneMaterial.SetColor("_Color", new Color(0.4f, 0.4f, 0.4f, 0.25f));
+#endif
+
+				}
+
+				return _boneMaterial;
+			}
+		}
+
+		internal static Material _boneMaterial;
+
+		public static void Initialize () {
+			skeleton = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skeleton.png");
+			nullBone = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-null.png");
+			bone = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-bone.png");
+			poseBones = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-poseBones.png");
+			boneNib = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-boneNib.png");
+			slot = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-slot.png");
+			skinPlaceholder = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skinPlaceholder.png");
+			image = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-image.png");
+			boundingBox = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-boundingBox.png");
+			mesh = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-mesh.png");
+			skin = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skinPlaceholder.png");
+			skinsRoot = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skinsRoot.png");
+			animation = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-animation.png");
+			animationRoot = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-animationRoot.png");
+			spine = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-spine.png");
+			_event = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-event.png");
+			constraintNib = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-constraintNib.png");
+			warning = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-warning.png");
+			skeletonUtility = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-skeletonUtility.png");
+			hingeChain = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-hingeChain.png");
+			subMeshRenderer = (Texture2D)AssetDatabase.LoadMainAssetAtPath(SpineEditorUtilities.editorGUIPath + "/icon-subMeshRenderer.png");
+		}
+	}
+
+	public static string editorPath = "";
+	public static string editorGUIPath = "";
+	static Dictionary<int, GameObject> skeletonRendererTable;
+	static Dictionary<int, SkeletonUtilityBone> skeletonUtilityBoneTable;
+	public static float defaultScale = 0.01f;
+	public static float defaultMix = 0.2f;
+	public static string defaultShader = "Spine/Skeleton";
+	
+	static SpineEditorUtilities () {
+		DirectoryInfo rootDir = new DirectoryInfo(Application.dataPath);
+		FileInfo[] files = rootDir.GetFiles("SpineEditorUtilities.cs", SearchOption.AllDirectories);
+		editorPath = Path.GetDirectoryName(files[0].FullName.Replace("\\", "/").Replace(Application.dataPath, "Assets"));
+		editorGUIPath = editorPath + "/GUI";	
+
+		Icons.Initialize();
+
+		skeletonRendererTable = new Dictionary<int, GameObject>();
+		skeletonUtilityBoneTable = new Dictionary<int, SkeletonUtilityBone>();
+
+		EditorApplication.hierarchyWindowChanged += HierarchyWindowChanged;
+		EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowItemOnGUI;
+
+		HierarchyWindowChanged();
+	}
+
+	static void HierarchyWindowChanged () {
+		skeletonRendererTable.Clear();
+		skeletonUtilityBoneTable.Clear();
+
+		SkeletonRenderer[] arr = Object.FindObjectsOfType<SkeletonRenderer>();
+
+		foreach (SkeletonRenderer r in arr)
+			skeletonRendererTable.Add(r.gameObject.GetInstanceID(), r.gameObject);
+
+		SkeletonUtilityBone[] boneArr = Object.FindObjectsOfType<SkeletonUtilityBone>();
+		foreach (SkeletonUtilityBone b in boneArr)
+			skeletonUtilityBoneTable.Add(b.gameObject.GetInstanceID(), b);
+	}
+
+	static void HierarchyWindowItemOnGUI (int instanceId, Rect selectionRect) {
+		if (skeletonRendererTable.ContainsKey(instanceId)) {
+			Rect r = new Rect(selectionRect); 
+			r.x = r.width - 15;
+			r.width = 15;
+
+			GUI.Label(r, Icons.spine);
+		} else if (skeletonUtilityBoneTable.ContainsKey(instanceId)) {
+				Rect r = new Rect(selectionRect); 
+				r.x -= 26;
+
+				if (skeletonUtilityBoneTable[instanceId] != null) {
+					if (skeletonUtilityBoneTable[instanceId].transform.childCount == 0)
+						r.x += 13;
+				
+					r.y += 2;
+
+					r.width = 13;
+					r.height = 13;
+
+					if (skeletonUtilityBoneTable[instanceId].mode == SkeletonUtilityBone.Mode.Follow) {
+						GUI.DrawTexture(r, Icons.bone);
+					} else {
+						GUI.DrawTexture(r, Icons.poseBones);
+					}
+				}
+
+			}
+
+	}
+
+	[MenuItem("Assets/Spine/Spawn")]
+	static void SpawnAnimatedSkeleton () {
+		Object[] arr = Selection.objects;
+		foreach (Object o in arr) {
+			string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(o));
+			string skinName = EditorPrefs.GetString(guid + "_lastSkin", "");
+
+			SpawnAnimatedSkeleton((SkeletonDataAsset)o, skinName);
+			SceneView.RepaintAll();
+		}
+	}
+
+	[MenuItem("Assets/Spine/Spawn", true)]
+	static bool ValidateSpawnAnimatedSkeleton () {
+		Object[] arr = Selection.objects;
+		
+		if (arr.Length == 0)
+			return false;
+		
+		foreach (Object o in arr) {
+			if (o.GetType() != typeof(SkeletonDataAsset))
+				return false;
+		}
+		
+		return true;
+	}
+
+	public static SkeletonAnimation SpawnAnimatedSkeleton (SkeletonDataAsset skeletonDataAsset, string skinName) {
+		return SpawnAnimatedSkeleton(skeletonDataAsset, skeletonDataAsset.GetSkeletonData(true).FindSkin(skinName));
+	}
+
+	public static SkeletonAnimation SpawnAnimatedSkeleton (SkeletonDataAsset skeletonDataAsset, Skin skin = null) {
+		GameObject go = new GameObject(skeletonDataAsset.name.Replace("_SkeletonData", ""), typeof(MeshFilter), typeof(MeshRenderer), typeof(SkeletonAnimation));
+		SkeletonAnimation anim = go.GetComponent<SkeletonAnimation>();
+		anim.skeletonDataAsset = skeletonDataAsset;
+
+
+
+		SkeletonData data = skeletonDataAsset.GetSkeletonData(true);
+
+		if (data == null) {
+			return null;
+		}
+
+		if (skin == null)
+			skin = data.DefaultSkin;
+			
+		if (skin == null)
+			skin = data.Skins[0];
+
+		anim.Reset();
+		
+		anim.skeleton.SetSkin(skin);
+		anim.initialSkinName = skin.Name;
+		
+		anim.skeleton.Update(1);
+		anim.state.Update(1);
+		anim.state.Apply(anim.skeleton);
+		anim.skeleton.UpdateWorldTransform();
+
+		return anim;
+	}
+}

+ 8 - 0
spine-tk2d/Assets/spine-tk2d/Editor/SpineEditorUtilities.cs.meta

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

+ 69 - 0
spine-tk2d/Assets/spine-tk2d/Shaders/Bones.shader

@@ -0,0 +1,69 @@
+Shader "Spine/Bones" {
+Properties {
+	_Color ("Color", Color) = (0.5,0.5,0.5,0.5)
+	_MainTex ("Particle Texture", 2D) = "white" {}
+}
+
+Category {
+	Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
+	Blend SrcAlpha OneMinusSrcAlpha
+	AlphaTest Greater .01
+	ColorMask RGB
+	
+	Lighting Off Cull Off ZTest Always ZWrite Off Fog { Mode Off }
+
+	SubShader {
+		Pass {
+		
+			CGPROGRAM
+			#pragma vertex vert
+			#pragma fragment frag
+			#pragma multi_compile_particles
+			
+			#include "UnityCG.cginc"
+
+			sampler2D _MainTex;
+			fixed4 _Color;
+			
+			struct appdata_t {
+				float4 vertex : POSITION;
+				fixed4 color : COLOR;
+				float2 texcoord : TEXCOORD0;
+			};
+
+			struct v2f {
+				float4 vertex : SV_POSITION;
+				fixed4 color : COLOR;
+				float2 texcoord : TEXCOORD0;
+				#ifdef SOFTPARTICLES_ON
+				float4 projPos : TEXCOORD1;
+				#endif
+			};
+			
+			float4 _MainTex_ST;
+
+			v2f vert (appdata_t v)
+			{
+				v2f o;
+				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
+				#ifdef SOFTPARTICLES_ON
+				o.projPos = ComputeScreenPos (o.vertex);
+				COMPUTE_EYEDEPTH(o.projPos.z);
+				#endif
+				o.color = v.color;
+				o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
+				return o;
+			}
+
+			sampler2D_float _CameraDepthTexture;
+
+			
+			fixed4 frag (v2f i) : SV_Target
+			{				
+				return 2.0f * i.color * _Color * tex2D(_MainTex, i.texcoord);
+			}
+			ENDCG 
+		}
+	}	
+}
+}

+ 5 - 0
spine-tk2d/Assets/spine-tk2d/Shaders/Bones.shader.meta

@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: 66988de88a15abd4e8846c6805485f57
+ShaderImporter:
+  defaultTextures: []
+  userData: 

BIN
spine-tk2d/Assets/spine-tk2d/Shaders/HiddenPass.mat


+ 4 - 0
spine-tk2d/Assets/spine-tk2d/Shaders/HiddenPass.mat.meta

@@ -0,0 +1,4 @@
+fileFormatVersion: 2
+guid: 43227e5adadc6f24bb4bf74b92a56fb4
+NativeFormatImporter:
+  userData: 

+ 21 - 0
spine-tk2d/Assets/spine-tk2d/Shaders/HiddenPass.shader

@@ -0,0 +1,21 @@
+Shader "Spine/HiddenPass" {
+    SubShader
+
+    {
+
+        Tags {"Queue" = "Geometry-1" }
+
+        Lighting Off
+
+        Pass
+
+        {
+
+            ZWrite Off
+
+            ColorMask 0     
+
+        }
+
+    }
+}

+ 5 - 0
spine-tk2d/Assets/spine-tk2d/Shaders/HiddenPass.shader.meta

@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: 913475501bf19374c84390868a9d6d3d
+ShaderImporter:
+  defaultTextures: []
+  userData: 

+ 26 - 7
spine-tk2d/Assets/spine-tk2d/SkeletonAnimation.cs

@@ -41,18 +41,23 @@ public class SkeletonAnimation : SkeletonRenderer {
 	public bool loop;
 	public Spine.AnimationState state;
 
-	public delegate void UpdateBonesDelegate(SkeletonAnimation skeleton);
-	public UpdateBonesDelegate UpdateBones;
+	public delegate void UpdateBonesDelegate (SkeletonAnimation skeleton);
 
+	public UpdateBonesDelegate UpdateLocal;
+	public UpdateBonesDelegate UpdateWorld;
+	public UpdateBonesDelegate UpdateComplete;
 	[SerializeField]
-	private String _animationName;
+	private String
+		_animationName;
+
 	public String AnimationName {
 		get {
 			TrackEntry entry = state.GetCurrent(0);
 			return entry == null ? null : entry.Animation.Name;
 		}
 		set {
-			if (_animationName == value) return;
+			if (_animationName == value)
+				return;
 			_animationName = value;
 			if (value == null || value.Length == 0)
 				state.ClearTrack(0);
@@ -63,7 +68,8 @@ public class SkeletonAnimation : SkeletonRenderer {
 
 	public override void Reset () {
 		base.Reset();
-		if (!valid) return;
+		if (!valid)
+			return;
 
 		state = new Spine.AnimationState(skeletonDataAsset.GetAnimationStateData());
 		if (_animationName != null && _animationName.Length > 0) {
@@ -77,13 +83,26 @@ public class SkeletonAnimation : SkeletonRenderer {
 	}
 
 	public virtual void Update (float deltaTime) {
-		if (!valid) return;
+		if (!valid)
+			return;
 
 		deltaTime *= timeScale;
 		skeleton.Update(deltaTime);
 		state.Update(deltaTime);
 		state.Apply(skeleton);
-		if (UpdateBones != null) UpdateBones(this);
+
+		if (UpdateLocal != null) 
+			UpdateLocal(this);
+
 		skeleton.UpdateWorldTransform();
+
+		if (UpdateWorld != null) { 
+			UpdateWorld(this);
+			skeleton.UpdateWorldTransform();
+		}
+
+		if (UpdateComplete != null) { 
+			UpdateComplete(this);
+		}
 	}
 }

+ 5 - 4
spine-tk2d/Assets/spine-tk2d/SkeletonDataAsset.cs

@@ -53,14 +53,14 @@ public class SkeletonDataAsset : ScriptableObject {
 	public SkeletonData GetSkeletonData (bool quiet) {
 		if (spriteCollection == null) {
 			if (!quiet)
-				Debug.LogError("Sprite collection not set for skeleton data asset: " + name, this);
+				Debug.LogError("SpriteCollection not set for SkeletonData asset: " + name, this);
 			Reset();
 			return null;
 		}
-		
+
 		if (skeletonJSON == null) {
 			if (!quiet)
-				Debug.LogError("Skeleton JSON file not set for skeleton data asset: " + name, this);
+				Debug.LogError("Skeleton JSON file not set for SkeletonData asset: " + name, this);
 			Reset();
 			return null;
 		}
@@ -81,7 +81,8 @@ public class SkeletonDataAsset : ScriptableObject {
 		stateData = new AnimationStateData(skeletonData);
 		stateData.DefaultMix = defaultMix;
 		for (int i = 0, n = fromAnimation.Length; i < n; i++) {
-			if (fromAnimation[i].Length == 0 || toAnimation[i].Length == 0) continue;
+			if (fromAnimation[i].Length == 0 || toAnimation[i].Length == 0)
+				continue;
 			stateData.SetMix(fromAnimation[i], toAnimation[i], duration[i]);
 		}
 

+ 108 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonExtensions.cs

@@ -0,0 +1,108 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.1
+ * 
+ * Copyright (c) 2013, Esoteric Software
+ * All rights reserved.
+ * 
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to install, execute and perform the Spine Runtimes
+ * Software (the "Software") solely for internal use. Without the written
+ * permission of Esoteric Software (typically granted by licensing Spine), 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 SOFTARE 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Spine Extensions created by Mitch Thompson
+ * Full irrevocable rights and permissions granted to Esoteric Software
+*****************************************************************************/
+
+using UnityEngine;
+using System.Collections;
+using Spine;
+
+public static class SkeletonExtensions {
+	
+	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 / 255f;
+		slot.R = color.r / 255f;
+		slot.G = color.g / 255f;
+		slot.B = color.b / 255f;
+	}
+
+	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 / 255f;
+		attachment.R = color.r / 255f;
+		attachment.G = color.g / 255f;
+		attachment.B = color.b / 255f;
+	}
+
+	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 / 255f;
+		attachment.R = color.r / 255f;
+		attachment.G = color.g / 255f;
+		attachment.B = color.b / 255f;
+	}
+
+	public static void SetColor (this SkinnedMeshAttachment attachment, Color color) {
+		attachment.A = color.a;
+		attachment.R = color.r;
+		attachment.G = color.g;
+		attachment.B = color.b;
+	}
+
+	public static void SetColor (this SkinnedMeshAttachment attachment, Color32 color) {
+		attachment.A = color.a / 255f;
+		attachment.R = color.r / 255f;
+		attachment.G = color.g / 255f;
+		attachment.B = color.b / 255f;
+	}
+
+	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;
+	}
+
+}

+ 8 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonExtensions.cs.meta

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

+ 69 - 50
spine-tk2d/Assets/spine-tk2d/SkeletonRenderer.cs

@@ -37,17 +37,20 @@ using Spine;
 /// <summary>Renders a skeleton.</summary>
 [ExecuteInEditMode, RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
 public class SkeletonRenderer : MonoBehaviour {
+
+	public delegate void SkeletonRendererDelegate (SkeletonRenderer skeletonRenderer);
+
+	public SkeletonRendererDelegate OnReset;
 	[System.NonSerialized]
 	public bool valid;
 	[System.NonSerialized]
 	public Skeleton skeleton;
-	
 	public SkeletonDataAsset skeletonDataAsset;
 	public String initialSkinName;
 	public bool calculateNormals, calculateTangents;
 	public float zSpacing;
 	public bool renderMeshes = true, immutableTriangles;
-	
+	public bool logErrors = false;
 	private MeshFilter meshFilter;
 	private Mesh mesh, mesh1, mesh2;
 	private bool useMesh1;
@@ -61,9 +64,12 @@ public class SkeletonRenderer : MonoBehaviour {
 	private readonly List<Submesh> submeshes = new List<Submesh>();
 
 	public virtual void Reset () {
-		if (meshFilter != null) meshFilter.sharedMesh = null;
-		if (mesh != null) DestroyImmediate(mesh);
-		if (renderer != null) renderer.sharedMaterial = null;
+		if (meshFilter != null)
+			meshFilter.sharedMesh = null;
+		if (mesh != null)
+			DestroyImmediate(mesh);
+		if (renderer != null)
+			renderer.sharedMaterial = null;
 		mesh = null;
 		mesh1 = null;
 		mesh2 = null;
@@ -78,11 +84,14 @@ public class SkeletonRenderer : MonoBehaviour {
 
 		valid = false;
 		if (!skeletonDataAsset) {
-			Debug.LogError("Missing SkeletonData asset.", this);
+			if (logErrors)
+				Debug.LogError("Missing SkeletonData asset.", this);
+
 			return;
 		}
 		SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(false);
-		if (skeletonData == null) return;
+		if (skeletonData == null)
+			return;
 		valid = true;
 		
 		meshFilter = GetComponent<MeshFilter>();
@@ -93,6 +102,8 @@ public class SkeletonRenderer : MonoBehaviour {
 		skeleton = new Skeleton(skeletonData);
 		if (initialSkinName != null && initialSkinName.Length > 0 && initialSkinName != "default")
 			skeleton.SetSkin(initialSkinName);
+		if (OnReset != null)
+			OnReset(this);
 	}
 	
 	public void Awake () {
@@ -108,8 +119,8 @@ public class SkeletonRenderer : MonoBehaviour {
 	}
 	
 	public virtual void LateUpdate () {
-		if (!valid) return;
-		
+		if (!valid)
+			return;
 		// Count vertices and submesh triangles.
 		int vertexCount = 0;
 		int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;
@@ -119,7 +130,8 @@ public class SkeletonRenderer : MonoBehaviour {
 		int drawOrderCount = drawOrder.Count;
 		bool renderMeshes = this.renderMeshes;
 		for (int i = 0; i < drawOrderCount; i++) {
-			Attachment attachment = drawOrder[i].attachment;
+			Slot slot = drawOrder[i];
+			Attachment attachment = slot.attachment;
 			
 			object rendererObject;
 			int attachmentVertexCount, attachmentTriangleCount;
@@ -129,24 +141,25 @@ public class SkeletonRenderer : MonoBehaviour {
 				attachmentVertexCount = 4;
 				attachmentTriangleCount = 6;
 			} else {
-				if (!renderMeshes) continue;
+				if (!renderMeshes)
+					continue;
 				if (attachment is MeshAttachment) {
 					MeshAttachment meshAttachment = (MeshAttachment)attachment;
 					rendererObject = meshAttachment.RendererObject;
 					attachmentVertexCount = meshAttachment.vertices.Length >> 1;
 					attachmentTriangleCount = meshAttachment.triangles.Length;
 				} else if (attachment is SkinnedMeshAttachment) {
-					SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
-					rendererObject = meshAttachment.RendererObject;
-					attachmentVertexCount = meshAttachment.uvs.Length >> 1;
-					attachmentTriangleCount = meshAttachment.triangles.Length;
-				} else
-					continue;
+						SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
+						rendererObject = meshAttachment.RendererObject;
+						attachmentVertexCount = meshAttachment.uvs.Length >> 1;
+						attachmentTriangleCount = meshAttachment.triangles.Length;
+					} else
+						continue;
 			}
 
 			// Populate submesh when material changes.
 			Material material = (Material)rendererObject;
-			if (lastMaterial != material && lastMaterial != null) {
+			if ((lastMaterial != material && lastMaterial != null) || slot.Data.name[0] == '*') {
 				AddSubmesh(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false);
 				submeshTriangleCount = 0;
 				submeshFirstVertex = vertexCount;
@@ -209,7 +222,8 @@ public class SkeletonRenderer : MonoBehaviour {
 				color.r = (byte)(r * slot.r * regionAttachment.r * color.a);
 				color.g = (byte)(g * slot.g * regionAttachment.g * color.a);
 				color.b = (byte)(b * slot.b * regionAttachment.b * color.a);
-				if (slot.data.additiveBlending) color.a = 0;
+				if (slot.data.additiveBlending)
+					color.a = 0;
 				colors[vertexIndex] = color;
 				colors[vertexIndex + 1] = color;
 				colors[vertexIndex + 2] = color;
@@ -223,18 +237,21 @@ public class SkeletonRenderer : MonoBehaviour {
 				
 				vertexIndex += 4;
 			} else {
-				if (!renderMeshes) continue;
+				if (!renderMeshes)
+					continue;
 				if (attachment is MeshAttachment) {
 					MeshAttachment meshAttachment = (MeshAttachment)attachment;
 					int meshVertexCount = meshAttachment.vertices.Length;
-					if (tempVertices.Length < meshVertexCount) tempVertices = new float[meshVertexCount];
+					if (tempVertices.Length < meshVertexCount)
+						tempVertices = new float[meshVertexCount];
 					meshAttachment.ComputeWorldVertices(slot, tempVertices);
 					
 					color.a = (byte)(a * slot.a * meshAttachment.a);
 					color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
 					color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
 					color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
-					if (slot.data.additiveBlending) color.a = 0;
+					if (slot.data.additiveBlending)
+						color.a = 0;
 					
 					float[] meshUVs = meshAttachment.uvs;
 					float z = i * zSpacing;
@@ -244,25 +261,27 @@ public class SkeletonRenderer : MonoBehaviour {
 						uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]);
 					}
 				} else if (attachment is SkinnedMeshAttachment) {
-					SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
-					int meshVertexCount = meshAttachment.uvs.Length;
-					if (tempVertices.Length < meshVertexCount) tempVertices = new float[meshVertexCount];
-					meshAttachment.ComputeWorldVertices(slot, tempVertices);
+						SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
+						int meshVertexCount = meshAttachment.uvs.Length;
+						if (tempVertices.Length < meshVertexCount)
+							tempVertices = new float[meshVertexCount];
+						meshAttachment.ComputeWorldVertices(slot, tempVertices);
 					
-					color.a = (byte)(a * slot.a * meshAttachment.a);
-					color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
-					color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
-					color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
-					if (slot.data.additiveBlending) color.a = 0;
+						color.a = (byte)(a * slot.a * meshAttachment.a);
+						color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
+						color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
+						color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
+						if (slot.data.additiveBlending)
+							color.a = 0;
 					
-					float[] meshUVs = meshAttachment.uvs;
-					float z = i * zSpacing;
-					for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {
-						vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z);
-						colors[vertexIndex] = color;
-						uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]);
+						float[] meshUVs = meshAttachment.uvs;
+						float z = i * zSpacing;
+						for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {
+							vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z);
+							colors[vertexIndex] = color;
+							uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]);
+						}
 					}
-				}
 			}
 		}
 		
@@ -310,7 +329,7 @@ public class SkeletonRenderer : MonoBehaviour {
 		if (submeshes.Count <= submeshIndex)
 			submeshes.Add(new Submesh());
 		else if (immutableTriangles)
-			return;
+				return;
 
 		Submesh submesh = submeshes[submeshIndex];
 		
@@ -322,10 +341,10 @@ public class SkeletonRenderer : MonoBehaviour {
 				triangles[i] = 0;
 			submesh.triangleCount = triangleCount;
 		} else if (trianglesCapacity != triangleCount) {
-			// Reallocate triangles when not the exact size needed.
-			submesh.triangles = triangles = new int[triangleCount];
-			submesh.triangleCount = 0;
-		}
+				// Reallocate triangles when not the exact size needed.
+				submesh.triangles = triangles = new int[triangleCount];
+				submesh.triangleCount = 0;
+			}
 
 		if (!renderMeshes) {
 			// Use stored triangles if possible.
@@ -366,18 +385,18 @@ public class SkeletonRenderer : MonoBehaviour {
 				attachmentVertexCount = meshAttachment.vertices.Length >> 1;
 				attachmentTriangles = meshAttachment.triangles;
 			} else if (attachment is SkinnedMeshAttachment) {
-				SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
-				attachmentVertexCount = meshAttachment.uvs.Length >> 1;
-				attachmentTriangles = meshAttachment.triangles;
-			} else
-				continue;
+					SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
+					attachmentVertexCount = meshAttachment.uvs.Length >> 1;
+					attachmentTriangles = meshAttachment.triangles;
+				} else
+					continue;
 			for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii++, triangleIndex++)
 				triangles[triangleIndex] = firstVertex + attachmentTriangles[ii];
 			firstVertex += attachmentVertexCount;
 		}
 	}
 	
-	#if UNITY_EDITOR
+#if UNITY_EDITOR
 	void OnDrawGizmos() {
 		// Make selection easier by drawing a clear gizmo over the skeleton.
 		if (vertices == null) return;
@@ -397,7 +416,7 @@ public class SkeletonRenderer : MonoBehaviour {
 		Gizmos.matrix = transform.localToWorldMatrix;
 		Gizmos.DrawCube(gizmosCenter, gizmosSize);
 	}
-	#endif
+#endif
 }
 
 class Submesh {

+ 5 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility.meta

@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: f6e0caaafe294de48af468a6a9321473
+folderAsset: yes
+DefaultImporter:
+  userData: 

+ 5 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/Editor.meta

@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: a751a9d1e3e26d64d997b66a781df8e9
+folderAsset: yes
+DefaultImporter:
+  userData: 

+ 304 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs

@@ -0,0 +1,304 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.1
+ * 
+ * Copyright (c) 2013, Esoteric Software
+ * All rights reserved.
+ * 
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to install, execute and perform the Spine Runtimes
+ * Software (the "Software") solely for internal use. Without the written
+ * permission of Esoteric Software (typically granted by licensing Spine), 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 SOFTARE 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Skeleton Utility created by Mitch Thompson
+ * Full irrevocable rights and permissions granted to Esoteric Software
+*****************************************************************************/
+using UnityEngine;
+using UnityEditor;
+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, flip, flipX;
+
+	//multi selected flags
+	bool containsFollows, containsOverrides, multiObject;
+	
+	//single selected helpers
+	SkeletonUtilityBone utilityBone;
+	SkeletonUtility skeletonUtility;
+	bool canCreateHingeChain = false;
+	
+	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");
+		flip = this.serializedObject.FindProperty("flip");
+		flipX = this.serializedObject.FindProperty("flipX");
+
+		EvaluateFlags();
+
+		if (utilityBone.valid == false && skeletonUtility != null && skeletonUtility.skeletonRenderer != null) {
+			skeletonUtility.skeletonRenderer.Reset();
+		}
+
+		canCreateHingeChain = CanCreateHingeChain();
+	}
+
+	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 (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>";
+
+			GUILayout.BeginHorizontal();
+			EditorGUILayout.PrefixLabel("Bone");
+
+			if (GUILayout.Button(str, EditorStyles.popup)) {
+				BoneSelectorContextMenu(str, ((SkeletonUtilityBone)target).skeletonUtility.skeletonRenderer.skeleton.Bones, "<None>", TargetBoneSelected);
+			}
+
+			GUILayout.EndHorizontal();
+		}
+		EditorGUI.EndDisabledGroup();
+
+		EditorGUILayout.PropertyField(zPosition);
+		EditorGUILayout.PropertyField(position);
+		EditorGUILayout.PropertyField(rotation);
+		EditorGUILayout.PropertyField(scale);
+		EditorGUILayout.PropertyField(flip);
+
+		EditorGUI.BeginDisabledGroup(containsFollows);
+		{
+			EditorGUILayout.PropertyField(overrideAlpha);
+			EditorGUILayout.PropertyField(parentReference);
+
+			EditorGUI.BeginDisabledGroup(multiObject || !flip.boolValue);
+			{
+				EditorGUI.BeginChangeCheck();
+				EditorGUILayout.PropertyField(flipX);
+				if (EditorGUI.EndChangeCheck()) {
+					FlipX(flipX.boolValue);
+				}
+			}
+			EditorGUI.EndDisabledGroup();
+
+		}
+		EditorGUI.EndDisabledGroup();
+
+		EditorGUILayout.Space();
+
+		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);
+			}
+			EditorGUI.EndDisabledGroup();
+
+			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 || !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();
+
+		serializedObject.ApplyModifiedProperties();
+	}
+
+	void FlipX (bool state) {
+		utilityBone.FlipX(state);
+		if (Application.isPlaying == false) {
+			skeletonUtility.skeletonAnimation.LateUpdate();
+		}
+	}
+
+	void BoneSelectorContextMenu (string current, List<Bone> bones, string topValue, GenericMenu.MenuFunction2 callback) {
+		GenericMenu menu = new GenericMenu();
+
+		if (topValue != "")
+			menu.AddItem(new GUIContent(topValue), current == topValue, callback, null);
+
+		for (int i = 0; i < bones.Count; i++) {
+			menu.AddItem(new GUIContent(bones[i].Data.Name), bones[i].Data.Name == current, callback, bones[i]);
+		}
+
+		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();
+
+			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);
+			}
+		} 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);
+		}
+	}
+
+	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.rigidbody != null)
+			return false;
+		if (utilityBone.bone != null && utilityBone.bone.Children.Count == 0)
+			return false;
+
+		Rigidbody[] rigidbodies = utilityBone.GetComponentsInChildren<Rigidbody>();
+
+		if (rigidbodies.Length > 0)
+			return false;
+
+		return true;
+	}
+
+	void CreateHingeChain () {
+		var utilBoneArr = utilityBone.GetComponentsInChildren<SkeletonUtilityBone>();
+
+		foreach (var utilBone in utilBoneArr) {
+			AttachRigidbody(utilBone);
+		}
+
+		utilityBone.rigidbody.isKinematic = true;
+
+		foreach (var utilBone in utilBoneArr) {
+			if (utilBone == utilityBone)
+				continue;
+
+			utilBone.mode = SkeletonUtilityBone.Mode.Override;
+
+			HingeJoint joint = utilBone.gameObject.AddComponent<HingeJoint>();
+			joint.axis = Vector3.forward;
+			joint.connectedBody = utilBone.transform.parent.rigidbody;
+			joint.useLimits = true;
+			JointLimits limits = new JointLimits();
+			limits.min = -20;
+			limits.max = 20;
+			joint.limits = limits;
+			utilBone.rigidbody.mass = utilBone.transform.parent.rigidbody.mass * 0.75f;
+		}
+	}
+	
+	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>();
+	}
+}

+ 8 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs.meta

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

+ 311 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/Editor/SkeletonUtilityInspector.cs

@@ -0,0 +1,311 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.1
+ * 
+ * Copyright (c) 2013, Esoteric Software
+ * All rights reserved.
+ * 
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to install, execute and perform the Spine Runtimes
+ * Software (the "Software") solely for internal use. Without the written
+ * permission of Esoteric Software (typically granted by licensing Spine), 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 SOFTARE 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Skeleton Utility created by Mitch Thompson
+ * Full irrevocable rights and permissions granted to Esoteric Software
+*****************************************************************************/
+using UnityEngine;
+using UnityEditor;
+
+#if UNITY_4_3
+//nothing
+#else
+using UnityEditor.AnimatedValues;
+#endif
+using System.Collections;
+using System.Collections.Generic;
+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;
+			}
+		}
+		
+		
+		
+		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 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
+	static bool showSlots;
+#else
+	static AnimBool showSlots;
+#endif
+
+	void OnEnable () {
+		skeletonUtility = (SkeletonUtility)target;
+		skeletonRenderer = skeletonUtility.GetComponent<SkeletonRenderer>();
+		skeleton = skeletonRenderer.skeleton;
+		transform = skeletonRenderer.transform;
+
+		if (skeleton == null) {
+			skeletonRenderer.Reset();
+			skeletonRenderer.LateUpdate();
+
+			skeleton = skeletonRenderer.skeleton;
+		}
+
+		UpdateAttachments();
+
+		if (PrefabUtility.GetPrefabType(this.target) == PrefabType.Prefab)
+			isPrefab = true;
+
+	}
+
+	void OnDestroy () {
+
+	}
+
+	void OnSceneGUI () {
+		if (skeleton == null) {
+			OnEnable();
+			return;
+		}
+
+		float flipRotation = skeleton.FlipX ? -1 : 1;
+
+		foreach (Bone b in skeleton.Bones) {
+			Vector3 vec = transform.TransformPoint(new Vector3(b.WorldX, b.WorldY, 0));
+
+			Quaternion rot = Quaternion.Euler(0, 0, b.WorldRotation * flipRotation);
+			Vector3 forward = transform.TransformDirection(rot * Vector3.right);
+			forward *= flipRotation;
+
+			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));
+		}
+	}
+
+	void UpdateAttachments () {
+		attachmentTable = new Dictionary<Slot, List<Attachment>>();
+		Skin skin = skeleton.Skin;
+
+		if (skin == null) {
+			skin = skeletonRenderer.skeletonDataAsset.GetSkeletonData(true).DefaultSkin;
+		}
+
+		for (int i = skeleton.Slots.Count-1; i >= 0; i--) {
+			List<Attachment> attachments = new List<Attachment>();
+			skin.FindAttachmentsForSlot(i, attachments);
+
+			attachmentTable.Add(skeleton.Slots[i], attachments);
+		}
+	}
+
+	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) {
+				return;
+			}
+
+			skeletonUtility.SpawnHierarchy(mode, pos, rot, sca);
+
+			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();
+
+		if (GUILayout.Button(new GUIContent("Spawn Submeshes", SpineEditorUtilities.Icons.subMeshRenderer), GUILayout.Width(150), GUILayout.Height(24)))
+			skeletonUtility.SpawnSubRenderers(true);
+		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();
+		}
+
+#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;
+
+				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));
+
+				if (EditorGUI.EndChangeCheck()) {
+					slot.SetColor(c);
+					skeletonRenderer.LateUpdate();
+				}
+
+				EditorGUILayout.EndHorizontal();
+
+
+
+				foreach (Attachment attachment in pair.Value) {
+
+					if (slot.Attachment == attachment) {
+						GUI.contentColor = Color.white;
+					} else {
+						GUI.contentColor = Color.grey;
+					}
+
+					EditorGUI.indentLevel = 2;
+					bool isAttached = attachment == slot.Attachment;
+
+					Texture2D icon = null;
+
+					if (attachment is MeshAttachment || attachment is SkinnedMeshAttachment)
+						icon = SpineEditorUtilities.Icons.mesh;
+					else
+						icon = SpineEditorUtilities.Icons.image;
+
+					bool swap = EditorGUILayout.ToggleLeft(new GUIContent(attachment.Name, icon), attachment == slot.Attachment);
+
+					if (!isAttached && swap) {
+						slot.Attachment = attachment;
+						skeletonRenderer.LateUpdate();
+					} else if (isAttached && !swap) {
+							slot.Attachment = null;
+							skeletonRenderer.LateUpdate();
+						}
+
+					GUI.contentColor = Color.white;
+				}
+			}
+			#if UNITY_4_3
+
+#else
+		}
+		EditorGUILayout.EndFadeGroup();
+		if (showSlots.isAnimating)
+			Repaint();
+#endif
+	}
+
+	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.ShowAsContext();
+	}
+
+	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 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);
+	}
+}

+ 8 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/Editor/SkeletonUtilityInspector.cs.meta

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

+ 346 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtility.cs

@@ -0,0 +1,346 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.1
+ * 
+ * Copyright (c) 2013, Esoteric Software
+ * All rights reserved.
+ * 
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to install, execute and perform the Spine Runtimes
+ * Software (the "Software") solely for internal use. Without the written
+ * permission of Esoteric Software (typically granted by licensing Spine), 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 SOFTARE 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Skeleton Utility created by Mitch Thompson
+ * Full irrevocable rights and permissions granted to Esoteric Software
+*****************************************************************************/
+
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+using Spine;
+
+[RequireComponent(typeof(SkeletonAnimation))]
+[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 parent.GetComponent<T>();
+#else
+		return origin.GetComponentInParent<T>();
+#endif
+	}
+
+
+	public delegate void SkeletonUtilityDelegate ();
+
+	public event SkeletonUtilityDelegate OnReset;
+
+	public Transform boneRoot;
+
+	void Update () {
+		if (boneRoot != null && skeletonRenderer.skeleton != null) {
+			Vector3 flipScale = Vector3.one;
+			if (skeletonRenderer.skeleton.FlipX)
+				flipScale.x = -1;
+
+			if (skeletonRenderer.skeleton.FlipY)
+				flipScale.y = -1;
+
+			boneRoot.localScale = flipScale;
+		}
+	}
+
+	[HideInInspector]
+	public SkeletonRenderer skeletonRenderer;
+	[HideInInspector]
+	public SkeletonAnimation 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>();
+		}
+
+		if (skeletonAnimation == null) {
+			skeletonAnimation = GetComponent<SkeletonAnimation>();
+		}
+
+		skeletonRenderer.OnReset -= HandleRendererReset;
+		skeletonRenderer.OnReset += HandleRendererReset;
+
+		if (skeletonAnimation != null) {
+			skeletonAnimation.UpdateLocal -= UpdateLocal;
+			skeletonAnimation.UpdateLocal += UpdateLocal;
+		}
+
+
+		CollectBones();
+	}
+
+	void Start () {
+		//recollect because order of operations failure when switching between game mode and edit mode...
+//		CollectBones();
+	}
+
+	void OnDisable () {
+		skeletonRenderer.OnReset -= HandleRendererReset;
+
+		if (skeletonAnimation != null) {
+			skeletonAnimation.UpdateLocal -= UpdateLocal;
+			skeletonAnimation.UpdateWorld -= UpdateWorld;
+			skeletonAnimation.UpdateComplete -= UpdateComplete;
+		}
+	}
+	
+	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 UnregisterBone (SkeletonUtilityBone bone) {
+		utilityBones.Remove(bone);
+	}
+
+	public void RegisterConstraint (SkeletonUtilityConstraint constraint) {
+
+		if (utilityConstraints.Contains(constraint))
+			return;
+		else {
+			utilityConstraints.Add(constraint);
+			needToReprocessBones = true;
+		}
+	}
+	
+	public void UnregisterConstraint (SkeletonUtilityConstraint constraint) {
+		utilityConstraints.Remove(constraint);
+	}
+
+	public void CollectBones () {
+		if (skeletonRenderer.skeleton == null)
+			return;
+
+		if (boneRoot != null) {
+			List<string> constraintTargetNames = new List<string>();
+
+			foreach (IkConstraint c in skeletonRenderer.skeleton.IkConstraints) {
+				constraintTargetNames.Add(c.Target.Data.Name);
+			}
+
+			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 (utilityConstraints.Count > 0)
+				hasUtilityConstraints = true;
+
+			if (skeletonAnimation != null) {
+				skeletonAnimation.UpdateWorld -= UpdateWorld;
+				skeletonAnimation.UpdateComplete -= UpdateComplete;
+
+				if (hasTransformBones || hasUtilityConstraints) {
+					skeletonAnimation.UpdateWorld += UpdateWorld;
+				}
+
+				if (hasUtilityConstraints) {
+					skeletonAnimation.UpdateComplete += UpdateComplete;
+				}
+			}
+
+			needToReprocessBones = false;
+		} else {
+			utilityBones.Clear();
+			utilityConstraints.Clear();
+		}
+
+	}
+
+	void UpdateLocal (SkeletonAnimation anim) {
+
+		if (needToReprocessBones)
+			CollectBones();
+
+		if (utilityBones == null)
+			return;
+
+		foreach (SkeletonUtilityBone b in utilityBones) {
+			b.transformLerpComplete = false;
+		}
+
+		UpdateAllBones();
+	}
+
+	void UpdateWorld (SkeletonAnimation anim) {
+		UpdateAllBones();
+
+		foreach (SkeletonUtilityConstraint c in utilityConstraints)
+			c.DoUpdate();
+	}
+
+	void UpdateComplete (SkeletonAnimation anim) {
+		UpdateAllBones();
+	}
+
+	void UpdateAllBones () {
+		if (boneRoot == null) {
+			CollectBones();
+		}
+
+		if (utilityBones == null)
+			return;
+
+		foreach (SkeletonUtilityBone b in utilityBones) {
+			b.DoUpdate();
+		}
+	}
+
+	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;
+
+		GameObject go = SpawnBone(skeleton.RootBone, boneRoot, mode, pos, rot, sca);
+
+		CollectBones();
+
+		return go;
+	}
+
+	public GameObject SpawnHierarchy (SkeletonUtilityBone.Mode mode, bool pos, bool rot, bool sca) {
+		GetBoneRoot();
+
+		Skeleton skeleton = this.skeletonRenderer.skeleton;
+
+		GameObject go = SpawnBoneRecursively(skeleton.RootBone, boneRoot, mode, pos, rot, sca);
+
+		CollectBones();
+
+		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);
+
+		foreach (Bone child in bone.Children) {
+			SpawnBoneRecursively(child, go.transform, mode, pos, rot, sca);
+		}
+
+		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.RotationIK);
+			
+			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;
+	}
+	
+	public void SpawnSubRenderers (bool disablePrimaryRenderer) {
+		int submeshCount = GetComponent<MeshFilter>().sharedMesh.subMeshCount;
+
+		for (int i = 0; i < submeshCount; i++) {
+			GameObject go = new GameObject("Submesh " + i, typeof(MeshFilter), typeof(MeshRenderer));
+			go.transform.parent = transform;
+			go.transform.localPosition = Vector3.zero;
+			go.transform.localRotation = Quaternion.identity;
+			go.transform.localScale = Vector3.one;
+
+			SkeletonUtilitySubmeshRenderer s = go.AddComponent<SkeletonUtilitySubmeshRenderer>();
+			s.sortingOrder = i * 10;
+			s.submeshIndex = i;
+			s.Initialize(renderer);
+			s.Update();
+		}
+
+		if (disablePrimaryRenderer)
+			renderer.enabled = false;
+	}
+}

+ 8 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtility.cs.meta

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

+ 293 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityBone.cs

@@ -0,0 +1,293 @@
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.1
+ * 
+ * Copyright (c) 2013, Esoteric Software
+ * All rights reserved.
+ * 
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to install, execute and perform the Spine Runtimes
+ * Software (the "Software") solely for internal use. Without the written
+ * permission of Esoteric Software (typically granted by licensing Spine), 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 SOFTARE 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Skeleton Utility created by Mitch Thompson
+ * Full irrevocable rights and permissions granted to Esoteric Software
+*****************************************************************************/
+
+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/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;
+	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;
+	[HideInInspector]
+	public bool transformLerpComplete;
+	protected Transform cachedTransform;
+	protected Transform skeletonTransform;
+
+	public bool NonUniformScaleWarning {
+		get {
+			return nonUniformScaleWarning;
+		}
+	}
+
+	private bool nonUniformScaleWarning;
+
+	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();
+	}
+
+	void OnEnable () {
+		skeletonUtility = SkeletonUtility.GetInParent<SkeletonUtility>(transform);
+
+		if (skeletonUtility == null)
+			return;
+
+		skeletonUtility.RegisterBone(this);
+
+		skeletonUtility.OnReset += HandleOnReset;
+	}
+
+	void HandleOnReset () {
+		Reset();
+	}
+
+	void OnDisable () {
+		if (skeletonUtility != null) {
+			skeletonUtility.OnReset -= HandleOnReset;
+
+			skeletonUtility.UnregisterBone(this);
+		}
+	}
+
+	public void DoUpdate () {
+
+		if (!valid) {
+			Reset();
+			return;
+		}
+
+		Spine.Skeleton skeleton = skeletonUtility.skeletonRenderer.skeleton;
+
+		if (bone == null) {
+			if (boneName == null || boneName.Length == 0)
+				return;
+			bone = skeleton.FindBone(boneName);
+			if (bone == null) {
+				Debug.LogError("Bone not found: " + boneName, this);
+				return;
+			}
+		}
+
+        
+
+		float skeletonFlipRotation = (skeleton.flipX ^ skeleton.flipY) ? -1f : 1f;
+        
+		float flipCompensation = 0;
+		if (flip && (flipX || (flipX != bone.flipX)) && bone.parent != null) {
+			flipCompensation = bone.parent.WorldRotation * -2;
+		}
+
+		if (mode == Mode.Follow) {
+			if (flip) {
+				flipX = bone.flipX;
+			}
+
+
+			if (position) {
+				cachedTransform.localPosition = new Vector3(bone.x, bone.y, 0);
+			}
+
+			if (rotation) {
+
+				if (bone.Data.InheritRotation) {
+					if (bone.FlipX) {
+						cachedTransform.localRotation = Quaternion.Euler(0, 180, bone.rotationIK - flipCompensation);
+					} else { 
+						cachedTransform.localRotation = Quaternion.Euler(0, 0, bone.rotationIK);
+					}
+				} else {
+					Vector3 euler = skeletonTransform.rotation.eulerAngles;
+					cachedTransform.rotation = Quaternion.Euler(euler.x, euler.y, skeletonTransform.rotation.eulerAngles.z + (bone.worldRotation * skeletonFlipRotation));
+				}
+
+			}
+
+			if (scale) {
+				cachedTransform.localScale = new Vector3(bone.scaleX, bone.scaleY, 1);
+
+				nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
+			}
+
+		} else if (mode == Mode.Override) {
+
+
+
+				if (transformLerpComplete)
+					return;            
+
+				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) + 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;
+					}
+
+					if (scale) {
+						bone.scaleX = Mathf.Lerp(bone.scaleX, cachedTransform.localScale.x, overrideAlpha);
+						bone.scaleY = Mathf.Lerp(bone.scaleY, cachedTransform.localScale.y, overrideAlpha);
+
+						nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
+					}
+
+					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);
+					}
+				
+					if (rotation) {
+						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;
+					}
+
+					//TODO: Something about this
+					if (scale) {
+						bone.scaleX = Mathf.Lerp(bone.scaleX, cachedTransform.localScale.x, overrideAlpha);
+						bone.scaleY = Mathf.Lerp(bone.scaleY, cachedTransform.localScale.y, overrideAlpha);
+					
+						nonUniformScaleWarning = (bone.scaleX != bone.scaleY);
+					}
+
+					if (flip) {
+						bone.flipX = flipX;
+					}
+
+				}
+
+				transformLerpComplete = true;
+			}		
+	}
+
+	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;
+		transform.localRotation = Quaternion.Euler(euler);
+	}
+
+	void OnDrawGizmos () {
+		if (NonUniformScaleWarning) {
+			Gizmos.DrawIcon(transform.position + new Vector3(0, 0.128f, 0), "icon-warning");
+		}
+	}
+}

+ 8 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityBone.cs.meta

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

+ 22 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityConstraint.cs

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

+ 8 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityConstraint.cs.meta

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

+ 56 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityEyeConstraint.cs

@@ -0,0 +1,56 @@
+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]);
+		}
+
+		centerPoint = centerBounds.center;
+	}
+	
+	protected override void OnDisable () {
+		if (!Application.isPlaying)
+			return;
+
+		base.OnDisable();
+	}
+	
+	public override void DoUpdate () {
+
+		if (target != null)
+			targetPosition = target.position;
+
+		Vector3 goal = targetPosition;
+
+		Vector3 center = transform.TransformPoint(centerPoint);
+		Vector3 dir = goal - center;
+
+		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);
+		}
+		
+	}	
+}

+ 8 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityEyeConstraint.cs.meta

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

+ 120 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityGroundConstraint.cs

@@ -0,0 +1,120 @@
+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();
+	}
+
+	protected override void OnDisable () {
+		base.OnDisable();
+	}
+
+	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);
+				}
+			} else {
+				if (Application.isPlaying)
+					hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustSpeed * Time.deltaTime);
+			}
+		} else {
+			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 (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);
+			}
+		}
+
+		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;
+
+		lastHitY = hitY;
+	}
+
+	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));
+		}
+
+		Gizmos.color = Color.red;
+		Gizmos.DrawLine(hitEnd, clearEnd);
+	}
+}

+ 8 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityGroundConstraint.cs.meta

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

+ 79 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityKinematicShadow.cs

@@ -0,0 +1,79 @@
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+
+public class SkeletonUtilityKinematicShadow : MonoBehaviour {
+	public bool hideShadow = true;
+	Dictionary<Transform, Transform> shadowTable;
+	GameObject shadowRoot;
+
+	void Start () {
+		shadowRoot = (GameObject)Instantiate(gameObject);
+		if (hideShadow)
+			shadowRoot.hideFlags = HideFlags.HideInHierarchy;
+
+		shadowRoot.transform.parent = transform.root;
+
+		shadowTable = new Dictionary<Transform, Transform>();
+
+		Destroy(shadowRoot.GetComponent<SkeletonUtilityKinematicShadow>());
+
+		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;
+
+		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 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;
+
+			foreach (var sb in shadowBones) {
+				if (sb.rigidbody == null)
+					continue;
+
+				if (sb.boneName == b.boneName) {
+					shadowTable.Add(sb.transform, b.transform);
+					break;
+				}
+			}
+		}
+
+		foreach (var b in shadowBones)
+			Destroy(b);
+	}
+
+	void FixedUpdate () {
+		shadowRoot.rigidbody.MovePosition(transform.position);
+		shadowRoot.rigidbody.MoveRotation(transform.rotation);
+
+		foreach (var pair in shadowTable) {
+			pair.Value.localPosition = pair.Key.localPosition;
+			pair.Value.localRotation = pair.Key.localRotation;
+		}
+	}
+}

+ 8 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilityKinematicShadow.cs.meta

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

+ 96 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs

@@ -0,0 +1,96 @@
+using UnityEngine;
+using System.Collections;
+
+[ExecuteInEditMode]
+public class SkeletonUtilitySubmeshRenderer : MonoBehaviour {
+	public Renderer parentRenderer;
+	[System.NonSerialized]
+	public Mesh mesh;
+	public int submeshIndex = 0;
+	public int sortingOrder = 0;
+	public int sortingLayerID = 0;
+	public Material hiddenPassMaterial;
+	Renderer cachedRenderer;
+	MeshFilter filter;
+	Material[] sharedMaterials;
+	MeshFilter parentFilter;
+
+	void Awake () {
+		cachedRenderer = renderer;
+		sharedMaterials = cachedRenderer.sharedMaterials;
+		filter = GetComponent<MeshFilter>();
+
+		if (parentRenderer != null)
+			Initialize(parentRenderer);
+	}
+
+	void OnEnable () {
+		parentRenderer = transform.parent.GetComponent<Renderer>();
+		parentRenderer.GetComponent<SkeletonRenderer>().OnReset += HandleSkeletonReset;
+	}
+
+	void OnDisable () {
+		parentRenderer.GetComponent<SkeletonRenderer>().OnReset -= HandleSkeletonReset;
+	}
+
+	void HandleSkeletonReset (SkeletonRenderer r) {
+		if (parentRenderer != null)
+			Initialize(parentRenderer);
+	}
+
+	public void Initialize (Renderer parentRenderer) {
+		this.parentRenderer = parentRenderer;
+		parentFilter = parentRenderer.GetComponent<MeshFilter>();
+		mesh = parentFilter.sharedMesh;
+		filter.sharedMesh = mesh;
+		Debug.Log("Mesh: " + mesh);
+	}
+
+	public void Update () {
+		if (mesh == null || mesh != parentFilter.sharedMesh) {
+			mesh = parentFilter.sharedMesh;
+			filter.sharedMesh = mesh;
+		}
+
+		if (cachedRenderer == null)
+			cachedRenderer = renderer;
+
+		if (mesh == null || submeshIndex > mesh.subMeshCount - 1) {
+			cachedRenderer.enabled = false;
+			return;
+		} else {
+			renderer.enabled = true;
+		}
+
+		bool changed = false;
+
+		if (sharedMaterials.Length != parentRenderer.sharedMaterials.Length) {
+			sharedMaterials = parentRenderer.sharedMaterials;
+			changed = true;
+		}
+
+
+
+		for (int i = 0; i < renderer.sharedMaterials.Length; i++) {
+			if (i == submeshIndex)
+				continue;
+
+			if (sharedMaterials[i] != hiddenPassMaterial) {
+				sharedMaterials[i] = hiddenPassMaterial;
+				changed = true;
+			}
+		}
+
+		if (sharedMaterials[submeshIndex] != parentRenderer.sharedMaterials[submeshIndex]) {
+			sharedMaterials[submeshIndex] = parentRenderer.sharedMaterials[submeshIndex];
+			changed = true;
+		}
+
+		if (changed) {
+			cachedRenderer.sharedMaterials = sharedMaterials;
+		}
+
+		cachedRenderer.sortingLayerID = sortingLayerID;
+		cachedRenderer.sortingOrder = sortingOrder;
+	}
+}

+ 12 - 0
spine-tk2d/Assets/spine-tk2d/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs.meta

@@ -0,0 +1,12 @@
+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: