diff --git a/spine-unity/Assets/spine-unity/Asset Types/AtlasAsset.cs b/spine-unity/Assets/spine-unity/Asset Types/AtlasAsset.cs
index 19dadb509..44b178fb9 100644
--- a/spine-unity/Assets/spine-unity/Asset Types/AtlasAsset.cs
+++ b/spine-unity/Assets/spine-unity/Asset Types/AtlasAsset.cs
@@ -34,148 +34,150 @@ using System.IO;
using UnityEngine;
using Spine;
-/// Loads and stores a Spine atlas and list of materials.
-public class AtlasAsset : ScriptableObject {
- public TextAsset atlasFile;
- public Material[] materials;
- private Atlas atlas;
+namespace Spine.Unity {
+ /// Loads and stores a Spine atlas and list of materials.
+ public class AtlasAsset : ScriptableObject {
+ public TextAsset atlasFile;
+ public Material[] materials;
+ private Atlas atlas;
- public void Reset () {
- atlas = null;
- }
-
- /// The atlas or null if it could not be loaded.
- public Atlas GetAtlas () {
- if (atlasFile == null) {
- Debug.LogError("Atlas file not set for atlas asset: " + name, this);
- Reset();
- return null;
+ public void Reset () {
+ atlas = null;
}
- if (materials == null || materials.Length == 0) {
- Debug.LogError("Materials not set for atlas asset: " + name, this);
- Reset();
- return null;
- }
-
- if (atlas != null)
- return atlas;
-
- try {
- atlas = new Atlas(new StringReader(atlasFile.text), "", new MaterialsTextureLoader(this));
- atlas.FlipV();
- return atlas;
- } catch (Exception ex) {
- Debug.LogError("Error reading atlas file for atlas asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, this);
- return null;
- }
- }
-
- public Sprite GenerateSprite (string name, out Material material) {
- AtlasRegion region = atlas.FindRegion(name);
-
- Sprite sprite = null;
- material = null;
-
- if (region != null) {
- //sprite.rect
- }
-
- return sprite;
- }
-
- public Mesh GenerateMesh (string name, Mesh mesh, out Material material, float scale = 0.01f) {
- AtlasRegion region = atlas.FindRegion(name);
- material = null;
- if (region != null) {
- if (mesh == null) {
- mesh = new Mesh();
- mesh.name = name;
+ /// The atlas or null if it could not be loaded.
+ public Atlas GetAtlas () {
+ if (atlasFile == null) {
+ Debug.LogError("Atlas file not set for atlas asset: " + name, this);
+ Reset();
+ return null;
}
- Vector3[] verts = new Vector3[4];
- Vector2[] uvs = new Vector2[4];
- Color[] colors = new Color[4] { Color.white, Color.white, Color.white, Color.white };
- int[] triangles = new int[6] { 0, 1, 2, 2, 3, 0 };
+ if (materials == null || materials.Length == 0) {
+ Debug.LogError("Materials not set for atlas asset: " + name, this);
+ Reset();
+ return null;
+ }
- float left, right, top, bottom;
- left = region.width / -2f;
- right = left * -1f;
- top = region.height / 2f;
- bottom = top * -1;
+ if (atlas != null)
+ return atlas;
- verts[0] = new Vector3(left, bottom, 0) * scale;
- verts[1] = new Vector3(left, top, 0) * scale;
- verts[2] = new Vector3(right, top, 0) * scale;
- verts[3] = new Vector3(right, bottom, 0) * scale;
- float u, v, u2, v2;
- u = region.u;
- v = region.v;
- u2 = region.u2;
- v2 = region.v2;
+ try {
+ atlas = new Atlas(new StringReader(atlasFile.text), "", new MaterialsTextureLoader(this));
+ atlas.FlipV();
+ return atlas;
+ } catch (Exception ex) {
+ Debug.LogError("Error reading atlas file for atlas asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, this);
+ return null;
+ }
+ }
- if (!region.rotate) {
- uvs[0] = new Vector2(u, v2);
- uvs[1] = new Vector2(u, v);
- uvs[2] = new Vector2(u2, v);
- uvs[3] = new Vector2(u2, v2);
+ public Sprite GenerateSprite (string name, out Material material) {
+ AtlasRegion region = atlas.FindRegion(name);
+
+ Sprite sprite = null;
+ material = null;
+
+ if (region != null) {
+ //sprite.rect
+ }
+
+ return sprite;
+ }
+
+ public Mesh GenerateMesh (string name, Mesh mesh, out Material material, float scale = 0.01f) {
+ AtlasRegion region = atlas.FindRegion(name);
+ material = null;
+ if (region != null) {
+ if (mesh == null) {
+ mesh = new Mesh();
+ mesh.name = name;
+ }
+
+ Vector3[] verts = new Vector3[4];
+ Vector2[] uvs = new Vector2[4];
+ Color[] colors = new Color[4] { Color.white, Color.white, Color.white, Color.white };
+ int[] triangles = new int[6] { 0, 1, 2, 2, 3, 0 };
+
+ float left, right, top, bottom;
+ left = region.width / -2f;
+ right = left * -1f;
+ top = region.height / 2f;
+ bottom = top * -1;
+
+ verts[0] = new Vector3(left, bottom, 0) * scale;
+ verts[1] = new Vector3(left, top, 0) * scale;
+ verts[2] = new Vector3(right, top, 0) * scale;
+ verts[3] = new Vector3(right, bottom, 0) * scale;
+ float u, v, u2, v2;
+ u = region.u;
+ v = region.v;
+ u2 = region.u2;
+ v2 = region.v2;
+
+ if (!region.rotate) {
+ uvs[0] = new Vector2(u, v2);
+ uvs[1] = new Vector2(u, v);
+ uvs[2] = new Vector2(u2, v);
+ uvs[3] = new Vector2(u2, v2);
+ } else {
+ uvs[0] = new Vector2(u2, v2);
+ uvs[1] = new Vector2(u, v2);
+ uvs[2] = new Vector2(u, v);
+ uvs[3] = new Vector2(u2, v);
+ }
+
+ mesh.triangles = new int[0];
+ mesh.vertices = verts;
+ mesh.uv = uvs;
+ mesh.colors = colors;
+ mesh.triangles = triangles;
+ mesh.RecalculateNormals();
+ mesh.RecalculateBounds();
+
+ material = (Material)region.page.rendererObject;
} else {
- uvs[0] = new Vector2(u2, v2);
- uvs[1] = new Vector2(u, v2);
- uvs[2] = new Vector2(u, v);
- uvs[3] = new Vector2(u2, v);
+ mesh = null;
}
- mesh.triangles = new int[0];
- mesh.vertices = verts;
- mesh.uv = uvs;
- mesh.colors = colors;
- mesh.triangles = triangles;
- mesh.RecalculateNormals();
- mesh.RecalculateBounds();
+ return mesh;
+ }
+ }
- material = (Material)region.page.rendererObject;
- } else {
- mesh = null;
+ public class MaterialsTextureLoader : TextureLoader {
+ AtlasAsset atlasAsset;
+
+ public MaterialsTextureLoader (AtlasAsset atlasAsset) {
+ this.atlasAsset = atlasAsset;
}
- return mesh;
- }
-}
-
-public class MaterialsTextureLoader : TextureLoader {
- AtlasAsset atlasAsset;
-
- public MaterialsTextureLoader (AtlasAsset atlasAsset) {
- this.atlasAsset = atlasAsset;
- }
-
- public void Load (AtlasPage page, String path) {
- String name = Path.GetFileNameWithoutExtension(path);
- Material material = null;
- foreach (Material other in atlasAsset.materials) {
- if (other.mainTexture == null) {
- Debug.LogError("Material is missing texture: " + other.name, other);
+ public void Load (AtlasPage page, String path) {
+ String name = Path.GetFileNameWithoutExtension(path);
+ Material material = null;
+ foreach (Material other in atlasAsset.materials) {
+ if (other.mainTexture == null) {
+ Debug.LogError("Material is missing texture: " + other.name, other);
+ return;
+ }
+ if (other.mainTexture.name == name) {
+ material = other;
+ break;
+ }
+ }
+ if (material == null) {
+ Debug.LogError("Material with texture name \"" + name + "\" not found for atlas asset: " + atlasAsset.name, atlasAsset);
return;
}
- if (other.mainTexture.name == name) {
- material = other;
- break;
+ page.rendererObject = material;
+
+ // Very old atlas files expected the texture's actual size to be used at runtime.
+ if (page.width == 0 || page.height == 0) {
+ page.width = material.mainTexture.width;
+ page.height = material.mainTexture.height;
}
}
- if (material == null) {
- Debug.LogError("Material with texture name \"" + name + "\" not found for atlas asset: " + atlasAsset.name, atlasAsset);
- return;
- }
- page.rendererObject = material;
- // Very old atlas files expected the texture's actual size to be used at runtime.
- if (page.width == 0 || page.height == 0) {
- page.width = material.mainTexture.width;
- page.height = material.mainTexture.height;
+ public void Unload (object texture) {
}
}
-
- public void Unload (object texture) {
- }
}
diff --git a/spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs b/spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs
index 661f7336e..503b99e22 100644
--- a/spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs
+++ b/spine-unity/Assets/spine-unity/Asset Types/Editor/SkeletonDataAssetInspector.cs
@@ -182,10 +182,7 @@ namespace Spine.Unity.Editor {
EditorGUI.EndDisabledGroup();
EditorGUI.indentLevel++;
- GUILayout.BeginHorizontal();
- {
-
-
+ using (new EditorGUILayout.HorizontalScope()) {
if (GUILayout.Button(new GUIContent("Bake All Skins", SpineEditorUtilities.Icons.unityIcon), GUILayout.Height(32), GUILayout.Width(150)))
SkeletonBaker.BakeToPrefab(m_skeletonDataAsset, m_skeletonData.Skins, "", bakeAnimations, bakeIK, bakeEventOptions);
@@ -200,35 +197,20 @@ namespace Spine.Unity.Editor {
} else
skinName = m_skeletonAnimation.skeleton.Skin.Name;
- bool oops = false;
-
- try {
- GUILayout.BeginVertical();
+ using (var m = new EditorGUILayout.VerticalScope()) {
if (GUILayout.Button(new GUIContent("Bake " + skinName, SpineEditorUtilities.Icons.unityIcon), GUILayout.Height(32), GUILayout.Width(250)))
SkeletonBaker.BakeToPrefab(m_skeletonDataAsset, new ExposedList(new [] { bakeSkin }), "", bakeAnimations, bakeIK, bakeEventOptions);
-
- GUILayout.BeginHorizontal();
- GUILayout.Label(new GUIContent("Skins", SpineEditorUtilities.Icons.skinsRoot), GUILayout.Width(50));
- if (GUILayout.Button(skinName, EditorStyles.popup, GUILayout.Width(196))) {
- SelectSkinContext();
+ using (new EditorGUILayout.HorizontalScope()) {
+ GUILayout.Label(new GUIContent("Skins", SpineEditorUtilities.Icons.skinsRoot), GUILayout.Width(50));
+ if (GUILayout.Button(skinName, EditorStyles.popup, GUILayout.Width(196))) {
+ SelectSkinContext();
+ }
}
- GUILayout.EndHorizontal();
-
-
- } catch {
- oops = true;
- //GUILayout.BeginVertical();
}
-
-
-
- if (!oops)
- GUILayout.EndVertical();
}
}
- GUILayout.EndHorizontal();
EditorGUI.indentLevel--;
EditorGUI.indentLevel--;
}
diff --git a/spine-unity/Assets/spine-unity/Asset Types/SkeletonDataAsset.cs b/spine-unity/Assets/spine-unity/Asset Types/SkeletonDataAsset.cs
index 3912a3461..499ec80f2 100644
--- a/spine-unity/Assets/spine-unity/Asset Types/SkeletonDataAsset.cs
+++ b/spine-unity/Assets/spine-unity/Asset Types/SkeletonDataAsset.cs
@@ -31,145 +31,147 @@
using System;
using System.IO;
-using System.Collections.Generic;
using UnityEngine;
using Spine;
-public class SkeletonDataAsset : ScriptableObject {
- public AtlasAsset[] atlasAssets;
-#if SPINE_TK2D
- public tk2dSpriteCollectionData spriteCollection;
-#endif
- public TextAsset skeletonJSON;
- public float scale = 0.01f;
- public String[] fromAnimation;
- public String[] toAnimation;
- public float[] duration;
- public float defaultMix;
- public RuntimeAnimatorController controller;
- private SkeletonData skeletonData;
- private AnimationStateData stateData;
+namespace Spine.Unity {
+ public class SkeletonDataAsset : ScriptableObject {
+ public AtlasAsset[] atlasAssets;
+ #if SPINE_TK2D
+ public tk2dSpriteCollectionData spriteCollection;
+ #endif
+ public TextAsset skeletonJSON;
+ public float scale = 0.01f;
+ public String[] fromAnimation;
+ public String[] toAnimation;
+ public float[] duration;
+ public float defaultMix;
+ public RuntimeAnimatorController controller;
+ private SkeletonData skeletonData;
+ private AnimationStateData stateData;
- void OnEnable () {
- if (atlasAssets == null)
- atlasAssets = new AtlasAsset[0];
- }
-
- public void Reset () {
- skeletonData = null;
- stateData = null;
- }
-
- public SkeletonData GetSkeletonData (bool quiet) {
- if (atlasAssets == null) {
- atlasAssets = new AtlasAsset[0];
- if (!quiet)
- Debug.LogError("Atlas not set for SkeletonData asset: " + name, this);
- Reset();
- return null;
+ void OnEnable () {
+ if (atlasAssets == null)
+ atlasAssets = new AtlasAsset[0];
}
- if (skeletonJSON == null) {
- if (!quiet)
- Debug.LogError("Skeleton JSON file not set for SkeletonData asset: " + name, this);
- Reset();
- return null;
+ public void Reset () {
+ skeletonData = null;
+ stateData = null;
}
-#if !SPINE_TK2D
- if (atlasAssets.Length == 0) {
- Reset();
- return null;
- }
-#else
- if (atlasAssets.Length == 0 && spriteCollection == null) {
- Reset();
- return null;
- }
-#endif
-
- Atlas[] atlasArr = new Atlas[atlasAssets.Length];
- for (int i = 0; i < atlasAssets.Length; i++) {
- if (atlasAssets[i] == null) {
+ public SkeletonData GetSkeletonData (bool quiet) {
+ if (atlasAssets == null) {
+ atlasAssets = new AtlasAsset[0];
+ if (!quiet)
+ Debug.LogError("Atlas not set for SkeletonData asset: " + name, this);
Reset();
return null;
}
- atlasArr[i] = atlasAssets[i].GetAtlas();
- if (atlasArr[i] == null) {
+
+ if (skeletonJSON == null) {
+ if (!quiet)
+ Debug.LogError("Skeleton JSON file not set for SkeletonData asset: " + name, this);
Reset();
return null;
}
- }
- if (skeletonData != null)
- return skeletonData;
-
- AttachmentLoader attachmentLoader;
- float skeletonDataScale;
-
-#if !SPINE_TK2D
- attachmentLoader = new AtlasAttachmentLoader(atlasArr);
- skeletonDataScale = scale;
-#else
- if (spriteCollection != null) {
- attachmentLoader = new SpriteCollectionAttachmentLoader(spriteCollection);
- skeletonDataScale = (1.0f / (spriteCollection.invOrthoSize * spriteCollection.halfTargetHeight) * scale);
- } else {
- if (atlasArr.Length == 0) {
+ #if !SPINE_TK2D
+ if (atlasAssets.Length == 0) {
Reset();
- if (!quiet) Debug.LogError("Atlas not set for SkeletonData asset: " + name, this);
return null;
}
+ #else
+ if (atlasAssets.Length == 0 && spriteCollection == null) {
+ Reset();
+ return null;
+ }
+ #endif
+
+ Atlas[] atlasArr = new Atlas[atlasAssets.Length];
+ for (int i = 0; i < atlasAssets.Length; i++) {
+ if (atlasAssets[i] == null) {
+ Reset();
+ return null;
+ }
+ atlasArr[i] = atlasAssets[i].GetAtlas();
+ if (atlasArr[i] == null) {
+ Reset();
+ return null;
+ }
+ }
+
+ if (skeletonData != null)
+ return skeletonData;
+
+ AttachmentLoader attachmentLoader;
+ float skeletonDataScale;
+
+ #if !SPINE_TK2D
attachmentLoader = new AtlasAttachmentLoader(atlasArr);
skeletonDataScale = scale;
- }
-#endif
-
- try {
- //var stopwatch = new System.Diagnostics.Stopwatch();
- if (skeletonJSON.name.ToLower().Contains(".skel")) {
- var input = new MemoryStream(skeletonJSON.bytes);
- var binary = new SkeletonBinary(attachmentLoader);
- binary.Scale = skeletonDataScale;
- //stopwatch.Start();
- skeletonData = binary.ReadSkeletonData(input);
+ #else
+ if (spriteCollection != null) {
+ attachmentLoader = new Spine.Unity.TK2D.SpriteCollectionAttachmentLoader(spriteCollection);
+ skeletonDataScale = (1.0f / (spriteCollection.invOrthoSize * spriteCollection.halfTargetHeight) * scale);
} else {
- var input = new StringReader(skeletonJSON.text);
- var json = new SkeletonJson(attachmentLoader);
- json.Scale = skeletonDataScale;
- //stopwatch.Start();
- skeletonData = json.ReadSkeletonData(input);
+ if (atlasArr.Length == 0) {
+ Reset();
+ if (!quiet) Debug.LogError("Atlas not set for SkeletonData asset: " + name, this);
+ return null;
+ }
+ attachmentLoader = new AtlasAttachmentLoader(atlasArr);
+ skeletonDataScale = scale;
}
- //stopwatch.Stop();
- //Debug.Log(stopwatch.Elapsed);
- } catch (Exception ex) {
- if (!quiet)
- Debug.LogError("Error reading skeleton JSON file for SkeletonData asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, this);
- return null;
+ #endif
+
+ try {
+ //var stopwatch = new System.Diagnostics.Stopwatch();
+ if (skeletonJSON.name.ToLower().Contains(".skel")) {
+ var input = new MemoryStream(skeletonJSON.bytes);
+ var binary = new SkeletonBinary(attachmentLoader);
+ binary.Scale = skeletonDataScale;
+ //stopwatch.Start();
+ skeletonData = binary.ReadSkeletonData(input);
+ } else {
+ var input = new StringReader(skeletonJSON.text);
+ var json = new SkeletonJson(attachmentLoader);
+ json.Scale = skeletonDataScale;
+ //stopwatch.Start();
+ skeletonData = json.ReadSkeletonData(input);
+ }
+ //stopwatch.Stop();
+ //Debug.Log(stopwatch.Elapsed);
+ } catch (Exception ex) {
+ if (!quiet)
+ Debug.LogError("Error reading skeleton JSON file for SkeletonData asset: " + name + "\n" + ex.Message + "\n" + ex.StackTrace, this);
+ return null;
+ }
+
+ stateData = new AnimationStateData(skeletonData);
+ FillStateData();
+
+ return skeletonData;
}
- stateData = new AnimationStateData(skeletonData);
- FillStateData();
+ public void FillStateData () {
+ if (stateData == null)
+ return;
- return skeletonData;
- }
-
- public void FillStateData () {
- if (stateData == null)
- return;
-
- stateData.DefaultMix = defaultMix;
- for (int i = 0, n = fromAnimation.Length; i < n; i++) {
- if (fromAnimation[i].Length == 0 || toAnimation[i].Length == 0)
- continue;
- stateData.SetMix(fromAnimation[i], toAnimation[i], duration[i]);
+ stateData.DefaultMix = defaultMix;
+ for (int i = 0, n = fromAnimation.Length; i < n; i++) {
+ if (fromAnimation[i].Length == 0 || toAnimation[i].Length == 0)
+ continue;
+ stateData.SetMix(fromAnimation[i], toAnimation[i], duration[i]);
+ }
}
- }
- public AnimationStateData GetAnimationStateData () {
- if (stateData != null)
+ public AnimationStateData GetAnimationStateData () {
+ if (stateData != null)
+ return stateData;
+ GetSkeletonData(false);
return stateData;
- GetSkeletonData(false);
- return stateData;
+ }
}
+
}
diff --git a/spine-unity/Assets/spine-unity/BoneFollower.cs b/spine-unity/Assets/spine-unity/BoneFollower.cs
index 43c18fac8..e43622c3f 100644
--- a/spine-unity/Assets/spine-unity/BoneFollower.cs
+++ b/spine-unity/Assets/spine-unity/BoneFollower.cs
@@ -28,119 +28,118 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
-
using System;
-using System.IO;
-using System.Collections.Generic;
using UnityEngine;
-using Spine;
-/// Sets a GameObject's transform to match a bone on a Spine skeleton.
-[ExecuteInEditMode]
-[AddComponentMenu("Spine/BoneFollower")]
-public class BoneFollower : MonoBehaviour {
+namespace Spine.Unity {
+ /// Sets a GameObject's transform to match a bone on a Spine skeleton.
+ [ExecuteInEditMode]
+ [AddComponentMenu("Spine/BoneFollower")]
+ public class BoneFollower : MonoBehaviour {
- #region Inspector
- public SkeletonRenderer skeletonRenderer;
- public SkeletonRenderer SkeletonRenderer {
- get { return skeletonRenderer; }
- set {
- skeletonRenderer = value;
+ #region Inspector
+ public SkeletonRenderer skeletonRenderer;
+ public SkeletonRenderer SkeletonRenderer {
+ get { return skeletonRenderer; }
+ set {
+ skeletonRenderer = value;
+ Reset();
+ }
+ }
+ /// If a bone isn't set, boneName is used to find the bone.
+ [SpineBone(dataField: "skeletonRenderer")]
+ public String boneName;
+
+ public bool followZPosition = true;
+ public bool followBoneRotation = true;
+ public bool resetOnAwake = true;
+ #endregion
+
+ [NonSerialized]
+ public bool valid;
+
+ [NonSerialized]
+ public Bone bone;
+ Transform skeletonTransform;
+
+ public void HandleResetRenderer (SkeletonRenderer skeletonRenderer) {
Reset();
}
- }
- /// If a bone isn't set, boneName is used to find the bone.
- [SpineBone(dataField: "skeletonRenderer")]
- public String boneName;
- public bool followZPosition = true;
- public bool followBoneRotation = true;
- public bool resetOnAwake = true;
- #endregion
+ public void Reset () {
+ bone = null;
+ valid = skeletonRenderer != null && skeletonRenderer.valid;
- [NonSerialized]
- public bool valid;
+ if (!valid) return;
- [NonSerialized]
- public Bone bone;
- Transform skeletonTransform;
-
- public void HandleResetRenderer (SkeletonRenderer skeletonRenderer) {
- Reset();
- }
-
- public void Reset () {
- bone = null;
- valid = skeletonRenderer != null && skeletonRenderer.valid;
-
- if (!valid) return;
-
- skeletonTransform = skeletonRenderer.transform;
- skeletonRenderer.OnRebuild -= HandleResetRenderer;
- skeletonRenderer.OnRebuild += HandleResetRenderer;
-
- #if UNITY_EDITOR
- if (Application.isEditor)
- DoUpdate();
- #endif
- }
-
- void OnDestroy () {
- if (skeletonRenderer != null)
+ skeletonTransform = skeletonRenderer.transform;
skeletonRenderer.OnRebuild -= HandleResetRenderer;
- }
+ skeletonRenderer.OnRebuild += HandleResetRenderer;
- public void Awake () {
- if (resetOnAwake)
- Reset();
- }
-
- void LateUpdate () {
- DoUpdate();
- }
-
- public void DoUpdate () {
- if (!valid) {
- Reset();
- return;
+ #if UNITY_EDITOR
+ if (Application.isEditor)
+ DoUpdate();
+ #endif
}
- if (bone == null) {
- if (boneName == null || boneName.Length == 0)
+ void OnDestroy () {
+ if (skeletonRenderer != null)
+ skeletonRenderer.OnRebuild -= HandleResetRenderer;
+ }
+
+ public void Awake () {
+ if (resetOnAwake)
+ Reset();
+ }
+
+ void LateUpdate () {
+ DoUpdate();
+ }
+
+ public void DoUpdate () {
+ if (!valid) {
+ Reset();
return;
- bone = skeletonRenderer.skeleton.FindBone(boneName);
+ }
+
if (bone == null) {
- Debug.LogError("Bone not found: " + boneName, this);
- return;
+ if (boneName == null || boneName.Length == 0)
+ return;
+ bone = skeletonRenderer.skeleton.FindBone(boneName);
+ if (bone == null) {
+ Debug.LogError("Bone not found: " + boneName, this);
+ return;
+ }
}
+
+ Skeleton skeleton = skeletonRenderer.skeleton;
+ float flipRotation = (skeleton.flipX ^ skeleton.flipY) ? -1f : 1f;
+ Transform thisTransform = this.transform;
+
+ // Recommended setup: Use local transform properties if Spine GameObject is parent
+ if (thisTransform.parent == skeletonTransform) {
+ thisTransform.localPosition = new Vector3(bone.worldX, bone.worldY, followZPosition ? 0f : thisTransform.localPosition.z);
+
+ if (followBoneRotation) {
+ Vector3 rotation = thisTransform.localRotation.eulerAngles;
+ thisTransform.localRotation = Quaternion.Euler(rotation.x, rotation.y, bone.WorldRotationX * flipRotation);
+ }
+
+ // For special cases: Use transform world properties if transform relationship is complicated
+ } else {
+ Vector3 targetWorldPosition = skeletonTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY, 0f));
+ if (!followZPosition)
+ targetWorldPosition.z = thisTransform.position.z;
+
+ thisTransform.position = targetWorldPosition;
+
+ if (followBoneRotation) {
+ Vector3 worldRotation = skeletonTransform.rotation.eulerAngles;
+ thisTransform.rotation = Quaternion.Euler(worldRotation.x, worldRotation.y, skeletonTransform.rotation.eulerAngles.z + (bone.WorldRotationX * flipRotation));
+ }
+ }
+
}
-
- Skeleton skeleton = skeletonRenderer.skeleton;
- float flipRotation = (skeleton.flipX ^ skeleton.flipY) ? -1f : 1f;
- Transform thisTransform = this.transform;
-
- // Recommended setup: Use local transform properties if Spine GameObject is parent
- if (thisTransform.parent == skeletonTransform) {
- thisTransform.localPosition = new Vector3(bone.worldX, bone.worldY, followZPosition ? 0f : thisTransform.localPosition.z);
-
- if (followBoneRotation) {
- Vector3 rotation = thisTransform.localRotation.eulerAngles;
- thisTransform.localRotation = Quaternion.Euler(rotation.x, rotation.y, bone.WorldRotationX * flipRotation);
- }
-
- // For special cases: Use transform world properties if transform relationship is complicated
- } else {
- Vector3 targetWorldPosition = skeletonTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY, 0f));
- if (!followZPosition)
- targetWorldPosition.z = thisTransform.position.z;
-
- thisTransform.position = targetWorldPosition;
-
- if (followBoneRotation) {
- Vector3 worldRotation = skeletonTransform.rotation.eulerAngles;
- thisTransform.rotation = Quaternion.Euler(worldRotation.x, worldRotation.y, skeletonTransform.rotation.eulerAngles.z + (bone.WorldRotationX * flipRotation));
- }
- }
-
}
+
}
diff --git a/spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs b/spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs
index 7bcf31343..129ba97b6 100644
--- a/spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs
+++ b/spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs
@@ -30,10 +30,8 @@
*****************************************************************************/
using UnityEngine;
-using System.Collections;
using UnityEditor;
using System.Reflection;
-using System;
namespace Spine.Unity.Editor {
public static class SpineInspectorUtility {
diff --git a/spine-unity/Assets/spine-unity/Modules/AtlasRegionAttacher.cs b/spine-unity/Assets/spine-unity/Modules/AtlasRegionAttacher.cs
index cc95706b6..3b2866094 100644
--- a/spine-unity/Assets/spine-unity/Modules/AtlasRegionAttacher.cs
+++ b/spine-unity/Assets/spine-unity/Modules/AtlasRegionAttacher.cs
@@ -28,53 +28,53 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
-
using UnityEngine;
using System.Collections;
using Spine;
+namespace Spine.Unity.Modules {
+ public class AtlasRegionAttacher : MonoBehaviour {
-public class AtlasRegionAttacher : MonoBehaviour {
+ [System.Serializable]
+ public class SlotRegionPair {
+ [SpineSlot]
+ public string slot;
- [System.Serializable]
- public class SlotRegionPair {
- [SpineSlot]
- public string slot;
-
- [SpineAtlasRegion]
- public string region;
- }
-
- public AtlasAsset atlasAsset;
- public SlotRegionPair[] attachments;
-
- Atlas atlas;
-
- void Awake () {
- GetComponent().OnRebuild += Apply;
- }
-
-
- void Apply (SkeletonRenderer skeletonRenderer) {
- atlas = atlasAsset.GetAtlas();
-
- AtlasAttachmentLoader loader = new AtlasAttachmentLoader(atlas);
-
- float scaleMultiplier = skeletonRenderer.skeletonDataAsset.scale;
-
- var enumerator = attachments.GetEnumerator();
- while (enumerator.MoveNext()) {
- var entry = (SlotRegionPair)enumerator.Current;
- var regionAttachment = loader.NewRegionAttachment(null, entry.region, entry.region);
- regionAttachment.Width = regionAttachment.RegionOriginalWidth * scaleMultiplier;
- regionAttachment.Height = regionAttachment.RegionOriginalHeight * scaleMultiplier;
-
- regionAttachment.SetColor(new Color(1, 1, 1, 1));
- regionAttachment.UpdateOffset();
-
- var slot = skeletonRenderer.skeleton.FindSlot(entry.slot);
- slot.Attachment = regionAttachment;
+ [SpineAtlasRegion]
+ public string region;
}
- }
+ public AtlasAsset atlasAsset;
+ public SlotRegionPair[] attachments;
+
+ Atlas atlas;
+
+ void Awake () {
+ GetComponent().OnRebuild += Apply;
+ }
+
+
+ void Apply (SkeletonRenderer skeletonRenderer) {
+ atlas = atlasAsset.GetAtlas();
+
+ AtlasAttachmentLoader loader = new AtlasAttachmentLoader(atlas);
+
+ float scaleMultiplier = skeletonRenderer.skeletonDataAsset.scale;
+
+ var enumerator = attachments.GetEnumerator();
+ while (enumerator.MoveNext()) {
+ var entry = (SlotRegionPair)enumerator.Current;
+ var regionAttachment = loader.NewRegionAttachment(null, entry.region, entry.region);
+ regionAttachment.Width = regionAttachment.RegionOriginalWidth * scaleMultiplier;
+ regionAttachment.Height = regionAttachment.RegionOriginalHeight * scaleMultiplier;
+
+ regionAttachment.SetColor(new Color(1, 1, 1, 1));
+ regionAttachment.UpdateOffset();
+
+ var slot = skeletonRenderer.skeleton.FindSlot(entry.slot);
+ slot.Attachment = regionAttachment;
+ }
+ }
+
+ }
}
diff --git a/spine-unity/Assets/spine-unity/Modules/BoundingBoxFollower/BoundingBoxFollower.cs b/spine-unity/Assets/spine-unity/Modules/BoundingBoxFollower/BoundingBoxFollower.cs
index a3c71fc8b..c3269e13a 100644
--- a/spine-unity/Assets/spine-unity/Modules/BoundingBoxFollower/BoundingBoxFollower.cs
+++ b/spine-unity/Assets/spine-unity/Modules/BoundingBoxFollower/BoundingBoxFollower.cs
@@ -28,167 +28,159 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
-
using UnityEngine;
-using System.Collections;
using System.Collections.Generic;
-using Spine;
-[ExecuteInEditMode]
-public class BoundingBoxFollower : MonoBehaviour {
+namespace Spine.Unity {
+ [ExecuteInEditMode]
+ public class BoundingBoxFollower : MonoBehaviour {
+
+ public SkeletonRenderer skeletonRenderer;
- public SkeletonRenderer skeletonRenderer;
+ [SpineSlot(dataField: "skeletonRenderer", containsBoundingBoxes: true)]
+ public string slotName;
- [SpineSlot(dataField: "skeletonRenderer", containsBoundingBoxes: true)]
- public string slotName;
+ //TODO: not this
+ [Tooltip("LOL JK, Someone else do it!")]
+ public bool use3DMeshCollider;
- //TODO: not this
- [Tooltip("LOL JK, Someone else do it!")]
- public bool use3DMeshCollider;
+ private Slot slot;
+ private BoundingBoxAttachment currentAttachment;
+ private PolygonCollider2D currentCollider;
+ private string currentAttachmentName;
+ private bool valid = false;
+ private bool hasReset;
- private Slot slot;
- private BoundingBoxAttachment currentAttachment;
- private PolygonCollider2D currentCollider;
- private string currentAttachmentName;
- private bool valid = false;
- private bool hasReset;
+ public Dictionary colliderTable = new Dictionary();
+ public Dictionary attachmentNameTable = new Dictionary();
- public Dictionary colliderTable = new Dictionary();
- public Dictionary attachmentNameTable = new Dictionary();
-
- public string CurrentAttachmentName {
- get {
- return currentAttachmentName;
+ public string CurrentAttachmentName {
+ get { return currentAttachmentName; }
}
- }
- public BoundingBoxAttachment CurrentAttachment {
- get {
- return currentAttachment;
+ public BoundingBoxAttachment CurrentAttachment {
+ get { return currentAttachment; }
}
- }
- public PolygonCollider2D CurrentCollider {
- get {
- return currentCollider;
+ public PolygonCollider2D CurrentCollider {
+ get { return currentCollider; }
}
- }
- public Slot Slot {
- get {
- return slot;
+ public Slot Slot {
+ get { return slot; }
}
- }
- void OnEnable () {
- ClearColliders();
+ void OnEnable () {
+ ClearColliders();
- if (skeletonRenderer == null)
- skeletonRenderer = GetComponentInParent();
+ if (skeletonRenderer == null)
+ skeletonRenderer = GetComponentInParent();
- if (skeletonRenderer != null) {
+ if (skeletonRenderer != null) {
+ skeletonRenderer.OnRebuild -= HandleReset;
+ skeletonRenderer.OnRebuild += HandleReset;
+
+ if (hasReset)
+ HandleReset(skeletonRenderer);
+ }
+ }
+
+ void OnDisable () {
skeletonRenderer.OnRebuild -= HandleReset;
- skeletonRenderer.OnRebuild += HandleReset;
+ }
- if (hasReset)
+ void Start () {
+ if (!hasReset && skeletonRenderer != null)
HandleReset(skeletonRenderer);
}
- }
- void OnDisable () {
- skeletonRenderer.OnRebuild -= HandleReset;
- }
+ public void HandleReset (SkeletonRenderer renderer) {
+ if (slotName == null || slotName == "")
+ return;
- void Start () {
- if (!hasReset && skeletonRenderer != null)
- HandleReset(skeletonRenderer);
- }
+ hasReset = true;
- public void HandleReset (SkeletonRenderer renderer) {
- if (slotName == null || slotName == "")
- return;
+ ClearColliders();
+ colliderTable.Clear();
- hasReset = true;
-
- ClearColliders();
- colliderTable.Clear();
-
- if (skeletonRenderer.skeleton == null) {
- skeletonRenderer.OnRebuild -= HandleReset;
- skeletonRenderer.Initialize(false);
- skeletonRenderer.OnRebuild += HandleReset;
- }
+ if (skeletonRenderer.skeleton == null) {
+ skeletonRenderer.OnRebuild -= HandleReset;
+ skeletonRenderer.Initialize(false);
+ skeletonRenderer.OnRebuild += HandleReset;
+ }
- var skeleton = skeletonRenderer.skeleton;
- slot = skeleton.FindSlot(slotName);
- int slotIndex = skeleton.FindSlotIndex(slotName);
+ var skeleton = skeletonRenderer.skeleton;
+ slot = skeleton.FindSlot(slotName);
+ int slotIndex = skeleton.FindSlotIndex(slotName);
- foreach (var skin in skeleton.Data.Skins) {
- List attachmentNames = new List();
- skin.FindNamesForSlot(slotIndex, attachmentNames);
+ foreach (var skin in skeleton.Data.Skins) {
+ List attachmentNames = new List();
+ skin.FindNamesForSlot(slotIndex, attachmentNames);
- foreach (var name in attachmentNames) {
- var attachment = skin.GetAttachment(slotIndex, name);
- if (attachment is BoundingBoxAttachment) {
- var collider = SkeletonUtility.AddBoundingBoxAsComponent((BoundingBoxAttachment)attachment, gameObject, true);
- collider.enabled = false;
- collider.hideFlags = HideFlags.HideInInspector;
- colliderTable.Add((BoundingBoxAttachment)attachment, collider);
- attachmentNameTable.Add((BoundingBoxAttachment)attachment, name);
+ foreach (var name in attachmentNames) {
+ var attachment = skin.GetAttachment(slotIndex, name);
+ if (attachment is BoundingBoxAttachment) {
+ var collider = SkeletonUtility.AddBoundingBoxAsComponent((BoundingBoxAttachment)attachment, gameObject, true);
+ collider.enabled = false;
+ collider.hideFlags = HideFlags.HideInInspector;
+ colliderTable.Add((BoundingBoxAttachment)attachment, collider);
+ attachmentNameTable.Add((BoundingBoxAttachment)attachment, name);
+ }
}
}
+
+ if (colliderTable.Count == 0)
+ valid = false;
+ else
+ valid = true;
+
+ if (!valid)
+ Debug.LogWarning("Bounding Box Follower not valid! Slot [" + slotName + "] does not contain any Bounding Box Attachments!");
}
- if (colliderTable.Count == 0)
- valid = false;
- else
- valid = true;
-
- if (!valid)
- Debug.LogWarning("Bounding Box Follower not valid! Slot [" + slotName + "] does not contain any Bounding Box Attachments!");
- }
-
- void ClearColliders () {
- var colliders = GetComponents();
- if (Application.isPlaying) {
- foreach (var c in colliders) {
- Destroy(c);
+ void ClearColliders () {
+ var colliders = GetComponents();
+ if (Application.isPlaying) {
+ foreach (var c in colliders) {
+ Destroy(c);
+ }
+ } else {
+ foreach (var c in colliders) {
+ DestroyImmediate(c);
+ }
}
- } else {
- foreach (var c in colliders) {
- DestroyImmediate(c);
+
+ colliderTable.Clear();
+ attachmentNameTable.Clear();
+ }
+
+ void LateUpdate () {
+ if (!skeletonRenderer.valid)
+ return;
+
+ if (slot != null) {
+ if (slot.Attachment != currentAttachment)
+ SetCurrent((BoundingBoxAttachment)slot.Attachment);
}
}
- colliderTable.Clear();
- attachmentNameTable.Clear();
- }
+ void SetCurrent (BoundingBoxAttachment attachment) {
+ if (currentCollider)
+ currentCollider.enabled = false;
- void LateUpdate () {
- if (!skeletonRenderer.valid)
- return;
+ if (attachment != null) {
+ currentCollider = colliderTable[attachment];
+ currentCollider.enabled = true;
+ } else {
+ currentCollider = null;
+ }
- if (slot != null) {
- if (slot.Attachment != currentAttachment)
- SetCurrent((BoundingBoxAttachment)slot.Attachment);
+ currentAttachment = attachment;
+
+ currentAttachmentName = currentAttachment == null ? null : attachmentNameTable[attachment];
}
}
- void SetCurrent (BoundingBoxAttachment attachment) {
- if (currentCollider)
- currentCollider.enabled = false;
-
- if (attachment != null) {
- currentCollider = colliderTable[attachment];
- currentCollider.enabled = true;
- } else {
- currentCollider = null;
- }
-
- currentAttachment = attachment;
-
- currentAttachmentName = currentAttachment == null ? null : attachmentNameTable[attachment];
- }
}
diff --git a/spine-unity/Assets/spine-unity/Modules/CustomSkin.cs b/spine-unity/Assets/spine-unity/Modules/CustomSkin.cs
index fab223b14..70f514def 100644
--- a/spine-unity/Assets/spine-unity/Modules/CustomSkin.cs
+++ b/spine-unity/Assets/spine-unity/Modules/CustomSkin.cs
@@ -28,54 +28,56 @@
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/
-
using UnityEngine;
-using System.Collections;
using Spine;
+using Spine.Unity;
-public class CustomSkin : MonoBehaviour {
+namespace Spine.Unity.Modules {
+ public class CustomSkin : MonoBehaviour {
- [System.Serializable]
- public class SkinPair {
- /// SpineAttachment attachment path to help find the attachment.
- /// This use of SpineAttachment generates an attachment path string that can only be used by SpineAttachment.GetAttachment.
- [SpineAttachment(currentSkinOnly: false, returnAttachmentPath: true, dataField: "skinSource")]
- [UnityEngine.Serialization.FormerlySerializedAs("sourceAttachment")]
- public string sourceAttachmentPath;
+ [System.Serializable]
+ public class SkinPair {
+ /// SpineAttachment attachment path to help find the attachment.
+ /// This use of SpineAttachment generates an attachment path string that can only be used by SpineAttachment.GetAttachment.
+ [SpineAttachment(currentSkinOnly: false, returnAttachmentPath: true, dataField: "skinSource")]
+ [UnityEngine.Serialization.FormerlySerializedAs("sourceAttachment")]
+ public string sourceAttachmentPath;
- [SpineSlot]
- public string targetSlot;
+ [SpineSlot]
+ public string targetSlot;
- /// The name of the skin placeholder/skin dictionary entry this attachment should be associated with.
- /// This name is used by the skin dictionary, used in the method Skin.AddAttachment as well as setting a slot attachment
- [SpineAttachment(currentSkinOnly: true, placeholdersOnly: true)]
- public string targetAttachment;
- }
-
- #region Inspector
- public SkeletonDataAsset skinSource;
-
- [UnityEngine.Serialization.FormerlySerializedAs("skinning")]
- public SkinPair[] skinItems;
-
- public Skin customSkin;
- #endregion
-
- SkeletonRenderer skeletonRenderer;
-
- void Start () {
- skeletonRenderer = GetComponent();
- Skeleton skeleton = skeletonRenderer.skeleton;
-
- customSkin = new Skin("CustomSkin");
-
- foreach (var pair in skinItems) {
- var attachment = SpineAttachment.GetAttachment(pair.sourceAttachmentPath, skinSource);
- customSkin.AddAttachment(skeleton.FindSlotIndex(pair.targetSlot), pair.targetAttachment, attachment);
+ /// The name of the skin placeholder/skin dictionary entry this attachment should be associated with.
+ /// This name is used by the skin dictionary, used in the method Skin.AddAttachment as well as setting a slot attachment
+ [SpineAttachment(currentSkinOnly: true, placeholdersOnly: true)]
+ public string targetAttachment;
}
- // The custom skin does not need to be added to the skeleton data for it to work.
- // But it's useful for your script to keep a reference to it.
- skeleton.SetSkin(customSkin);
+ #region Inspector
+ public SkeletonDataAsset skinSource;
+
+ [UnityEngine.Serialization.FormerlySerializedAs("skinning")]
+ public SkinPair[] skinItems;
+
+ public Skin customSkin;
+ #endregion
+
+ SkeletonRenderer skeletonRenderer;
+
+ void Start () {
+ skeletonRenderer = GetComponent();
+ Skeleton skeleton = skeletonRenderer.skeleton;
+
+ customSkin = new Skin("CustomSkin");
+
+ foreach (var pair in skinItems) {
+ var attachment = SpineAttachment.GetAttachment(pair.sourceAttachmentPath, skinSource);
+ customSkin.AddAttachment(skeleton.FindSlotIndex(pair.targetSlot), pair.targetAttachment, attachment);
+ }
+
+ // The custom skin does not need to be added to the skeleton data for it to work.
+ // But it's useful for your script to keep a reference to it.
+ skeleton.SetSkin(customSkin);
+ }
}
+
}
diff --git a/spine-unity/Assets/spine-unity/Modules/Ghost/SkeletonGhost.cs b/spine-unity/Assets/spine-unity/Modules/Ghost/SkeletonGhost.cs
index 3717bc9a6..3de748487 100644
--- a/spine-unity/Assets/spine-unity/Modules/Ghost/SkeletonGhost.cs
+++ b/spine-unity/Assets/spine-unity/Modules/Ghost/SkeletonGhost.cs
@@ -4,150 +4,153 @@
*****************************************************************************/
using UnityEngine;
-using System.Collections;
using System.Collections.Generic;
-[RequireComponent(typeof(SkeletonRenderer))]
-public class SkeletonGhost : MonoBehaviour {
- public bool ghostingEnabled = true;
- public float spawnRate = 0.05f;
- public Color32 color = new Color32(0xFF, 0xFF, 0xFF, 0x00); // default for additive.
- [Tooltip("Remember to set color alpha to 0 if Additive is true")]
- public bool additive = true;
- public int maximumGhosts = 10;
- public float fadeSpeed = 10;
- public Shader ghostShader;
- [Tooltip("0 is Color and Alpha, 1 is Alpha only.")]
- [Range(0, 1)]
- public float textureFade = 1;
+namespace Spine.Unity.Modules {
+
+ [RequireComponent(typeof(SkeletonRenderer))]
+ public class SkeletonGhost : MonoBehaviour {
+ public bool ghostingEnabled = true;
+ public float spawnRate = 0.05f;
+ public Color32 color = new Color32(0xFF, 0xFF, 0xFF, 0x00); // default for additive.
+ [Tooltip("Remember to set color alpha to 0 if Additive is true")]
+ public bool additive = true;
+ public int maximumGhosts = 10;
+ public float fadeSpeed = 10;
+ public Shader ghostShader;
+ [Tooltip("0 is Color and Alpha, 1 is Alpha only.")]
+ [Range(0, 1)]
+ public float textureFade = 1;
- [Header("Sorting")]
- public bool sortWithDistanceOnly;
- public float zOffset = 0f;
+ [Header("Sorting")]
+ public bool sortWithDistanceOnly;
+ public float zOffset = 0f;
- float nextSpawnTime;
- SkeletonGhostRenderer[] pool;
- int poolIndex = 0;
- SkeletonRenderer skeletonRenderer;
- MeshRenderer meshRenderer;
- MeshFilter meshFilter;
+ float nextSpawnTime;
+ SkeletonGhostRenderer[] pool;
+ int poolIndex = 0;
+ SkeletonRenderer skeletonRenderer;
+ MeshRenderer meshRenderer;
+ MeshFilter meshFilter;
- Dictionary materialTable = new Dictionary();
+ Dictionary materialTable = new Dictionary();
- void Start () {
- if (ghostShader == null)
- ghostShader = Shader.Find("Spine/SkeletonGhost");
+ void Start () {
+ if (ghostShader == null)
+ ghostShader = Shader.Find("Spine/SkeletonGhost");
+
+ skeletonRenderer = GetComponent();
+ meshFilter = GetComponent();
+ meshRenderer = GetComponent();
+ nextSpawnTime = Time.time + spawnRate;
+ pool = new SkeletonGhostRenderer[maximumGhosts];
+ for (int i = 0; i < maximumGhosts; i++) {
+ GameObject go = new GameObject(gameObject.name + " Ghost", typeof(SkeletonGhostRenderer));
+ pool[i] = go.GetComponent();
+ go.SetActive(false);
+ go.hideFlags = HideFlags.HideInHierarchy;
+ }
+
+ if (skeletonRenderer is SkeletonAnimation)
+ ((SkeletonAnimation)skeletonRenderer).state.Event += OnEvent;
- skeletonRenderer = GetComponent();
- meshFilter = GetComponent();
- meshRenderer = GetComponent();
- nextSpawnTime = Time.time + spawnRate;
- pool = new SkeletonGhostRenderer[maximumGhosts];
- for (int i = 0; i < maximumGhosts; i++) {
- GameObject go = new GameObject(gameObject.name + " Ghost", typeof(SkeletonGhostRenderer));
- pool[i] = go.GetComponent();
- go.SetActive(false);
- go.hideFlags = HideFlags.HideInHierarchy;
}
- if (skeletonRenderer is SkeletonAnimation)
- ((SkeletonAnimation)skeletonRenderer).state.Event += OnEvent;
-
- }
-
- //SkeletonAnimation
- /*
+ //SkeletonAnimation
+ /*
* Int Value: 0 sets ghostingEnabled to false, 1 sets ghostingEnabled to true
* Float Value: Values greater than 0 set the spawnRate equal the float value
* String Value: Pass RGBA hex color values in to set the color property. IE: "A0FF8BFF"
*/
- void OnEvent (Spine.AnimationState state, int trackIndex, Spine.Event e) {
- if (e.Data.Name == "Ghosting") {
- ghostingEnabled = e.Int > 0;
- if (e.Float > 0)
- spawnRate = e.Float;
- if (e.String != null) {
- this.color = HexToColor(e.String);
+ void OnEvent (Spine.AnimationState state, int trackIndex, Spine.Event e) {
+ if (e.Data.Name == "Ghosting") {
+ ghostingEnabled = e.Int > 0;
+ if (e.Float > 0)
+ spawnRate = e.Float;
+ if (e.String != null) {
+ this.color = HexToColor(e.String);
+ }
}
}
- }
- //SkeletonAnimator
- //SkeletonAnimator or Mecanim based animations only support toggling ghostingEnabled. Be sure not to set anything other than the Int param in Spine or String will take priority.
- void Ghosting (float val) {
- ghostingEnabled = val > 0;
- }
+ //SkeletonAnimator
+ //SkeletonAnimator or Mecanim based animations only support toggling ghostingEnabled. Be sure not to set anything other than the Int param in Spine or String will take priority.
+ void Ghosting (float val) {
+ ghostingEnabled = val > 0;
+ }
- void Update () {
- if (!ghostingEnabled)
- return;
+ void Update () {
+ if (!ghostingEnabled)
+ return;
- if (Time.time >= nextSpawnTime) {
- GameObject go = pool[poolIndex].gameObject;
+ if (Time.time >= nextSpawnTime) {
+ GameObject go = pool[poolIndex].gameObject;
- Material[] materials = meshRenderer.sharedMaterials;
- for (int i = 0; i < materials.Length; i++) {
- var originalMat = materials[i];
- Material ghostMat;
- if (!materialTable.ContainsKey(originalMat)) {
- ghostMat = new Material(originalMat);
- ghostMat.shader = ghostShader;
- ghostMat.color = Color.white;
- if (ghostMat.HasProperty("_TextureFade"))
- ghostMat.SetFloat("_TextureFade", textureFade);
- materialTable.Add(originalMat, ghostMat);
- } else {
- ghostMat = materialTable[originalMat];
+ Material[] materials = meshRenderer.sharedMaterials;
+ for (int i = 0; i < materials.Length; i++) {
+ var originalMat = materials[i];
+ Material ghostMat;
+ if (!materialTable.ContainsKey(originalMat)) {
+ ghostMat = new Material(originalMat);
+ ghostMat.shader = ghostShader;
+ ghostMat.color = Color.white;
+ if (ghostMat.HasProperty("_TextureFade"))
+ ghostMat.SetFloat("_TextureFade", textureFade);
+ materialTable.Add(originalMat, ghostMat);
+ } else {
+ ghostMat = materialTable[originalMat];
+ }
+
+ materials[i] = ghostMat;
}
- materials[i] = ghostMat;
+ var goTransform = go.transform;
+ goTransform.parent = transform;
+
+ pool[poolIndex].Initialize(meshFilter.sharedMesh, materials, color, additive, fadeSpeed, meshRenderer.sortingLayerID, (sortWithDistanceOnly) ? meshRenderer.sortingOrder : meshRenderer.sortingOrder - 1);
+
+ goTransform.localPosition = new Vector3(0f, 0f, zOffset);
+ goTransform.localRotation = Quaternion.identity;
+ goTransform.localScale = Vector3.one;
+
+ goTransform.parent = null;
+
+ poolIndex++;
+
+ if (poolIndex == pool.Length)
+ poolIndex = 0;
+
+ nextSpawnTime = Time.time + spawnRate;
+ }
+ }
+
+ void OnDestroy () {
+ for (int i = 0; i < maximumGhosts; i++) {
+ if (pool[i] != null)
+ pool[i].Cleanup();
}
- var goTransform = go.transform;
- goTransform.parent = transform;
+ foreach (var mat in materialTable.Values)
+ Destroy(mat);
+ }
- pool[poolIndex].Initialize(meshFilter.sharedMesh, materials, color, additive, fadeSpeed, meshRenderer.sortingLayerID, (sortWithDistanceOnly) ? meshRenderer.sortingOrder : meshRenderer.sortingOrder - 1);
- goTransform.localPosition = new Vector3(0f, 0f, zOffset);
- goTransform.localRotation = Quaternion.identity;
- goTransform.localScale = Vector3.one;
+ //based on UnifyWiki http://wiki.unity3d.com/index.php?title=HexConverter
+ static Color32 HexToColor (string hex) {
+ if (hex.Length < 6)
+ return Color.magenta;
- goTransform.parent = null;
+ hex = hex.Replace("#", "");
+ byte r = byte.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
+ byte g = byte.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
+ byte b = byte.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
+ byte a = 0xFF;
+ if (hex.Length == 8)
+ a = byte.Parse(hex.Substring(6, 2), System.Globalization.NumberStyles.HexNumber);
- poolIndex++;
-
- if (poolIndex == pool.Length)
- poolIndex = 0;
-
- nextSpawnTime = Time.time + spawnRate;
+ return new Color32(r, g, b, a);
}
}
- void OnDestroy () {
- for (int i = 0; i < maximumGhosts; i++) {
- if (pool[i] != null)
- pool[i].Cleanup();
- }
-
- foreach (var mat in materialTable.Values)
- Destroy(mat);
- }
-
-
- //based on UnifyWiki http://wiki.unity3d.com/index.php?title=HexConverter
- static Color32 HexToColor (string hex) {
- if (hex.Length < 6)
- return Color.magenta;
-
- hex = hex.Replace("#", "");
- byte r = byte.Parse(hex.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
- byte g = byte.Parse(hex.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
- byte b = byte.Parse(hex.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
- byte a = 0xFF;
- if (hex.Length == 8)
- a = byte.Parse(hex.Substring(6, 2), System.Globalization.NumberStyles.HexNumber);
-
- return new Color32(r, g, b, a);
- }
}
diff --git a/spine-unity/Assets/spine-unity/Modules/Ragdoll/Editor/SkeletonRagdoll2DInspector.cs b/spine-unity/Assets/spine-unity/Modules/Ragdoll/Editor/SkeletonRagdoll2DInspector.cs
index 87c3da693..649345d0e 100644
--- a/spine-unity/Assets/spine-unity/Modules/Ragdoll/Editor/SkeletonRagdoll2DInspector.cs
+++ b/spine-unity/Assets/spine-unity/Modules/Ragdoll/Editor/SkeletonRagdoll2DInspector.cs
@@ -5,48 +5,49 @@
using UnityEngine;
using UnityEditor;
-using System.Collections;
-using System.Collections.Generic;
-[CustomEditor(typeof(SkeletonRagdoll2D))]
-public class SkeletonRagdoll2DInspector : Editor {
- SerializedProperty startingBoneName, stopBoneNames, applyOnStart, pinStartBone, enableJointCollision, gravityScale, disableIK, thickness, rotationLimit, colliderLayer, mix, rootMass, massFalloffFactor;
+namespace Spine.Unity.Modules {
+ [CustomEditor(typeof(SkeletonRagdoll2D))]
+ public class SkeletonRagdoll2DInspector : UnityEditor.Editor {
+ SerializedProperty startingBoneName, stopBoneNames, applyOnStart, pinStartBone, enableJointCollision, gravityScale, disableIK, thickness, rotationLimit, colliderLayer, mix, rootMass, massFalloffFactor;
- void OnEnable () {
- startingBoneName = serializedObject.FindProperty("startingBoneName");
- stopBoneNames = serializedObject.FindProperty("stopBoneNames");
- applyOnStart = serializedObject.FindProperty("applyOnStart");
- pinStartBone = serializedObject.FindProperty("pinStartBone");
- gravityScale = serializedObject.FindProperty("gravityScale");
- disableIK = serializedObject.FindProperty("disableIK");
- thickness = serializedObject.FindProperty("thickness");
- rotationLimit = serializedObject.FindProperty("rotationLimit");
- colliderLayer = serializedObject.FindProperty("colliderLayer");
- mix = serializedObject.FindProperty("mix");
- rootMass = serializedObject.FindProperty("rootMass");
- massFalloffFactor = serializedObject.FindProperty("massFalloffFactor");
+ void OnEnable () {
+ startingBoneName = serializedObject.FindProperty("startingBoneName");
+ stopBoneNames = serializedObject.FindProperty("stopBoneNames");
+ applyOnStart = serializedObject.FindProperty("applyOnStart");
+ pinStartBone = serializedObject.FindProperty("pinStartBone");
+ gravityScale = serializedObject.FindProperty("gravityScale");
+ disableIK = serializedObject.FindProperty("disableIK");
+ thickness = serializedObject.FindProperty("thickness");
+ rotationLimit = serializedObject.FindProperty("rotationLimit");
+ colliderLayer = serializedObject.FindProperty("colliderLayer");
+ mix = serializedObject.FindProperty("mix");
+ rootMass = serializedObject.FindProperty("rootMass");
+ massFalloffFactor = serializedObject.FindProperty("massFalloffFactor");
+ }
+
+ public override void OnInspectorGUI () {
+ EditorGUILayout.PropertyField(startingBoneName);
+ EditorGUILayout.PropertyField(stopBoneNames, true);
+ EditorGUILayout.PropertyField(applyOnStart);
+ EditorGUILayout.PropertyField(pinStartBone);
+ EditorGUILayout.PropertyField(gravityScale);
+ EditorGUILayout.PropertyField(disableIK);
+ EditorGUILayout.PropertyField(thickness);
+ EditorGUILayout.PropertyField(rotationLimit);
+ EditorGUILayout.PropertyField(rootMass);
+ EditorGUILayout.PropertyField(massFalloffFactor);
+ colliderLayer.intValue = EditorGUILayout.LayerField(colliderLayer.displayName, colliderLayer.intValue);
+ EditorGUILayout.PropertyField(mix);
+
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ void Header (string name) {
+ GUILayout.Space(20);
+ EditorGUILayout.LabelField(name, EditorStyles.boldLabel);
+ }
}
- public override void OnInspectorGUI () {
- EditorGUILayout.PropertyField(startingBoneName);
- EditorGUILayout.PropertyField(stopBoneNames, true);
- EditorGUILayout.PropertyField(applyOnStart);
- EditorGUILayout.PropertyField(pinStartBone);
- EditorGUILayout.PropertyField(gravityScale);
- EditorGUILayout.PropertyField(disableIK);
- EditorGUILayout.PropertyField(thickness);
- EditorGUILayout.PropertyField(rotationLimit);
- EditorGUILayout.PropertyField(rootMass);
- EditorGUILayout.PropertyField(massFalloffFactor);
- colliderLayer.intValue = EditorGUILayout.LayerField(colliderLayer.displayName, colliderLayer.intValue);
- EditorGUILayout.PropertyField(mix);
-
-
- serializedObject.ApplyModifiedProperties();
- }
-
- void Header (string name) {
- GUILayout.Space(20);
- EditorGUILayout.LabelField(name, EditorStyles.boldLabel);
- }
}
diff --git a/spine-unity/Assets/spine-unity/Modules/Ragdoll/Editor/SkeletonRagdollInspector.cs b/spine-unity/Assets/spine-unity/Modules/Ragdoll/Editor/SkeletonRagdollInspector.cs
index af1627af4..bac20be1b 100644
--- a/spine-unity/Assets/spine-unity/Modules/Ragdoll/Editor/SkeletonRagdollInspector.cs
+++ b/spine-unity/Assets/spine-unity/Modules/Ragdoll/Editor/SkeletonRagdollInspector.cs
@@ -8,46 +8,49 @@ using UnityEditor;
using System.Collections;
using System.Collections.Generic;
-[CustomEditor(typeof(SkeletonRagdoll))]
-public class SkeletonRagdollInspector : Editor {
- SerializedProperty startingBoneName, stopBoneNames, applyOnStart, pinStartBone, enableJointCollision, useGravity, disableIK, thickness, rotationLimit, colliderLayer, mix, rootMass, massFalloffFactor;
+namespace Spine.Unity.Modules {
+ [CustomEditor(typeof(SkeletonRagdoll))]
+ public class SkeletonRagdollInspector : UnityEditor.Editor {
+ SerializedProperty startingBoneName, stopBoneNames, applyOnStart, pinStartBone, enableJointCollision, useGravity, disableIK, thickness, rotationLimit, colliderLayer, mix, rootMass, massFalloffFactor;
- void OnEnable () {
- startingBoneName = serializedObject.FindProperty("startingBoneName");
- stopBoneNames = serializedObject.FindProperty("stopBoneNames");
- applyOnStart = serializedObject.FindProperty("applyOnStart");
- pinStartBone = serializedObject.FindProperty("pinStartBone");
- enableJointCollision = serializedObject.FindProperty("enableJointCollision");
- useGravity = serializedObject.FindProperty("useGravity");
- disableIK = serializedObject.FindProperty("disableIK");
- thickness = serializedObject.FindProperty("thickness");
- rotationLimit = serializedObject.FindProperty("rotationLimit");
- colliderLayer = serializedObject.FindProperty("colliderLayer");
- mix = serializedObject.FindProperty("mix");
- rootMass = serializedObject.FindProperty("rootMass");
- massFalloffFactor = serializedObject.FindProperty("massFalloffFactor");
+ void OnEnable () {
+ startingBoneName = serializedObject.FindProperty("startingBoneName");
+ stopBoneNames = serializedObject.FindProperty("stopBoneNames");
+ applyOnStart = serializedObject.FindProperty("applyOnStart");
+ pinStartBone = serializedObject.FindProperty("pinStartBone");
+ enableJointCollision = serializedObject.FindProperty("enableJointCollision");
+ useGravity = serializedObject.FindProperty("useGravity");
+ disableIK = serializedObject.FindProperty("disableIK");
+ thickness = serializedObject.FindProperty("thickness");
+ rotationLimit = serializedObject.FindProperty("rotationLimit");
+ colliderLayer = serializedObject.FindProperty("colliderLayer");
+ mix = serializedObject.FindProperty("mix");
+ rootMass = serializedObject.FindProperty("rootMass");
+ massFalloffFactor = serializedObject.FindProperty("massFalloffFactor");
+ }
+
+ public override void OnInspectorGUI () {
+ EditorGUILayout.PropertyField(startingBoneName);
+ EditorGUILayout.PropertyField(stopBoneNames, true);
+ EditorGUILayout.PropertyField(applyOnStart);
+ EditorGUILayout.PropertyField(pinStartBone);
+ EditorGUILayout.PropertyField(enableJointCollision);
+ EditorGUILayout.PropertyField(useGravity);
+ EditorGUILayout.PropertyField(disableIK);
+ EditorGUILayout.PropertyField(thickness);
+ EditorGUILayout.PropertyField(rotationLimit);
+ EditorGUILayout.PropertyField(rootMass);
+ EditorGUILayout.PropertyField(massFalloffFactor);
+ colliderLayer.intValue = EditorGUILayout.LayerField(colliderLayer.displayName, colliderLayer.intValue);
+ EditorGUILayout.PropertyField(mix);
+
+ serializedObject.ApplyModifiedProperties();
+ }
+
+ void Header (string name) {
+ GUILayout.Space(20);
+ EditorGUILayout.LabelField(name, EditorStyles.boldLabel);
+ }
}
- public override void OnInspectorGUI () {
- EditorGUILayout.PropertyField(startingBoneName);
- EditorGUILayout.PropertyField(stopBoneNames, true);
- EditorGUILayout.PropertyField(applyOnStart);
- EditorGUILayout.PropertyField(pinStartBone);
- EditorGUILayout.PropertyField(enableJointCollision);
- EditorGUILayout.PropertyField(useGravity);
- EditorGUILayout.PropertyField(disableIK);
- EditorGUILayout.PropertyField(thickness);
- EditorGUILayout.PropertyField(rotationLimit);
- EditorGUILayout.PropertyField(rootMass);
- EditorGUILayout.PropertyField(massFalloffFactor);
- colliderLayer.intValue = EditorGUILayout.LayerField(colliderLayer.displayName, colliderLayer.intValue);
- EditorGUILayout.PropertyField(mix);
-
- serializedObject.ApplyModifiedProperties();
- }
-
- void Header (string name) {
- GUILayout.Space(20);
- EditorGUILayout.LabelField(name, EditorStyles.boldLabel);
- }
}
diff --git a/spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll.cs b/spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll.cs
index 9e5f2f5bb..1275edb25 100644
--- a/spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll.cs
+++ b/spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll.cs
@@ -6,421 +6,423 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
-using Spine;
-[RequireComponent(typeof(SkeletonRenderer))]
-public class SkeletonRagdoll : MonoBehaviour {
- private static Transform helper;
+namespace Spine.Unity.Modules {
+ [RequireComponent(typeof(SkeletonRenderer))]
+ public class SkeletonRagdoll : MonoBehaviour {
+ private static Transform helper;
- [Header("Hierarchy")]
- [SpineBone]
- public string startingBoneName = "";
- [SpineBone]
- public List stopBoneNames = new List();
+ [Header("Hierarchy")]
+ [SpineBone]
+ public string startingBoneName = "";
+ [SpineBone]
+ public List stopBoneNames = new List();
- [Header("Parameters")]
- public bool applyOnStart;
- [Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
- public bool pinStartBone;
- [Tooltip("Enable Collision between adjacent ragdoll elements (IE: Neck and Head)")]
- public bool enableJointCollision;
- public bool useGravity = true;
- [Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
- public bool disableIK = true;
- [Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
- public float thickness = 0.125f;
- [Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")]
- public float rotationLimit = 20;
- public float rootMass = 20;
- [Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
- [Range(0.01f, 1f)]
- public float massFalloffFactor = 0.4f;
- [Tooltip("The layer assigned to all of the rigidbody parts.")]
- public int colliderLayer = 0;
- [Range(0, 1)]
- public float mix = 1;
+ [Header("Parameters")]
+ public bool applyOnStart;
+ [Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
+ public bool pinStartBone;
+ [Tooltip("Enable Collision between adjacent ragdoll elements (IE: Neck and Head)")]
+ public bool enableJointCollision;
+ public bool useGravity = true;
+ [Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
+ public bool disableIK = true;
+ [Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
+ public float thickness = 0.125f;
+ [Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")]
+ public float rotationLimit = 20;
+ public float rootMass = 20;
+ [Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
+ [Range(0.01f, 1f)]
+ public float massFalloffFactor = 0.4f;
+ [Tooltip("The layer assigned to all of the rigidbody parts.")]
+ public int colliderLayer = 0;
+ [Range(0, 1)]
+ public float mix = 1;
- public Rigidbody RootRigidbody {
- get {
- return this.rootRigidbody;
- }
- }
-
- public Vector3 RootOffset {
- get {
- return this.rootOffset;
- }
- }
-
- public Vector3 EstimatedSkeletonPosition {
- get {
- return rootRigidbody.position - rootOffset;
- }
- }
-
- public bool IsActive {
- get {
- return this.isActive;
- }
- }
-
- private Rigidbody rootRigidbody;
- private ISkeletonAnimation skeletonAnim;
- private Skeleton skeleton;
- private Dictionary boneTable = new Dictionary();
- private Bone startingBone;
- private Transform ragdollRoot;
- private Vector3 rootOffset;
- private bool isActive;
-
- IEnumerator Start () {
- skeletonAnim = (ISkeletonAnimation)GetComponent();
- if (helper == null) {
- helper = (Transform)(new GameObject("Helper")).transform;
- helper.hideFlags = HideFlags.HideInHierarchy;
+ public Rigidbody RootRigidbody {
+ get {
+ return this.rootRigidbody;
+ }
}
- if (applyOnStart) {
- yield return null;
- Apply();
- }
- }
-
- public Coroutine SmoothMix (float target, float duration) {
- return StartCoroutine(SmoothMixCoroutine(target, duration));
- }
-
- IEnumerator SmoothMixCoroutine (float target, float duration) {
- float startTime = Time.time;
- float startMix = mix;
- while (mix > 0) {
- mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
- yield return null;
- }
- }
-
- public void SetSkeletonPosition (Vector3 worldPosition) {
- if (!isActive) {
- Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
- return;
+ public Vector3 RootOffset {
+ get {
+ return this.rootOffset;
+ }
}
- Vector3 offset = worldPosition - transform.position;
- transform.position = worldPosition;
- foreach (Transform t in boneTable.Values) {
- t.position -= offset;
+ public Vector3 EstimatedSkeletonPosition {
+ get {
+ return rootRigidbody.position - rootOffset;
+ }
}
- UpdateWorld(null);
- skeleton.UpdateWorldTransform();
- }
-
- public Rigidbody[] GetRigidbodyArray () {
- if (!isActive)
- return new Rigidbody[0];
-
- Rigidbody[] arr = new Rigidbody[boneTable.Count];
- int i = 0;
- foreach (Transform t in boneTable.Values) {
- arr[i] = t.GetComponent();
- i++;
+ public bool IsActive {
+ get {
+ return this.isActive;
+ }
}
- return arr;
- }
+ private Rigidbody rootRigidbody;
+ private ISkeletonAnimation skeletonAnim;
+ private Skeleton skeleton;
+ private Dictionary boneTable = new Dictionary();
+ private Bone startingBone;
+ private Transform ragdollRoot;
+ private Vector3 rootOffset;
+ private bool isActive;
+
+ IEnumerator Start () {
+ skeletonAnim = (ISkeletonAnimation)GetComponent();
+ if (helper == null) {
+ helper = (Transform)(new GameObject("Helper")).transform;
+ helper.hideFlags = HideFlags.HideInHierarchy;
+ }
+
+ if (applyOnStart) {
+ yield return null;
+ Apply();
+ }
+ }
+
+ public Coroutine SmoothMix (float target, float duration) {
+ return StartCoroutine(SmoothMixCoroutine(target, duration));
+ }
+
+ IEnumerator SmoothMixCoroutine (float target, float duration) {
+ float startTime = Time.time;
+ float startMix = mix;
+ while (mix > 0) {
+ mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
+ yield return null;
+ }
+ }
+
+ public void SetSkeletonPosition (Vector3 worldPosition) {
+ if (!isActive) {
+ Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
+ return;
+ }
+
+ Vector3 offset = worldPosition - transform.position;
+ transform.position = worldPosition;
+ foreach (Transform t in boneTable.Values) {
+ t.position -= offset;
+ }
+
+ UpdateWorld(null);
+ skeleton.UpdateWorldTransform();
+ }
+
+ public Rigidbody[] GetRigidbodyArray () {
+ if (!isActive)
+ return new Rigidbody[0];
+
+ Rigidbody[] arr = new Rigidbody[boneTable.Count];
+ int i = 0;
+ foreach (Transform t in boneTable.Values) {
+ arr[i] = t.GetComponent();
+ i++;
+ }
+
+ return arr;
+ }
+
+ public Rigidbody GetRigidbody (string boneName) {
+ var bone = skeleton.FindBone(boneName);
+ if (bone == null)
+ return null;
+
+ if (boneTable.ContainsKey(bone))
+ return boneTable[bone].GetComponent();
- public Rigidbody GetRigidbody (string boneName) {
- var bone = skeleton.FindBone(boneName);
- if (bone == null)
return null;
-
- if (boneTable.ContainsKey(bone))
- return boneTable[bone].GetComponent();
-
- return null;
- }
-
- public void Remove () {
- isActive = false;
- foreach (var t in boneTable.Values) {
- Destroy(t.gameObject);
}
- Destroy(ragdollRoot.gameObject);
- boneTable.Clear();
- skeletonAnim.UpdateWorld -= UpdateWorld;
- }
+ public void Remove () {
+ isActive = false;
+ foreach (var t in boneTable.Values) {
+ Destroy(t.gameObject);
+ }
+ Destroy(ragdollRoot.gameObject);
- public void Apply () {
- isActive = true;
- skeleton = skeletonAnim.Skeleton;
- mix = 1;
+ boneTable.Clear();
+ skeletonAnim.UpdateWorld -= UpdateWorld;
+ }
- var ragdollRootBone = skeleton.FindBone(startingBoneName);
- startingBone = ragdollRootBone;
- RecursivelyCreateBoneProxies(ragdollRootBone);
+ public void Apply () {
+ isActive = true;
+ skeleton = skeletonAnim.Skeleton;
+ mix = 1;
- rootRigidbody = boneTable[ragdollRootBone].GetComponent();
- rootRigidbody.isKinematic = pinStartBone;
+ var ragdollRootBone = skeleton.FindBone(startingBoneName);
+ startingBone = ragdollRootBone;
+ RecursivelyCreateBoneProxies(ragdollRootBone);
- rootRigidbody.mass = rootMass;
+ rootRigidbody = boneTable[ragdollRootBone].GetComponent();
+ rootRigidbody.isKinematic = pinStartBone;
- List boneColliders = new List();
+ rootRigidbody.mass = rootMass;
- foreach (var pair in boneTable) {
- var b = pair.Key;
- var t = pair.Value;
- Bone parentBone = null;
- Transform parentTransform = transform;
+ List boneColliders = new List();
- boneColliders.Add(t.GetComponent());
+ foreach (var pair in boneTable) {
+ var b = pair.Key;
+ var t = pair.Value;
+ Bone parentBone = null;
+ Transform parentTransform = transform;
- if (b != startingBone) {
- parentBone = b.Parent;
- parentTransform = boneTable[parentBone];
- } else {
- ragdollRoot = new GameObject("RagdollRoot").transform;
- ragdollRoot.parent = transform;
+ boneColliders.Add(t.GetComponent());
- if (b == skeleton.RootBone) {
- ragdollRoot.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
- ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b));
- parentTransform = ragdollRoot;
+ if (b != startingBone) {
+ parentBone = b.Parent;
+ parentTransform = boneTable[parentBone];
} else {
- ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
- ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b.Parent));
- parentTransform = ragdollRoot;
+ ragdollRoot = new GameObject("RagdollRoot").transform;
+ ragdollRoot.parent = transform;
+
+ if (b == skeleton.RootBone) {
+ ragdollRoot.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
+ ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b));
+ parentTransform = ragdollRoot;
+ } else {
+ ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
+ ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b.Parent));
+ parentTransform = ragdollRoot;
+ }
+
+ rootOffset = t.position - transform.position;
}
- rootOffset = t.position - transform.position;
- }
+ var rbParent = parentTransform.GetComponent();
- var rbParent = parentTransform.GetComponent();
-
- if (rbParent != null) {
- var joint = t.gameObject.AddComponent();
- joint.connectedBody = rbParent;
- Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
- localPos.x *= 1;
- joint.connectedAnchor = localPos;
- joint.axis = Vector3.forward;
- joint.GetComponent().mass = joint.connectedBody.mass * massFalloffFactor;
- JointLimits limits = new JointLimits();
- limits.min = -rotationLimit;
- limits.max = rotationLimit;
- joint.limits = limits;
- joint.useLimits = true;
- joint.enableCollision = enableJointCollision;
- }
- }
-
- for (int x = 0; x < boneColliders.Count; x++) {
- for (int y = 0; y < boneColliders.Count; y++) {
- if (x == y) continue;
- Physics.IgnoreCollision(boneColliders[x], boneColliders[y]);
- }
- }
-
- var utilityBones = GetComponentsInChildren();
- if (utilityBones.Length > 0) {
- List destroyedUtilityBoneNames = new List();
- foreach (var ub in utilityBones) {
- if (ub.mode == SkeletonUtilityBone.Mode.Override) {
- destroyedUtilityBoneNames.Add(ub.gameObject.name);
- Destroy(ub.gameObject);
+ if (rbParent != null) {
+ var joint = t.gameObject.AddComponent();
+ joint.connectedBody = rbParent;
+ Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
+ localPos.x *= 1;
+ joint.connectedAnchor = localPos;
+ joint.axis = Vector3.forward;
+ joint.GetComponent().mass = joint.connectedBody.mass * massFalloffFactor;
+ JointLimits limits = new JointLimits();
+ limits.min = -rotationLimit;
+ limits.max = rotationLimit;
+ joint.limits = limits;
+ joint.useLimits = true;
+ joint.enableCollision = enableJointCollision;
}
}
- if (destroyedUtilityBoneNames.Count > 0) {
- string msg = "Destroyed Utility Bones: ";
- for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
- msg += destroyedUtilityBoneNames[i];
- if (i != destroyedUtilityBoneNames.Count - 1) {
- msg += ",";
+ for (int x = 0; x < boneColliders.Count; x++) {
+ for (int y = 0; y < boneColliders.Count; y++) {
+ if (x == y) continue;
+ Physics.IgnoreCollision(boneColliders[x], boneColliders[y]);
+ }
+ }
+
+ var utilityBones = GetComponentsInChildren();
+ if (utilityBones.Length > 0) {
+ List destroyedUtilityBoneNames = new List();
+ foreach (var ub in utilityBones) {
+ if (ub.mode == SkeletonUtilityBone.Mode.Override) {
+ destroyedUtilityBoneNames.Add(ub.gameObject.name);
+ Destroy(ub.gameObject);
}
}
- Debug.LogWarning(msg);
- }
- }
- if (disableIK) {
- foreach (IkConstraint ik in skeleton.IkConstraints) {
- ik.Mix = 0;
- }
- }
-
- skeletonAnim.UpdateWorld += UpdateWorld;
- }
-
- void RecursivelyCreateBoneProxies (Bone b) {
- if (stopBoneNames.Contains(b.Data.Name))
- return;
-
- GameObject go = new GameObject(b.Data.Name);
- go.layer = colliderLayer;
- Transform t = go.transform;
- boneTable.Add(b, t);
-
- t.parent = transform;
-
- t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
- // MITCH
- // t.localRotation = Quaternion.Euler(0, 0, b.WorldFlipX ^ b.WorldFlipY ? -b.WorldRotation : b.WorldRotation);
- t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX);
- t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 1);
-
- float length = b.Data.Length;
-
- var colliders = AttachBoundingBoxRagdollColliders(b);
-
- if (length == 0) {
- //physics
- if (colliders.Count == 0) {
- var ball = go.AddComponent();
- ball.radius = thickness / 2f;
- }
- } else {
- //physics
- if (colliders.Count == 0) {
- var box = go.AddComponent();
- box.size = new Vector3(length, thickness, thickness);
- // MITCH
- // box.center = new Vector3((b.WorldFlipX ? -length : length) / 2, 0);
- box.center = new Vector3(length / 2, 0);
- }
- }
-
- var rb = go.AddComponent();
- rb.constraints = RigidbodyConstraints.FreezePositionZ;
- foreach (Bone child in b.Children) {
- RecursivelyCreateBoneProxies(child);
- }
- }
-
- List AttachBoundingBoxRagdollColliders (Bone b) {
- List colliders = new List();
-
- Transform t = boneTable[b];
- GameObject go = t.gameObject;
- var skin = skeleton.Skin;
- if (skin == null)
- skin = skeleton.Data.DefaultSkin;
-
- // MITCH
- // bool flipX = b.WorldFlipX;
- // bool flipY = b.WorldFlipY;
- bool flipX = false;
- bool flipY = false;
-
- List attachments = new List();
- foreach (Slot s in skeleton.Slots) {
- if (s.Bone == b) {
- skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(s), attachments);
- foreach (var a in attachments) {
- if (a is BoundingBoxAttachment) {
- if (!a.Name.ToLower().Contains("ragdoll"))
- continue;
-
- var collider = go.AddComponent();
- var bounds = SkeletonUtility.GetBoundingBoxBounds((BoundingBoxAttachment)a, thickness);
-
- collider.center = bounds.center;
- collider.size = bounds.size;
-
- if (flipX || flipY) {
- Vector3 center = collider.center;
-
- if (flipX)
- center.x *= -1;
-
- if (flipY)
- center.y *= -1;
-
- collider.center = center;
+ if (destroyedUtilityBoneNames.Count > 0) {
+ string msg = "Destroyed Utility Bones: ";
+ for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
+ msg += destroyedUtilityBoneNames[i];
+ if (i != destroyedUtilityBoneNames.Count - 1) {
+ msg += ",";
}
+ }
+ Debug.LogWarning(msg);
+ }
+ }
- colliders.Add(collider);
+ if (disableIK) {
+ foreach (IkConstraint ik in skeleton.IkConstraints) {
+ ik.Mix = 0;
+ }
+ }
+
+ skeletonAnim.UpdateWorld += UpdateWorld;
+ }
+
+ void RecursivelyCreateBoneProxies (Bone b) {
+ if (stopBoneNames.Contains(b.Data.Name))
+ return;
+
+ GameObject go = new GameObject(b.Data.Name);
+ go.layer = colliderLayer;
+ Transform t = go.transform;
+ boneTable.Add(b, t);
+
+ t.parent = transform;
+
+ t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
+ // MITCH
+ // t.localRotation = Quaternion.Euler(0, 0, b.WorldFlipX ^ b.WorldFlipY ? -b.WorldRotation : b.WorldRotation);
+ t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX);
+ t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 1);
+
+ float length = b.Data.Length;
+
+ var colliders = AttachBoundingBoxRagdollColliders(b);
+
+ if (length == 0) {
+ //physics
+ if (colliders.Count == 0) {
+ var ball = go.AddComponent();
+ ball.radius = thickness / 2f;
+ }
+ } else {
+ //physics
+ if (colliders.Count == 0) {
+ var box = go.AddComponent();
+ box.size = new Vector3(length, thickness, thickness);
+ // MITCH
+ // box.center = new Vector3((b.WorldFlipX ? -length : length) / 2, 0);
+ box.center = new Vector3(length / 2, 0);
+ }
+ }
+
+ var rb = go.AddComponent();
+ rb.constraints = RigidbodyConstraints.FreezePositionZ;
+ foreach (Bone child in b.Children) {
+ RecursivelyCreateBoneProxies(child);
+ }
+ }
+
+ List AttachBoundingBoxRagdollColliders (Bone b) {
+ List colliders = new List();
+
+ Transform t = boneTable[b];
+ GameObject go = t.gameObject;
+ var skin = skeleton.Skin;
+ if (skin == null)
+ skin = skeleton.Data.DefaultSkin;
+
+ // MITCH
+ // bool flipX = b.WorldFlipX;
+ // bool flipY = b.WorldFlipY;
+ bool flipX = false;
+ bool flipY = false;
+
+ List attachments = new List();
+ foreach (Slot s in skeleton.Slots) {
+ if (s.Bone == b) {
+ skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(s), attachments);
+ foreach (var a in attachments) {
+ if (a is BoundingBoxAttachment) {
+ if (!a.Name.ToLower().Contains("ragdoll"))
+ continue;
+
+ var collider = go.AddComponent();
+ var bounds = SkeletonUtility.GetBoundingBoxBounds((BoundingBoxAttachment)a, thickness);
+
+ collider.center = bounds.center;
+ collider.size = bounds.size;
+
+ if (flipX || flipY) {
+ Vector3 center = collider.center;
+
+ if (flipX)
+ center.x *= -1;
+
+ if (flipY)
+ center.y *= -1;
+
+ collider.center = center;
+ }
+
+ colliders.Add(collider);
+ }
}
}
}
+
+ return colliders;
}
- return colliders;
- }
+ void UpdateWorld (ISkeletonAnimation skeletonRenderer) {
+ foreach (var pair in boneTable) {
+ var b = pair.Key;
+ var t = pair.Value;
+ // bool flip = false;
+ bool flipX = false; //TODO: deal with negative scale instead of Flip Key for Spine 3.0
+ bool flipY = false; //TODO: deal with negative scale instead of Flip Key for Spine 3.0
+ Bone parentBone = null;
+ Transform parentTransform = transform;
- void UpdateWorld (ISkeletonAnimation skeletonRenderer) {
- foreach (var pair in boneTable) {
- var b = pair.Key;
- var t = pair.Value;
- // bool flip = false;
- bool flipX = false; //TODO: deal with negative scale instead of Flip Key for Spine 3.0
- bool flipY = false; //TODO: deal with negative scale instead of Flip Key for Spine 3.0
- Bone parentBone = null;
- Transform parentTransform = transform;
+ if (b != startingBone) {
+ parentBone = b.Parent;
+ parentTransform = boneTable[parentBone];
+ // MITCH
+ // flipX = parentBone.WorldFlipX;
+ // flipY = parentBone.WorldFlipY;
- if (b != startingBone) {
- parentBone = b.Parent;
- parentTransform = boneTable[parentBone];
- // MITCH
- // flipX = parentBone.WorldFlipX;
- // flipY = parentBone.WorldFlipY;
-
- } else {
- parentBone = b.Parent;
- parentTransform = ragdollRoot;
- if (b.Parent != null) {
- // MITCH
- // flipX = b.worldFlipX;
- // flipY = b.WorldFlipY;
- } else {
- flipX = b.Skeleton.FlipX;
- flipY = b.Skeleton.FlipY;
+ } else {
+ parentBone = b.Parent;
+ parentTransform = ragdollRoot;
+ if (b.Parent != null) {
+ // MITCH
+ // flipX = b.worldFlipX;
+ // flipY = b.WorldFlipY;
+ } else {
+ flipX = b.Skeleton.FlipX;
+ flipY = b.Skeleton.FlipY;
+ }
}
- }
- //flip = flipX ^ flipY;
+ //flip = flipX ^ flipY;
- helper.position = parentTransform.position;
- helper.rotation = parentTransform.rotation;
- helper.localScale = new Vector3(flipX ? -parentTransform.localScale.x : parentTransform.localScale.x, flipY ? -parentTransform.localScale.y : parentTransform.localScale.y, 1);
+ helper.position = parentTransform.position;
+ helper.rotation = parentTransform.rotation;
+ helper.localScale = new Vector3(flipX ? -parentTransform.localScale.x : parentTransform.localScale.x, flipY ? -parentTransform.localScale.y : parentTransform.localScale.y, 1);
- Vector3 pos = t.position;
- pos = helper.InverseTransformPoint(pos);
- b.X = Mathf.Lerp(b.X, pos.x, mix);
- b.Y = Mathf.Lerp(b.Y, pos.y, mix);
+ Vector3 pos = t.position;
+ pos = helper.InverseTransformPoint(pos);
+ b.X = Mathf.Lerp(b.X, pos.x, mix);
+ b.Y = Mathf.Lerp(b.Y, pos.y, mix);
- Vector3 right = helper.InverseTransformDirection(t.right);
+ Vector3 right = helper.InverseTransformDirection(t.right);
- float a = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
+ float a = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
- // MITCH
- //if (b.WorldFlipX ^ b.WorldFlipY) {
- // a *= -1;
- //}
-
- if (parentBone != null) {
- // MITCH
- //if ((b.WorldFlipX ^ b.WorldFlipY) != flip) {
- // a -= GetCompensatedRotationIK(parentBone) * 2;
+ // MITCH
+ //if (b.WorldFlipX ^ b.WorldFlipY) {
+ // a *= -1;
//}
+
+ if (parentBone != null) {
+ // MITCH
+ //if ((b.WorldFlipX ^ b.WorldFlipY) != flip) {
+ // a -= GetCompensatedRotationIK(parentBone) * 2;
+ //}
+ }
+
+ b.Rotation = Mathf.Lerp(b.Rotation, a, mix);
+ // MITCH
+ // b.RotationIK = Mathf.Lerp(b.rotationIK, a, mix);
+ }
+ }
+
+ float GetCompensatedRotationIK (Bone b) {
+ Bone parent = b.Parent;
+ // MITCH
+ float a = b.AppliedRotation;
+ while (parent != null) {
+ a += parent.AppliedRotation;
+ parent = parent.parent;
}
- b.Rotation = Mathf.Lerp(b.Rotation, a, mix);
- // MITCH
- // b.RotationIK = Mathf.Lerp(b.rotationIK, a, mix);
+ return a;
}
}
- float GetCompensatedRotationIK (Bone b) {
- Bone parent = b.Parent;
- // MITCH
- float a = b.AppliedRotation;
- while (parent != null) {
- a += parent.AppliedRotation;
- parent = parent.parent;
- }
-
- return a;
- }
}
diff --git a/spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs b/spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs
index b0dca43b0..79a3d6f6a 100644
--- a/spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs
+++ b/spine-unity/Assets/spine-unity/Modules/Ragdoll/SkeletonRagdoll2D.cs
@@ -6,432 +6,427 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
-using Spine;
+using Spine.Unity;
-[RequireComponent(typeof(SkeletonRenderer))]
-public class SkeletonRagdoll2D : MonoBehaviour {
- private static Transform helper;
+namespace Spine.Unity.Modules {
+ [RequireComponent(typeof(SkeletonRenderer))]
+ public class SkeletonRagdoll2D : MonoBehaviour {
+ private static Transform helper;
- [Header("Hierarchy")]
- [SpineBone]
- public string startingBoneName = "";
- [SpineBone]
- public List stopBoneNames = new List();
+ [Header("Hierarchy")]
+ [SpineBone]
+ public string startingBoneName = "";
+ [SpineBone]
+ public List stopBoneNames = new List();
- [Header("Parameters")]
- public bool applyOnStart;
- [Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
- public bool pinStartBone;
- public float gravityScale = 1;
- [Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
- public bool disableIK = true;
- [Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
- public float thickness = 0.125f;
- [Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")]
- public float rotationLimit = 20;
- public float rootMass = 20;
- [Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
- [Range(0.01f, 1f)]
- public float massFalloffFactor = 0.4f;
- [Tooltip("The layer assigned to all of the rigidbody parts.")]
- public int colliderLayer = 0;
- [Range(0, 1)]
- public float mix = 1;
+ [Header("Parameters")]
+ public bool applyOnStart;
+ [Tooltip("Set RootRigidbody IsKinematic to true when Apply is called.")]
+ public bool pinStartBone;
+ public float gravityScale = 1;
+ [Tooltip("Warning! You will have to re-enable and tune mix values manually if attempting to remove the ragdoll system.")]
+ public bool disableIK = true;
+ [Tooltip("If no BoundingBox Attachment is attached to a bone, this becomes the default Width or Radius of a Bone's ragdoll Rigidbody")]
+ public float thickness = 0.125f;
+ [Tooltip("Default rotational limit value. Min is negative this value, Max is this value.")]
+ public float rotationLimit = 20;
+ public float rootMass = 20;
+ [Tooltip("If your ragdoll seems unstable or uneffected by limits, try lowering this value.")]
+ [Range(0.01f, 1f)]
+ public float massFalloffFactor = 0.4f;
+ [Tooltip("The layer assigned to all of the rigidbody parts.")]
+ public int colliderLayer = 0;
+ [Range(0, 1)]
+ public float mix = 1;
- public Rigidbody2D RootRigidbody {
- get {
- return this.rootRigidbody;
- }
- }
-
- public Vector3 RootOffset {
- get {
- return this.rootOffset;
- }
- }
-
- public Vector3 EstimatedSkeletonPosition {
- get {
- return this.rootRigidbody.position - rootOffset;
- }
- }
-
- public bool IsActive {
- get {
- return this.isActive;
- }
- }
-
- private Rigidbody2D rootRigidbody;
- private ISkeletonAnimation skeletonAnim;
- private Skeleton skeleton;
- private Dictionary boneTable = new Dictionary();
- private Bone startingBone;
- private Transform ragdollRoot;
- private Vector2 rootOffset;
- private bool isActive;
-
-
- IEnumerator Start () {
- skeletonAnim = (ISkeletonAnimation)GetComponent();
- if (helper == null) {
- helper = (Transform)(new GameObject("Helper")).transform;
- helper.hideFlags = HideFlags.HideInHierarchy;
+ public Rigidbody2D RootRigidbody {
+ get { return this.rootRigidbody; }
}
- if (applyOnStart) {
- yield return null;
- Apply();
- }
- }
-
- public Coroutine SmoothMix (float target, float duration) {
- return StartCoroutine(SmoothMixCoroutine(target, duration));
- }
-
- IEnumerator SmoothMixCoroutine (float target, float duration) {
- float startTime = Time.time;
- float startMix = mix;
- while (mix > 0) {
- mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
- yield return null;
- }
- }
-
- public void SetSkeletonPosition (Vector3 worldPosition) {
- if (!isActive) {
- Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
- return;
+ public Vector3 RootOffset {
+ get { return this.rootOffset; }
}
- Vector3 offset = worldPosition - transform.position;
- transform.position = worldPosition;
- foreach (Transform t in boneTable.Values) {
- t.position -= offset;
+ public Vector3 EstimatedSkeletonPosition {
+ get { return this.rootRigidbody.position - rootOffset; }
}
- UpdateWorld(null);
- skeleton.UpdateWorldTransform();
- }
-
- public Rigidbody2D[] GetRigidbodyArray () {
- if (!isActive)
- return new Rigidbody2D[0];
-
- Rigidbody2D[] arr = new Rigidbody2D[boneTable.Count];
- int i = 0;
- foreach (Transform t in boneTable.Values) {
- arr[i] = t.GetComponent();
- i++;
+ public bool IsActive {
+ get { return this.isActive; }
}
- return arr;
- }
+ private Rigidbody2D rootRigidbody;
+ private ISkeletonAnimation skeletonAnim;
+ private Skeleton skeleton;
+ private Dictionary boneTable = new Dictionary();
+ private Bone startingBone;
+ private Transform ragdollRoot;
+ private Vector2 rootOffset;
+ private bool isActive;
+
+
+ IEnumerator Start () {
+ skeletonAnim = (ISkeletonAnimation)GetComponent();
+ if (helper == null) {
+ helper = (Transform)(new GameObject("Helper")).transform;
+ helper.hideFlags = HideFlags.HideInHierarchy;
+ }
+
+ if (applyOnStart) {
+ yield return null;
+ Apply();
+ }
+ }
+
+ public Coroutine SmoothMix (float target, float duration) {
+ return StartCoroutine(SmoothMixCoroutine(target, duration));
+ }
+
+ IEnumerator SmoothMixCoroutine (float target, float duration) {
+ float startTime = Time.time;
+ float startMix = mix;
+ while (mix > 0) {
+ mix = Mathf.SmoothStep(startMix, target, (Time.time - startTime) / duration);
+ yield return null;
+ }
+ }
+
+ public void SetSkeletonPosition (Vector3 worldPosition) {
+ if (!isActive) {
+ Debug.LogWarning("Can't call SetSkeletonPosition while Ragdoll is not active!");
+ return;
+ }
+
+ Vector3 offset = worldPosition - transform.position;
+ transform.position = worldPosition;
+ foreach (Transform t in boneTable.Values) {
+ t.position -= offset;
+ }
+
+ UpdateWorld(null);
+ skeleton.UpdateWorldTransform();
+ }
+
+ public Rigidbody2D[] GetRigidbodyArray () {
+ if (!isActive)
+ return new Rigidbody2D[0];
+
+ Rigidbody2D[] arr = new Rigidbody2D[boneTable.Count];
+ int i = 0;
+ foreach (Transform t in boneTable.Values) {
+ arr[i] = t.GetComponent();
+ i++;
+ }
+
+ return arr;
+ }
+
+ public Rigidbody2D GetRigidbody (string boneName) {
+ var bone = skeleton.FindBone(boneName);
+ if (bone == null)
+ return null;
+
+ if (boneTable.ContainsKey(bone))
+ return boneTable[bone].GetComponent();
- public Rigidbody2D GetRigidbody (string boneName) {
- var bone = skeleton.FindBone(boneName);
- if (bone == null)
return null;
-
- if (boneTable.ContainsKey(bone))
- return boneTable[bone].GetComponent();
-
- return null;
- }
-
- public void Remove () {
- isActive = false;
- foreach (var t in boneTable.Values) {
- Destroy(t.gameObject);
}
- Destroy(ragdollRoot.gameObject);
- boneTable.Clear();
- skeletonAnim.UpdateWorld -= UpdateWorld;
- }
+ public void Remove () {
+ isActive = false;
+ foreach (var t in boneTable.Values) {
+ Destroy(t.gameObject);
+ }
+ Destroy(ragdollRoot.gameObject);
- public void Apply () {
- isActive = true;
- skeleton = skeletonAnim.Skeleton;
- mix = 1;
+ boneTable.Clear();
+ skeletonAnim.UpdateWorld -= UpdateWorld;
+ }
- var ragdollRootBone = skeleton.FindBone(startingBoneName);
- startingBone = ragdollRootBone;
- RecursivelyCreateBoneProxies(ragdollRootBone);
+ public void Apply () {
+ isActive = true;
+ skeleton = skeletonAnim.Skeleton;
+ mix = 1;
- rootRigidbody = boneTable[ragdollRootBone].GetComponent();
- rootRigidbody.isKinematic = pinStartBone;
- rootRigidbody.mass = rootMass;
+ var ragdollRootBone = skeleton.FindBone(startingBoneName);
+ startingBone = ragdollRootBone;
+ RecursivelyCreateBoneProxies(ragdollRootBone);
- List boneColliders = new List();
+ rootRigidbody = boneTable[ragdollRootBone].GetComponent();
+ rootRigidbody.isKinematic = pinStartBone;
+ rootRigidbody.mass = rootMass;
- foreach (var pair in boneTable) {
- var b = pair.Key;
- var t = pair.Value;
- Bone parentBone = null;
- Transform parentTransform = transform;
+ List boneColliders = new List();
- boneColliders.Add(t.GetComponent());
+ foreach (var pair in boneTable) {
+ var b = pair.Key;
+ var t = pair.Value;
+ Bone parentBone = null;
+ Transform parentTransform = transform;
- if (b != startingBone) {
- parentBone = b.Parent;
- parentTransform = boneTable[parentBone];
- } else {
- ragdollRoot = new GameObject("RagdollRoot").transform;
- ragdollRoot.parent = transform;
+ boneColliders.Add(t.GetComponent());
- if (b == skeleton.RootBone) {
- ragdollRoot.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
- ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b));
- parentTransform = ragdollRoot;
+ if (b != startingBone) {
+ parentBone = b.Parent;
+ parentTransform = boneTable[parentBone];
} else {
- ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
- ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b.Parent));
- parentTransform = ragdollRoot;
+ ragdollRoot = new GameObject("RagdollRoot").transform;
+ ragdollRoot.parent = transform;
+
+ if (b == skeleton.RootBone) {
+ ragdollRoot.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
+ ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b));
+ parentTransform = ragdollRoot;
+ } else {
+ ragdollRoot.localPosition = new Vector3(b.Parent.WorldX, b.Parent.WorldY, 0);
+ ragdollRoot.localRotation = Quaternion.Euler(0, 0, GetCompensatedRotationIK(b.Parent));
+ parentTransform = ragdollRoot;
+ }
+
+ rootOffset = t.position - transform.position;
}
- rootOffset = t.position - transform.position;
- }
+ var rbParent = parentTransform.GetComponent();
- var rbParent = parentTransform.GetComponent();
-
- if (rbParent != null) {
- var joint = t.gameObject.AddComponent();
- joint.connectedBody = rbParent;
- Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
- localPos.x *= 1;
- joint.connectedAnchor = localPos;
- joint.GetComponent().mass = joint.connectedBody.mass * massFalloffFactor;
- JointAngleLimits2D limits = new JointAngleLimits2D();
- limits.min = -rotationLimit;
- limits.max = rotationLimit;
- joint.limits = limits;
- joint.useLimits = true;
- }
- }
-
- for (int x = 0; x < boneColliders.Count; x++) {
- for (int y = 0; y < boneColliders.Count; y++) {
- if (x == y) continue;
- Physics2D.IgnoreCollision(boneColliders[x], boneColliders[y]);
- }
- }
-
- var utilityBones = GetComponentsInChildren();
- if (utilityBones.Length > 0) {
- List destroyedUtilityBoneNames = new List();
- foreach (var ub in utilityBones) {
- if (ub.mode == SkeletonUtilityBone.Mode.Override) {
- destroyedUtilityBoneNames.Add(ub.gameObject.name);
- Destroy(ub.gameObject);
+ if (rbParent != null) {
+ var joint = t.gameObject.AddComponent();
+ joint.connectedBody = rbParent;
+ Vector3 localPos = parentTransform.InverseTransformPoint(t.position);
+ localPos.x *= 1;
+ joint.connectedAnchor = localPos;
+ joint.GetComponent().mass = joint.connectedBody.mass * massFalloffFactor;
+ JointAngleLimits2D limits = new JointAngleLimits2D();
+ limits.min = -rotationLimit;
+ limits.max = rotationLimit;
+ joint.limits = limits;
+ joint.useLimits = true;
}
}
- if (destroyedUtilityBoneNames.Count > 0) {
- string msg = "Destroyed Utility Bones: ";
- for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
- msg += destroyedUtilityBoneNames[i];
- if (i != destroyedUtilityBoneNames.Count - 1) {
- msg += ",";
+ for (int x = 0; x < boneColliders.Count; x++) {
+ for (int y = 0; y < boneColliders.Count; y++) {
+ if (x == y) continue;
+ Physics2D.IgnoreCollision(boneColliders[x], boneColliders[y]);
+ }
+ }
+
+ var utilityBones = GetComponentsInChildren();
+ if (utilityBones.Length > 0) {
+ List destroyedUtilityBoneNames = new List();
+ foreach (var ub in utilityBones) {
+ if (ub.mode == SkeletonUtilityBone.Mode.Override) {
+ destroyedUtilityBoneNames.Add(ub.gameObject.name);
+ Destroy(ub.gameObject);
}
}
- Debug.LogWarning(msg);
+
+ if (destroyedUtilityBoneNames.Count > 0) {
+ string msg = "Destroyed Utility Bones: ";
+ for (int i = 0; i < destroyedUtilityBoneNames.Count; i++) {
+ msg += destroyedUtilityBoneNames[i];
+ if (i != destroyedUtilityBoneNames.Count - 1) {
+ msg += ",";
+ }
+ }
+ Debug.LogWarning(msg);
+ }
+ }
+
+ if (disableIK) {
+ foreach (IkConstraint ik in skeleton.IkConstraints) {
+ ik.Mix = 0;
+ }
+ }
+
+ skeletonAnim.UpdateWorld += UpdateWorld;
+ }
+
+ void RecursivelyCreateBoneProxies (Bone b) {
+ if (stopBoneNames.Contains(b.Data.Name))
+ return;
+
+ GameObject go = new GameObject(b.Data.Name);
+ go.layer = colliderLayer;
+ Transform t = go.transform;
+ boneTable.Add(b, t);
+
+ t.parent = transform;
+
+ t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
+ //TODO: deal with WorldFlipY
+ // MITCH
+ // t.localRotation = Quaternion.Euler(0, 0, b.WorldFlipX ? -b.WorldRotation : b.WorldRotation);
+ t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX);
+ t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 0);
+
+ float length = b.Data.Length;
+
+ //TODO proper ragdoll branching
+ var colliders = AttachBoundingBoxRagdollColliders(b);
+
+ if (length == 0) {
+ //physics
+ if (colliders.Count == 0) {
+ var circle = go.AddComponent();
+ circle.radius = thickness / 2f;
+ }
+ } else {
+ //physics
+ if (colliders.Count == 0) {
+ var box = go.AddComponent();
+ box.size = new Vector2(length, thickness);
+ #if UNITY_5
+ // MITCH
+ // box.offset = new Vector2((b.WorldFlipX ? -length : length) / 2, 0);
+ box.offset = new Vector2(length / 2, 0);
+ #else
+ //box.center = new Vector2((b.WorldFlipX ? -length : length) / 2, 0);
+ box.center = new Vector2(length/2, 0);
+ #endif
+ }
+ }
+
+ var rb = go.AddComponent();
+ rb.gravityScale = gravityScale;
+
+ foreach (Bone child in b.Children) {
+ RecursivelyCreateBoneProxies(child);
}
}
- if (disableIK) {
- foreach (IkConstraint ik in skeleton.IkConstraints) {
- ik.Mix = 0;
- }
- }
+ List AttachBoundingBoxRagdollColliders (Bone b) {
+ List colliders = new List();
+ Transform t = boneTable[b];
+ GameObject go = t.gameObject;
+ var skin = skeleton.Skin;
+ if (skin == null)
+ skin = skeleton.Data.DefaultSkin;
- skeletonAnim.UpdateWorld += UpdateWorld;
- }
+ // MITCH
+ // bool flipX = b.WorldFlipX;
+ // bool flipY = b.WorldFlipY;
+ bool flipX = false;
+ bool flipY = false;
- void RecursivelyCreateBoneProxies (Bone b) {
- if (stopBoneNames.Contains(b.Data.Name))
- return;
+ List attachments = new List();
+ foreach (Slot s in skeleton.Slots) {
+ if (s.Bone == b) {
+ skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(s), attachments);
+ foreach (var a in attachments) {
+ if (a is BoundingBoxAttachment) {
+ if (!a.Name.ToLower().Contains("ragdoll"))
+ continue;
- GameObject go = new GameObject(b.Data.Name);
- go.layer = colliderLayer;
- Transform t = go.transform;
- boneTable.Add(b, t);
+ var collider = SkeletonUtility.AddBoundingBoxAsComponent((BoundingBoxAttachment)a, go, false);
- t.parent = transform;
+ if (flipX || flipY) {
+ Vector2[] points = collider.points;
- t.localPosition = new Vector3(b.WorldX, b.WorldY, 0);
- //TODO: deal with WorldFlipY
- // MITCH
- // t.localRotation = Quaternion.Euler(0, 0, b.WorldFlipX ? -b.WorldRotation : b.WorldRotation);
- t.localRotation = Quaternion.Euler(0, 0, b.WorldRotationX);
- t.localScale = new Vector3(b.WorldScaleX, b.WorldScaleY, 0);
+ for (int i = 0; i < points.Length; i++) {
+ if (flipX)
+ points[i].x *= -1;
- float length = b.Data.Length;
+ if (flipY)
+ points[i].y *= -1;
+ }
- //TODO proper ragdoll branching
- var colliders = AttachBoundingBoxRagdollColliders(b);
-
- if (length == 0) {
- //physics
- if (colliders.Count == 0) {
- var circle = go.AddComponent();
- circle.radius = thickness / 2f;
- }
- } else {
- //physics
- if (colliders.Count == 0) {
- var box = go.AddComponent();
- box.size = new Vector2(length, thickness);
-#if UNITY_5
- // MITCH
- // box.offset = new Vector2((b.WorldFlipX ? -length : length) / 2, 0);
- box.offset = new Vector2(length / 2, 0);
-#else
- //box.center = new Vector2((b.WorldFlipX ? -length : length) / 2, 0);
- box.center = new Vector2(length/2, 0);
-#endif
- }
- }
-
- var rb = go.AddComponent();
- rb.gravityScale = gravityScale;
-
- foreach (Bone child in b.Children) {
- RecursivelyCreateBoneProxies(child);
- }
- }
-
- List AttachBoundingBoxRagdollColliders (Bone b) {
- List colliders = new List();
- Transform t = boneTable[b];
- GameObject go = t.gameObject;
- var skin = skeleton.Skin;
- if (skin == null)
- skin = skeleton.Data.DefaultSkin;
-
- // MITCH
- // bool flipX = b.WorldFlipX;
- // bool flipY = b.WorldFlipY;
- bool flipX = false;
- bool flipY = false;
-
- List attachments = new List();
- foreach (Slot s in skeleton.Slots) {
- if (s.Bone == b) {
- skin.FindAttachmentsForSlot(skeleton.Slots.IndexOf(s), attachments);
- foreach (var a in attachments) {
- if (a is BoundingBoxAttachment) {
- if (!a.Name.ToLower().Contains("ragdoll"))
- continue;
-
- var collider = SkeletonUtility.AddBoundingBoxAsComponent((BoundingBoxAttachment)a, go, false);
-
- if (flipX || flipY) {
- Vector2[] points = collider.points;
-
- for (int i = 0; i < points.Length; i++) {
- if (flipX)
- points[i].x *= -1;
-
- if (flipY)
- points[i].y *= -1;
+ collider.points = points;
}
- collider.points = points;
+ colliders.Add(collider);
}
-
- colliders.Add(collider);
}
}
}
+
+ return colliders;
}
- return colliders;
- }
+ void UpdateWorld (ISkeletonAnimation skeletonRenderer) {
+ foreach (var pair in boneTable) {
+ var b = pair.Key;
+ var t = pair.Value;
+ //bool flip = false;
+ bool flipX = false; //TODO: deal with negative scale instead of Flip Key
+ bool flipY = false; //TODO: deal with negative scale instead of Flip Key
+ Bone parentBone = null;
+ Transform parentTransform = transform;
- void UpdateWorld (ISkeletonAnimation skeletonRenderer) {
- foreach (var pair in boneTable) {
- var b = pair.Key;
- var t = pair.Value;
- //bool flip = false;
- bool flipX = false; //TODO: deal with negative scale instead of Flip Key
- bool flipY = false; //TODO: deal with negative scale instead of Flip Key
- Bone parentBone = null;
- Transform parentTransform = transform;
+ if (b != startingBone) {
+ parentBone = b.Parent;
+ parentTransform = boneTable[parentBone];
+ // MITCH
+ // flipX = parentBone.WorldFlipX;
+ // flipY = parentBone.WorldFlipY;
- if (b != startingBone) {
- parentBone = b.Parent;
- parentTransform = boneTable[parentBone];
- // MITCH
- // flipX = parentBone.WorldFlipX;
- // flipY = parentBone.WorldFlipY;
-
- } else {
- parentBone = b.Parent;
- parentTransform = ragdollRoot;
- if (b.Parent != null) {
- // MITCH
- // flipX = b.worldFlipX;
- // flipY = b.WorldFlipY;
} else {
- flipX = b.Skeleton.FlipX;
- flipY = b.Skeleton.FlipY;
+ parentBone = b.Parent;
+ parentTransform = ragdollRoot;
+ if (b.Parent != null) {
+ // MITCH
+ // flipX = b.worldFlipX;
+ // flipY = b.WorldFlipY;
+ } else {
+ flipX = b.Skeleton.FlipX;
+ flipY = b.Skeleton.FlipY;
+ }
}
- }
- //flip = flipX ^ flipY;
+ //flip = flipX ^ flipY;
- helper.position = parentTransform.position;
- helper.rotation = parentTransform.rotation;
- helper.localScale = new Vector3(flipX ? -parentTransform.localScale.x : parentTransform.localScale.x, flipY ? -parentTransform.localScale.y : parentTransform.localScale.y, 1);
+ helper.position = parentTransform.position;
+ helper.rotation = parentTransform.rotation;
+ helper.localScale = new Vector3(flipX ? -parentTransform.localScale.x : parentTransform.localScale.x, flipY ? -parentTransform.localScale.y : parentTransform.localScale.y, 1);
- Vector3 pos = t.position;
- pos = helper.InverseTransformPoint(pos);
- b.X = Mathf.Lerp(b.X, pos.x, mix);
- b.Y = Mathf.Lerp(b.Y, pos.y, mix);
+ Vector3 pos = t.position;
+ pos = helper.InverseTransformPoint(pos);
+ b.X = Mathf.Lerp(b.X, pos.x, mix);
+ b.Y = Mathf.Lerp(b.Y, pos.y, mix);
- Vector3 right = helper.InverseTransformDirection(t.right);
+ Vector3 right = helper.InverseTransformDirection(t.right);
- float a = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
+ float a = Mathf.Atan2(right.y, right.x) * Mathf.Rad2Deg;
- // MITCH
- //if (b.WorldFlipX ^ b.WorldFlipY) {
- // a *= -1;
- //}
-
- if (parentBone != null) {
- // MITCH
- //if ((b.WorldFlipX ^ b.WorldFlipY) != flip) {
- // a -= GetCompensatedRotationIK(parentBone) * 2;
+ // MITCH
+ //if (b.WorldFlipX ^ b.WorldFlipY) {
+ // a *= -1;
//}
+
+ if (parentBone != null) {
+ // MITCH
+ //if ((b.WorldFlipX ^ b.WorldFlipY) != flip) {
+ // a -= GetCompensatedRotationIK(parentBone) * 2;
+ //}
+ }
+
+ b.Rotation = Mathf.Lerp(b.Rotation, a, mix);
+ // MITCH
+ // b.RotationIK = Mathf.Lerp(b.rotationIK, a, mix);
+ }
+ }
+
+ float GetCompensatedRotationIK (Bone b) {
+ Bone parent = b.Parent;
+ // MITCH
+ float a = b.AppliedRotation;
+ while (parent != null) {
+ a += parent.AppliedRotation;
+ parent = parent.parent;
}
- b.Rotation = Mathf.Lerp(b.Rotation, a, mix);
- // MITCH
- // b.RotationIK = Mathf.Lerp(b.rotationIK, a, mix);
- }
- }
-
- float GetCompensatedRotationIK (Bone b) {
- Bone parent = b.Parent;
- // MITCH
- float a = b.AppliedRotation;
- while (parent != null) {
- a += parent.AppliedRotation;
- parent = parent.parent;
+ return a;
}
- return a;
- }
-
- void OnDrawGizmosSelected () {
- if (isActive) {
- Gizmos.DrawWireSphere(transform.position, thickness * 1.2f);
- Vector3 newTransformPos = rootRigidbody.position - rootOffset;
- Gizmos.DrawLine(transform.position, newTransformPos);
- Gizmos.DrawWireSphere(newTransformPos, thickness * 1.2f);
+ void OnDrawGizmosSelected () {
+ if (isActive) {
+ Gizmos.DrawWireSphere(transform.position, thickness * 1.2f);
+ Vector3 newTransformPos = rootRigidbody.position - rootOffset;
+ Gizmos.DrawLine(transform.position, newTransformPos);
+ Gizmos.DrawWireSphere(newTransformPos, thickness * 1.2f);
+ }
}
+
}
}
diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs
index 15db2ef77..e2b531a5c 100644
--- a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs
+++ b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonPartsRendererInspector.cs
@@ -1,9 +1,38 @@
-using UnityEngine;
-using System.Collections;
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ *
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ *
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+using UnityEngine;
using UnityEditor;
-using Spine.Unity;
+using Spine.Unity.Editor;
-namespace Spine.Unity.Editor {
+namespace Spine.Unity.Modules {
[CustomEditor(typeof(SkeletonPartsRenderer))]
public class SkeletonRenderPartInspector : UnityEditor.Editor {
SpineInspectorUtility.SerializedSortingProperties sortingProperties;
@@ -13,7 +42,6 @@ namespace Spine.Unity.Editor {
}
public override void OnInspectorGUI () {
- DrawDefaultInspector();
SpineInspectorUtility.SortingPropertyFields(sortingProperties, true);
}
}
diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs
index 95eb165f4..a8e75cf7f 100644
--- a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs
+++ b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/Editor/SkeletonRenderSeparatorInspector.cs
@@ -1,9 +1,40 @@
-using UnityEngine;
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ *
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ *
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+using UnityEngine;
using UnityEditor;
using Spine.Unity;
+using Spine.Unity.Editor;
-namespace Spine.Unity.Editor {
+namespace Spine.Unity.Modules {
[CustomEditor(typeof(SkeletonRenderSeparator))]
public class SkeletonRenderSeparatorInspector : UnityEditor.Editor {
diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonPartsRenderer.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonPartsRenderer.cs
index 273121195..d1822fd5a 100644
--- a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonPartsRenderer.cs
+++ b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonPartsRenderer.cs
@@ -1,8 +1,37 @@
-using UnityEngine;
-using System.Collections;
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ *
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ *
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+using UnityEngine;
using Spine.Unity.MeshGeneration;
-namespace Spine.Unity {
+namespace Spine.Unity.Modules {
[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
public class SkeletonPartsRenderer : MonoBehaviour {
diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs
index 29bee2a67..6852f7a77 100644
--- a/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs
+++ b/spine-unity/Assets/spine-unity/Modules/SkeletonRenderSeparator/SkeletonRenderSeparator.cs
@@ -1,9 +1,38 @@
-using UnityEngine;
-using System.Collections;
+/******************************************************************************
+ * Spine Runtimes Software License
+ * Version 2.3
+ *
+ * Copyright (c) 2013-2015, Esoteric Software
+ * All rights reserved.
+ *
+ * You are granted a perpetual, non-exclusive, non-sublicensable and
+ * non-transferable license to use, install, execute and perform the Spine
+ * Runtimes Software (the "Software") and derivative works solely for personal
+ * or internal use. Without the written permission of Esoteric Software (see
+ * Section 2 of the Spine Software License Agreement), you may not (a) modify,
+ * translate, adapt or otherwise create derivative works, improvements of the
+ * Software or develop new applications using the Software or (b) remove,
+ * delete, alter or obscure any trademarks or any copyright, trademark, patent
+ * or other intellectual property or proprietary rights notices on or in the
+ * Software, including any copy thereof. Redistributions in binary or source
+ * form must include this license and terms.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+using UnityEngine;
using System.Collections.Generic;
using Spine.Unity;
-namespace Spine.Unity {
+namespace Spine.Unity.Modules {
[ExecuteInEditMode]
[HelpURL("https://github.com/pharan/spine-unity-docs/blob/master/SkeletonRenderSeparator.md")]
@@ -28,7 +57,7 @@ namespace Spine.Unity {
public bool copyPropertyBlock = false;
[Tooltip("Copies MeshRenderer flags into ")]
public bool copyMeshRendererFlags = false;
- public List partsRenderers = new List();
+ public List partsRenderers = new List();
#if UNITY_EDITOR
void Reset () {
diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityEyeConstraint.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityEyeConstraint.cs
index 7b0e81430..f7c2714c5 100644
--- a/spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityEyeConstraint.cs
+++ b/spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityEyeConstraint.cs
@@ -32,56 +32,57 @@
using UnityEngine;
using System.Collections;
-public class SkeletonUtilityEyeConstraint : SkeletonUtilityConstraint {
+namespace Spine.Unity.Modules {
+ public class SkeletonUtilityEyeConstraint : SkeletonUtilityConstraint {
+ public Transform[] eyes;
+ public float radius = 0.5f;
+ public Transform target;
+ public Vector3 targetPosition;
+ public float speed = 10;
+ Vector3[] origins;
+ Vector3 centerPoint;
- 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;
- protected override void OnEnable () {
- if (!Application.isPlaying)
- return;
+ base.OnEnable();
- 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]);
+ }
- Bounds centerBounds = new Bounds(eyes[0].localPosition, Vector3.zero);
- origins = new Vector3[eyes.Length];
- for (int i = 0; i < eyes.Length; i++) {
- origins[i] = eyes[i].localPosition;
- centerBounds.Encapsulate(origins[i]);
+ centerPoint = centerBounds.center;
}
- centerPoint = centerBounds.center;
- }
+ protected override void OnDisable () {
+ if (!Application.isPlaying)
+ return;
- protected override void OnDisable () {
- if (!Application.isPlaying)
- return;
-
- base.OnDisable();
- }
-
- 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);
+ 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);
+ }
+
+ }
}
}
diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityGroundConstraint.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityGroundConstraint.cs
index 2b8837eac..a60182e3f 100644
--- a/spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityGroundConstraint.cs
+++ b/spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityGroundConstraint.cs
@@ -32,121 +32,124 @@
using UnityEngine;
using System.Collections;
-[RequireComponent(typeof(SkeletonUtilityBone)), ExecuteInEditMode]
-public class SkeletonUtilityGroundConstraint : SkeletonUtilityConstraint {
+namespace Spine.Unity.Modules {
+ [RequireComponent(typeof(SkeletonUtilityBone)), ExecuteInEditMode]
+ public class SkeletonUtilityGroundConstraint : SkeletonUtilityConstraint {
-#if UNITY_4_3
- public LayerMask groundMask;
- public bool use2D = false;
- public bool useRadius = false;
- public float castRadius = 0.1f;
- public float castDistance = 5f;
- public float castOffset = 0;
- public float groundOffset = 0;
- public float adjustSpeed = 5;
-#else
- [Tooltip("LayerMask for what objects to raycast against")]
- public LayerMask groundMask;
- [Tooltip("The 2D")]
- public bool use2D = false;
- [Tooltip("Uses SphereCast for 3D mode and CircleCast for 2D mode")]
- public bool useRadius = false;
- [Tooltip("The Radius")]
- public float castRadius = 0.1f;
- [Tooltip("How high above the target bone to begin casting from")]
- public float castDistance = 5f;
- [Tooltip("X-Axis adjustment")]
- public float castOffset = 0;
- [Tooltip("Y-Axis adjustment")]
- public float groundOffset = 0;
- [Tooltip("How fast the target IK position adjusts to the ground. Use smaller values to prevent snapping")]
- public float adjustSpeed = 5;
-#endif
+ #if UNITY_4_3
+ public LayerMask groundMask;
+ public bool use2D = false;
+ public bool useRadius = false;
+ public float castRadius = 0.1f;
+ public float castDistance = 5f;
+ public float castOffset = 0;
+ public float groundOffset = 0;
+ public float adjustSpeed = 5;
+ #else
+ [Tooltip("LayerMask for what objects to raycast against")]
+ public LayerMask groundMask;
+ [Tooltip("The 2D")]
+ public bool use2D = false;
+ [Tooltip("Uses SphereCast for 3D mode and CircleCast for 2D mode")]
+ public bool useRadius = false;
+ [Tooltip("The Radius")]
+ public float castRadius = 0.1f;
+ [Tooltip("How high above the target bone to begin casting from")]
+ public float castDistance = 5f;
+ [Tooltip("X-Axis adjustment")]
+ public float castOffset = 0;
+ [Tooltip("Y-Axis adjustment")]
+ public float groundOffset = 0;
+ [Tooltip("How fast the target IK position adjusts to the ground. Use smaller values to prevent snapping")]
+ public float adjustSpeed = 5;
+ #endif
- Vector3 rayOrigin;
- Vector3 rayDir = new Vector3(0, -1, 0);
- float hitY;
- float lastHitY;
+ Vector3 rayOrigin;
+ Vector3 rayDir = new Vector3(0, -1, 0);
+ float hitY;
+ float lastHitY;
- protected override void OnEnable () {
- base.OnEnable();
- lastHitY = transform.position.y;
- }
-
- protected override void OnDisable () {
- base.OnDisable();
- }
-
- public override void DoUpdate () {
- rayOrigin = transform.position + new Vector3(castOffset, castDistance, 0);
-
- hitY = float.MinValue;
- if (use2D) {
- RaycastHit2D hit;
-
- if (useRadius) {
-#if UNITY_4_3
- //NOTE: Unity 4.3.x does not have CircleCast
- hit = Physics2D.Raycast(rayOrigin , rayDir, castDistance + groundOffset, groundMask);
-#else
- hit = Physics2D.CircleCast(rayOrigin, castRadius, rayDir, castDistance + groundOffset, groundMask);
-#endif
- } else {
- hit = Physics2D.Raycast(rayOrigin, rayDir, castDistance + groundOffset, groundMask);
- }
-
- if (hit.collider != null) {
- hitY = hit.point.y + groundOffset;
- if (Application.isPlaying) {
- hitY = Mathf.MoveTowards(lastHitY, hitY, adjustSpeed * Time.deltaTime);
- }
- } else {
- if (Application.isPlaying)
- hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustSpeed * Time.deltaTime);
- }
- } else {
- RaycastHit hit;
- bool validHit = false;
-
- if (useRadius) {
- validHit = Physics.SphereCast(rayOrigin, castRadius, rayDir, out hit, castDistance + groundOffset, groundMask);
- } else {
- validHit = Physics.Raycast(rayOrigin, rayDir, out hit, castDistance + groundOffset, groundMask);
- }
-
- if (validHit) {
- hitY = hit.point.y + groundOffset;
- if (Application.isPlaying) {
- hitY = Mathf.MoveTowards(lastHitY, hitY, adjustSpeed * Time.deltaTime);
- }
- } else {
- if (Application.isPlaying)
- hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustSpeed * Time.deltaTime);
- }
+ protected override void OnEnable () {
+ base.OnEnable();
+ lastHitY = transform.position.y;
}
- Vector3 v = transform.position;
- v.y = Mathf.Clamp(v.y, Mathf.Min(lastHitY, hitY), float.MaxValue);
- transform.position = v;
-
- utilBone.bone.X = transform.localPosition.x;
- utilBone.bone.Y = transform.localPosition.y;
-
- lastHitY = hitY;
- }
-
- void OnDrawGizmos () {
- Vector3 hitEnd = rayOrigin + (rayDir * Mathf.Min(castDistance, rayOrigin.y - hitY));
- Vector3 clearEnd = rayOrigin + (rayDir * castDistance);
- Gizmos.DrawLine(rayOrigin, hitEnd);
-
- if (useRadius) {
- Gizmos.DrawLine(new Vector3(hitEnd.x - castRadius, hitEnd.y - groundOffset, hitEnd.z), new Vector3(hitEnd.x + castRadius, hitEnd.y - groundOffset, hitEnd.z));
- Gizmos.DrawLine(new Vector3(clearEnd.x - castRadius, clearEnd.y, clearEnd.z), new Vector3(clearEnd.x + castRadius, clearEnd.y, clearEnd.z));
+ protected override void OnDisable () {
+ base.OnDisable();
}
- Gizmos.color = Color.red;
- Gizmos.DrawLine(hitEnd, clearEnd);
+ public override void DoUpdate () {
+ rayOrigin = transform.position + new Vector3(castOffset, castDistance, 0);
+
+ hitY = float.MinValue;
+ if (use2D) {
+ RaycastHit2D hit;
+
+ if (useRadius) {
+ #if UNITY_4_3
+ //NOTE: Unity 4.3.x does not have CircleCast
+ hit = Physics2D.Raycast(rayOrigin , rayDir, castDistance + groundOffset, groundMask);
+ #else
+ hit = Physics2D.CircleCast(rayOrigin, castRadius, rayDir, castDistance + groundOffset, groundMask);
+ #endif
+ } else {
+ hit = Physics2D.Raycast(rayOrigin, rayDir, castDistance + groundOffset, groundMask);
+ }
+
+ if (hit.collider != null) {
+ hitY = hit.point.y + groundOffset;
+ if (Application.isPlaying) {
+ hitY = Mathf.MoveTowards(lastHitY, hitY, adjustSpeed * Time.deltaTime);
+ }
+ } else {
+ if (Application.isPlaying)
+ hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustSpeed * Time.deltaTime);
+ }
+ } else {
+ RaycastHit hit;
+ bool validHit = false;
+
+ if (useRadius) {
+ validHit = Physics.SphereCast(rayOrigin, castRadius, rayDir, out hit, castDistance + groundOffset, groundMask);
+ } else {
+ validHit = Physics.Raycast(rayOrigin, rayDir, out hit, castDistance + groundOffset, groundMask);
+ }
+
+ if (validHit) {
+ hitY = hit.point.y + groundOffset;
+ if (Application.isPlaying) {
+ hitY = Mathf.MoveTowards(lastHitY, hitY, adjustSpeed * Time.deltaTime);
+ }
+ } else {
+ if (Application.isPlaying)
+ hitY = Mathf.MoveTowards(lastHitY, transform.position.y, adjustSpeed * Time.deltaTime);
+ }
+ }
+
+ Vector3 v = transform.position;
+ v.y = Mathf.Clamp(v.y, Mathf.Min(lastHitY, hitY), float.MaxValue);
+ transform.position = v;
+
+ utilBone.bone.X = transform.localPosition.x;
+ utilBone.bone.Y = transform.localPosition.y;
+
+ lastHitY = hitY;
+ }
+
+ void OnDrawGizmos () {
+ Vector3 hitEnd = rayOrigin + (rayDir * Mathf.Min(castDistance, rayOrigin.y - hitY));
+ Vector3 clearEnd = rayOrigin + (rayDir * castDistance);
+ Gizmos.DrawLine(rayOrigin, hitEnd);
+
+ if (useRadius) {
+ Gizmos.DrawLine(new Vector3(hitEnd.x - castRadius, hitEnd.y - groundOffset, hitEnd.z), new Vector3(hitEnd.x + castRadius, hitEnd.y - groundOffset, hitEnd.z));
+ Gizmos.DrawLine(new Vector3(clearEnd.x - castRadius, clearEnd.y, clearEnd.z), new Vector3(clearEnd.x + castRadius, clearEnd.y, clearEnd.z));
+ }
+
+ Gizmos.color = Color.red;
+ Gizmos.DrawLine(hitEnd, clearEnd);
+ }
}
+
}
diff --git a/spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityKinematicShadow.cs b/spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityKinematicShadow.cs
index 8f88297be..f1398b58e 100644
--- a/spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityKinematicShadow.cs
+++ b/spine-unity/Assets/spine-unity/Modules/SkeletonUtility Modules/SkeletonUtilityKinematicShadow.cs
@@ -30,85 +30,86 @@
*****************************************************************************/
using UnityEngine;
-using System.Collections;
using System.Collections.Generic;
-public class SkeletonUtilityKinematicShadow : MonoBehaviour {
- public bool hideShadow = true;
- public Transform parent;
- Dictionary shadowTable;
- GameObject shadowRoot;
+namespace Spine.Unity.Modules {
+ public class SkeletonUtilityKinematicShadow : MonoBehaviour {
+ public bool hideShadow = true;
+ public Transform parent;
+ Dictionary shadowTable;
+ GameObject shadowRoot;
- void Start () {
- shadowRoot = (GameObject)Instantiate(gameObject);
- if (hideShadow)
- shadowRoot.hideFlags = HideFlags.HideInHierarchy;
+ void Start () {
+ shadowRoot = (GameObject)Instantiate(gameObject);
+ if (hideShadow)
+ shadowRoot.hideFlags = HideFlags.HideInHierarchy;
- if (parent == null)
- shadowRoot.transform.parent = transform.root;
- else
- shadowRoot.transform.parent = parent;
+ if (parent == null)
+ shadowRoot.transform.parent = transform.root;
+ else
+ shadowRoot.transform.parent = parent;
- shadowTable = new Dictionary();
+ shadowTable = new Dictionary();
- Destroy(shadowRoot.GetComponent());
+ Destroy(shadowRoot.GetComponent());
- shadowRoot.transform.position = transform.position;
- shadowRoot.transform.rotation = transform.rotation;
+ shadowRoot.transform.position = transform.position;
+ shadowRoot.transform.rotation = transform.rotation;
- Vector3 scaleRef = transform.TransformPoint(Vector3.right);
- float scale = Vector3.Distance(transform.position, scaleRef);
- shadowRoot.transform.localScale = Vector3.one;
+ Vector3 scaleRef = transform.TransformPoint(Vector3.right);
+ float scale = Vector3.Distance(transform.position, scaleRef);
+ shadowRoot.transform.localScale = Vector3.one;
- var shadowJoints = shadowRoot.GetComponentsInChildren();
- foreach (Joint j in shadowJoints) {
- j.connectedAnchor *= scale;
- }
+ var shadowJoints = shadowRoot.GetComponentsInChildren();
+ foreach (Joint j in shadowJoints) {
+ j.connectedAnchor *= scale;
+ }
- var joints = GetComponentsInChildren();
- foreach (var j in joints)
- Destroy(j);
+ var joints = GetComponentsInChildren();
+ foreach (var j in joints)
+ Destroy(j);
- var rbs = GetComponentsInChildren();
- foreach (var rb in rbs)
- Destroy(rb);
+ var rbs = GetComponentsInChildren();
+ foreach (var rb in rbs)
+ Destroy(rb);
- var colliders = GetComponentsInChildren();
- foreach (var c in colliders)
- Destroy(c);
+ var colliders = GetComponentsInChildren();
+ foreach (var c in colliders)
+ Destroy(c);
- //match by bone name
- var shadowBones = shadowRoot.GetComponentsInChildren();
- var bones = GetComponentsInChildren();
+ //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.GetComponent() == null)
+ //build bone lookup
+ foreach (var b in bones) {
+ if (b.gameObject == gameObject)
continue;
- if (sb.boneName == b.boneName) {
- shadowTable.Add(sb.transform, b.transform);
- break;
+ foreach (var sb in shadowBones) {
+ if (sb.GetComponent() == null)
+ continue;
+
+ if (sb.boneName == b.boneName) {
+ shadowTable.Add(sb.transform, b.transform);
+ break;
+ }
}
}
+
+ foreach (var b in shadowBones)
+ Destroy(b);
}
- foreach (var b in shadowBones)
- Destroy(b);
- }
+ void FixedUpdate () {
+ shadowRoot.GetComponent().MovePosition(transform.position);
+ shadowRoot.GetComponent().MoveRotation(transform.rotation);
- void FixedUpdate () {
- shadowRoot.GetComponent().MovePosition(transform.position);
- shadowRoot.GetComponent().MoveRotation(transform.rotation);
-
- foreach (var pair in shadowTable) {
- pair.Value.localPosition = pair.Key.localPosition;
- pair.Value.localRotation = pair.Key.localRotation;
+ foreach (var pair in shadowTable) {
+ pair.Value.localPosition = pair.Key.localPosition;
+ pair.Value.localRotation = pair.Key.localRotation;
+ }
}
}
}
diff --git a/spine-unity/Assets/spine-unity/Modules/SpriteAttacher.cs b/spine-unity/Assets/spine-unity/Modules/SpriteAttacher.cs
index 8a6faed44..5f44696ca 100644
--- a/spine-unity/Assets/spine-unity/Modules/SpriteAttacher.cs
+++ b/spine-unity/Assets/spine-unity/Modules/SpriteAttacher.cs
@@ -30,170 +30,198 @@
*****************************************************************************/
using UnityEngine;
-using System.Collections;
using System.Collections.Generic;
using Spine;
-public class SpriteAttacher : MonoBehaviour {
+namespace Spine.Unity.Modules {
+ public class SpriteAttacher : MonoBehaviour {
+ public bool attachOnStart = true;
+ public bool keepLoaderInMemory = true;
+ public Sprite sprite;
- public bool attachOnStart = true;
- public bool keepLoaderInMemory = true;
+ [SpineSlot]
+ public string slot;
- public Sprite sprite;
+ private SpriteAttachmentLoader loader;
+ private RegionAttachment attachment;
- [SpineSlot]
- public string slot;
-
- private SpriteAttachmentLoader loader;
- private RegionAttachment attachment;
-
- void Start () {
- if (attachOnStart)
- Attach();
- }
-
- public void Attach () {
- var skeletonRenderer = GetComponent();
-
- if (loader == null)
- //create loader instance, tell it what sprite and shader to use
- loader = new SpriteAttachmentLoader(sprite, Shader.Find("Spine/Skeleton"));
-
- if (attachment == null)
- attachment = loader.NewRegionAttachment(null, sprite.name, "");
-
- skeletonRenderer.skeleton.FindSlot(slot).Attachment = attachment;
-
- if (!keepLoaderInMemory)
- loader = null;
- }
-}
-
-public class SpriteAttachmentLoader : AttachmentLoader {
-
- //TODO: Memory cleanup functions
-
- //IMPORTANT: Make sure you clear this when you don't need it anymore. Goodluck.
- public static Dictionary atlasTable = new Dictionary();
-
- //Shouldn't need to clear this, should just prevent redoing premultiply alpha pass on packed atlases
- public static List premultipliedAtlasIds = new List();
-
- Sprite sprite;
- Shader shader;
-
- public SpriteAttachmentLoader (Sprite sprite, Shader shader) {
-
- if (sprite.packed && sprite.packingMode == SpritePackingMode.Tight) {
- Debug.LogError("Tight Packer Policy not supported yet!");
- return;
+ void Start () {
+ if (attachOnStart)
+ Attach();
}
- this.sprite = sprite;
- this.shader = shader;
+ public void Attach () {
+ var skeletonRenderer = GetComponent();
- Texture2D tex = sprite.texture;
- //premultiply texture if it hasn't been yet
- int instanceId = tex.GetInstanceID();
- if (!premultipliedAtlasIds.Contains(instanceId)) {
- try {
- var colors = tex.GetPixels();
- Color c;
- float a;
- for (int i = 0; i < colors.Length; i++) {
- c = colors[i];
- a = c.a;
- c.r *= a;
- c.g *= a;
- c.b *= a;
- colors[i] = c;
+ if (loader == null)
+ //create loader instance, tell it what sprite and shader to use
+ loader = new SpriteAttachmentLoader(sprite, Shader.Find("Spine/Skeleton"));
+
+ if (attachment == null)
+ attachment = loader.NewRegionAttachment(null, sprite.name, "");
+
+ skeletonRenderer.skeleton.FindSlot(slot).Attachment = attachment;
+
+ if (!keepLoaderInMemory)
+ loader = null;
+ }
+ }
+
+ public class SpriteAttachmentLoader : AttachmentLoader {
+
+ //TODO: Memory cleanup functions
+
+ //IMPORTANT: Make sure you clear this when you don't need it anymore. Goodluck.
+ public static Dictionary atlasTable = new Dictionary();
+
+ //Shouldn't need to clear this, should just prevent redoing premultiply alpha pass on packed atlases
+ public static List premultipliedAtlasIds = new List();
+
+ Sprite sprite;
+ Shader shader;
+
+ public SpriteAttachmentLoader (Sprite sprite, Shader shader) {
+
+ if (sprite.packed && sprite.packingMode == SpritePackingMode.Tight) {
+ Debug.LogError("Tight Packer Policy not supported yet!");
+ return;
+ }
+
+ this.sprite = sprite;
+ this.shader = shader;
+
+ Texture2D tex = sprite.texture;
+ //premultiply texture if it hasn't been yet
+ int instanceId = tex.GetInstanceID();
+ if (!premultipliedAtlasIds.Contains(instanceId)) {
+ try {
+ var colors = tex.GetPixels();
+ Color c;
+ float a;
+ for (int i = 0; i < colors.Length; i++) {
+ c = colors[i];
+ a = c.a;
+ c.r *= a;
+ c.g *= a;
+ c.b *= a;
+ colors[i] = c;
+ }
+
+ tex.SetPixels(colors);
+ tex.Apply();
+
+ premultipliedAtlasIds.Add(instanceId);
+ } catch {
+ //texture is not readable! Can't pre-multiply it, you're on your own.
}
-
- tex.SetPixels(colors);
- tex.Apply();
-
- premultipliedAtlasIds.Add(instanceId);
- } catch {
- //texture is not readable! Can't pre-multiply it, you're on your own.
}
}
- }
- public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) {
- RegionAttachment attachment = new RegionAttachment(name);
+ public RegionAttachment NewRegionAttachment (Skin skin, string name, string path) {
+ RegionAttachment attachment = new RegionAttachment(name);
- Texture2D tex = sprite.texture;
- int instanceId = tex.GetInstanceID();
- AtlasRegion atlasRegion;
+ Texture2D tex = sprite.texture;
+ int instanceId = tex.GetInstanceID();
+ AtlasRegion atlasRegion;
- //check cache first
- if (atlasTable.ContainsKey(instanceId)) {
- atlasRegion = atlasTable[instanceId];
- } else {
- //Setup new material
- Material mat = new Material(shader);
+ //check cache first
+ if (atlasTable.ContainsKey(instanceId)) {
+ atlasRegion = atlasTable[instanceId];
+ } else {
+ //Setup new material
+ Material mat = new Material(shader);
+ if (sprite.packed)
+ mat.name = "Unity Packed Sprite Material";
+ else
+ mat.name = sprite.name + " Sprite Material";
+ mat.mainTexture = tex;
+
+ //create faux-region to play nice with SkeletonRenderer
+ atlasRegion = new AtlasRegion();
+ AtlasPage page = new AtlasPage();
+ page.rendererObject = mat;
+ atlasRegion.page = page;
+
+ //cache it
+ atlasTable[instanceId] = atlasRegion;
+ }
+
+ Rect texRect = sprite.textureRect;
+
+ //normalize rect to UV space of packed atlas
+ texRect.x = Mathf.InverseLerp(0, tex.width, texRect.x);
+ texRect.y = Mathf.InverseLerp(0, tex.height, texRect.y);
+ texRect.width = Mathf.InverseLerp(0, tex.width, texRect.width);
+ texRect.height = Mathf.InverseLerp(0, tex.height, texRect.height);
+
+ Bounds bounds = sprite.bounds;
+ Vector3 size = bounds.size;
+
+ //TODO: make sure this rotation thing actually works
+ bool rotated = false;
if (sprite.packed)
- mat.name = "Unity Packed Sprite Material";
- else
- mat.name = sprite.name + " Sprite Material";
- mat.mainTexture = tex;
+ rotated = sprite.packingRotation == SpritePackingRotation.Any;
- //create faux-region to play nice with SkeletonRenderer
- atlasRegion = new AtlasRegion();
- AtlasPage page = new AtlasPage();
- page.rendererObject = mat;
- atlasRegion.page = page;
+ //do some math and assign UVs and sizes
+ attachment.SetUVs(texRect.xMin, texRect.yMax, texRect.xMax, texRect.yMin, rotated);
+ attachment.RendererObject = atlasRegion;
+ attachment.SetColor(Color.white);
+ attachment.ScaleX = 1;
+ attachment.ScaleY = 1;
+ attachment.RegionOffsetX = sprite.rect.width * (0.5f - Mathf.InverseLerp(bounds.min.x, bounds.max.x, 0)) / sprite.pixelsPerUnit;
+ attachment.RegionOffsetY = sprite.rect.height * (0.5f - Mathf.InverseLerp(bounds.min.y, bounds.max.y, 0)) / sprite.pixelsPerUnit;
+ attachment.Width = size.x;
+ attachment.Height = size.y;
+ attachment.RegionWidth = size.x;
+ attachment.RegionHeight = size.y;
+ attachment.RegionOriginalWidth = size.x;
+ attachment.RegionOriginalHeight = size.y;
+ attachment.UpdateOffset();
- //cache it
- atlasTable[instanceId] = atlasRegion;
+ return attachment;
}
- Rect texRect = sprite.textureRect;
+ public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) {
+ //TODO: Unity 5 only
+ throw new System.NotImplementedException();
+ }
- //normalize rect to UV space of packed atlas
- texRect.x = Mathf.InverseLerp(0, tex.width, texRect.x);
- texRect.y = Mathf.InverseLerp(0, tex.height, texRect.y);
- texRect.width = Mathf.InverseLerp(0, tex.width, texRect.width);
- texRect.height = Mathf.InverseLerp(0, tex.height, texRect.height);
+ public WeightedMeshAttachment NewWeightedMeshAttachment(Skin skin, string name, string path) {
+ throw new System.NotImplementedException();
+ }
- Bounds bounds = sprite.bounds;
- Vector3 size = bounds.size;
-
- //TODO: make sure this rotation thing actually works
- bool rotated = false;
- if (sprite.packed)
- rotated = sprite.packingRotation == SpritePackingRotation.Any;
-
- //do some math and assign UVs and sizes
- attachment.SetUVs(texRect.xMin, texRect.yMax, texRect.xMax, texRect.yMin, rotated);
- attachment.RendererObject = atlasRegion;
- attachment.SetColor(Color.white);
- attachment.ScaleX = 1;
- attachment.ScaleY = 1;
- attachment.RegionOffsetX = sprite.rect.width * (0.5f - Mathf.InverseLerp(bounds.min.x, bounds.max.x, 0)) / sprite.pixelsPerUnit;
- attachment.RegionOffsetY = sprite.rect.height * (0.5f - Mathf.InverseLerp(bounds.min.y, bounds.max.y, 0)) / sprite.pixelsPerUnit;
- attachment.Width = size.x;
- attachment.Height = size.y;
- attachment.RegionWidth = size.x;
- attachment.RegionHeight = size.y;
- attachment.RegionOriginalWidth = size.x;
- attachment.RegionOriginalHeight = size.y;
- attachment.UpdateOffset();
-
- return attachment;
+ public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name) {
+ throw new System.NotImplementedException();
+ }
}
- public MeshAttachment NewMeshAttachment (Skin skin, string name, string path) {
- //TODO: Unity 5 only
- throw new System.NotImplementedException();
- }
+ public static class SpriteAttachmentExtensions {
+ public static Attachment AttachUnitySprite (this Skeleton skeleton, string slotName, Sprite sprite, string shaderName = "Spine/Skeleton") {
+ var att = sprite.ToRegionAttachment(shaderName);
+ skeleton.FindSlot(slotName).Attachment = att;
+ return att;
+ }
- public WeightedMeshAttachment NewWeightedMeshAttachment(Skin skin, string name, string path) {
- throw new System.NotImplementedException();
- }
+ public static Attachment AddUnitySprite (this SkeletonData skeletonData, string slotName, Sprite sprite, string skinName = "", string shaderName = "Spine/Skeleton") {
+ var att = sprite.ToRegionAttachment(shaderName);
- public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, string name) {
- throw new System.NotImplementedException();
+ var slotIndex = skeletonData.FindSlotIndex(slotName);
+ Skin skin = skeletonData.defaultSkin;
+ if (skinName != "")
+ skin = skeletonData.FindSkin(skinName);
+
+ skin.AddAttachment(slotIndex, att.Name, att);
+
+ return att;
+ }
+
+ public static RegionAttachment ToRegionAttachment (this Sprite sprite, string shaderName = "Spine/Skeleton") {
+ var loader = new SpriteAttachmentLoader(sprite, Shader.Find(shaderName));
+ var att = loader.NewRegionAttachment(null, sprite.name, "");
+ loader = null;
+ return att;
+ }
}
}
+
diff --git a/spine-unity/Assets/spine-unity/Modules/TK2D/SpriteCollectionAttachmentLoader.cs b/spine-unity/Assets/spine-unity/Modules/TK2D/SpriteCollectionAttachmentLoader.cs
index b9c10613a..3c6097de6 100644
--- a/spine-unity/Assets/spine-unity/Modules/TK2D/SpriteCollectionAttachmentLoader.cs
+++ b/spine-unity/Assets/spine-unity/Modules/TK2D/SpriteCollectionAttachmentLoader.cs
@@ -35,131 +35,132 @@ using UnityEngine;
using Spine;
// TODO: handle TPackerCW flip mode (probably not swap uv horizontaly)
+namespace Spine.Unity.TK2D {
+ public class SpriteCollectionAttachmentLoader : AttachmentLoader {
+ private tk2dSpriteCollectionData sprites;
+ private float u, v, u2, v2;
+ private bool regionRotated;
+ private float regionOriginalWidth, regionOriginalHeight;
+ private float regionWidth, regionHeight;
+ private float regionOffsetX, regionOffsetY;
+ private Material material;
-public class SpriteCollectionAttachmentLoader : AttachmentLoader {
- private tk2dSpriteCollectionData sprites;
- private float u, v, u2, v2;
- private bool regionRotated;
- private float regionOriginalWidth, regionOriginalHeight;
- private float regionWidth, regionHeight;
- private float regionOffsetX, regionOffsetY;
- private Material material;
-
- public SpriteCollectionAttachmentLoader (tk2dSpriteCollectionData sprites) {
- if (sprites == null)
- throw new ArgumentNullException("sprites cannot be null.");
- this.sprites = sprites;
- }
-
- private void ProcessSpriteDefinition (String name) {
- // Strip folder names.
- int index = name.LastIndexOfAny(new char[] {'/', '\\'});
- if (index != -1)
- name = name.Substring(index + 1);
-
- tk2dSpriteDefinition def = sprites.inst.GetSpriteDefinition(name);
-
- if (def == null) {
- Debug.Log("Sprite not found in atlas: " + name, sprites);
- throw new Exception("Sprite not found in atlas: " + name);
+ public SpriteCollectionAttachmentLoader (tk2dSpriteCollectionData sprites) {
+ if (sprites == null)
+ throw new ArgumentNullException("sprites cannot be null.");
+ this.sprites = sprites;
}
- if (def.complexGeometry)
- throw new NotImplementedException("Complex geometry is not supported: " + name);
- if (def.flipped == tk2dSpriteDefinition.FlipMode.TPackerCW)
- throw new NotImplementedException("Only 2D Toolkit atlases are supported: " + name);
- Vector2 minTexCoords = Vector2.one, maxTexCoords = Vector2.zero;
- for (int i = 0; i < def.uvs.Length; ++i) {
- Vector2 uv = def.uvs[i];
- minTexCoords = Vector2.Min(minTexCoords, uv);
- maxTexCoords = Vector2.Max(maxTexCoords, uv);
+ private void ProcessSpriteDefinition (String name) {
+ // Strip folder names.
+ int index = name.LastIndexOfAny(new char[] {'/', '\\'});
+ if (index != -1)
+ name = name.Substring(index + 1);
+
+ tk2dSpriteDefinition def = sprites.inst.GetSpriteDefinition(name);
+
+ if (def == null) {
+ Debug.Log("Sprite not found in atlas: " + name, sprites);
+ throw new Exception("Sprite not found in atlas: " + name);
+ }
+ if (def.complexGeometry)
+ throw new NotImplementedException("Complex geometry is not supported: " + name);
+ if (def.flipped == tk2dSpriteDefinition.FlipMode.TPackerCW)
+ throw new NotImplementedException("Only 2D Toolkit atlases are supported: " + name);
+
+ Vector2 minTexCoords = Vector2.one, maxTexCoords = Vector2.zero;
+ for (int i = 0; i < def.uvs.Length; ++i) {
+ Vector2 uv = def.uvs[i];
+ minTexCoords = Vector2.Min(minTexCoords, uv);
+ maxTexCoords = Vector2.Max(maxTexCoords, uv);
+ }
+ regionRotated = def.flipped == tk2dSpriteDefinition.FlipMode.Tk2d;
+ if (regionRotated) {
+ float temp = minTexCoords.x;
+ minTexCoords.x = maxTexCoords.x;
+ maxTexCoords.x = temp;
+ }
+ u = minTexCoords.x;
+ v = maxTexCoords.y;
+ u2 = maxTexCoords.x;
+ v2 = minTexCoords.y;
+
+ regionOriginalWidth = (int)(def.untrimmedBoundsData[1].x / def.texelSize.x);
+ regionOriginalHeight = (int)(def.untrimmedBoundsData[1].y / def.texelSize.y);
+
+ regionWidth = (int)(def.boundsData[1].x / def.texelSize.x);
+ regionHeight = (int)(def.boundsData[1].y / def.texelSize.y);
+
+ float x0 = def.untrimmedBoundsData[0].x - def.untrimmedBoundsData[1].x / 2;
+ float x1 = def.boundsData[0].x - def.boundsData[1].x / 2;
+ regionOffsetX = (int)((x1 - x0) / def.texelSize.x);
+
+ float y0 = def.untrimmedBoundsData[0].y - def.untrimmedBoundsData[1].y / 2;
+ float y1 = def.boundsData[0].y - def.boundsData[1].y / 2;
+ regionOffsetY = (int)((y1 - y0) / def.texelSize.y);
+
+ material = def.materialInst;
}
- regionRotated = def.flipped == tk2dSpriteDefinition.FlipMode.Tk2d;
- if (regionRotated) {
- float temp = minTexCoords.x;
- minTexCoords.x = maxTexCoords.x;
- maxTexCoords.x = temp;
+
+ public RegionAttachment NewRegionAttachment (Skin skin, String name, String path) {
+ ProcessSpriteDefinition(path);
+
+ RegionAttachment region = new RegionAttachment(name);
+ region.Path = path;
+ region.RendererObject = material;
+ region.SetUVs(u, v, u2, v2, regionRotated);
+ region.RegionOriginalWidth = regionOriginalWidth;
+ region.RegionOriginalHeight = regionOriginalHeight;
+ region.RegionWidth = regionWidth;
+ region.RegionHeight = regionHeight;
+ region.RegionOffsetX = regionOffsetX;
+ region.RegionOffsetY = regionOffsetY;
+ return region;
}
- u = minTexCoords.x;
- v = maxTexCoords.y;
- u2 = maxTexCoords.x;
- v2 = minTexCoords.y;
- regionOriginalWidth = (int)(def.untrimmedBoundsData[1].x / def.texelSize.x);
- regionOriginalHeight = (int)(def.untrimmedBoundsData[1].y / def.texelSize.y);
-
- regionWidth = (int)(def.boundsData[1].x / def.texelSize.x);
- regionHeight = (int)(def.boundsData[1].y / def.texelSize.y);
-
- float x0 = def.untrimmedBoundsData[0].x - def.untrimmedBoundsData[1].x / 2;
- float x1 = def.boundsData[0].x - def.boundsData[1].x / 2;
- regionOffsetX = (int)((x1 - x0) / def.texelSize.x);
-
- float y0 = def.untrimmedBoundsData[0].y - def.untrimmedBoundsData[1].y / 2;
- float y1 = def.boundsData[0].y - def.boundsData[1].y / 2;
- regionOffsetY = (int)((y1 - y0) / def.texelSize.y);
+ public MeshAttachment NewMeshAttachment (Skin skin, String name, String path) {
+ ProcessSpriteDefinition(path);
- material = def.materialInst;
- }
+ MeshAttachment mesh = new MeshAttachment(name);
+ mesh.Path = path;
+ mesh.RendererObject = material;
+ mesh.RegionU = u;
+ mesh.RegionV = v;
+ mesh.RegionU2 = u2;
+ mesh.RegionV2 = v2;
+ mesh.RegionRotate = regionRotated;
+ mesh.RegionOriginalWidth = regionOriginalWidth;
+ mesh.RegionOriginalHeight = regionOriginalHeight;
+ mesh.RegionWidth = regionWidth;
+ mesh.RegionHeight = regionHeight;
+ mesh.RegionOffsetX = regionOffsetX;
+ mesh.RegionOffsetY = regionOffsetY;
+ return mesh;
+ }
- public RegionAttachment NewRegionAttachment (Skin skin, String name, String path) {
- ProcessSpriteDefinition(path);
-
- RegionAttachment region = new RegionAttachment(name);
- region.Path = path;
- region.RendererObject = material;
- region.SetUVs(u, v, u2, v2, regionRotated);
- region.RegionOriginalWidth = regionOriginalWidth;
- region.RegionOriginalHeight = regionOriginalHeight;
- region.RegionWidth = regionWidth;
- region.RegionHeight = regionHeight;
- region.RegionOffsetX = regionOffsetX;
- region.RegionOffsetY = regionOffsetY;
- return region;
- }
-
- public MeshAttachment NewMeshAttachment (Skin skin, String name, String path) {
- ProcessSpriteDefinition(path);
-
- MeshAttachment mesh = new MeshAttachment(name);
- mesh.Path = path;
- mesh.RendererObject = material;
- mesh.RegionU = u;
- mesh.RegionV = v;
- mesh.RegionU2 = u2;
- mesh.RegionV2 = v2;
- mesh.RegionRotate = regionRotated;
- mesh.RegionOriginalWidth = regionOriginalWidth;
- mesh.RegionOriginalHeight = regionOriginalHeight;
- mesh.RegionWidth = regionWidth;
- mesh.RegionHeight = regionHeight;
- mesh.RegionOffsetX = regionOffsetX;
- mesh.RegionOffsetY = regionOffsetY;
- return mesh;
- }
-
- public WeightedMeshAttachment NewWeightedMeshAttachment (Skin skin, String name, String path) {
- ProcessSpriteDefinition(path);
-
- WeightedMeshAttachment mesh = new WeightedMeshAttachment(name);
- mesh.Path = path;
- mesh.RendererObject = material;
- mesh.RegionU = u;
- mesh.RegionV = v;
- mesh.RegionU2 = u2;
- mesh.RegionV2 = v2;
- mesh.RegionRotate = regionRotated;
- mesh.RegionOriginalWidth = regionOriginalWidth;
- mesh.RegionOriginalHeight = regionOriginalHeight;
- mesh.RegionWidth = regionWidth;
- mesh.RegionHeight = regionHeight;
- mesh.RegionOffsetX = regionOffsetX;
- mesh.RegionOffsetY = regionOffsetY;
- return mesh;
- }
+ public WeightedMeshAttachment NewWeightedMeshAttachment (Skin skin, String name, String path) {
+ ProcessSpriteDefinition(path);
- public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, String name) {
- return new BoundingBoxAttachment(name);
+ WeightedMeshAttachment mesh = new WeightedMeshAttachment(name);
+ mesh.Path = path;
+ mesh.RendererObject = material;
+ mesh.RegionU = u;
+ mesh.RegionV = v;
+ mesh.RegionU2 = u2;
+ mesh.RegionV2 = v2;
+ mesh.RegionRotate = regionRotated;
+ mesh.RegionOriginalWidth = regionOriginalWidth;
+ mesh.RegionOriginalHeight = regionOriginalHeight;
+ mesh.RegionWidth = regionWidth;
+ mesh.RegionHeight = regionHeight;
+ mesh.RegionOffsetX = regionOffsetX;
+ mesh.RegionOffsetY = regionOffsetY;
+ return mesh;
+ }
+
+ public BoundingBoxAttachment NewBoundingBoxAttachment (Skin skin, String name) {
+ return new BoundingBoxAttachment(name);
+ }
}
}
#endif
diff --git a/spine-unity/Assets/spine-unity/SkeletonAnimation.cs b/spine-unity/Assets/spine-unity/SkeletonAnimation.cs
index 05cee27b1..5608ec762 100644
--- a/spine-unity/Assets/spine-unity/SkeletonAnimation.cs
+++ b/spine-unity/Assets/spine-unity/SkeletonAnimation.cs
@@ -30,163 +30,165 @@
*****************************************************************************/
using System;
-using System.Collections.Generic;
using UnityEngine;
-using Spine;
-[ExecuteInEditMode]
-[AddComponentMenu("Spine/SkeletonAnimation")]
-[HelpURL("http://esotericsoftware.com/spine-unity-documentation#Controlling-Animation")]
-public class SkeletonAnimation : SkeletonRenderer, ISkeletonAnimation {
+namespace Spine.Unity {
+
+ [ExecuteInEditMode]
+ [AddComponentMenu("Spine/SkeletonAnimation")]
+ [HelpURL("http://esotericsoftware.com/spine-unity-documentation#Controlling-Animation")]
+ public class SkeletonAnimation : SkeletonRenderer, ISkeletonAnimation {
- ///
- /// This is the Spine.AnimationState object of this SkeletonAnimation. You can control animations through it.
- /// Note that this object, like .skeleton, is not guaranteed to exist in Awake. Do all accesses and caching to it in Start
- public Spine.AnimationState state;
+ ///
+ /// This is the Spine.AnimationState object of this SkeletonAnimation. You can control animations through it.
+ /// Note that this object, like .skeleton, is not guaranteed to exist in Awake. Do all accesses and caching to it in Start
+ public Spine.AnimationState state;
- public event UpdateBonesDelegate UpdateLocal {
- add { _UpdateLocal += value; }
- remove { _UpdateLocal -= value; }
- }
-
- public event UpdateBonesDelegate UpdateWorld {
- add { _UpdateWorld += value; }
- remove { _UpdateWorld -= value; }
- }
-
- public event UpdateBonesDelegate UpdateComplete {
- add { _UpdateComplete += value; }
- remove { _UpdateComplete -= value; }
- }
-
- protected event UpdateBonesDelegate _UpdateLocal;
- protected event UpdateBonesDelegate _UpdateWorld;
- protected event UpdateBonesDelegate _UpdateComplete;
-
- /// Gets the skeleton.
- public Skeleton Skeleton {
- get {
- this.Initialize(false);
- return this.skeleton;
+ public event UpdateBonesDelegate UpdateLocal {
+ add { _UpdateLocal += value; }
+ remove { _UpdateLocal -= value; }
}
- }
- [SerializeField]
- [SpineAnimation]
- private String _animationName;
+ public event UpdateBonesDelegate UpdateWorld {
+ add { _UpdateWorld += value; }
+ remove { _UpdateWorld -= value; }
+ }
- public String AnimationName {
- get {
- if (!valid) {
- Debug.LogWarning("You tried access AnimationName but the SkeletonAnimation was not valid. Try checking your Skeleton Data for errors.");
- return null;
+ public event UpdateBonesDelegate UpdateComplete {
+ add { _UpdateComplete += value; }
+ remove { _UpdateComplete -= value; }
+ }
+
+ protected event UpdateBonesDelegate _UpdateLocal;
+ protected event UpdateBonesDelegate _UpdateWorld;
+ protected event UpdateBonesDelegate _UpdateComplete;
+
+ /// Gets the skeleton.
+ public Skeleton Skeleton {
+ get {
+ this.Initialize(false);
+ return this.skeleton;
}
-
- TrackEntry entry = state.GetCurrent(0);
- return entry == null ? null : entry.Animation.Name;
}
- set {
- if (_animationName == value)
+
+ [SerializeField]
+ [SpineAnimation]
+ private String _animationName;
+
+ public String AnimationName {
+ get {
+ if (!valid) {
+ Debug.LogWarning("You tried access AnimationName but the SkeletonAnimation was not valid. Try checking your Skeleton Data for errors.");
+ return null;
+ }
+
+ TrackEntry entry = state.GetCurrent(0);
+ return entry == null ? null : entry.Animation.Name;
+ }
+ set {
+ if (_animationName == value)
+ return;
+ _animationName = value;
+
+ if (!valid) {
+ Debug.LogWarning("You tried to change AnimationName but the SkeletonAnimation was not valid. Try checking your Skeleton Data for errors.");
+ return;
+ }
+
+ if (value == null || value.Length == 0)
+ state.ClearTrack(0);
+ else
+ state.SetAnimation(0, value, loop);
+ }
+ }
+
+ /// Whether or not an animation should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.
+ #if UNITY_5
+ [Tooltip("Whether or not an animation should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.")]
+ #endif
+ public bool loop;
+
+ ///
+ /// The rate at which animations progress over time. 1 means 100%. 0.5 means 50%.
+ /// AnimationState and TrackEntry also have their own timeScale. These are combined multiplicatively.
+ #if UNITY_5
+ [Tooltip("The rate at which animations progress over time. 1 means 100%. 0.5 means 50%.")]
+ #endif
+ public float timeScale = 1;
+
+ #region Runtime Instantiation
+ /// Adds and prepares a SkeletonAnimation component to a GameObject at runtime.
+ /// The newly instantiated SkeletonAnimation
+ public static SkeletonAnimation AddToGameObject (GameObject gameObject, SkeletonDataAsset skeletonDataAsset) {
+ return SkeletonRenderer.AddSpineComponent(gameObject, skeletonDataAsset);
+ }
+
+ /// Instantiates a new UnityEngine.GameObject and adds a prepared SkeletonAnimation component to it.
+ /// The newly instantiated SkeletonAnimation component.
+ public static SkeletonAnimation NewSkeletonAnimationGameObject (SkeletonDataAsset skeletonDataAsset) {
+ return SkeletonRenderer.NewSpineGameObject(skeletonDataAsset);
+ }
+ #endregion
+
+ public override void Initialize (bool overwrite) {
+ if (valid && !overwrite)
return;
- _animationName = value;
-
- if (!valid) {
- Debug.LogWarning("You tried to change AnimationName but the SkeletonAnimation was not valid. Try checking your Skeleton Data for errors.");
+
+ base.Initialize(overwrite);
+
+ if (!valid)
return;
+
+ state = new Spine.AnimationState(skeletonDataAsset.GetAnimationStateData());
+
+ #if UNITY_EDITOR
+ if (!string.IsNullOrEmpty(_animationName)) {
+ if (Application.isPlaying) {
+ state.SetAnimation(0, _animationName, loop);
+ } else {
+ // Assume SkeletonAnimation is valid for skeletonData and skeleton. Checked above.
+ var animationObject = skeletonDataAsset.GetSkeletonData(false).FindAnimation(_animationName);
+ if (animationObject != null)
+ animationObject.Apply(skeleton, 0f, 0f, false, null);
+ }
+ Update(0);
}
-
- if (value == null || value.Length == 0)
- state.ClearTrack(0);
- else
- state.SetAnimation(0, value, loop);
- }
- }
-
- /// Whether or not an animation should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.
- #if UNITY_5
- [Tooltip("Whether or not an animation should loop. This only applies to the initial animation specified in the inspector, or any subsequent Animations played through .AnimationName. Animations set through state.SetAnimation are unaffected.")]
- #endif
- public bool loop;
-
- ///
- /// The rate at which animations progress over time. 1 means 100%. 0.5 means 50%.
- /// AnimationState and TrackEntry also have their own timeScale. These are combined multiplicatively.
- #if UNITY_5
- [Tooltip("The rate at which animations progress over time. 1 means 100%. 0.5 means 50%.")]
- #endif
- public float timeScale = 1;
-
- #region Runtime Instantiation
- /// Adds and prepares a SkeletonAnimation component to a GameObject at runtime.
- /// The newly instantiated SkeletonAnimation
- public static SkeletonAnimation AddToGameObject (GameObject gameObject, SkeletonDataAsset skeletonDataAsset) {
- return SkeletonRenderer.AddSpineComponent(gameObject, skeletonDataAsset);
- }
-
- /// Instantiates a new UnityEngine.GameObject and adds a prepared SkeletonAnimation component to it.
- /// The newly instantiated SkeletonAnimation component.
- public static SkeletonAnimation NewSkeletonAnimationGameObject (SkeletonDataAsset skeletonDataAsset) {
- return SkeletonRenderer.NewSpineGameObject(skeletonDataAsset);
- }
- #endregion
-
- public override void Initialize (bool overwrite) {
- if (valid && !overwrite)
- return;
-
- base.Initialize(overwrite);
-
- if (!valid)
- return;
-
- state = new Spine.AnimationState(skeletonDataAsset.GetAnimationStateData());
-
- #if UNITY_EDITOR
- if (!string.IsNullOrEmpty(_animationName)) {
- if (Application.isPlaying) {
- state.SetAnimation(0, _animationName, loop);
- } else {
- // Assume SkeletonAnimation is valid for skeletonData and skeleton. Checked above.
- var animationObject = skeletonDataAsset.GetSkeletonData(false).FindAnimation(_animationName);
- if (animationObject != null)
- animationObject.Apply(skeleton, 0f, 0f, false, null);
- }
- Update(0);
- }
- #else
- if (!string.IsNullOrEmpty(_animationName)) {
+ #else
+ if (!string.IsNullOrEmpty(_animationName)) {
state.SetAnimation(0, _animationName, loop);
Update(0);
+ }
+ #endif
}
- #endif
- }
- public virtual void Update () {
- Update(Time.deltaTime);
- }
+ public virtual void Update () {
+ Update(Time.deltaTime);
+ }
- public virtual void Update (float deltaTime) {
- if (!valid)
- return;
+ public virtual void Update (float deltaTime) {
+ if (!valid)
+ return;
- deltaTime *= timeScale;
- skeleton.Update(deltaTime);
- state.Update(deltaTime);
- state.Apply(skeleton);
+ deltaTime *= timeScale;
+ skeleton.Update(deltaTime);
+ state.Update(deltaTime);
+ state.Apply(skeleton);
- if (_UpdateLocal != null)
- _UpdateLocal(this);
+ if (_UpdateLocal != null)
+ _UpdateLocal(this);
- skeleton.UpdateWorldTransform();
-
- if (_UpdateWorld != null) {
- _UpdateWorld(this);
skeleton.UpdateWorldTransform();
+
+ if (_UpdateWorld != null) {
+ _UpdateWorld(this);
+ skeleton.UpdateWorldTransform();
+ }
+
+ if (_UpdateComplete != null) {
+ _UpdateComplete(this);
+ }
}
- if (_UpdateComplete != null) {
- _UpdateComplete(this);
- }
}
-
+
}
diff --git a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs
index 9cab006f6..5a8600907 100644
--- a/spine-unity/Assets/spine-unity/SkeletonAnimator.cs
+++ b/spine-unity/Assets/spine-unity/SkeletonAnimator.cs
@@ -5,161 +5,173 @@
* Full irrevocable rights and permissions granted to Esoteric Software
*****************************************************************************/
using UnityEngine;
-using System.Collections;
using System.Collections.Generic;
-using Spine;
-[RequireComponent(typeof(Animator))]
-public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation {
+namespace Spine.Unity {
+ [RequireComponent(typeof(Animator))]
+ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation {
- public enum MixMode { AlwaysMix, MixNext, SpineStyle }
- public MixMode[] layerMixModes = new MixMode[0];
+ public enum MixMode { AlwaysMix, MixNext, SpineStyle }
+ public MixMode[] layerMixModes = new MixMode[0];
- public event UpdateBonesDelegate UpdateLocal {
- add { _UpdateLocal += value; }
- remove { _UpdateLocal -= value; }
- }
-
- public event UpdateBonesDelegate UpdateWorld {
- add { _UpdateWorld += value; }
- remove { _UpdateWorld -= value; }
- }
-
- public event UpdateBonesDelegate UpdateComplete {
- add { _UpdateComplete += value; }
- remove { _UpdateComplete -= value; }
- }
-
- protected event UpdateBonesDelegate _UpdateLocal;
- protected event UpdateBonesDelegate _UpdateWorld;
- protected event UpdateBonesDelegate _UpdateComplete;
-
- public Skeleton Skeleton {
- get {
- return this.skeleton;
- }
- }
-
- readonly Dictionary animationTable = new Dictionary();
- readonly Dictionary clipNameHashCodeTable = new Dictionary();
- Animator animator;
- float lastTime;
-
- public override void Initialize (bool overwrite) {
- if (valid && !overwrite)
- return;
-
- base.Initialize(overwrite);
-
- if (!valid)
- return;
-
- animationTable.Clear();
- clipNameHashCodeTable.Clear();
-
- var data = skeletonDataAsset.GetSkeletonData(true);
-
- foreach (var a in data.Animations) {
- animationTable.Add(a.Name.GetHashCode(), a);
+ public event UpdateBonesDelegate UpdateLocal {
+ add { _UpdateLocal += value; }
+ remove { _UpdateLocal -= value; }
}
- animator = GetComponent();
-
- lastTime = Time.time;
- }
-
- void Update () {
- if (!valid)
- return;
-
- if (layerMixModes.Length != animator.layerCount) {
- System.Array.Resize(ref layerMixModes, animator.layerCount);
+ public event UpdateBonesDelegate UpdateWorld {
+ add { _UpdateWorld += value; }
+ remove { _UpdateWorld -= value; }
}
- float deltaTime = Time.time - lastTime;
- skeleton.Update(Time.deltaTime);
+ public event UpdateBonesDelegate UpdateComplete {
+ add { _UpdateComplete += value; }
+ remove { _UpdateComplete -= value; }
+ }
- //apply
- int layerCount = animator.layerCount;
+ protected event UpdateBonesDelegate _UpdateLocal;
+ protected event UpdateBonesDelegate _UpdateWorld;
+ protected event UpdateBonesDelegate _UpdateComplete;
- for (int i = 0; i < layerCount; i++) {
+ public Skeleton Skeleton {
+ get {
+ return this.skeleton;
+ }
+ }
- float layerWeight = animator.GetLayerWeight(i);
- if (i == 0)
- layerWeight = 1;
+ readonly Dictionary animationTable = new Dictionary();
+ readonly Dictionary clipNameHashCodeTable = new Dictionary();
+ Animator animator;
+ float lastTime;
- var stateInfo = animator.GetCurrentAnimatorStateInfo(i);
- var nextStateInfo = animator.GetNextAnimatorStateInfo(i);
+ public override void Initialize (bool overwrite) {
+ if (valid && !overwrite)
+ return;
-#if UNITY_5
- var clipInfo = animator.GetCurrentAnimatorClipInfo(i);
- var nextClipInfo = animator.GetNextAnimatorClipInfo(i);
-#else
- var clipInfo = animator.GetCurrentAnimationClipState(i);
- var nextClipInfo = animator.GetNextAnimationClipState(i);
-#endif
- MixMode mode = layerMixModes[i];
+ base.Initialize(overwrite);
- if (mode == MixMode.AlwaysMix) {
- //always use Mix instead of Applying the first non-zero weighted clip
- for (int c = 0; c < clipInfo.Length; c++) {
- var info = clipInfo[c];
- float weight = info.weight * layerWeight;
- if (weight == 0)
- continue;
+ if (!valid)
+ return;
- float time = stateInfo.normalizedTime * info.clip.length;
- animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight);
- }
-#if UNITY_5
- if (nextStateInfo.fullPathHash != 0) {
-#else
- if (nextStateInfo.nameHash != 0) {
-#endif
- for (int c = 0; c < nextClipInfo.Length; c++) {
- var info = nextClipInfo[c];
+ animationTable.Clear();
+ clipNameHashCodeTable.Clear();
+
+ var data = skeletonDataAsset.GetSkeletonData(true);
+
+ foreach (var a in data.Animations) {
+ animationTable.Add(a.Name.GetHashCode(), a);
+ }
+
+ animator = GetComponent();
+
+ lastTime = Time.time;
+ }
+
+ void Update () {
+ if (!valid)
+ return;
+
+ if (layerMixModes.Length != animator.layerCount) {
+ System.Array.Resize(ref layerMixModes, animator.layerCount);
+ }
+ float deltaTime = Time.time - lastTime;
+
+ skeleton.Update(Time.deltaTime);
+
+ //apply
+ int layerCount = animator.layerCount;
+
+ for (int i = 0; i < layerCount; i++) {
+
+ float layerWeight = animator.GetLayerWeight(i);
+ if (i == 0)
+ layerWeight = 1;
+
+ var stateInfo = animator.GetCurrentAnimatorStateInfo(i);
+ var nextStateInfo = animator.GetNextAnimatorStateInfo(i);
+
+ #if UNITY_5
+ var clipInfo = animator.GetCurrentAnimatorClipInfo(i);
+ var nextClipInfo = animator.GetNextAnimatorClipInfo(i);
+ #else
+ var clipInfo = animator.GetCurrentAnimationClipState(i);
+ var nextClipInfo = animator.GetNextAnimationClipState(i);
+ #endif
+ MixMode mode = layerMixModes[i];
+
+ if (mode == MixMode.AlwaysMix) {
+ //always use Mix instead of Applying the first non-zero weighted clip
+ for (int c = 0; c < clipInfo.Length; c++) {
+ var info = clipInfo[c];
float weight = info.weight * layerWeight;
if (weight == 0)
continue;
- float time = nextStateInfo.normalizedTime * info.clip.length;
- animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight);
+ float time = stateInfo.normalizedTime * info.clip.length;
+ animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight);
}
- }
- } else if (mode >= MixMode.MixNext) {
- //apply first non-zero weighted clip
- int c = 0;
+ #if UNITY_5
+ if (nextStateInfo.fullPathHash != 0) {
+ #else
+ if (nextStateInfo.nameHash != 0) {
+ #endif
+ for (int c = 0; c < nextClipInfo.Length; c++) {
+ var info = nextClipInfo[c];
+ float weight = info.weight * layerWeight;
+ if (weight == 0)
+ continue;
- for (; c < clipInfo.Length; c++) {
- var info = clipInfo[c];
- float weight = info.weight * layerWeight;
- if (weight == 0)
- continue;
+ float time = nextStateInfo.normalizedTime * info.clip.length;
+ animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight);
+ }
+ }
+ } else if (mode >= MixMode.MixNext) {
+ //apply first non-zero weighted clip
+ int c = 0;
- float time = stateInfo.normalizedTime * info.clip.length;
- animationTable[GetAnimationClipNameHashCode(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null);
- break;
- }
+ for (; c < clipInfo.Length; c++) {
+ var info = clipInfo[c];
+ float weight = info.weight * layerWeight;
+ if (weight == 0)
+ continue;
- //mix the rest
- for (; c < clipInfo.Length; c++) {
- var info = clipInfo[c];
- float weight = info.weight * layerWeight;
- if (weight == 0)
- continue;
+ float time = stateInfo.normalizedTime * info.clip.length;
+ animationTable[GetAnimationClipNameHashCode(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null);
+ break;
+ }
- float time = stateInfo.normalizedTime * info.clip.length;
- animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight);
- }
+ //mix the rest
+ for (; c < clipInfo.Length; c++) {
+ var info = clipInfo[c];
+ float weight = info.weight * layerWeight;
+ if (weight == 0)
+ continue;
- c = 0;
-#if UNITY_5
- if (nextStateInfo.fullPathHash != 0) {
-#else
- if (nextStateInfo.nameHash != 0) {
-#endif
- //apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
- if (mode == MixMode.SpineStyle) {
+ float time = stateInfo.normalizedTime * info.clip.length;
+ animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, stateInfo.loop, null, weight);
+ }
+
+ c = 0;
+ #if UNITY_5
+ if (nextStateInfo.fullPathHash != 0) {
+ #else
+ if (nextStateInfo.nameHash != 0) {
+ #endif
+ //apply next clip directly instead of mixing (ie: no crossfade, ignores mecanim transition weights)
+ if (mode == MixMode.SpineStyle) {
+ for (; c < nextClipInfo.Length; c++) {
+ var info = nextClipInfo[c];
+ float weight = info.weight * layerWeight;
+ if (weight == 0)
+ continue;
+
+ float time = nextStateInfo.normalizedTime * info.clip.length;
+ animationTable[GetAnimationClipNameHashCode(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null);
+ break;
+ }
+ }
+
+ //mix the rest
for (; c < nextClipInfo.Length; c++) {
var info = nextClipInfo[c];
float weight = info.weight * layerWeight;
@@ -167,49 +179,37 @@ public class SkeletonAnimator : SkeletonRenderer, ISkeletonAnimation {
continue;
float time = nextStateInfo.normalizedTime * info.clip.length;
- animationTable[GetAnimationClipNameHashCode(info.clip)].Apply(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null);
- break;
+ animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight);
}
}
-
- //mix the rest
- for (; c < nextClipInfo.Length; c++) {
- var info = nextClipInfo[c];
- float weight = info.weight * layerWeight;
- if (weight == 0)
- continue;
-
- float time = nextStateInfo.normalizedTime * info.clip.length;
- animationTable[GetAnimationClipNameHashCode(info.clip)].Mix(skeleton, Mathf.Max(0, time - deltaTime), time, nextStateInfo.loop, null, weight);
- }
}
}
- }
- if (_UpdateLocal != null)
- _UpdateLocal(this);
+ if (_UpdateLocal != null)
+ _UpdateLocal(this);
- skeleton.UpdateWorldTransform();
-
- if (_UpdateWorld != null) {
- _UpdateWorld(this);
skeleton.UpdateWorldTransform();
+
+ if (_UpdateWorld != null) {
+ _UpdateWorld(this);
+ skeleton.UpdateWorldTransform();
+ }
+
+ if (_UpdateComplete != null) {
+ _UpdateComplete(this);
+ }
+
+ lastTime = Time.time;
}
- if (_UpdateComplete != null) {
- _UpdateComplete(this);
+ private int GetAnimationClipNameHashCode (AnimationClip clip) {
+ int clipNameHashCode;
+ if (!clipNameHashCodeTable.TryGetValue(clip, out clipNameHashCode)) {
+ clipNameHashCode = clip.name.GetHashCode();
+ clipNameHashCodeTable.Add(clip, clipNameHashCode);
+ }
+
+ return clipNameHashCode;
}
-
- lastTime = Time.time;
- }
-
- private int GetAnimationClipNameHashCode (AnimationClip clip) {
- int clipNameHashCode;
- if (!clipNameHashCodeTable.TryGetValue(clip, out clipNameHashCode)) {
- clipNameHashCode = clip.name.GetHashCode();
- clipNameHashCodeTable.Add(clip, clipNameHashCode);
- }
-
- return clipNameHashCode;
}
}
diff --git a/spine-unity/Assets/spine-unity/SkeletonExtensions.cs b/spine-unity/Assets/spine-unity/SkeletonExtensions.cs
index 0db50e09d..525edbff9 100644
--- a/spine-unity/Assets/spine-unity/SkeletonExtensions.cs
+++ b/spine-unity/Assets/spine-unity/SkeletonExtensions.cs
@@ -6,153 +6,125 @@
*****************************************************************************/
using UnityEngine;
-using System.Collections;
using Spine;
+using Spine.Unity;
-public static class SkeletonExtensions {
+namespace Spine.Unity {
+ public static class SkeletonExtensions {
- const float ByteToFloat = 1f / 255f;
+ const float ByteToFloat = 1f / 255f;
- #region Colors
- public static Color GetColor (this Skeleton s) { return new Color(s.r, s.g, s.b, s.a); }
- public static Color GetColor (this RegionAttachment a) { return new Color(a.r, a.g, a.b, a.a); }
- public static Color GetColor (this MeshAttachment a) { return new Color(a.r, a.g, a.b, a.a); }
- public static Color GetColor (this WeightedMeshAttachment a) { return new Color(a.r, a.g, a.b, a.a); }
+ #region Colors
+ public static Color GetColor (this Skeleton s) { return new Color(s.r, s.g, s.b, s.a); }
+ public static Color GetColor (this RegionAttachment a) { return new Color(a.r, a.g, a.b, a.a); }
+ public static Color GetColor (this MeshAttachment a) { return new Color(a.r, a.g, a.b, a.a); }
+ public static Color GetColor (this WeightedMeshAttachment a) { return new Color(a.r, a.g, a.b, a.a); }
- public static void SetColor (this Skeleton skeleton, Color color) {
- skeleton.A = color.a;
- skeleton.R = color.r;
- skeleton.G = color.g;
- skeleton.B = color.b;
+ public static void SetColor (this Skeleton skeleton, Color color) {
+ skeleton.A = color.a;
+ skeleton.R = color.r;
+ skeleton.G = color.g;
+ skeleton.B = color.b;
+ }
+
+ public static void SetColor (this Skeleton skeleton, Color32 color) {
+ skeleton.A = color.a * ByteToFloat;
+ skeleton.R = color.r * ByteToFloat;
+ skeleton.G = color.g * ByteToFloat;
+ skeleton.B = color.b * ByteToFloat;
+ }
+
+ public static void SetColor (this Slot slot, Color color) {
+ slot.A = color.a;
+ slot.R = color.r;
+ slot.G = color.g;
+ slot.B = color.b;
+ }
+
+ public static void SetColor (this Slot slot, Color32 color) {
+ slot.A = color.a * ByteToFloat;
+ slot.R = color.r * ByteToFloat;
+ slot.G = color.g * ByteToFloat;
+ slot.B = color.b * ByteToFloat;
+ }
+
+ public static void SetColor (this RegionAttachment attachment, Color color) {
+ attachment.A = color.a;
+ attachment.R = color.r;
+ attachment.G = color.g;
+ attachment.B = color.b;
+ }
+
+ public static void SetColor (this RegionAttachment attachment, Color32 color) {
+ attachment.A = color.a * ByteToFloat;
+ attachment.R = color.r * ByteToFloat;
+ attachment.G = color.g * ByteToFloat;
+ attachment.B = color.b * ByteToFloat;
+ }
+
+ public static void SetColor (this MeshAttachment attachment, Color color) {
+ attachment.A = color.a;
+ attachment.R = color.r;
+ attachment.G = color.g;
+ attachment.B = color.b;
+ }
+
+ public static void SetColor (this MeshAttachment attachment, Color32 color) {
+ attachment.A = color.a * ByteToFloat;
+ attachment.R = color.r * ByteToFloat;
+ attachment.G = color.g * ByteToFloat;
+ attachment.B = color.b * ByteToFloat;
+ }
+
+ public static void SetColor (this WeightedMeshAttachment attachment, Color color) {
+ attachment.A = color.a;
+ attachment.R = color.r;
+ attachment.G = color.g;
+ attachment.B = color.b;
+ }
+
+ public static void SetColor (this WeightedMeshAttachment attachment, Color32 color) {
+ attachment.A = color.a * ByteToFloat;
+ attachment.R = color.r * ByteToFloat;
+ attachment.G = color.g * ByteToFloat;
+ attachment.B = color.b * ByteToFloat;
+ }
+ #endregion
+
+ #region Bone Position
+ public static void SetPosition (this Bone bone, Vector2 position) {
+ bone.X = position.x;
+ bone.Y = position.y;
+ }
+
+ public static void SetPosition (this Bone bone, Vector3 position) {
+ bone.X = position.x;
+ bone.Y = position.y;
+ }
+
+ public static Vector2 GetSkeletonSpacePosition (this Bone bone) {
+ return new Vector2(bone.worldX, bone.worldY);
+ }
+
+ public static Vector3 GetWorldPosition (this Bone bone, UnityEngine.Transform parentTransform) {
+ return parentTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY));
+ }
+ #endregion
+
+ #region Posing
+ ///
+ /// Shortcut for posing a skeleton at a specific time. Time is in seconds. (frameNumber / 30f) will give you seconds.
+ /// If you need to do this often, you should get the Animation object yourself using skeleton.data.FindAnimation. and call Apply on that.
+ /// The skeleton to pose.
+ /// The name of the animation to use.
+ /// The time of the pose within the animation.
+ /// Wraps the time around if it is longer than the duration of the animation.
+ public static void PoseWithAnimation (this Skeleton skeleton, string animationName, float time, bool loop) {
+ // Fail loud when skeleton.data is null.
+ Spine.Animation animation = skeleton.data.FindAnimation(animationName);
+ if (animation == null) return;
+ animation.Apply(skeleton, 0, time, loop, null);
+ }
+ #endregion
}
-
- public static void SetColor (this Skeleton skeleton, Color32 color) {
- skeleton.A = color.a * ByteToFloat;
- skeleton.R = color.r * ByteToFloat;
- skeleton.G = color.g * ByteToFloat;
- skeleton.B = color.b * ByteToFloat;
- }
-
- public static void SetColor (this Slot slot, Color color) {
- slot.A = color.a;
- slot.R = color.r;
- slot.G = color.g;
- slot.B = color.b;
- }
-
- public static void SetColor (this Slot slot, Color32 color) {
- slot.A = color.a * ByteToFloat;
- slot.R = color.r * ByteToFloat;
- slot.G = color.g * ByteToFloat;
- slot.B = color.b * ByteToFloat;
- }
-
- public static void SetColor (this RegionAttachment attachment, Color color) {
- attachment.A = color.a;
- attachment.R = color.r;
- attachment.G = color.g;
- attachment.B = color.b;
- }
-
- public static void SetColor (this RegionAttachment attachment, Color32 color) {
- attachment.A = color.a * ByteToFloat;
- attachment.R = color.r * ByteToFloat;
- attachment.G = color.g * ByteToFloat;
- attachment.B = color.b * ByteToFloat;
- }
-
- public static void SetColor (this MeshAttachment attachment, Color color) {
- attachment.A = color.a;
- attachment.R = color.r;
- attachment.G = color.g;
- attachment.B = color.b;
- }
-
- public static void SetColor (this MeshAttachment attachment, Color32 color) {
- attachment.A = color.a * ByteToFloat;
- attachment.R = color.r * ByteToFloat;
- attachment.G = color.g * ByteToFloat;
- attachment.B = color.b * ByteToFloat;
- }
-
- public static void SetColor (this WeightedMeshAttachment attachment, Color color) {
- attachment.A = color.a;
- attachment.R = color.r;
- attachment.G = color.g;
- attachment.B = color.b;
- }
-
- public static void SetColor (this WeightedMeshAttachment attachment, Color32 color) {
- attachment.A = color.a * ByteToFloat;
- attachment.R = color.r * ByteToFloat;
- attachment.G = color.g * ByteToFloat;
- attachment.B = color.b * ByteToFloat;
- }
- #endregion
-
- #region Bone Position
- public static void SetPosition (this Bone bone, Vector2 position) {
- bone.X = position.x;
- bone.Y = position.y;
- }
-
- public static void SetPosition (this Bone bone, Vector3 position) {
- bone.X = position.x;
- bone.Y = position.y;
- }
-
- public static Vector2 GetSkeletonSpacePosition (this Bone bone) {
- // TODO: This changes in v3.0
- return new Vector2(bone.worldX, bone.worldY);
- }
-
- public static Vector3 GetWorldPosition (this Bone bone, UnityEngine.Transform parentTransform) {
- return parentTransform.TransformPoint(new Vector3(bone.worldX, bone.worldY));
- }
- #endregion
-
- #region Posing
- ///
- /// Shortcut for posing a skeleton at a specific time. Time is in seconds. (frameNumber / 30f) will give you seconds.
- /// If you need to do this often, you should get the Animation object yourself using skeleton.data.FindAnimation. and call Apply on that.
- /// The skeleton to pose.
- /// The name of the animation to use.
- /// The time of the pose within the animation.
- /// Wraps the time around if it is longer than the duration of the animation.
- public static void PoseWithAnimation (this Skeleton skeleton, string animationName, float time, bool loop) {
- // Fail loud when skeleton.data is null.
- Spine.Animation animation = skeleton.data.FindAnimation(animationName);
- if (animation == null) return;
- animation.Apply(skeleton, 0, time, loop, null);
- }
- #endregion
-
- #region Unity Sprite To Attachments
- public static Attachment AttachUnitySprite (this Skeleton skeleton, string slotName, Sprite sprite, string shaderName = "Spine/Skeleton") {
- var att = sprite.ToRegionAttachment(shaderName);
- skeleton.FindSlot(slotName).Attachment = att;
- return att;
- }
-
- public static Attachment AddUnitySprite (this SkeletonData skeletonData, string slotName, Sprite sprite, string skinName = "", string shaderName = "Spine/Skeleton") {
- var att = sprite.ToRegionAttachment(shaderName);
-
- var slotIndex = skeletonData.FindSlotIndex(slotName);
- Skin skin = skeletonData.defaultSkin;
- if (skinName != "")
- skin = skeletonData.FindSkin(skinName);
-
- skin.AddAttachment(slotIndex, att.Name, att);
-
- return att;
- }
-
- public static RegionAttachment ToRegionAttachment (this Sprite sprite, string shaderName = "Spine/Skeleton") {
- var loader = new SpriteAttachmentLoader(sprite, Shader.Find(shaderName));
- var att = loader.NewRegionAttachment(null, sprite.name, "");
- loader = null;
- return att;
- }
- #endregion
-
-}
\ No newline at end of file
+}
diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs
index 35b2d9969..4cf20e743 100644
--- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs
+++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs
@@ -31,549 +31,518 @@
#define SPINE_OPTIONAL_NORMALS
#define SPINE_OPTIONAL_FRONTFACING
#define SPINE_OPTIONAL_RENDEROVERRIDE
+//#define SPINE_OPTIONAL_SUBMESHRENDERER // Deprecated
using System;
using System.Collections.Generic;
using UnityEngine;
-using Spine;
-using Spine.Unity;
using Spine.Unity.MeshGeneration;
-/// Renders a skeleton.
-[ExecuteInEditMode, RequireComponent(typeof(MeshFilter), typeof(MeshRenderer)), DisallowMultipleComponent]
-[HelpURL("http://esotericsoftware.com/spine-unity-documentation#Rendering")]
-public class SkeletonRenderer : MonoBehaviour {
+namespace Spine.Unity {
+ /// Renders a skeleton.
+ [ExecuteInEditMode, RequireComponent(typeof(MeshFilter), typeof(MeshRenderer)), DisallowMultipleComponent]
+ [HelpURL("http://esotericsoftware.com/spine-unity-documentation#Rendering")]
+ public class SkeletonRenderer : MonoBehaviour {
- public delegate void SkeletonRendererDelegate (SkeletonRenderer skeletonRenderer);
- public SkeletonRendererDelegate OnRebuild;
+ public delegate void SkeletonRendererDelegate (SkeletonRenderer skeletonRenderer);
+ public SkeletonRendererDelegate OnRebuild;
- public SkeletonDataAsset skeletonDataAsset;
- public String initialSkinName;
+ public SkeletonDataAsset skeletonDataAsset;
+ public String initialSkinName;
-#region Advanced
- // Submesh Separation
- [UnityEngine.Serialization.FormerlySerializedAs("submeshSeparators")]
- [SpineSlot]
- public string[] separatorSlotNames = new string[0];
- [System.NonSerialized]
- public readonly List separatorSlots = new List();
-
- public float zSpacing;
- public bool renderMeshes = true, immutableTriangles;
- public bool pmaVertexColors = true;
- #if SPINE_OPTIONAL_NORMALS
- public bool calculateNormals, calculateTangents;
- #endif
- #if SPINE_OPTIONAL_FRONTFACING
- public bool frontFacing;
- #endif
-
- public bool logErrors = false;
-
- #if SPINE_OPTIONAL_RENDEROVERRIDE
- public bool disableRenderingOnOverride = true;
- public delegate void InstructionDelegate (SkeletonRenderer.SmartMesh.Instruction instruction);
- event InstructionDelegate generateMeshOverride;
- public event InstructionDelegate GenerateMeshOverride {
- add {
- generateMeshOverride += value;
- if (disableRenderingOnOverride && generateMeshOverride != null) {
- Initialize(false);
- meshRenderer.enabled = false;
- }
- }
- remove {
- generateMeshOverride -= value;
- if (disableRenderingOnOverride && generateMeshOverride == null) {
- Initialize(false);
- meshRenderer.enabled = true;
- }
- }
- }
-
- #endif
-
- // Custom Slot Material
- [System.NonSerialized] readonly Dictionary customSlotMaterials = new Dictionary();
- public Dictionary CustomSlotMaterials { get { return customSlotMaterials; } }
-#endregion
-
- [System.NonSerialized] public bool valid;
- [System.NonSerialized] public Skeleton skeleton;
-
- MeshRenderer meshRenderer;
- MeshFilter meshFilter;
-
- Spine.Unity.DoubleBuffered doubleBufferedMesh;
- readonly SmartMesh.Instruction currentInstructions = new SmartMesh.Instruction();
- readonly ExposedList submeshes = new ExposedList();
-
- float[] tempVertices = new float[8];
- Vector3[] vertices;
- Color32[] colors;
- Vector2[] uvs;
-
- readonly ExposedList submeshMaterials = new ExposedList();
- Material[] sharedMaterials = new Material[0];
-
- #if SPINE_OPTIONAL_NORMALS
- Vector3[] normals;
- Vector4[] tangents;
- #endif
-
- #region Runtime Instantiation
- public static T NewSpineGameObject (SkeletonDataAsset skeletonDataAsset) where T : SkeletonRenderer {
- return SkeletonRenderer.AddSpineComponent(new GameObject("New Spine GameObject"), skeletonDataAsset);
- }
-
- /// Add and prepare a Spine component that derives from SkeletonRenderer to a GameObject at runtime.
- /// T should be SkeletonRenderer or any of its derived classes.
- public static T AddSpineComponent (GameObject gameObject, SkeletonDataAsset skeletonDataAsset) where T : SkeletonRenderer {
- var c = gameObject.AddComponent();
- if (skeletonDataAsset != null) {
- c.skeletonDataAsset = skeletonDataAsset;
- c.Initialize(false);
- }
- return c;
- }
- #endregion
-
- public virtual void Awake () {
- Initialize(false);
- }
-
- public virtual void Initialize (bool overwrite) {
- if (valid && !overwrite)
- return;
-
- // Clear
- {
- if (meshFilter != null)
- meshFilter.sharedMesh = null;
-
- meshRenderer = GetComponent();
- if (meshRenderer != null) meshRenderer.sharedMaterial = null;
-
- currentInstructions.Clear();
- vertices = null;
- colors = null;
- uvs = null;
- sharedMaterials = new Material[0];
- submeshMaterials.Clear();
- submeshes.Clear();
- skeleton = null;
-
- valid = false;
- }
-
- if (!skeletonDataAsset) {
- if (logErrors)
- Debug.LogError("Missing SkeletonData asset.", this);
-
- return;
- }
- SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(false);
- if (skeletonData == null)
- return;
- valid = true;
-
- meshFilter = GetComponent();
- meshRenderer = GetComponent();
- doubleBufferedMesh = new DoubleBuffered();
- vertices = new Vector3[0];
-
- skeleton = new Skeleton(skeletonData);
- if (initialSkinName != null && initialSkinName.Length > 0 && initialSkinName != "default")
- skeleton.SetSkin(initialSkinName);
-
- separatorSlots.Clear();
- for (int i = 0; i < separatorSlotNames.Length; i++) {
- separatorSlots.Add(skeleton.FindSlot(separatorSlotNames[i]));
- }
-
- LateUpdate();
-
- if (OnRebuild != null)
- OnRebuild(this);
- }
-
- public virtual void LateUpdate () {
- if (!valid)
- return;
-
- if (
- (
- !meshRenderer.enabled
-
- )
- #if SPINE_OPTIONAL_RENDEROVERRIDE
- && this.generateMeshOverride == null
- #endif
-
- )
- return;
-
-
-
- // STEP 1. Determine a SmartMesh.Instruction. Split up instructions into submeshes.
-
- // This method caches several .Items arrays.
- // Never mutate their overlying ExposedList objects.
- ExposedList drawOrder = skeleton.drawOrder;
- var drawOrderItems = drawOrder.Items;
- int drawOrderCount = drawOrder.Count;
- int separatorSlotCount = separatorSlots.Count;
- bool renderMeshes = this.renderMeshes;
-
- // Clear last state of attachments and submeshes
- var workingInstruction = this.currentInstructions;
- var workingAttachments = workingInstruction.attachments;
- workingAttachments.Clear(false);
- workingAttachments.GrowIfNeeded(drawOrderCount);
- workingAttachments.Count = drawOrderCount;
- var workingAttachmentsItems = workingInstruction.attachments.Items;
+ #region Advanced
+ // Submesh Separation
+ [UnityEngine.Serialization.FormerlySerializedAs("submeshSeparators")]
+ [SpineSlot]
+ public string[] separatorSlotNames = new string[0];
+ [System.NonSerialized]
+ public readonly List separatorSlots = new List();
+ public float zSpacing;
+ public bool renderMeshes = true, immutableTriangles;
+ public bool pmaVertexColors = true;
+ #if SPINE_OPTIONAL_NORMALS
+ public bool calculateNormals, calculateTangents;
+ #endif
#if SPINE_OPTIONAL_FRONTFACING
- var workingFlips = workingInstruction.attachmentFlips;
- workingFlips.Clear(false);
- workingFlips.GrowIfNeeded(drawOrderCount);
- workingFlips.Count = drawOrderCount;
- var workingFlipsItems = workingFlips.Items;
+ public bool frontFacing;
#endif
- var workingSubmeshInstructions = workingInstruction.submeshInstructions; // Items array should not be cached. There is dynamic writing to this list.
- workingSubmeshInstructions.Clear(false);
-
- bool isCustomMaterialsPopulated = customSlotMaterials.Count > 0;
-
- int vertexCount = 0;
- int submeshVertexCount = 0;
- int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;
- Material lastMaterial = null;
- for (int i = 0; i < drawOrderCount; i++) {
- Slot slot = drawOrderItems[i];
- Attachment attachment = slot.attachment;
-
- workingAttachmentsItems[i] = attachment;
-
- #if SPINE_OPTIONAL_FRONTFACING
- bool flip = frontFacing && (slot.bone.WorldSignX != slot.bone.WorldSignY);
- workingFlipsItems[i] = flip;
- #endif
-
- object rendererObject; // An AtlasRegion in plain Spine-Unity. Spine-TK2D hooks into TK2D's system. eventual source of Material object.
- int attachmentVertexCount, attachmentTriangleCount;
-
- var regionAttachment = attachment as RegionAttachment;
- if (regionAttachment != null) {
- rendererObject = regionAttachment.RendererObject;
- attachmentVertexCount = 4;
- attachmentTriangleCount = 6;
- } else {
- if (!renderMeshes)
- continue;
- var meshAttachment = attachment as MeshAttachment;
- if (meshAttachment != null) {
- rendererObject = meshAttachment.RendererObject;
- attachmentVertexCount = meshAttachment.vertices.Length >> 1;
- attachmentTriangleCount = meshAttachment.triangles.Length;
- } else {
- var skinnedMeshAttachment = attachment as WeightedMeshAttachment;
- if (skinnedMeshAttachment != null) {
- rendererObject = skinnedMeshAttachment.RendererObject;
- attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1;
- attachmentTriangleCount = skinnedMeshAttachment.triangles.Length;
- } else
- continue;
- }
- }
-
- #if !SPINE_TK2D
- // Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject; // For no customSlotMaterials
-
- Material material;
- if (isCustomMaterialsPopulated) {
- if (!customSlotMaterials.TryGetValue(slot, out material)) {
- material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
- }
- } else {
- material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
- }
- #else
- Material material = (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject;
- #endif
-
- // Create a new SubmeshInstruction when material changes. (or when forced to separate by a submeshSeparator)
- bool forceSeparate = (separatorSlotCount > 0 && separatorSlots.Contains(slot));
- if ((vertexCount > 0 && lastMaterial.GetInstanceID() != material.GetInstanceID()) || forceSeparate) {
- workingSubmeshInstructions.Add(
- new Spine.Unity.MeshGeneration.SubmeshInstruction {
- skeleton = this.skeleton,
- material = lastMaterial,
- startSlot = submeshStartSlotIndex,
- endSlot = i,
- triangleCount = submeshTriangleCount,
- firstVertexIndex = submeshFirstVertex,
- vertexCount = submeshVertexCount,
- forceSeparate = forceSeparate
- }
- );
-
- submeshTriangleCount = 0;
- submeshVertexCount = 0;
- submeshFirstVertex = vertexCount;
- submeshStartSlotIndex = i;
- }
- lastMaterial = material;
-
- submeshTriangleCount += attachmentTriangleCount;
- vertexCount += attachmentVertexCount;
- submeshVertexCount += attachmentVertexCount;
- }
-
- workingSubmeshInstructions.Add(
- new Spine.Unity.MeshGeneration.SubmeshInstruction {
- skeleton = this.skeleton,
- material = lastMaterial,
- startSlot = submeshStartSlotIndex,
- endSlot = drawOrderCount,
- triangleCount = submeshTriangleCount,
- firstVertexIndex = submeshFirstVertex,
- vertexCount = submeshVertexCount,
- forceSeparate = false
- }
- );
-
- workingInstruction.vertexCount = vertexCount;
- workingInstruction.immutableTriangles = this.immutableTriangles;
- #if SPINE_OPTIONAL_FRONTFACING
- workingInstruction.frontFacing = this.frontFacing;
- #endif
+ public bool logErrors = false;
#if SPINE_OPTIONAL_RENDEROVERRIDE
- if (this.generateMeshOverride != null) {
- this.generateMeshOverride(workingInstruction);
-
- if (disableRenderingOnOverride) {
- return;
+ public bool disableRenderingOnOverride = true;
+ public delegate void InstructionDelegate (SkeletonRenderer.SmartMesh.Instruction instruction);
+ event InstructionDelegate generateMeshOverride;
+ public event InstructionDelegate GenerateMeshOverride {
+ add {
+ generateMeshOverride += value;
+ if (disableRenderingOnOverride && generateMeshOverride != null) {
+ Initialize(false);
+ meshRenderer.enabled = false;
+ }
+ }
+ remove {
+ generateMeshOverride -= value;
+ if (disableRenderingOnOverride && generateMeshOverride == null) {
+ Initialize(false);
+ meshRenderer.enabled = true;
+ }
}
}
#endif
- // STEP 2. Update vertex buffer based on verts from the attachments.
- // Uses values that were also stored in workingInstruction.
- Vector3[] vertices = this.vertices;
- bool vertexCountIncreased = vertexCount > vertices.Length;
+ #if SPINE_OPTIONAL_SUBMESHRENDERER
+ private Spine.Unity.Modules.SkeletonUtilitySubmeshRenderer[] submeshRenderers;
+ #endif
- if (vertexCountIncreased) {
- this.vertices = vertices = new Vector3[vertexCount];
- this.colors = new Color32[vertexCount];
- this.uvs = new Vector2[vertexCount];
+ // Custom Slot Material
+ [System.NonSerialized] readonly Dictionary customSlotMaterials = new Dictionary();
+ public Dictionary CustomSlotMaterials { get { return customSlotMaterials; } }
+ #endregion
- #if SPINE_OPTIONAL_NORMALS
- if (calculateNormals) {
- Vector3[] localNormals = this.normals = new Vector3[vertexCount];
- Vector3 normal = new Vector3(0, 0, -1);
- for (int i = 0; i < vertexCount; i++)
- localNormals[i] = normal;
- }
+ [System.NonSerialized] public bool valid;
+ [System.NonSerialized] public Skeleton skeleton;
- // For dynamic tangent calculation, you can remove the tangent-filling logic and add tangent calculation logic below.
- if (calculateTangents) {
- Vector4[] localTangents = this.tangents = new Vector4[vertexCount];
- Vector4 tangent = new Vector4(1, 0, 0, -1);
- for (int i = 0; i < vertexCount; i++)
- localTangents[i] = tangent;
- }
- #endif
- } else {
- Vector3 zero = Vector3.zero;
- for (int i = vertexCount, n = vertices.Length; i < n; i++)
- vertices[i] = zero;
+ MeshRenderer meshRenderer;
+ MeshFilter meshFilter;
+
+ Spine.Unity.DoubleBuffered doubleBufferedMesh;
+ readonly SmartMesh.Instruction currentInstructions = new SmartMesh.Instruction();
+ readonly ExposedList submeshes = new ExposedList();
+
+ float[] tempVertices = new float[8];
+ Vector3[] vertices;
+ Color32[] colors;
+ Vector2[] uvs;
+
+ readonly ExposedList submeshMaterials = new ExposedList();
+ Material[] sharedMaterials = new Material[0];
+
+ #if SPINE_OPTIONAL_NORMALS
+ Vector3[] normals;
+ Vector4[] tangents;
+ #endif
+
+ #region Runtime Instantiation
+ public static T NewSpineGameObject (SkeletonDataAsset skeletonDataAsset) where T : SkeletonRenderer {
+ return SkeletonRenderer.AddSpineComponent(new GameObject("New Spine GameObject"), skeletonDataAsset);
}
- float zSpacing = this.zSpacing;
- float[] tempVertices = this.tempVertices;
- Vector2[] uvs = this.uvs;
- Color32[] colors = this.colors;
- int vertexIndex = 0;
- bool pmaVertexColors = this.pmaVertexColors;
- Color32 color;
- float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b;
-
- Vector3 meshBoundsMin;
- Vector3 meshBoundsMax;
- if (vertexCount == 0) {
- meshBoundsMin = new Vector3(0, 0, 0);
- meshBoundsMax = new Vector3(0, 0, 0);
- } else {
- meshBoundsMin.x = int.MaxValue;
- meshBoundsMin.y = int.MaxValue;
- meshBoundsMax.x = int.MinValue;
- meshBoundsMax.y = int.MinValue;
- if (zSpacing > 0f) {
- meshBoundsMin.z = 0f;
- meshBoundsMax.z = zSpacing * (drawOrderCount - 1);
- } else {
- meshBoundsMin.z = zSpacing * (drawOrderCount - 1);
- meshBoundsMax.z = 0f;
+ /// Add and prepare a Spine component that derives from SkeletonRenderer to a GameObject at runtime.
+ /// T should be SkeletonRenderer or any of its derived classes.
+ public static T AddSpineComponent (GameObject gameObject, SkeletonDataAsset skeletonDataAsset) where T : SkeletonRenderer {
+ var c = gameObject.AddComponent();
+ if (skeletonDataAsset != null) {
+ c.skeletonDataAsset = skeletonDataAsset;
+ c.Initialize(false);
}
- int i = 0;
- do {
+ return c;
+ }
+ #endregion
+
+ public virtual void Awake () {
+ Initialize(false);
+ }
+
+ public virtual void Initialize (bool overwrite) {
+ if (valid && !overwrite)
+ return;
+
+ // Clear
+ {
+ if (meshFilter != null)
+ meshFilter.sharedMesh = null;
+
+ meshRenderer = GetComponent();
+ if (meshRenderer != null) meshRenderer.sharedMaterial = null;
+
+ currentInstructions.Clear();
+ vertices = null;
+ colors = null;
+ uvs = null;
+ sharedMaterials = new Material[0];
+ submeshMaterials.Clear();
+ submeshes.Clear();
+ skeleton = null;
+
+ valid = false;
+ }
+
+ if (!skeletonDataAsset) {
+ if (logErrors)
+ Debug.LogError("Missing SkeletonData asset.", this);
+
+ return;
+ }
+ SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(false);
+ if (skeletonData == null)
+ return;
+ valid = true;
+
+ meshFilter = GetComponent();
+ meshRenderer = GetComponent();
+ doubleBufferedMesh = new DoubleBuffered();
+ vertices = new Vector3[0];
+
+ skeleton = new Skeleton(skeletonData);
+ if (initialSkinName != null && initialSkinName.Length > 0 && initialSkinName != "default")
+ skeleton.SetSkin(initialSkinName);
+
+ separatorSlots.Clear();
+ for (int i = 0; i < separatorSlotNames.Length; i++)
+ separatorSlots.Add(skeleton.FindSlot(separatorSlotNames[i]));
+
+ #if SPINE_OPTIONAL_SUBMESHRENDERER
+ submeshRenderers = GetComponentsInChildren();
+ #endif
+
+ LateUpdate();
+
+ if (OnRebuild != null)
+ OnRebuild(this);
+ }
+
+ public virtual void LateUpdate () {
+ if (!valid)
+ return;
+
+ if (
+ (
+ !meshRenderer.enabled
+
+ )
+ #if SPINE_OPTIONAL_RENDEROVERRIDE
+ && this.generateMeshOverride == null
+ #endif
+
+ #if SPINE_OPTIONAL_SUBMESHRENDERER
+ && submeshRenderers.Length > 0
+ #endif
+
+ )
+ return;
+
+
+
+ // STEP 1. Determine a SmartMesh.Instruction. Split up instructions into submeshes.
+
+ // This method caches several .Items arrays.
+ // Never mutate their overlying ExposedList objects.
+ ExposedList drawOrder = skeleton.drawOrder;
+ var drawOrderItems = drawOrder.Items;
+ int drawOrderCount = drawOrder.Count;
+ int separatorSlotCount = separatorSlots.Count;
+ bool renderMeshes = this.renderMeshes;
+
+ // Clear last state of attachments and submeshes
+ var workingInstruction = this.currentInstructions;
+ var workingAttachments = workingInstruction.attachments;
+ workingAttachments.Clear(false);
+ workingAttachments.GrowIfNeeded(drawOrderCount);
+ workingAttachments.Count = drawOrderCount;
+ var workingAttachmentsItems = workingInstruction.attachments.Items;
+
+ #if SPINE_OPTIONAL_FRONTFACING
+ var workingFlips = workingInstruction.attachmentFlips;
+ workingFlips.Clear(false);
+ workingFlips.GrowIfNeeded(drawOrderCount);
+ workingFlips.Count = drawOrderCount;
+ var workingFlipsItems = workingFlips.Items;
+ #endif
+
+ var workingSubmeshInstructions = workingInstruction.submeshInstructions; // Items array should not be cached. There is dynamic writing to this list.
+ workingSubmeshInstructions.Clear(false);
+
+ bool isCustomMaterialsPopulated = customSlotMaterials.Count > 0;
+
+ int vertexCount = 0;
+ int submeshVertexCount = 0;
+ int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;
+ Material lastMaterial = null;
+ for (int i = 0; i < drawOrderCount; i++) {
Slot slot = drawOrderItems[i];
Attachment attachment = slot.attachment;
- RegionAttachment regionAttachment = attachment as RegionAttachment;
+
+ workingAttachmentsItems[i] = attachment;
+
+ #if SPINE_OPTIONAL_FRONTFACING
+ bool flip = frontFacing && (slot.bone.WorldSignX != slot.bone.WorldSignY);
+ workingFlipsItems[i] = flip;
+ #endif
+
+ object rendererObject; // An AtlasRegion in plain Spine-Unity. Spine-TK2D hooks into TK2D's system. eventual source of Material object.
+ int attachmentVertexCount, attachmentTriangleCount;
+
+ var regionAttachment = attachment as RegionAttachment;
if (regionAttachment != null) {
- regionAttachment.ComputeWorldVertices(slot.bone, tempVertices);
-
- float z = i * zSpacing;
- float x1 = tempVertices[RegionAttachment.X1], y1 = tempVertices[RegionAttachment.Y1];
- float x2 = tempVertices[RegionAttachment.X2], y2 = tempVertices[RegionAttachment.Y2];
- float x3 = tempVertices[RegionAttachment.X3], y3 = tempVertices[RegionAttachment.Y3];
- float x4 = tempVertices[RegionAttachment.X4], y4 = tempVertices[RegionAttachment.Y4];
- vertices[vertexIndex].x = x1;
- vertices[vertexIndex].y = y1;
- vertices[vertexIndex].z = z;
- vertices[vertexIndex + 1].x = x4;
- vertices[vertexIndex + 1].y = y4;
- vertices[vertexIndex + 1].z = z;
- vertices[vertexIndex + 2].x = x2;
- vertices[vertexIndex + 2].y = y2;
- vertices[vertexIndex + 2].z = z;
- vertices[vertexIndex + 3].x = x3;
- vertices[vertexIndex + 3].y = y3;
- vertices[vertexIndex + 3].z = z;
-
- if (pmaVertexColors) {
- color.a = (byte)(a * slot.a * regionAttachment.a);
- color.r = (byte)(r * slot.r * regionAttachment.r * color.a);
- color.g = (byte)(g * slot.g * regionAttachment.g * color.a);
- color.b = (byte)(b * slot.b * regionAttachment.b * color.a);
- if (slot.data.blendMode == BlendMode.additive) color.a = 0;
- } else {
- color.a = (byte)(a * slot.a * regionAttachment.a);
- color.r = (byte)(r * slot.r * regionAttachment.r * 255);
- color.g = (byte)(g * slot.g * regionAttachment.g * 255);
- color.b = (byte)(b * slot.b * regionAttachment.b * 255);
- }
-
- colors[vertexIndex] = color;
- colors[vertexIndex + 1] = color;
- colors[vertexIndex + 2] = color;
- colors[vertexIndex + 3] = color;
-
- float[] regionUVs = regionAttachment.uvs;
- uvs[vertexIndex].x = regionUVs[RegionAttachment.X1];
- uvs[vertexIndex].y = regionUVs[RegionAttachment.Y1];
- uvs[vertexIndex + 1].x = regionUVs[RegionAttachment.X4];
- uvs[vertexIndex + 1].y = regionUVs[RegionAttachment.Y4];
- uvs[vertexIndex + 2].x = regionUVs[RegionAttachment.X2];
- uvs[vertexIndex + 2].y = regionUVs[RegionAttachment.Y2];
- uvs[vertexIndex + 3].x = regionUVs[RegionAttachment.X3];
- uvs[vertexIndex + 3].y = regionUVs[RegionAttachment.Y3];
-
- // Calculate min/max X
- if (x1 < meshBoundsMin.x)
- meshBoundsMin.x = x1;
- else if (x1 > meshBoundsMax.x)
- meshBoundsMax.x = x1;
- if (x2 < meshBoundsMin.x)
- meshBoundsMin.x = x2;
- else if (x2 > meshBoundsMax.x)
- meshBoundsMax.x = x2;
- if (x3 < meshBoundsMin.x)
- meshBoundsMin.x = x3;
- else if (x3 > meshBoundsMax.x)
- meshBoundsMax.x = x3;
- if (x4 < meshBoundsMin.x)
- meshBoundsMin.x = x4;
- else if (x4 > meshBoundsMax.x)
- meshBoundsMax.x = x4;
-
- // Calculate min/max Y
- if (y1 < meshBoundsMin.y)
- meshBoundsMin.y = y1;
- else if (y1 > meshBoundsMax.y)
- meshBoundsMax.y = y1;
- if (y2 < meshBoundsMin.y)
- meshBoundsMin.y = y2;
- else if (y2 > meshBoundsMax.y)
- meshBoundsMax.y = y2;
- if (y3 < meshBoundsMin.y)
- meshBoundsMin.y = y3;
- else if (y3 > meshBoundsMax.y)
- meshBoundsMax.y = y3;
- if (y4 < meshBoundsMin.y)
- meshBoundsMin.y = y4;
- else if (y4 > meshBoundsMax.y)
- meshBoundsMax.y = y4;
-
- vertexIndex += 4;
+ rendererObject = regionAttachment.RendererObject;
+ attachmentVertexCount = 4;
+ attachmentTriangleCount = 6;
} else {
if (!renderMeshes)
continue;
- MeshAttachment meshAttachment = attachment as MeshAttachment;
+ var meshAttachment = attachment as MeshAttachment;
if (meshAttachment != null) {
- int meshVertexCount = meshAttachment.vertices.Length;
- if (tempVertices.Length < meshVertexCount)
- this.tempVertices = tempVertices = new float[meshVertexCount];
- meshAttachment.ComputeWorldVertices(slot, tempVertices);
+ rendererObject = meshAttachment.RendererObject;
+ attachmentVertexCount = meshAttachment.vertices.Length >> 1;
+ attachmentTriangleCount = meshAttachment.triangles.Length;
+ } else {
+ var skinnedMeshAttachment = attachment as WeightedMeshAttachment;
+ if (skinnedMeshAttachment != null) {
+ rendererObject = skinnedMeshAttachment.RendererObject;
+ attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1;
+ attachmentTriangleCount = skinnedMeshAttachment.triangles.Length;
+ } else
+ continue;
+ }
+ }
+
+ #if !SPINE_TK2D
+ // Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject; // For no customSlotMaterials
+
+ Material material;
+ if (isCustomMaterialsPopulated) {
+ if (!customSlotMaterials.TryGetValue(slot, out material)) {
+ material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
+ }
+ } else {
+ material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
+ }
+ #else
+ Material material = (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject;
+ #endif
+
+ // Create a new SubmeshInstruction when material changes. (or when forced to separate by a submeshSeparator)
+ bool forceSeparate = (separatorSlotCount > 0 && separatorSlots.Contains(slot));
+ if ((vertexCount > 0 && lastMaterial.GetInstanceID() != material.GetInstanceID()) || forceSeparate) {
+ workingSubmeshInstructions.Add(
+ new Spine.Unity.MeshGeneration.SubmeshInstruction {
+ skeleton = this.skeleton,
+ material = lastMaterial,
+ startSlot = submeshStartSlotIndex,
+ endSlot = i,
+ triangleCount = submeshTriangleCount,
+ firstVertexIndex = submeshFirstVertex,
+ vertexCount = submeshVertexCount,
+ forceSeparate = forceSeparate
+ }
+ );
+
+ submeshTriangleCount = 0;
+ submeshVertexCount = 0;
+ submeshFirstVertex = vertexCount;
+ submeshStartSlotIndex = i;
+ }
+ lastMaterial = material;
+
+ submeshTriangleCount += attachmentTriangleCount;
+ vertexCount += attachmentVertexCount;
+ submeshVertexCount += attachmentVertexCount;
+ }
+
+ workingSubmeshInstructions.Add(
+ new Spine.Unity.MeshGeneration.SubmeshInstruction {
+ skeleton = this.skeleton,
+ material = lastMaterial,
+ startSlot = submeshStartSlotIndex,
+ endSlot = drawOrderCount,
+ triangleCount = submeshTriangleCount,
+ firstVertexIndex = submeshFirstVertex,
+ vertexCount = submeshVertexCount,
+ forceSeparate = false
+ }
+ );
+
+ workingInstruction.vertexCount = vertexCount;
+ workingInstruction.immutableTriangles = this.immutableTriangles;
+ #if SPINE_OPTIONAL_FRONTFACING
+ workingInstruction.frontFacing = this.frontFacing;
+ #endif
+
+ #if SPINE_OPTIONAL_RENDEROVERRIDE
+ if (this.generateMeshOverride != null) {
+ this.generateMeshOverride(workingInstruction);
+
+ if (disableRenderingOnOverride) {
+ return;
+ }
+ }
+ #endif
+
+ // STEP 2. Update vertex buffer based on verts from the attachments.
+ // Uses values that were also stored in workingInstruction.
+ Vector3[] vertices = this.vertices;
+ bool vertexCountIncreased = vertexCount > vertices.Length;
+
+ if (vertexCountIncreased) {
+ this.vertices = vertices = new Vector3[vertexCount];
+ this.colors = new Color32[vertexCount];
+ this.uvs = new Vector2[vertexCount];
+
+ #if SPINE_OPTIONAL_NORMALS
+ if (calculateNormals) {
+ Vector3[] localNormals = this.normals = new Vector3[vertexCount];
+ Vector3 normal = new Vector3(0, 0, -1);
+ for (int i = 0; i < vertexCount; i++)
+ localNormals[i] = normal;
+ }
+
+ // For dynamic tangent calculation, you can remove the tangent-filling logic and add tangent calculation logic below.
+ if (calculateTangents) {
+ Vector4[] localTangents = this.tangents = new Vector4[vertexCount];
+ Vector4 tangent = new Vector4(1, 0, 0, -1);
+ for (int i = 0; i < vertexCount; i++)
+ localTangents[i] = tangent;
+ }
+ #endif
+ } else {
+ Vector3 zero = Vector3.zero;
+ for (int i = vertexCount, n = vertices.Length; i < n; i++)
+ vertices[i] = zero;
+ }
+
+ float zSpacing = this.zSpacing;
+ float[] tempVertices = this.tempVertices;
+ Vector2[] uvs = this.uvs;
+ Color32[] colors = this.colors;
+ int vertexIndex = 0;
+ bool pmaVertexColors = this.pmaVertexColors;
+ Color32 color;
+ float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b;
+
+ Vector3 meshBoundsMin;
+ Vector3 meshBoundsMax;
+ if (vertexCount == 0) {
+ meshBoundsMin = new Vector3(0, 0, 0);
+ meshBoundsMax = new Vector3(0, 0, 0);
+ } else {
+ meshBoundsMin.x = int.MaxValue;
+ meshBoundsMin.y = int.MaxValue;
+ meshBoundsMax.x = int.MinValue;
+ meshBoundsMax.y = int.MinValue;
+ if (zSpacing > 0f) {
+ meshBoundsMin.z = 0f;
+ meshBoundsMax.z = zSpacing * (drawOrderCount - 1);
+ } else {
+ meshBoundsMin.z = zSpacing * (drawOrderCount - 1);
+ meshBoundsMax.z = 0f;
+ }
+ int i = 0;
+ do {
+ Slot slot = drawOrderItems[i];
+ Attachment attachment = slot.attachment;
+ RegionAttachment regionAttachment = attachment as RegionAttachment;
+ if (regionAttachment != null) {
+ regionAttachment.ComputeWorldVertices(slot.bone, tempVertices);
+
+ float z = i * zSpacing;
+ float x1 = tempVertices[RegionAttachment.X1], y1 = tempVertices[RegionAttachment.Y1];
+ float x2 = tempVertices[RegionAttachment.X2], y2 = tempVertices[RegionAttachment.Y2];
+ float x3 = tempVertices[RegionAttachment.X3], y3 = tempVertices[RegionAttachment.Y3];
+ float x4 = tempVertices[RegionAttachment.X4], y4 = tempVertices[RegionAttachment.Y4];
+ vertices[vertexIndex].x = x1;
+ vertices[vertexIndex].y = y1;
+ vertices[vertexIndex].z = z;
+ vertices[vertexIndex + 1].x = x4;
+ vertices[vertexIndex + 1].y = y4;
+ vertices[vertexIndex + 1].z = z;
+ vertices[vertexIndex + 2].x = x2;
+ vertices[vertexIndex + 2].y = y2;
+ vertices[vertexIndex + 2].z = z;
+ vertices[vertexIndex + 3].x = x3;
+ vertices[vertexIndex + 3].y = y3;
+ vertices[vertexIndex + 3].z = z;
if (pmaVertexColors) {
- color.a = (byte)(a * slot.a * meshAttachment.a);
- color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
- color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
- color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
+ color.a = (byte)(a * slot.a * regionAttachment.a);
+ color.r = (byte)(r * slot.r * regionAttachment.r * color.a);
+ color.g = (byte)(g * slot.g * regionAttachment.g * color.a);
+ color.b = (byte)(b * slot.b * regionAttachment.b * color.a);
if (slot.data.blendMode == BlendMode.additive) color.a = 0;
} else {
- color.a = (byte)(a * slot.a * meshAttachment.a);
- color.r = (byte)(r * slot.r * meshAttachment.r * 255);
- color.g = (byte)(g * slot.g * meshAttachment.g * 255);
- color.b = (byte)(b * slot.b * meshAttachment.b * 255);
+ color.a = (byte)(a * slot.a * regionAttachment.a);
+ color.r = (byte)(r * slot.r * regionAttachment.r * 255);
+ color.g = (byte)(g * slot.g * regionAttachment.g * 255);
+ color.b = (byte)(b * slot.b * regionAttachment.b * 255);
}
- float[] meshUVs = meshAttachment.uvs;
- float z = i * zSpacing;
- for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {
- float x = tempVertices[ii], y = tempVertices[ii + 1];
- vertices[vertexIndex].x = x;
- vertices[vertexIndex].y = y;
- vertices[vertexIndex].z = z;
- colors[vertexIndex] = color;
- uvs[vertexIndex].x = meshUVs[ii];
- uvs[vertexIndex].y = meshUVs[ii + 1];
+ colors[vertexIndex] = color;
+ colors[vertexIndex + 1] = color;
+ colors[vertexIndex + 2] = color;
+ colors[vertexIndex + 3] = color;
- if (x < meshBoundsMin.x)
- meshBoundsMin.x = x;
- else if (x > meshBoundsMax.x)
- meshBoundsMax.x = x;
- if (y < meshBoundsMin.y)
- meshBoundsMin.y = y;
- else if (y > meshBoundsMax.y)
- meshBoundsMax.y = y;
- }
+ float[] regionUVs = regionAttachment.uvs;
+ uvs[vertexIndex].x = regionUVs[RegionAttachment.X1];
+ uvs[vertexIndex].y = regionUVs[RegionAttachment.Y1];
+ uvs[vertexIndex + 1].x = regionUVs[RegionAttachment.X4];
+ uvs[vertexIndex + 1].y = regionUVs[RegionAttachment.Y4];
+ uvs[vertexIndex + 2].x = regionUVs[RegionAttachment.X2];
+ uvs[vertexIndex + 2].y = regionUVs[RegionAttachment.Y2];
+ uvs[vertexIndex + 3].x = regionUVs[RegionAttachment.X3];
+ uvs[vertexIndex + 3].y = regionUVs[RegionAttachment.Y3];
+
+ // Calculate min/max X
+ if (x1 < meshBoundsMin.x)
+ meshBoundsMin.x = x1;
+ else if (x1 > meshBoundsMax.x)
+ meshBoundsMax.x = x1;
+ if (x2 < meshBoundsMin.x)
+ meshBoundsMin.x = x2;
+ else if (x2 > meshBoundsMax.x)
+ meshBoundsMax.x = x2;
+ if (x3 < meshBoundsMin.x)
+ meshBoundsMin.x = x3;
+ else if (x3 > meshBoundsMax.x)
+ meshBoundsMax.x = x3;
+ if (x4 < meshBoundsMin.x)
+ meshBoundsMin.x = x4;
+ else if (x4 > meshBoundsMax.x)
+ meshBoundsMax.x = x4;
+
+ // Calculate min/max Y
+ if (y1 < meshBoundsMin.y)
+ meshBoundsMin.y = y1;
+ else if (y1 > meshBoundsMax.y)
+ meshBoundsMax.y = y1;
+ if (y2 < meshBoundsMin.y)
+ meshBoundsMin.y = y2;
+ else if (y2 > meshBoundsMax.y)
+ meshBoundsMax.y = y2;
+ if (y3 < meshBoundsMin.y)
+ meshBoundsMin.y = y3;
+ else if (y3 > meshBoundsMax.y)
+ meshBoundsMax.y = y3;
+ if (y4 < meshBoundsMin.y)
+ meshBoundsMin.y = y4;
+ else if (y4 > meshBoundsMax.y)
+ meshBoundsMax.y = y4;
+
+ vertexIndex += 4;
} else {
- WeightedMeshAttachment weightedMeshAttachment = attachment as WeightedMeshAttachment;
- if (weightedMeshAttachment != null) {
- int meshVertexCount = weightedMeshAttachment.uvs.Length;
+ if (!renderMeshes)
+ continue;
+ MeshAttachment meshAttachment = attachment as MeshAttachment;
+ if (meshAttachment != null) {
+ int meshVertexCount = meshAttachment.vertices.Length;
if (tempVertices.Length < meshVertexCount)
this.tempVertices = tempVertices = new float[meshVertexCount];
- weightedMeshAttachment.ComputeWorldVertices(slot, tempVertices);
+ meshAttachment.ComputeWorldVertices(slot, tempVertices);
if (pmaVertexColors) {
- color.a = (byte)(a * slot.a * weightedMeshAttachment.a);
- color.r = (byte)(r * slot.r * weightedMeshAttachment.r * color.a);
- color.g = (byte)(g * slot.g * weightedMeshAttachment.g * color.a);
- color.b = (byte)(b * slot.b * weightedMeshAttachment.b * color.a);
+ color.a = (byte)(a * slot.a * meshAttachment.a);
+ color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
+ color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
+ color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
if (slot.data.blendMode == BlendMode.additive) color.a = 0;
} else {
- color.a = (byte)(a * slot.a * weightedMeshAttachment.a);
- color.r = (byte)(r * slot.r * weightedMeshAttachment.r * 255);
- color.g = (byte)(g * slot.g * weightedMeshAttachment.g * 255);
- color.b = (byte)(b * slot.b * weightedMeshAttachment.b * 255);
+ color.a = (byte)(a * slot.a * meshAttachment.a);
+ color.r = (byte)(r * slot.r * meshAttachment.r * 255);
+ color.g = (byte)(g * slot.g * meshAttachment.g * 255);
+ color.b = (byte)(b * slot.b * meshAttachment.b * 255);
}
- float[] meshUVs = weightedMeshAttachment.uvs;
+ float[] meshUVs = meshAttachment.uvs;
float z = i * zSpacing;
for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {
float x = tempVertices[ii], y = tempVertices[ii + 1];
@@ -593,252 +562,305 @@ public class SkeletonRenderer : MonoBehaviour {
else if (y > meshBoundsMax.y)
meshBoundsMax.y = y;
}
+ } else {
+ WeightedMeshAttachment weightedMeshAttachment = attachment as WeightedMeshAttachment;
+ if (weightedMeshAttachment != null) {
+ int meshVertexCount = weightedMeshAttachment.uvs.Length;
+ if (tempVertices.Length < meshVertexCount)
+ this.tempVertices = tempVertices = new float[meshVertexCount];
+ weightedMeshAttachment.ComputeWorldVertices(slot, tempVertices);
+
+ if (pmaVertexColors) {
+ color.a = (byte)(a * slot.a * weightedMeshAttachment.a);
+ color.r = (byte)(r * slot.r * weightedMeshAttachment.r * color.a);
+ color.g = (byte)(g * slot.g * weightedMeshAttachment.g * color.a);
+ color.b = (byte)(b * slot.b * weightedMeshAttachment.b * color.a);
+ if (slot.data.blendMode == BlendMode.additive) color.a = 0;
+ } else {
+ color.a = (byte)(a * slot.a * weightedMeshAttachment.a);
+ color.r = (byte)(r * slot.r * weightedMeshAttachment.r * 255);
+ color.g = (byte)(g * slot.g * weightedMeshAttachment.g * 255);
+ color.b = (byte)(b * slot.b * weightedMeshAttachment.b * 255);
+ }
+
+ float[] meshUVs = weightedMeshAttachment.uvs;
+ float z = i * zSpacing;
+ for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {
+ float x = tempVertices[ii], y = tempVertices[ii + 1];
+ vertices[vertexIndex].x = x;
+ vertices[vertexIndex].y = y;
+ vertices[vertexIndex].z = z;
+ colors[vertexIndex] = color;
+ uvs[vertexIndex].x = meshUVs[ii];
+ uvs[vertexIndex].y = meshUVs[ii + 1];
+
+ if (x < meshBoundsMin.x)
+ meshBoundsMin.x = x;
+ else if (x > meshBoundsMax.x)
+ meshBoundsMax.x = x;
+ if (y < meshBoundsMin.y)
+ meshBoundsMin.y = y;
+ else if (y > meshBoundsMax.y)
+ meshBoundsMax.y = y;
+ }
+ }
+ }
+ }
+ } while (++i < drawOrderCount);
+ }
+
+ // Step 3. Move the mesh data into a UnityEngine.Mesh
+ var currentSmartMesh = doubleBufferedMesh.GetNext(); // Double-buffer for performance.
+ var currentMesh = currentSmartMesh.mesh;
+
+ currentMesh.vertices = vertices;
+ currentMesh.colors32 = colors;
+ currentMesh.uv = uvs;
+ var currentSmartMeshInstructionUsed = currentSmartMesh.instructionUsed;
+ #if SPINE_OPTIONAL_NORMALS
+ if (currentSmartMeshInstructionUsed.vertexCount < vertexCount) {
+ if (calculateNormals)
+ currentMesh.normals = normals;
+
+ // For dynamic calculated tangents, this needs to be moved out of the vertexCount check block when replacing the logic, also ensuring the size.
+ if (calculateTangents)
+ currentMesh.tangents = this.tangents;
+ }
+ #endif
+
+ // Check if the triangles should also be updated.
+ // This thorough structure check is cheaper than updating triangles every frame.
+ bool mustUpdateMeshStructure = CheckIfMustUpdateMeshStructure(workingInstruction, currentSmartMeshInstructionUsed);
+ if (mustUpdateMeshStructure) {
+ var thisSubmeshMaterials = this.submeshMaterials;
+ thisSubmeshMaterials.Clear(false);
+
+ int submeshCount = workingSubmeshInstructions.Count;
+ int oldSubmeshCount = submeshes.Count;
+
+ submeshes.Capacity = submeshCount;
+ for (int i = oldSubmeshCount; i < submeshCount; i++)
+ submeshes.Items[i] = new SubmeshTriangleBuffer();
+
+ var mutableTriangles = !workingInstruction.immutableTriangles;
+ for (int i = 0, last = submeshCount - 1; i < submeshCount; i++) {
+ var submeshInstruction = workingSubmeshInstructions.Items[i];
+ if (mutableTriangles || i >= oldSubmeshCount)
+ SetSubmesh(i, submeshInstruction,
+ #if SPINE_OPTIONAL_FRONTFACING
+ currentInstructions.attachmentFlips,
+ #endif
+ i == last);
+ thisSubmeshMaterials.Add(submeshInstruction.material);
+ }
+
+ currentMesh.subMeshCount = submeshCount;
+
+ for (int i = 0; i < submeshCount; ++i)
+ currentMesh.SetTriangles(submeshes.Items[i].triangles, i);
+ }
+
+ Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin;
+ Vector3 meshBoundsCenter = meshBoundsMin + meshBoundsExtents * 0.5f;
+ currentMesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents);
+
+ // CheckIfMustUpdateMaterialArray (last pushed materials vs currently parsed materials)
+ // Needs to check against the Working Submesh Instructions Materials instead of the cached submeshMaterials.
+ {
+ var lastPushedMaterials = this.sharedMaterials;
+ bool mustUpdateRendererMaterials = mustUpdateMeshStructure ||
+ (lastPushedMaterials.Length != workingSubmeshInstructions.Count);
+
+ if (!mustUpdateRendererMaterials) {
+ var workingSubmeshInstructionsItems = workingSubmeshInstructions.Items;
+ for (int i = 0, n = lastPushedMaterials.Length; i < n; i++) {
+ if (lastPushedMaterials[i].GetInstanceID() != workingSubmeshInstructionsItems[i].material.GetInstanceID()) { // Bounds check is implied above.
+ mustUpdateRendererMaterials = true;
+ break;
}
}
}
- } while (++i < drawOrderCount);
- }
- // Step 3. Move the mesh data into a UnityEngine.Mesh
- var currentSmartMesh = doubleBufferedMesh.GetNext(); // Double-buffer for performance.
- var currentMesh = currentSmartMesh.mesh;
+ if (mustUpdateRendererMaterials) {
+ if (submeshMaterials.Count == sharedMaterials.Length)
+ submeshMaterials.CopyTo(sharedMaterials);
+ else
+ sharedMaterials = submeshMaterials.ToArray();
- currentMesh.vertices = vertices;
- currentMesh.colors32 = colors;
- currentMesh.uv = uvs;
- var currentSmartMeshInstructionUsed = currentSmartMesh.instructionUsed;
- #if SPINE_OPTIONAL_NORMALS
- if (currentSmartMeshInstructionUsed.vertexCount < vertexCount) {
- if (calculateNormals)
- currentMesh.normals = normals;
-
- // For dynamic calculated tangents, this needs to be moved out of the vertexCount check block when replacing the logic, also ensuring the size.
- if (calculateTangents)
- currentMesh.tangents = this.tangents;
- }
- #endif
-
- // Check if the triangles should also be updated.
- // This thorough structure check is cheaper than updating triangles every frame.
- bool mustUpdateMeshStructure = CheckIfMustUpdateMeshStructure(workingInstruction, currentSmartMeshInstructionUsed);
- if (mustUpdateMeshStructure) {
- var thisSubmeshMaterials = this.submeshMaterials;
- thisSubmeshMaterials.Clear(false);
-
- int submeshCount = workingSubmeshInstructions.Count;
- int oldSubmeshCount = submeshes.Count;
-
- submeshes.Capacity = submeshCount;
- for (int i = oldSubmeshCount; i < submeshCount; i++)
- submeshes.Items[i] = new SubmeshTriangleBuffer();
-
- var mutableTriangles = !workingInstruction.immutableTriangles;
- for (int i = 0, last = submeshCount - 1; i < submeshCount; i++) {
- var submeshInstruction = workingSubmeshInstructions.Items[i];
- if (mutableTriangles || i >= oldSubmeshCount)
- SetSubmesh(i, submeshInstruction,
- #if SPINE_OPTIONAL_FRONTFACING
- currentInstructions.attachmentFlips,
- #endif
- i == last);
- thisSubmeshMaterials.Add(submeshInstruction.material);
- }
-
- currentMesh.subMeshCount = submeshCount;
-
- for (int i = 0; i < submeshCount; ++i)
- currentMesh.SetTriangles(submeshes.Items[i].triangles, i);
- }
-
- Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin;
- Vector3 meshBoundsCenter = meshBoundsMin + meshBoundsExtents * 0.5f;
- currentMesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents);
-
- // CheckIfMustUpdateMaterialArray (last pushed materials vs currently parsed materials)
- // Needs to check against the Working Submesh Instructions Materials instead of the cached submeshMaterials.
- {
- var lastPushedMaterials = this.sharedMaterials;
- bool mustUpdateRendererMaterials = mustUpdateMeshStructure ||
- (lastPushedMaterials.Length != workingSubmeshInstructions.Count);
-
- if (!mustUpdateRendererMaterials) {
- var workingSubmeshInstructionsItems = workingSubmeshInstructions.Items;
- for (int i = 0, n = lastPushedMaterials.Length; i < n; i++) {
- if (lastPushedMaterials[i].GetInstanceID() != workingSubmeshInstructionsItems[i].material.GetInstanceID()) { // Bounds check is implied above.
- mustUpdateRendererMaterials = true;
- break;
- }
+ meshRenderer.sharedMaterials = sharedMaterials;
}
}
- if (mustUpdateRendererMaterials) {
- if (submeshMaterials.Count == sharedMaterials.Length)
- submeshMaterials.CopyTo(sharedMaterials);
- else
- sharedMaterials = submeshMaterials.ToArray();
+ // Step 4. The UnityEngine.Mesh is ready. Set it as the MeshFilter's mesh. Store the instructions used for that mesh.
+ meshFilter.sharedMesh = currentMesh;
+ currentSmartMesh.instructionUsed.Set(workingInstruction);
- meshRenderer.sharedMaterials = sharedMaterials;
+
+ // Step 5. Miscellaneous
+ // Add stuff here if you want
+
+ #if SPINE_OPTIONAL_SUBMESHRENDERER
+ if (submeshRenderers.Length > 0) {
+ for (int i = 0; i < submeshRenderers.Length; i++) {
+ var submeshRenderer = submeshRenderers[i];
+ if (submeshRenderer.submeshIndex < sharedMaterials.Length)
+ submeshRenderer.SetMesh(meshRenderer, currentMesh, sharedMaterials[submeshRenderer.submeshIndex]);
+ else
+ submeshRenderer.GetComponent().enabled = false;
+ }
}
+ #endif
}
- // Step 4. The UnityEngine.Mesh is ready. Set it as the MeshFilter's mesh. Store the instructions used for that mesh.
- meshFilter.sharedMesh = currentMesh;
- currentSmartMesh.instructionUsed.Set(workingInstruction);
+ static bool CheckIfMustUpdateMeshStructure (SmartMesh.Instruction a, SmartMesh.Instruction b) {
-
- // Step 5. Miscellaneous
- // Add stuff here if you want
- }
-
- static bool CheckIfMustUpdateMeshStructure (SmartMesh.Instruction a, SmartMesh.Instruction b) {
-
- #if UNITY_EDITOR
- if (!Application.isPlaying)
- return true;
- #endif
-
- if (a.vertexCount != b.vertexCount)
- return true;
-
- if (a.immutableTriangles != b.immutableTriangles)
- return true;
-
- int attachmentCountB = b.attachments.Count;
- if (a.attachments.Count != attachmentCountB) // Bounds check for the looped storedAttachments count below.
- return true;
-
- var attachmentsA = a.attachments.Items;
- var attachmentsB = b.attachments.Items;
- for (int i = 0; i < attachmentCountB; i++) {
- if (attachmentsA[i] != attachmentsB[i])
+ #if UNITY_EDITOR
+ if (!Application.isPlaying)
return true;
- }
+ #endif
- #if SPINE_OPTIONAL_FRONTFACING
- if (a.frontFacing != b.frontFacing) { // if settings changed
- return true;
- } else if (a.frontFacing) { // if settings matched, only need to check one.
- var flipsA = a.attachmentFlips.Items;
- var flipsB = b.attachmentFlips.Items;
+ if (a.vertexCount != b.vertexCount)
+ return true;
+
+ if (a.immutableTriangles != b.immutableTriangles)
+ return true;
+
+ int attachmentCountB = b.attachments.Count;
+ if (a.attachments.Count != attachmentCountB) // Bounds check for the looped storedAttachments count below.
+ return true;
+
+ var attachmentsA = a.attachments.Items;
+ var attachmentsB = b.attachments.Items;
for (int i = 0; i < attachmentCountB; i++) {
- if (flipsA[i] != flipsB[i])
+ if (attachmentsA[i] != attachmentsB[i])
return true;
}
- }
- #endif
- // Submesh count changed
- int submeshCountA = a.submeshInstructions.Count;
- int submeshCountB = b.submeshInstructions.Count;
- if (submeshCountA != submeshCountB)
- return true;
-
- // Submesh Instruction mismatch
- var submeshInstructionsItemsA = a.submeshInstructions.Items;
- var submeshInstructionsItemsB = b.submeshInstructions.Items;
- for (int i = 0; i < submeshCountB; i++) {
- var submeshA = submeshInstructionsItemsA[i];
- var submeshB = submeshInstructionsItemsB[i];
-
- if (!(
- submeshA.vertexCount == submeshB.vertexCount &&
- submeshA.startSlot == submeshB.startSlot &&
- submeshA.endSlot == submeshB.endSlot &&
- submeshA.triangleCount == submeshB.triangleCount &&
- submeshA.firstVertexIndex == submeshB.firstVertexIndex
- ))
- return true;
- }
-
- return false;
- }
-
- #if SPINE_OPTIONAL_FRONTFACING
- void SetSubmesh (int submeshIndex, Spine.Unity.MeshGeneration.SubmeshInstruction submeshInstructions, ExposedList flipStates, bool isLastSubmesh) {
- #else
- void SetSubmesh (int submeshIndex, Spine.Unity.MeshGeneration.SubmeshInstruction submeshInstructions, bool isLastSubmesh) {
- #endif
- SubmeshTriangleBuffer currentSubmesh = submeshes.Items[submeshIndex];
- int[] triangles = currentSubmesh.triangles;
-
- int triangleCount = submeshInstructions.triangleCount;
- int firstVertex = submeshInstructions.firstVertexIndex;
-
- int trianglesCapacity = triangles.Length;
- if (isLastSubmesh && trianglesCapacity > triangleCount) {
- // Last submesh may have more triangles than required, so zero triangles to the end.
- for (int i = triangleCount; i < trianglesCapacity; i++)
- triangles[i] = 0;
-
- currentSubmesh.triangleCount = triangleCount;
-
- } else if (trianglesCapacity != triangleCount) {
- // Reallocate triangles when not the exact size needed.
- currentSubmesh.triangles = triangles = new int[triangleCount];
- currentSubmesh.triangleCount = 0;
- }
-
- #if SPINE_OPTIONAL_FRONTFACING
- if (!this.renderMeshes && !this.frontFacing) {
- #else
- if (!this.renderMeshes) {
- #endif
- // Use stored triangles if possible.
- if (currentSubmesh.firstVertex != firstVertex || currentSubmesh.triangleCount < triangleCount) { //|| currentSubmesh.triangleCount == 0
- currentSubmesh.triangleCount = triangleCount;
- currentSubmesh.firstVertex = firstVertex;
-
- for (int i = 0; i < triangleCount; i += 6, firstVertex += 4) {
- triangles[i] = firstVertex;
- triangles[i + 1] = firstVertex + 2;
- triangles[i + 2] = firstVertex + 1;
- triangles[i + 3] = firstVertex + 2;
- triangles[i + 4] = firstVertex + 3;
- triangles[i + 5] = firstVertex + 1;
- }
- }
- return;
- }
-
- // This method caches several .Items arrays.
- // Never mutate their overlying ExposedList objects.
-
- #if SPINE_OPTIONAL_FRONTFACING
- var flipStatesItems = flipStates.Items;
- #endif
-
- // Iterate through all slots and store their triangles.
- var drawOrderItems = skeleton.DrawOrder.Items;
- int triangleIndex = 0; // Modified by loop
- for (int i = submeshInstructions.startSlot, n = submeshInstructions.endSlot; i < n; i++) {
- Attachment attachment = drawOrderItems[i].attachment;
#if SPINE_OPTIONAL_FRONTFACING
- bool flip = frontFacing && flipStatesItems[i];
-
- // Add RegionAttachment triangles
- if (attachment is RegionAttachment) {
- if (!flip) {
- triangles[triangleIndex] = firstVertex;
- triangles[triangleIndex + 1] = firstVertex + 2;
- triangles[triangleIndex + 2] = firstVertex + 1;
- triangles[triangleIndex + 3] = firstVertex + 2;
- triangles[triangleIndex + 4] = firstVertex + 3;
- triangles[triangleIndex + 5] = firstVertex + 1;
- } else {
- triangles[triangleIndex] = firstVertex + 1;
- triangles[triangleIndex + 1] = firstVertex + 2;
- triangles[triangleIndex + 2] = firstVertex;
- triangles[triangleIndex + 3] = firstVertex + 1;
- triangles[triangleIndex + 4] = firstVertex + 3;
- triangles[triangleIndex + 5] = firstVertex + 2;
+ if (a.frontFacing != b.frontFacing) { // if settings changed
+ return true;
+ } else if (a.frontFacing) { // if settings matched, only need to check one.
+ var flipsA = a.attachmentFlips.Items;
+ var flipsB = b.attachmentFlips.Items;
+ for (int i = 0; i < attachmentCountB; i++) {
+ if (flipsA[i] != flipsB[i])
+ return true;
}
-
- triangleIndex += 6;
- firstVertex += 4;
- continue;
}
+ #endif
+
+ // Submesh count changed
+ int submeshCountA = a.submeshInstructions.Count;
+ int submeshCountB = b.submeshInstructions.Count;
+ if (submeshCountA != submeshCountB)
+ return true;
+
+ // Submesh Instruction mismatch
+ var submeshInstructionsItemsA = a.submeshInstructions.Items;
+ var submeshInstructionsItemsB = b.submeshInstructions.Items;
+ for (int i = 0; i < submeshCountB; i++) {
+ var submeshA = submeshInstructionsItemsA[i];
+ var submeshB = submeshInstructionsItemsB[i];
+
+ if (!(
+ submeshA.vertexCount == submeshB.vertexCount &&
+ submeshA.startSlot == submeshB.startSlot &&
+ submeshA.endSlot == submeshB.endSlot &&
+ submeshA.triangleCount == submeshB.triangleCount &&
+ submeshA.firstVertexIndex == submeshB.firstVertexIndex
+ ))
+ return true;
+ }
+
+ return false;
+ }
+
+ #if SPINE_OPTIONAL_FRONTFACING
+ void SetSubmesh (int submeshIndex, Spine.Unity.MeshGeneration.SubmeshInstruction submeshInstructions, ExposedList flipStates, bool isLastSubmesh) {
+ #else
+ void SetSubmesh (int submeshIndex, Spine.Unity.MeshGeneration.SubmeshInstruction submeshInstructions, bool isLastSubmesh) {
+ #endif
+ SubmeshTriangleBuffer currentSubmesh = submeshes.Items[submeshIndex];
+ int[] triangles = currentSubmesh.triangles;
+
+ int triangleCount = submeshInstructions.triangleCount;
+ int firstVertex = submeshInstructions.firstVertexIndex;
+
+ int trianglesCapacity = triangles.Length;
+ if (isLastSubmesh && trianglesCapacity > triangleCount) {
+ // Last submesh may have more triangles than required, so zero triangles to the end.
+ for (int i = triangleCount; i < trianglesCapacity; i++)
+ triangles[i] = 0;
+
+ currentSubmesh.triangleCount = triangleCount;
+
+ } else if (trianglesCapacity != triangleCount) {
+ // Reallocate triangles when not the exact size needed.
+ currentSubmesh.triangles = triangles = new int[triangleCount];
+ currentSubmesh.triangleCount = 0;
+ }
+
+ #if SPINE_OPTIONAL_FRONTFACING
+ if (!this.renderMeshes && !this.frontFacing) {
#else
- if (attachment is RegionAttachment) {
+ if (!this.renderMeshes) {
+ #endif
+ // Use stored triangles if possible.
+ if (currentSubmesh.firstVertex != firstVertex || currentSubmesh.triangleCount < triangleCount) { //|| currentSubmesh.triangleCount == 0
+ currentSubmesh.triangleCount = triangleCount;
+ currentSubmesh.firstVertex = firstVertex;
+
+ for (int i = 0; i < triangleCount; i += 6, firstVertex += 4) {
+ triangles[i] = firstVertex;
+ triangles[i + 1] = firstVertex + 2;
+ triangles[i + 2] = firstVertex + 1;
+ triangles[i + 3] = firstVertex + 2;
+ triangles[i + 4] = firstVertex + 3;
+ triangles[i + 5] = firstVertex + 1;
+ }
+ }
+ return;
+ }
+
+ // This method caches several .Items arrays.
+ // Never mutate their overlying ExposedList objects.
+
+ #if SPINE_OPTIONAL_FRONTFACING
+ var flipStatesItems = flipStates.Items;
+ #endif
+
+ // Iterate through all slots and store their triangles.
+ var drawOrderItems = skeleton.DrawOrder.Items;
+ int triangleIndex = 0; // Modified by loop
+ for (int i = submeshInstructions.startSlot, n = submeshInstructions.endSlot; i < n; i++) {
+ Attachment attachment = drawOrderItems[i].attachment;
+ #if SPINE_OPTIONAL_FRONTFACING
+ bool flip = frontFacing && flipStatesItems[i];
+
+ // Add RegionAttachment triangles
+ if (attachment is RegionAttachment) {
+ if (!flip) {
+ triangles[triangleIndex] = firstVertex;
+ triangles[triangleIndex + 1] = firstVertex + 2;
+ triangles[triangleIndex + 2] = firstVertex + 1;
+ triangles[triangleIndex + 3] = firstVertex + 2;
+ triangles[triangleIndex + 4] = firstVertex + 3;
+ triangles[triangleIndex + 5] = firstVertex + 1;
+ } else {
+ triangles[triangleIndex] = firstVertex + 1;
+ triangles[triangleIndex + 1] = firstVertex + 2;
+ triangles[triangleIndex + 2] = firstVertex;
+ triangles[triangleIndex + 3] = firstVertex + 1;
+ triangles[triangleIndex + 4] = firstVertex + 3;
+ triangles[triangleIndex + 5] = firstVertex + 2;
+ }
+
+ triangleIndex += 6;
+ firstVertex += 4;
+ continue;
+ }
+ #else
+ if (attachment is RegionAttachment) {
triangles[triangleIndex] = firstVertex;
triangles[triangleIndex + 1] = firstVertex + 2;
triangles[triangleIndex + 2] = firstVertex + 1;
@@ -849,121 +871,120 @@ public class SkeletonRenderer : MonoBehaviour {
triangleIndex += 6;
firstVertex += 4;
continue;
- }
- #endif
-
- // Add (Weighted)MeshAttachment triangles
- int[] attachmentTriangles;
- int attachmentVertexCount;
- var meshAttachment = attachment as MeshAttachment;
- if (meshAttachment != null) {
- attachmentVertexCount = meshAttachment.vertices.Length >> 1; // length/2
- attachmentTriangles = meshAttachment.triangles;
- } else {
- var weightedMeshAttachment = attachment as WeightedMeshAttachment;
- if (weightedMeshAttachment != null) {
- attachmentVertexCount = weightedMeshAttachment.uvs.Length >> 1; // length/2
- attachmentTriangles = weightedMeshAttachment.triangles;
- } else
- continue;
- }
-
- #if SPINE_OPTIONAL_FRONTFACING
- if (flip) {
- for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii += 3, triangleIndex += 3) {
- triangles[triangleIndex + 2] = firstVertex + attachmentTriangles[ii];
- triangles[triangleIndex + 1] = firstVertex + attachmentTriangles[ii + 1];
- triangles[triangleIndex] = firstVertex + attachmentTriangles[ii + 2];
}
- } else {
+ #endif
+
+ // Add (Weighted)MeshAttachment triangles
+ int[] attachmentTriangles;
+ int attachmentVertexCount;
+ var meshAttachment = attachment as MeshAttachment;
+ if (meshAttachment != null) {
+ attachmentVertexCount = meshAttachment.vertices.Length >> 1; // length/2
+ attachmentTriangles = meshAttachment.triangles;
+ } else {
+ var weightedMeshAttachment = attachment as WeightedMeshAttachment;
+ if (weightedMeshAttachment != null) {
+ attachmentVertexCount = weightedMeshAttachment.uvs.Length >> 1; // length/2
+ attachmentTriangles = weightedMeshAttachment.triangles;
+ } else
+ continue;
+ }
+
+ #if SPINE_OPTIONAL_FRONTFACING
+ if (flip) {
+ for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii += 3, triangleIndex += 3) {
+ triangles[triangleIndex + 2] = firstVertex + attachmentTriangles[ii];
+ triangles[triangleIndex + 1] = firstVertex + attachmentTriangles[ii + 1];
+ triangles[triangleIndex] = firstVertex + attachmentTriangles[ii + 2];
+ }
+ } else {
+ for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii++, triangleIndex++) {
+ triangles[triangleIndex] = firstVertex + attachmentTriangles[ii];
+ }
+ }
+ #else
for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii++, triangleIndex++) {
- triangles[triangleIndex] = firstVertex + attachmentTriangles[ii];
+ triangles[triangleIndex] = firstVertex + attachmentTriangles[ii];
+ }
+ #endif
+
+ firstVertex += attachmentVertexCount;
+ }
+ }
+
+ #if UNITY_EDITOR
+ void OnDrawGizmos () {
+ // Make scene view selection easier by drawing a clear gizmo over the skeleton.
+ meshFilter = GetComponent();
+ if (meshFilter == null) return;
+
+ Mesh mesh = meshFilter.sharedMesh;
+ if (mesh == null) return;
+
+ Bounds meshBounds = mesh.bounds;
+ Gizmos.color = Color.clear;
+ Gizmos.matrix = transform.localToWorldMatrix;
+ Gizmos.DrawCube(meshBounds.center, meshBounds.size);
+ }
+ #endif
+
+ ///This is a Mesh that also stores the instructions SkeletonRenderer generated for it.
+ public class SmartMesh {
+ public Mesh mesh = Spine.Unity.SpineMesh.NewMesh();
+ public SmartMesh.Instruction instructionUsed = new SmartMesh.Instruction();
+
+ public class Instruction {
+ public bool immutableTriangles;
+ public int vertexCount = -1;
+ public readonly ExposedList attachments = new ExposedList();
+ public readonly ExposedList submeshInstructions = new ExposedList();
+
+ #if SPINE_OPTIONAL_FRONTFACING
+ public bool frontFacing;
+ public readonly ExposedList attachmentFlips = new ExposedList();
+ #endif
+
+ public void Clear () {
+ this.attachments.Clear(false);
+ this.submeshInstructions.Clear(false);
+
+ #if SPINE_OPTIONAL_FRONTFACING
+ this.attachmentFlips.Clear(false);
+ #endif
+ }
+
+ public void Set (Instruction other) {
+ this.immutableTriangles = other.immutableTriangles;
+ this.vertexCount = other.vertexCount;
+
+ this.attachments.Clear(false);
+ this.attachments.GrowIfNeeded(other.attachments.Capacity);
+ this.attachments.Count = other.attachments.Count;
+ other.attachments.CopyTo(this.attachments.Items);
+
+ #if SPINE_OPTIONAL_FRONTFACING
+ this.frontFacing = other.frontFacing;
+ this.attachmentFlips.Clear(false);
+ this.attachmentFlips.GrowIfNeeded(other.attachmentFlips.Capacity);
+ this.attachmentFlips.Count = other.attachmentFlips.Count;
+ if (this.frontFacing)
+ other.attachmentFlips.CopyTo(this.attachmentFlips.Items);
+ #endif
+
+ this.submeshInstructions.Clear(false);
+ this.submeshInstructions.GrowIfNeeded(other.submeshInstructions.Capacity);
+ this.submeshInstructions.Count = other.submeshInstructions.Count;
+ other.submeshInstructions.CopyTo(this.submeshInstructions.Items);
}
}
- #else
- for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii++, triangleIndex++) {
- triangles[triangleIndex] = firstVertex + attachmentTriangles[ii];
- }
- #endif
+ }
- firstVertex += attachmentVertexCount;
+ class SubmeshTriangleBuffer {
+ public int[] triangles = new int[0];
+
+ // These two fields are used when renderMeshes == false
+ public int triangleCount;
+ public int firstVertex = -1;
}
}
-
- #if UNITY_EDITOR
- void OnDrawGizmos () {
- // Make scene view selection easier by drawing a clear gizmo over the skeleton.
- meshFilter = GetComponent();
- if (meshFilter == null) return;
-
- Mesh mesh = meshFilter.sharedMesh;
- if (mesh == null) return;
-
- Bounds meshBounds = mesh.bounds;
- Gizmos.color = Color.clear;
- Gizmos.matrix = transform.localToWorldMatrix;
- Gizmos.DrawCube(meshBounds.center, meshBounds.size);
- }
- #endif
-
- ///This is a Mesh that also stores the instructions SkeletonRenderer generated for it.
- public class SmartMesh {
- public Mesh mesh = Spine.Unity.SpineMesh.NewMesh();
- public SmartMesh.Instruction instructionUsed = new SmartMesh.Instruction();
-
- public class Instruction {
- public bool immutableTriangles;
- public int vertexCount = -1;
- public readonly ExposedList attachments = new ExposedList();
- public readonly ExposedList submeshInstructions = new ExposedList();
-
- #if SPINE_OPTIONAL_FRONTFACING
- public bool frontFacing;
- public readonly ExposedList attachmentFlips = new ExposedList();
- #endif
-
- public void Clear () {
- this.attachments.Clear(false);
- this.submeshInstructions.Clear(false);
-
- #if SPINE_OPTIONAL_FRONTFACING
- this.attachmentFlips.Clear(false);
- #endif
- }
-
- public void Set (Instruction other) {
- this.immutableTriangles = other.immutableTriangles;
- this.vertexCount = other.vertexCount;
-
- this.attachments.Clear(false);
- this.attachments.GrowIfNeeded(other.attachments.Capacity);
- this.attachments.Count = other.attachments.Count;
- other.attachments.CopyTo(this.attachments.Items);
-
- #if SPINE_OPTIONAL_FRONTFACING
- this.frontFacing = other.frontFacing;
- this.attachmentFlips.Clear(false);
- this.attachmentFlips.GrowIfNeeded(other.attachmentFlips.Capacity);
- this.attachmentFlips.Count = other.attachmentFlips.Count;
- if (this.frontFacing)
- other.attachmentFlips.CopyTo(this.attachmentFlips.Items);
- #endif
-
- this.submeshInstructions.Clear(false);
- this.submeshInstructions.GrowIfNeeded(other.submeshInstructions.Capacity);
- this.submeshInstructions.Count = other.submeshInstructions.Count;
- other.submeshInstructions.CopyTo(this.submeshInstructions.Items);
- }
- }
- }
-
- class SubmeshTriangleBuffer {
- public int[] triangles = new int[0];
-
- // These two fields are used when renderMeshes == false
- public int triangleCount;
- public int firstVertex = -1;
- }
-}
-
-
+}
\ No newline at end of file
diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs
index 613d4740b..b096efcad 100644
--- a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs
+++ b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityBoneInspector.cs
@@ -10,345 +10,348 @@ using System.Collections;
using System.Collections.Generic;
using Spine;
-[CustomEditor(typeof(SkeletonUtilityBone)), CanEditMultipleObjects]
-public class SkeletonUtilityBoneInspector : Editor {
- SerializedProperty mode, boneName, zPosition, position, rotation, scale, overrideAlpha, parentReference;
- // MITCH
-// SerializedProperty flip, flipX;
-
- //multi selected flags
- bool containsFollows, containsOverrides, multiObject;
-
- //single selected helpers
- SkeletonUtilityBone utilityBone;
- SkeletonUtility skeletonUtility;
- bool canCreateHingeChain = false;
-
- Dictionary> boundingBoxTable = new Dictionary>();
- string currentSkinName = "";
-
- void OnEnable () {
- mode = this.serializedObject.FindProperty("mode");
- boneName = this.serializedObject.FindProperty("boneName");
- zPosition = this.serializedObject.FindProperty("zPosition");
- position = this.serializedObject.FindProperty("position");
- rotation = this.serializedObject.FindProperty("rotation");
- scale = this.serializedObject.FindProperty("scale");
- overrideAlpha = this.serializedObject.FindProperty("overrideAlpha");
- parentReference = this.serializedObject.FindProperty("parentReference");
-
+namespace Spine.Unity.Editor {
+ [CustomEditor(typeof(SkeletonUtilityBone)), CanEditMultipleObjects]
+ public class SkeletonUtilityBoneInspector : UnityEditor.Editor {
+ SerializedProperty mode, boneName, zPosition, position, rotation, scale, overrideAlpha, parentReference;
// MITCH
-// flip = this.serializedObject.FindProperty("flip");
-// flipX = this.serializedObject.FindProperty("flipX");
+ // SerializedProperty flip, flipX;
- EvaluateFlags();
+ //multi selected flags
+ bool containsFollows, containsOverrides, multiObject;
- if (utilityBone.valid == false && skeletonUtility != null && skeletonUtility.skeletonRenderer != null) {
- skeletonUtility.skeletonRenderer.Initialize(false);
- }
+ //single selected helpers
+ SkeletonUtilityBone utilityBone;
+ SkeletonUtility skeletonUtility;
+ bool canCreateHingeChain = false;
- canCreateHingeChain = CanCreateHingeChain();
+ Dictionary> boundingBoxTable = new Dictionary>();
+ string currentSkinName = "";
- boundingBoxTable.Clear();
-
- if (multiObject)
- return;
-
- if (utilityBone.bone == null)
- return;
-
- var skeleton = utilityBone.bone.Skeleton;
- int slotCount = skeleton.Slots.Count;
- Skin skin = skeleton.Skin;
- if (skeleton.Skin == null)
- skin = skeleton.Data.DefaultSkin;
-
- currentSkinName = skin.Name;
- for(int i = 0; i < slotCount; i++){
- Slot slot = skeletonUtility.skeletonRenderer.skeleton.Slots.Items[i];
- if (slot.Bone == utilityBone.bone) {
- List attachments = new List();
-
-
- skin.FindAttachmentsForSlot(skeleton.FindSlotIndex(slot.Data.Name), attachments);
-
- List boundingBoxes = new List();
- foreach (var att in attachments) {
- if (att is BoundingBoxAttachment) {
- boundingBoxes.Add((BoundingBoxAttachment)att);
- }
- }
-
- if (boundingBoxes.Count > 0) {
- boundingBoxTable.Add(slot, boundingBoxes);
- }
- }
- }
-
- }
-
- 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 = "