diff --git a/spine-unity/Assets/spine-unity/BoneComponent.cs b/spine-unity/Assets/spine-unity/BoneFollower.cs
similarity index 85%
rename from spine-unity/Assets/spine-unity/BoneComponent.cs
rename to spine-unity/Assets/spine-unity/BoneFollower.cs
index acfe183cb..5c8fa3f92 100644
--- a/spine-unity/Assets/spine-unity/BoneComponent.cs
+++ b/spine-unity/Assets/spine-unity/BoneFollower.cs
@@ -36,8 +36,9 @@ using Spine;
/// Sets a GameObject's transform to match a bone on a Spine skeleton.
[ExecuteInEditMode]
-[AddComponentMenu("Spine/BoneComponent")]
-public class BoneComponent : MonoBehaviour {
+[AddComponentMenu("Spine/BoneFollower")]
+public class BoneFollower : MonoBehaviour {
+
[System.NonSerialized]
public bool valid;
@@ -55,31 +56,50 @@ public class BoneComponent : MonoBehaviour {
}
}
- // 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;
/// If a bone isn't set, boneName is used to find the bone.
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;
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;
@@ -92,6 +112,9 @@ public class BoneComponent : MonoBehaviour {
Debug.LogError("Bone not found: " + boneName, this);
return;
}
+ else{
+
+ }
}
Spine.Skeleton skeleton = skeletonRenderer.skeleton;
@@ -113,9 +136,10 @@ public class BoneComponent : MonoBehaviour {
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) );
}
}
+
}
}
\ No newline at end of file
diff --git a/spine-unity/Assets/spine-unity/BoneComponent.cs.meta b/spine-unity/Assets/spine-unity/BoneFollower.cs.meta
similarity index 78%
rename from spine-unity/Assets/spine-unity/BoneComponent.cs.meta
rename to spine-unity/Assets/spine-unity/BoneFollower.cs.meta
index a6a16dd66..29dabc13e 100644
--- a/spine-unity/Assets/spine-unity/BoneComponent.cs.meta
+++ b/spine-unity/Assets/spine-unity/BoneFollower.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 487b42efe96d8cc408a757541ea3f169
+guid: a1fd8daaed7b64148a34acb96ba14ce1
MonoImporter:
serializedVersion: 2
defaultReferences: []
diff --git a/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs b/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs
new file mode 100644
index 000000000..bbf164b4e
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs
@@ -0,0 +1,106 @@
+/******************************************************************************
+ * 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.
+ *****************************************************************************/
+
+using System;
+using UnityEditor;
+using UnityEngine;
+
+[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 = component.GetComponentInParent();
+ 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();
+
+ FindRenderer();
+
+ EditorGUILayout.PropertyField(skeletonRenderer);
+
+ if (component.valid) {
+ String[] bones = new String[1];
+ try{
+ bones = new String[component.skeletonRenderer.skeleton.Data.Bones.Count + 1];
+ }
+ catch{
+
+ }
+
+ bones[0] = "";
+ for (int i = 0; i < bones.Length - 1; i++)
+ bones[i + 1] = component.skeletonRenderer.skeleton.Data.Bones[i].Name;
+ Array.Sort(bones);
+ int boneIndex = Math.Max(0, Array.IndexOf(bones, boneName.stringValue));
+
+ EditorGUILayout.BeginHorizontal();
+ EditorGUILayout.LabelField("Bone");
+ EditorGUIUtility.LookLikeControls();
+ boneIndex = EditorGUILayout.Popup(boneIndex, bones);
+ 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")
+ ) {
+ component.Reset();
+ }
+ }
+}
diff --git a/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs.meta b/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs.meta
new file mode 100644
index 000000000..a5cf9ae89
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c71ca35fd6241cb49a0b0756a664fcf7
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-animation.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-animation.png.meta
index f8ac9f868..6d9bc41dd 100644
--- a/spine-unity/Assets/spine-unity/Editor/GUI/icon-animation.png.meta
+++ b/spine-unity/Assets/spine-unity/Editor/GUI/icon-animation.png.meta
@@ -1,6 +1,7 @@
fileFormatVersion: 2
guid: 52b12ec801461494185a4d3dc66f3d1d
TextureImporter:
+ fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-animationRoot.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-animationRoot.png.meta
index 1b4c1e24f..4bcf433e8 100644
--- a/spine-unity/Assets/spine-unity/Editor/GUI/icon-animationRoot.png.meta
+++ b/spine-unity/Assets/spine-unity/Editor/GUI/icon-animationRoot.png.meta
@@ -1,6 +1,7 @@
fileFormatVersion: 2
guid: 3d1be4ea889f3a14b864352fe49a1bde
TextureImporter:
+ fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-bone.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-bone.png
new file mode 100644
index 000000000..ec66a6a85
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-bone.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-bone.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-bone.png.meta
new file mode 100644
index 000000000..9c59ed87d
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-boneNib.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-boneNib.png
new file mode 100644
index 000000000..87373b8f0
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-boneNib.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-boneNib.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-boneNib.png.meta
new file mode 100644
index 000000000..955598a84
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-boundingBox.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-boundingBox.png
new file mode 100644
index 000000000..82beedfce
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-boundingBox.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-boundingBox.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-boundingBox.png.meta
new file mode 100644
index 000000000..c90f54d3c
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintNib.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintNib.png
new file mode 100644
index 000000000..175bcb047
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintNib.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintNib.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-constraintNib.png.meta
new file mode 100644
index 000000000..e7ab7aca3
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-event.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-event.png.meta
index 71c672b9c..2ab786189 100644
--- a/spine-unity/Assets/spine-unity/Editor/GUI/icon-event.png.meta
+++ b/spine-unity/Assets/spine-unity/Editor/GUI/icon-event.png.meta
@@ -1,6 +1,7 @@
fileFormatVersion: 2
guid: d226a80acc775714aa78b85e16a00e9b
TextureImporter:
+ fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-hingeChain.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-hingeChain.png
new file mode 100644
index 000000000..a27af1c7c
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-hingeChain.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-hingeChain.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-hingeChain.png.meta
new file mode 100644
index 000000000..6f346e072
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-image.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-image.png
new file mode 100644
index 000000000..663d11350
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-image.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-image.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-image.png.meta
new file mode 100644
index 000000000..24d78a242
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-mesh.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-mesh.png
new file mode 100644
index 000000000..1035553b7
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-mesh.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-mesh.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-mesh.png.meta
new file mode 100644
index 000000000..a98b0e9c8
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-null.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-null.png
new file mode 100644
index 000000000..9a6d738eb
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-null.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-null.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-null.png.meta
new file mode 100644
index 000000000..a949f63a6
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-poseBones.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-poseBones.png
new file mode 100644
index 000000000..102700af0
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-poseBones.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-poseBones.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-poseBones.png.meta
new file mode 100644
index 000000000..c3748ea88
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-skeleton.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-skeleton.png.meta
index 2b8ef8c4f..f607575fb 100644
--- a/spine-unity/Assets/spine-unity/Editor/GUI/icon-skeleton.png.meta
+++ b/spine-unity/Assets/spine-unity/Editor/GUI/icon-skeleton.png.meta
@@ -1,6 +1,7 @@
fileFormatVersion: 2
guid: f2216037084d99d4481810cb521ed96f
TextureImporter:
+ fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-skeletonUtility.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-skeletonUtility.png
new file mode 100644
index 000000000..ce4d937b2
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-skeletonUtility.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-skeletonUtility.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-skeletonUtility.png.meta
new file mode 100644
index 000000000..9d3c22794
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-skin.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-skin.png
new file mode 100644
index 000000000..3d9bddeb4
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-skin.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-skin.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-skin.png.meta
new file mode 100644
index 000000000..3be7a6e69
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-skinPlaceholder.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-skinPlaceholder.png
new file mode 100644
index 000000000..3b11d379e
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-skinPlaceholder.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-skinPlaceholder.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-skinPlaceholder.png.meta
new file mode 100644
index 000000000..e6ebc95cc
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-skinsRoot.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-skinsRoot.png.meta
index ab536e515..e332380e8 100644
--- a/spine-unity/Assets/spine-unity/Editor/GUI/icon-skinsRoot.png.meta
+++ b/spine-unity/Assets/spine-unity/Editor/GUI/icon-skinsRoot.png.meta
@@ -1,6 +1,7 @@
fileFormatVersion: 2
guid: 8bd14c7643597a74ba2edc10a5e4c4ed
TextureImporter:
+ fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-slot.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-slot.png
new file mode 100644
index 000000000..ca938722d
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-slot.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-slot.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-slot.png.meta
new file mode 100644
index 000000000..89224b580
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-spine.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-spine.png.meta
index e620c9210..c0ec65ca2 100644
--- a/spine-unity/Assets/spine-unity/Editor/GUI/icon-spine.png.meta
+++ b/spine-unity/Assets/spine-unity/Editor/GUI/icon-spine.png.meta
@@ -1,6 +1,7 @@
fileFormatVersion: 2
guid: 4e7c964fa5e07024c8bf1debecc3b7c8
TextureImporter:
+ fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-subMeshRenderer.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-subMeshRenderer.png
new file mode 100644
index 000000000..ec7c9e64b
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-subMeshRenderer.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-subMeshRenderer.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-subMeshRenderer.png.meta
new file mode 100644
index 000000000..35500c50d
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-warning.png b/spine-unity/Assets/spine-unity/Editor/GUI/icon-warning.png
new file mode 100644
index 000000000..05e3f4cdc
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Editor/GUI/icon-warning.png differ
diff --git a/spine-unity/Assets/spine-unity/Editor/GUI/icon-warning.png.meta b/spine-unity/Assets/spine-unity/Editor/GUI/icon-warning.png.meta
new file mode 100644
index 000000000..e32950ca4
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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:
diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs
index bc6d6b19c..f8d29894e 100644
--- a/spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs
+++ b/spine-unity/Assets/spine-unity/Editor/SkeletonAnimationInspector.cs
@@ -31,16 +31,23 @@
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 () {
@@ -49,6 +56,25 @@ public class SkeletonAnimationInspector : SkeletonRendererInspector {
SkeletonAnimation component = (SkeletonAnimation)target;
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;
+ }
+
+ if(loop.boolValue != currentState.Loop){
+ loop.boolValue = currentState.Loop;
+ }
+
+ if(timeScale.floatValue != currentState.TimeScale){
+ timeScale.floatValue = currentState.TimeScale;
+ }
+ }
+ }
+
+
// Animation name.
{
String[] animations = new String[component.skeleton.Data.Animations.Count + 1];
@@ -69,10 +95,21 @@ public class SkeletonAnimationInspector : SkeletonRendererInspector {
String selectedAnimationName = animationIndex == 0 ? null : animations[animationIndex];
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() == null){
+ if(GUILayout.Button(new GUIContent("Add Skeleton Utility", SpineEditorUtilities.Icons.skeletonUtility), GUILayout.Height(30))){
+ component.gameObject.AddComponent();
+ }
+ }
+ }
}
}
diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs
index d77647e42..09618fa45 100644
--- a/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs
+++ b/spine-unity/Assets/spine-unity/Editor/SkeletonDataAssetInspector.cs
@@ -28,6 +28,11 @@
* 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;
@@ -53,18 +58,26 @@ public class SkeletonDataAssetInspector : Editor {
private string m_skeletonDataAssetGUID;
void OnEnable () {
- atlasAsset = serializedObject.FindProperty("atlasAsset");
- 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;
+ try{
+
+ atlasAsset = serializedObject.FindProperty("atlasAsset");
+ 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(){
diff --git a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs
index eec7fc04d..ef614a1e0 100644
--- a/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs
+++ b/spine-unity/Assets/spine-unity/Editor/SpineEditorUtilities.cs
@@ -1,4 +1,38 @@
#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;
@@ -15,6 +49,7 @@ public class SpineEditorUtilities : AssetPostprocessor {
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;
@@ -27,6 +62,11 @@ public class SpineEditorUtilities : AssetPostprocessor {
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{
@@ -61,6 +101,7 @@ public class SpineEditorUtilities : AssetPostprocessor {
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");
@@ -73,6 +114,12 @@ public class SpineEditorUtilities : AssetPostprocessor {
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");
+
}
}
@@ -81,8 +128,9 @@ public class SpineEditorUtilities : AssetPostprocessor {
public static string editorPath = "";
public static string editorGUIPath = "";
-
- static List skeletonRendererInstanceIDs;
+
+ static Dictionary skeletonRendererTable;
+ static Dictionary skeletonUtilityBoneTable;
public static float defaultScale = 0.01f;
public static float defaultMix = 0.2f;
@@ -96,7 +144,8 @@ public class SpineEditorUtilities : AssetPostprocessor {
Icons.Initialize();
- skeletonRendererInstanceIDs = new List();
+ skeletonRendererTable = new Dictionary();
+ skeletonUtilityBoneTable = new Dictionary();
EditorApplication.hierarchyWindowChanged += HierarchyWindowChanged;
EditorApplication.hierarchyWindowItemOnGUI += HierarchyWindowItemOnGUI;
@@ -105,22 +154,49 @@ public class SpineEditorUtilities : AssetPostprocessor {
}
static void HierarchyWindowChanged(){
- skeletonRendererInstanceIDs.Clear();
+ skeletonRendererTable.Clear();
+ skeletonUtilityBoneTable.Clear();
SkeletonRenderer[] arr = Object.FindObjectsOfType();
foreach(SkeletonRenderer r in arr)
- skeletonRendererInstanceIDs.Add(r.gameObject.GetInstanceID());
+ skeletonRendererTable.Add( r.gameObject.GetInstanceID(), r.gameObject );
+
+ SkeletonUtilityBone[] boneArr = Object.FindObjectsOfType();
+ foreach(SkeletonUtilityBone b in boneArr)
+ skeletonUtilityBoneTable.Add(b.gameObject.GetInstanceID(), b);
}
static void HierarchyWindowItemOnGUI(int instanceId, Rect selectionRect){
- if(skeletonRendererInstanceIDs.Contains(instanceId)){
+ 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 = r.width - 15;
+ r.x -= 26;
+
+ if(skeletonUtilityBoneTable[instanceId] != null){
+ if( skeletonUtilityBoneTable[instanceId].transform.childCount == 0 )
+ r.x += 15;
+
+
+ r.width = 15;
+
+ if( skeletonUtilityBoneTable[instanceId].mode == SkeletonUtilityBone.Mode.Follow ){
+ GUI.Label(r, Icons.bone);
+ }
+ else{
+ GUI.Label(r, Icons.poseBones);
+ }
+ }
+
+ }
+
}
[MenuItem("Assets/Spine/Ingest")]
@@ -335,20 +411,24 @@ public class SpineEditorUtilities : AssetPostprocessor {
string primaryName = Path.GetFileNameWithoutExtension(spineJson.name);
string assetPath = Path.GetDirectoryName( AssetDatabase.GetAssetPath(spineJson));
+ string filePath = assetPath + "/" + primaryName + "_SkeletonData.asset";
if(spineJson != null && atlasAsset != null){
- SkeletonDataAsset skelDataAsset = SkeletonDataAsset.CreateInstance();
- skelDataAsset.atlasAsset = atlasAsset;
- skelDataAsset.skeletonJSON = spineJson;
- skelDataAsset.fromAnimation = new string[0];
- skelDataAsset.toAnimation = new string[0];
- skelDataAsset.duration = new float[0];
- skelDataAsset.defaultMix = defaultMix;
- skelDataAsset.scale = defaultScale;
-
- AssetDatabase.CreateAsset(skelDataAsset, assetPath + "/" + primaryName + "_SkeletonData.asset");
- AssetDatabase.SaveAssets();
+ SkeletonDataAsset skelDataAsset = (SkeletonDataAsset)AssetDatabase.LoadAssetAtPath(filePath, typeof(SkeletonDataAsset));
+ if(skelDataAsset == null){
+ skelDataAsset = SkeletonDataAsset.CreateInstance();
+ skelDataAsset.atlasAsset = atlasAsset;
+ skelDataAsset.skeletonJSON = spineJson;
+ skelDataAsset.fromAnimation = new string[0];
+ skelDataAsset.toAnimation = new string[0];
+ skelDataAsset.duration = new float[0];
+ skelDataAsset.defaultMix = defaultMix;
+ skelDataAsset.scale = defaultScale;
+
+ AssetDatabase.CreateAsset(skelDataAsset, filePath);
+ AssetDatabase.SaveAssets();
+ }
return skelDataAsset;
}
diff --git a/spine-unity/Assets/spine-unity/Shaders/Bones.shader b/spine-unity/Assets/spine-unity/Shaders/Bones.shader
new file mode 100644
index 000000000..61fc977e5
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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
+ }
+ }
+}
+}
diff --git a/spine-unity/Assets/spine-unity/Shaders/Bones.shader.meta b/spine-unity/Assets/spine-unity/Shaders/Bones.shader.meta
new file mode 100644
index 000000000..d01814ef9
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/Shaders/Bones.shader.meta
@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: 66988de88a15abd4e8846c6805485f57
+ShaderImporter:
+ defaultTextures: []
+ userData:
diff --git a/spine-unity/Assets/spine-unity/Shaders/HiddenPass.mat b/spine-unity/Assets/spine-unity/Shaders/HiddenPass.mat
new file mode 100644
index 000000000..31cf39d99
Binary files /dev/null and b/spine-unity/Assets/spine-unity/Shaders/HiddenPass.mat differ
diff --git a/spine-unity/Assets/spine-unity/Shaders/HiddenPass.mat.meta b/spine-unity/Assets/spine-unity/Shaders/HiddenPass.mat.meta
new file mode 100644
index 000000000..ef267ef07
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/Shaders/HiddenPass.mat.meta
@@ -0,0 +1,4 @@
+fileFormatVersion: 2
+guid: 43227e5adadc6f24bb4bf74b92a56fb4
+NativeFormatImporter:
+ userData:
diff --git a/spine-unity/Assets/spine-unity/Shaders/HiddenPass.shader b/spine-unity/Assets/spine-unity/Shaders/HiddenPass.shader
new file mode 100644
index 000000000..3a0de6756
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/Shaders/HiddenPass.shader
@@ -0,0 +1,21 @@
+Shader "Spine/HiddenPass" {
+ SubShader
+
+ {
+
+ Tags {"Queue" = "Geometry-1" }
+
+ Lighting Off
+
+ Pass
+
+ {
+
+ ZWrite Off
+
+ ColorMask 0
+
+ }
+
+ }
+}
diff --git a/spine-unity/Assets/spine-unity/Shaders/HiddenPass.shader.meta b/spine-unity/Assets/spine-unity/Shaders/HiddenPass.shader.meta
new file mode 100644
index 000000000..bcc031d30
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/Shaders/HiddenPass.shader.meta
@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: 913475501bf19374c84390868a9d6d3d
+ShaderImporter:
+ defaultTextures: []
+ userData:
diff --git a/spine-unity/Assets/spine-unity/SkeletonAnimation.cs b/spine-unity/Assets/spine-unity/SkeletonAnimation.cs
index 8810a5383..b2b367167 100644
--- a/spine-unity/Assets/spine-unity/SkeletonAnimation.cs
+++ b/spine-unity/Assets/spine-unity/SkeletonAnimation.cs
@@ -42,7 +42,9 @@ public class SkeletonAnimation : SkeletonRenderer {
public Spine.AnimationState state;
public delegate void UpdateBonesDelegate(SkeletonAnimation skeleton);
- public UpdateBonesDelegate UpdateBones;
+ public UpdateBonesDelegate UpdateLocal;
+ public UpdateBonesDelegate UpdateWorld;
+ public UpdateBonesDelegate UpdateComplete;
[SerializeField]
private String _animationName;
@@ -83,7 +85,19 @@ public class SkeletonAnimation : SkeletonRenderer {
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);
+ }
}
}
diff --git a/spine-unity/Assets/spine-unity/SkeletonExtensions.cs b/spine-unity/Assets/spine-unity/SkeletonExtensions.cs
index ca8e263df..06b414658 100644
--- a/spine-unity/Assets/spine-unity/SkeletonExtensions.cs
+++ b/spine-unity/Assets/spine-unity/SkeletonExtensions.cs
@@ -1,4 +1,39 @@
-using UnityEngine;
+/******************************************************************************
+ * 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;
diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs
index 56d475131..a09838247 100644
--- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs
+++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs
@@ -37,6 +37,10 @@ using Spine;
/// Renders a skeleton.
[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]
@@ -96,6 +100,7 @@ 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 () {
@@ -112,7 +117,6 @@ public class SkeletonRenderer : MonoBehaviour {
public virtual void LateUpdate () {
if (!valid) return;
-
// Count vertices and submesh triangles.
int vertexCount = 0;
int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;
@@ -122,7 +126,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;
@@ -149,7 +154,7 @@ public class SkeletonRenderer : MonoBehaviour {
// Populate submesh when material changes.
Material material = (Material)((AtlasRegion)rendererObject).page.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;
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility.meta b/spine-unity/Assets/spine-unity/SkeletonUtility.meta
new file mode 100644
index 000000000..d690c94de
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility.meta
@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: f6e0caaafe294de48af468a6a9321473
+folderAsset: yes
+DefaultImporter:
+ userData:
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor.meta b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor.meta
new file mode 100644
index 000000000..386e1e90b
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor.meta
@@ -0,0 +1,5 @@
+fileFormatVersion: 2
+guid: a751a9d1e3e26d64d997b66a781df8e9
+folderAsset: yes
+DefaultImporter:
+ userData:
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs
new file mode 100644
index 000000000..1a6b80054
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs
@@ -0,0 +1,287 @@
+/******************************************************************************
+ * 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;
+
+ //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");
+
+ EvaluateFlags();
+
+ if(utilityBone.valid == false && skeletonUtility != null && skeletonUtility.skeletonRenderer != null){
+ skeletonUtility.skeletonRenderer.Reset();
+ }
+
+ canCreateHingeChain = CanCreateHingeChain();
+ }
+
+ ///
+ /// Evaluates the flags.
+ ///
+ 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();
+ 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 = "";
+ if(multiObject) str = "";
+
+ GUILayout.BeginHorizontal();
+ EditorGUILayout.PrefixLabel("Bone");
+
+ if(GUILayout.Button( str, EditorStyles.popup )){
+ BoneSelectorContextMenu( str, ((SkeletonUtilityBone)target).skeletonUtility.skeletonRenderer.skeleton.Bones, "", TargetBoneSelected );
+ }
+
+ GUILayout.EndHorizontal();
+ }
+ EditorGUI.EndDisabledGroup();
+
+ EditorGUILayout.PropertyField(zPosition);
+ EditorGUILayout.PropertyField(position);
+ EditorGUILayout.PropertyField(rotation);
+ EditorGUILayout.PropertyField(scale);
+
+ EditorGUI.BeginDisabledGroup( containsFollows );
+ {
+ EditorGUILayout.PropertyField(overrideAlpha);
+ EditorGUILayout.PropertyField(parentReference);
+ }
+ 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, "", 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 BoneSelectorContextMenu(string current, List 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();
+ 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());
+ 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());
+ 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();
+
+ if(rigidbodies.Length > 0) return false;
+
+ return true;
+ }
+
+ void CreateHingeChain(){
+ var utilBoneArr = utilityBone.GetComponentsInChildren();
+
+ 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();
+ 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() == null){
+ if(utilBone.bone.Data.Length == 0){
+ SphereCollider sphere = utilBone.gameObject.AddComponent();
+ sphere.radius = 0.1f;
+ }
+ else{
+ float length = utilBone.bone.Data.Length;
+ BoxCollider box = utilBone.gameObject.AddComponent();
+ box.size = new Vector3( length, length / 3, 0.2f);
+ box.center = new Vector3(length / 2, 0, 0);
+ }
+ }
+
+ utilBone.gameObject.AddComponent();
+ }
+}
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs.meta b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs.meta
new file mode 100644
index 000000000..340d6e2eb
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: b3ae20b4bcc31f645afd6f5b64f82473
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs
new file mode 100644
index 000000000..7358c7635
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs
@@ -0,0 +1,316 @@
+/******************************************************************************
+ * 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();
+ 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> attachmentTable = new Dictionary>();
+
+
+ //GUI stuff
+#if UNITY_4_3
+ static bool showSlots;
+#else
+ static AnimBool showSlots;
+#endif
+
+ void OnEnable(){
+ skeletonUtility = (SkeletonUtility)target;
+ skeletonRenderer = skeletonUtility.GetComponent();
+ 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>();
+ Skin skin = skeleton.Skin;
+
+ if(skin == null){
+ skin = skeletonRenderer.skeletonDataAsset.GetSkeletonData(true).DefaultSkin;
+ }
+
+ for(int i = skeleton.Slots.Count-1; i >= 0; i--){
+ List attachments = new List();
+ 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();
+
+ if(skeletonUtility.boneRoot != null){
+ return;
+ }
+
+ skeletonUtility.SpawnHierarchy(mode, pos, rot, sca);
+
+ SkeletonUtilityBone[] boneComps = skeletonUtility.GetComponentsInChildren();
+ 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> 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 );
+ }
+}
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs.meta b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs.meta
new file mode 100644
index 000000000..7820cbd6d
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: a5b90df955eb8c2429ac67c8b2de6c5c
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs
new file mode 100644
index 000000000..1813512a7
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs
@@ -0,0 +1,335 @@
+/******************************************************************************
+ * 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 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 utilityBones = new List();
+
+ [System.NonSerialized]
+ public List utilityConstraints = new List();
+// Dictionary utilityBoneTable;
+
+
+ protected bool hasTransformBones;
+ protected bool hasUtilityConstraints;
+ protected bool needToReprocessBones;
+
+ void OnEnable(){
+ if(skeletonRenderer == null){
+ skeletonRenderer = GetComponent();
+ }
+
+ if(skeletonAnimation == null){
+ skeletonAnimation = GetComponent();
+ }
+
+ 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 constraintTargetNames = new List();
+
+ 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();
+ 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().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();
+ s.sortingOrder = i * 10;
+ s.submeshIndex = i;
+ s.Initialize( renderer );
+ s.Update();
+ }
+
+ if(disablePrimaryRenderer)
+ renderer.enabled = false;
+ }
+}
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs.meta b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs.meta
new file mode 100644
index 000000000..7d3d7a44f
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 7f726fb798ad621458c431cb9966d91d
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs
new file mode 100644
index 000000000..51dee1cc6
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs
@@ -0,0 +1,218 @@
+/******************************************************************************
+ * 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;
+
+/// Sets a GameObject's transform to match a bone on a Spine skeleton.
+[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;
+
+ [Range(0f,1f)]
+ public float overrideAlpha = 1;
+
+ /// If a bone isn't set, boneName is used to find the bone.
+ 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 = GetComponentInParent();
+ 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 flipRotation = (skeleton.flipX ^ skeleton.flipY) ? -1f : 1f;
+
+
+ if(mode == Mode.Follow){
+ if(position){
+ cachedTransform.localPosition = new Vector3(bone.x, bone.y, 0);
+ }
+
+ if(rotation){
+
+ if(bone.Data.InheritRotation){
+ 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 * flipRotation) );
+ }
+
+ }
+
+ 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){
+ bone.rotation = Mathf.LerpAngle(bone.Rotation, cachedTransform.localRotation.eulerAngles.z, overrideAlpha);
+ }
+
+ 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);
+ }
+ }
+ else{
+ 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){
+ bone.rotation = Mathf.LerpAngle(bone.Rotation, Quaternion.LookRotation( Vector3.forward, parentReference.InverseTransformDirection( cachedTransform.up ) ).eulerAngles.z, overrideAlpha);
+ }
+
+ //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);
+ }
+ }
+
+ transformLerpComplete = true;
+ }
+ }
+
+ void OnDrawGizmos(){
+ if(NonUniformScaleWarning){
+ Gizmos.DrawIcon(transform.position + new Vector3(0,0.128f,0), "icon-warning");
+ }
+ }
+}
\ No newline at end of file
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs.meta b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs.meta
new file mode 100644
index 000000000..f66d45053
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: b238dfcde8209044b97d23f62bcaadf6
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityConstraint.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityConstraint.cs
new file mode 100644
index 000000000..ffdcf1dd3
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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();
+ skeletonUtility = GetComponentInParent();
+ skeletonUtility.RegisterConstraint(this);
+ }
+
+ protected virtual void OnDisable(){
+ skeletonUtility.UnregisterConstraint(this);
+ }
+
+ public abstract void DoUpdate();
+}
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityConstraint.cs.meta b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityConstraint.cs.meta
new file mode 100644
index 000000000..dad11e0a2
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityConstraint.cs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 522dbfcc6c916df4396f14f35048d185
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityEyeConstraint.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityEyeConstraint.cs
new file mode 100644
index 000000000..07203faef
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityEyeConstraint.cs
@@ -0,0 +1,61 @@
+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);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityEyeConstraint.cs.meta b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityEyeConstraint.cs.meta
new file mode 100644
index 000000000..3e82746da
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityEyeConstraint.cs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 0d994c65b6daec64f80ae2ae04e9d999
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityGroundConstraint.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityGroundConstraint.cs
new file mode 100644
index 000000000..70301d92d
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityGroundConstraint.cs
@@ -0,0 +1,58 @@
+using UnityEngine;
+using System.Collections;
+
+[RequireComponent(typeof(SkeletonUtilityBone)), ExecuteInEditMode]
+public class SkeletonUtilityGroundConstraint : SkeletonUtilityConstraint {
+
+ public LayerMask groundMask;
+ public bool use2D = true;
+ public float castDistance = 5f;
+ Vector3 rayOrigin;
+ Vector3 rayDir = new Vector3(0,-1,0);
+ float hitY;
+
+ protected override void OnEnable ()
+ {
+ base.OnEnable ();
+ }
+
+ protected override void OnDisable ()
+ {
+ base.OnDisable ();
+ }
+
+ public override void DoUpdate()
+ {
+ rayOrigin = transform.position + new Vector3(0,castDistance,0);
+
+ hitY = float.MinValue;
+ if(use2D){
+ RaycastHit2D hit = Physics2D.Raycast(rayOrigin , rayDir, castDistance, groundMask);
+ if(hit.collider != null){
+ hitY = hit.point.y;
+ }
+ }
+ else{
+ RaycastHit hit;
+ if(Physics.Raycast( rayOrigin, rayDir, out hit, castDistance, groundMask)){
+ hitY = hit.point.y;
+ }
+ }
+
+ Vector3 v = transform.position;
+ v.y = Mathf.Clamp(v.y, hitY, float.MaxValue);
+ transform.position = v;
+
+ utilBone.bone.X = transform.localPosition.x;
+ utilBone.bone.Y = transform.localPosition.y;
+
+ }
+
+ void OnDrawGizmos(){
+ Vector3 hitEnd = rayOrigin + (rayDir * Mathf.Min(castDistance, rayOrigin.y - hitY));
+ Vector3 clearEnd = rayOrigin + (rayDir * castDistance);
+ Gizmos.DrawLine(rayOrigin, hitEnd);
+ Gizmos.color = Color.red;
+ Gizmos.DrawLine(hitEnd, clearEnd);
+ }
+}
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityGroundConstraint.cs.meta b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityGroundConstraint.cs.meta
new file mode 100644
index 000000000..5d9e6920c
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityGroundConstraint.cs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 3662334b99de5fe4396ab24e30c4fd12
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityKinematicShadow.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityKinematicShadow.cs
new file mode 100644
index 000000000..917eb5a45
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityKinematicShadow.cs
@@ -0,0 +1,81 @@
+using UnityEngine;
+using System.Collections;
+using System.Collections.Generic;
+
+public class SkeletonUtilityKinematicShadow : MonoBehaviour {
+
+ public bool hideShadow = true;
+
+ Dictionary shadowTable;
+ GameObject shadowRoot;
+
+ void Start(){
+ shadowRoot = (GameObject)Instantiate(gameObject);
+ if(hideShadow)
+ shadowRoot.hideFlags = HideFlags.HideInHierarchy;
+
+ shadowRoot.transform.parent = transform.root;
+
+ shadowTable = new Dictionary();
+
+ Destroy(shadowRoot.GetComponent());
+
+ 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();
+ foreach(Joint j in shadowJoints){
+ j.connectedAnchor *= scale;
+ }
+
+ var joints = GetComponentsInChildren();
+ foreach(var j in joints)
+ Destroy(j);
+
+ var rbs = GetComponentsInChildren();
+ foreach(var rb in rbs)
+ Destroy(rb);
+
+ var colliders = GetComponentsInChildren();
+ foreach(var c in colliders)
+ Destroy(c);
+
+
+ //match by bone name
+ var shadowBones = shadowRoot.GetComponentsInChildren();
+ var bones = GetComponentsInChildren();
+
+ //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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityKinematicShadow.cs.meta b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityKinematicShadow.cs.meta
new file mode 100644
index 000000000..06bcb6f4a
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityKinematicShadow.cs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: cfeac06b8a6aa1645813700e3e4c0863
+MonoImporter:
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs
new file mode 100644
index 000000000..f6a2e682b
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs
@@ -0,0 +1,102 @@
+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();
+
+ if(parentRenderer != null)
+ Initialize( parentRenderer );
+ }
+
+ void OnEnable(){
+ parentRenderer = transform.parent.GetComponent();
+ parentRenderer.GetComponent().OnReset += HandleSkeletonReset;
+ }
+
+ void OnDisable(){
+ parentRenderer.GetComponent().OnReset -= HandleSkeletonReset;
+ }
+
+ void HandleSkeletonReset(SkeletonRenderer r){
+ if(parentRenderer != null)
+ Initialize(parentRenderer);
+ }
+
+ public void Initialize(Renderer parentRenderer){
+ this.parentRenderer = parentRenderer;
+ parentFilter = parentRenderer.GetComponent();
+ 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;
+ }
+}
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs.meta b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs.meta
new file mode 100644
index 000000000..168ca8811
--- /dev/null
+++ b/spine-unity/Assets/spine-unity/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: