diff --git a/spine-tk2d/Assets/Spine/Editor/SkeletonAnimationInspector.cs b/spine-tk2d/Assets/Spine/Editor/SkeletonAnimationInspector.cs index 0ca0e6dd1..1574b3cdc 100644 --- a/spine-tk2d/Assets/Spine/Editor/SkeletonAnimationInspector.cs +++ b/spine-tk2d/Assets/Spine/Editor/SkeletonAnimationInspector.cs @@ -47,29 +47,10 @@ public class SkeletonAnimationInspector : SkeletonRendererInspector { base.gui(); SkeletonAnimation component = (SkeletonAnimation)target; + if (!component.valid) return; - EditorGUILayout.PropertyField(skeletonDataAsset); - - if (component.valid) { - // Initial skin name. - String[] skins = new String[component.skeleton.Data.Skins.Count]; - int skinIndex = 0; - for (int i = 0; i < skins.Length; i++) { - String name = component.skeleton.Data.Skins[i].Name; - skins[i] = name; - if (name == initialSkinName.stringValue) - skinIndex = i; - } - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Initial Skin"); - EditorGUIUtility.LookLikeControls(); - skinIndex = EditorGUILayout.Popup(skinIndex, skins); - EditorGUILayout.EndHorizontal(); - - initialSkinName.stringValue = skins[skinIndex]; - - // Animation name. + // Animation name. + { String[] animations = new String[component.skeleton.Data.Animations.Count + 1]; animations[0] = ""; int animationIndex = 0; @@ -81,19 +62,15 @@ public class SkeletonAnimationInspector : SkeletonRendererInspector { } EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Animation"); - EditorGUIUtility.LookLikeControls(); + EditorGUILayout.LabelField("Animation", GUILayout.Width(EditorGUIUtility.labelWidth)); animationIndex = EditorGUILayout.Popup(animationIndex, animations); EditorGUILayout.EndHorizontal(); - component.animationName = animationIndex == 0 ? null : animations[animationIndex]; - animationName.stringValue = component.animationName; + String selectedAnimationName = animationIndex == 0 ? null : animations[animationIndex]; + component.AnimationName = selectedAnimationName; + animationName.stringValue = selectedAnimationName; } - // Animation loop. - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Loop"); - loop.boolValue = EditorGUILayout.Toggle(loop.boolValue); - EditorGUILayout.EndHorizontal(); + EditorGUILayout.PropertyField(loop); } } diff --git a/spine-tk2d/Assets/Spine/Editor/SkeletonRendererInspector.cs b/spine-tk2d/Assets/Spine/Editor/SkeletonRendererInspector.cs index eee9ca031..701400766 100644 --- a/spine-tk2d/Assets/Spine/Editor/SkeletonRendererInspector.cs +++ b/spine-tk2d/Assets/Spine/Editor/SkeletonRendererInspector.cs @@ -34,7 +34,7 @@ using UnityEngine; [CustomEditor(typeof(SkeletonRenderer))] public class SkeletonRendererInspector : Editor { - protected SerializedProperty skeletonDataAsset, initialSkinName, normals, tangents, meshes; + protected SerializedProperty skeletonDataAsset, initialSkinName, normals, tangents, meshes, immutableTriangles; protected virtual void OnEnable () { skeletonDataAsset = serializedObject.FindProperty("skeletonDataAsset"); @@ -42,15 +42,29 @@ public class SkeletonRendererInspector : Editor { normals = serializedObject.FindProperty("calculateNormals"); tangents = serializedObject.FindProperty("calculateTangents"); meshes = serializedObject.FindProperty("renderMeshes"); + immutableTriangles = serializedObject.FindProperty("immutableTriangles"); } protected virtual void gui () { - SkeletonRenderer component = (SkeletonRenderer)target; - EditorGUILayout.PropertyField(skeletonDataAsset); - - if (component.valid) { - // Initial skin name. + + SkeletonRenderer component = (SkeletonRenderer)target; + if (!component.valid) { + component.Reset(); + component.LateUpdate(); + if (!component.valid) { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.Space(); + if (GUILayout.Button("Refresh")) component.Reset(); + EditorGUILayout.Space(); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.Space(); + return; + } + } + + // Initial skin name. + { String[] skins = new String[component.skeleton.Data.Skins.Count]; int skinIndex = 0; for (int i = 0; i < skins.Length; i++) { @@ -61,15 +75,17 @@ public class SkeletonRendererInspector : Editor { } EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Initial Skin"); - EditorGUIUtility.LookLikeControls(); + EditorGUILayout.LabelField("Initial Skin", GUILayout.Width(EditorGUIUtility.labelWidth)); skinIndex = EditorGUILayout.Popup(skinIndex, skins); EditorGUILayout.EndHorizontal(); initialSkinName.stringValue = skins[skinIndex]; } - EditorGUILayout.PropertyField(meshes); + EditorGUILayout.PropertyField(meshes, + new GUIContent("Render Meshes", "Disable to optimize rendering for skeletons that don't use meshes")); + EditorGUILayout.PropertyField(immutableTriangles, + new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility")); EditorGUILayout.PropertyField(normals); EditorGUILayout.PropertyField(tangents); } diff --git a/spine-tk2d/Assets/Spine/SkeletonAnimation.cs b/spine-tk2d/Assets/Spine/SkeletonAnimation.cs index 63a4be1a5..cb490af27 100644 --- a/spine-tk2d/Assets/Spine/SkeletonAnimation.cs +++ b/spine-tk2d/Assets/Spine/SkeletonAnimation.cs @@ -44,8 +44,9 @@ public class SkeletonAnimation : SkeletonRenderer { public delegate void UpdateBonesDelegate(SkeletonAnimation skeleton); public UpdateBonesDelegate UpdateBones; - public String _animationName; - public String animationName { + [SerializeField] + private String _animationName; + public String AnimationName { get { TrackEntry entry = state.GetCurrent(0); return entry == null ? null : entry.Animation.Name; diff --git a/spine-tk2d/Assets/Spine/SkeletonRenderer.cs b/spine-tk2d/Assets/Spine/SkeletonRenderer.cs index 86d027e36..2c78c67c4 100644 --- a/spine-tk2d/Assets/Spine/SkeletonRenderer.cs +++ b/spine-tk2d/Assets/Spine/SkeletonRenderer.cs @@ -44,10 +44,9 @@ public class SkeletonRenderer : MonoBehaviour { public SkeletonDataAsset skeletonDataAsset; public String initialSkinName; - public bool calculateNormals; - public bool calculateTangents; + public bool calculateNormals, calculateTangents; public float zSpacing; - public bool renderMeshes; + public bool renderMeshes = true, immutableTriangles; private MeshFilter meshFilter; private Mesh mesh, mesh1, mesh2; @@ -60,8 +59,7 @@ public class SkeletonRenderer : MonoBehaviour { private Material[] sharedMaterials = new Material[0]; private readonly List submeshMaterials = new List(); private readonly List submeshes = new List(); - private readonly int[] quadTriangles = {0, 2, 1, 2, 3, 1}; - + public virtual void Reset () { if (meshFilter != null) meshFilter.sharedMesh = null; if (mesh != null) DestroyImmediate(mesh); @@ -111,7 +109,7 @@ public class SkeletonRenderer : MonoBehaviour { public virtual void LateUpdate () { if (!valid) return; - + // Count vertices and submesh triangles. int vertexCount = 0; int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0; @@ -280,8 +278,7 @@ public class SkeletonRenderer : MonoBehaviour { mesh.subMeshCount = submeshCount; for (int i = 0; i < submeshCount; ++i) mesh.SetTriangles(submeshes[i].triangles, i); - mesh.RecalculateBounds(); - + if (newTriangles && calculateNormals) { Vector3[] normals = new Vector3[vertexCount]; Vector3 normal = new Vector3(0, 0, -1); @@ -309,7 +306,11 @@ public class SkeletonRenderer : MonoBehaviour { int submeshIndex = submeshMaterials.Count; submeshMaterials.Add(material); - if (submeshes.Count <= submeshIndex) submeshes.Add(new Submesh()); + if (submeshes.Count <= submeshIndex) + submeshes.Add(new Submesh()); + else if (immutableTriangles) + return; + Submesh submesh = submeshes[submeshIndex]; int[] triangles = submesh.triangles; @@ -346,12 +347,20 @@ public class SkeletonRenderer : MonoBehaviour { List drawOrder = skeleton.DrawOrder; for (int i = startSlot, triangleIndex = 0; i < endSlot; i++) { Attachment attachment = drawOrder[i].attachment; + if (attachment is RegionAttachment) { + 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; + triangleIndex += 6; + firstVertex += 4; + continue; + } int[] attachmentTriangles; int attachmentVertexCount; - if (attachment is RegionAttachment) { - attachmentVertexCount = 4; - attachmentTriangles = quadTriangles; - } else if (attachment is MeshAttachment) { + if (attachment is MeshAttachment) { MeshAttachment meshAttachment = (MeshAttachment)attachment; attachmentVertexCount = meshAttachment.vertices.Length >> 1; attachmentTriangles = meshAttachment.triangles; @@ -376,8 +385,8 @@ public class SkeletonRenderer : MonoBehaviour { Vector3 min = new Vector3(float.MaxValue, float.MaxValue, 0f); Vector3 max = new Vector3(float.MinValue, float.MinValue, 0f); foreach (Vector3 vert in vertices) { - min = Vector3.Min (min, vert); - max = Vector3.Max (max, vert); + min = Vector3.Min(min, vert); + max = Vector3.Max(max, vert); } float width = max.x - min.x; float height = max.y - min.y; diff --git a/spine-tk2d/Assets/examples/goblins/goblins.unity b/spine-tk2d/Assets/examples/goblins/goblins.unity index f1c441262..1774f0ba3 100644 Binary files a/spine-tk2d/Assets/examples/goblins/goblins.unity and b/spine-tk2d/Assets/examples/goblins/goblins.unity differ diff --git a/spine-tk2d/Assets/examples/spineboy/spineboy.unity b/spine-tk2d/Assets/examples/spineboy/spineboy.unity index 49906cadd..c358e4804 100644 Binary files a/spine-tk2d/Assets/examples/spineboy/spineboy.unity and b/spine-tk2d/Assets/examples/spineboy/spineboy.unity differ diff --git a/spine-unity/Assets/Spine/Editor/SkeletonAnimationInspector.cs b/spine-unity/Assets/Spine/Editor/SkeletonAnimationInspector.cs index 0ca0e6dd1..1574b3cdc 100644 --- a/spine-unity/Assets/Spine/Editor/SkeletonAnimationInspector.cs +++ b/spine-unity/Assets/Spine/Editor/SkeletonAnimationInspector.cs @@ -47,29 +47,10 @@ public class SkeletonAnimationInspector : SkeletonRendererInspector { base.gui(); SkeletonAnimation component = (SkeletonAnimation)target; + if (!component.valid) return; - EditorGUILayout.PropertyField(skeletonDataAsset); - - if (component.valid) { - // Initial skin name. - String[] skins = new String[component.skeleton.Data.Skins.Count]; - int skinIndex = 0; - for (int i = 0; i < skins.Length; i++) { - String name = component.skeleton.Data.Skins[i].Name; - skins[i] = name; - if (name == initialSkinName.stringValue) - skinIndex = i; - } - - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Initial Skin"); - EditorGUIUtility.LookLikeControls(); - skinIndex = EditorGUILayout.Popup(skinIndex, skins); - EditorGUILayout.EndHorizontal(); - - initialSkinName.stringValue = skins[skinIndex]; - - // Animation name. + // Animation name. + { String[] animations = new String[component.skeleton.Data.Animations.Count + 1]; animations[0] = ""; int animationIndex = 0; @@ -81,19 +62,15 @@ public class SkeletonAnimationInspector : SkeletonRendererInspector { } EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Animation"); - EditorGUIUtility.LookLikeControls(); + EditorGUILayout.LabelField("Animation", GUILayout.Width(EditorGUIUtility.labelWidth)); animationIndex = EditorGUILayout.Popup(animationIndex, animations); EditorGUILayout.EndHorizontal(); - component.animationName = animationIndex == 0 ? null : animations[animationIndex]; - animationName.stringValue = component.animationName; + String selectedAnimationName = animationIndex == 0 ? null : animations[animationIndex]; + component.AnimationName = selectedAnimationName; + animationName.stringValue = selectedAnimationName; } - // Animation loop. - EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Loop"); - loop.boolValue = EditorGUILayout.Toggle(loop.boolValue); - EditorGUILayout.EndHorizontal(); + EditorGUILayout.PropertyField(loop); } } diff --git a/spine-unity/Assets/Spine/Editor/SkeletonRendererInspector.cs b/spine-unity/Assets/Spine/Editor/SkeletonRendererInspector.cs index eee9ca031..701400766 100644 --- a/spine-unity/Assets/Spine/Editor/SkeletonRendererInspector.cs +++ b/spine-unity/Assets/Spine/Editor/SkeletonRendererInspector.cs @@ -34,7 +34,7 @@ using UnityEngine; [CustomEditor(typeof(SkeletonRenderer))] public class SkeletonRendererInspector : Editor { - protected SerializedProperty skeletonDataAsset, initialSkinName, normals, tangents, meshes; + protected SerializedProperty skeletonDataAsset, initialSkinName, normals, tangents, meshes, immutableTriangles; protected virtual void OnEnable () { skeletonDataAsset = serializedObject.FindProperty("skeletonDataAsset"); @@ -42,15 +42,29 @@ public class SkeletonRendererInspector : Editor { normals = serializedObject.FindProperty("calculateNormals"); tangents = serializedObject.FindProperty("calculateTangents"); meshes = serializedObject.FindProperty("renderMeshes"); + immutableTriangles = serializedObject.FindProperty("immutableTriangles"); } protected virtual void gui () { - SkeletonRenderer component = (SkeletonRenderer)target; - EditorGUILayout.PropertyField(skeletonDataAsset); - - if (component.valid) { - // Initial skin name. + + SkeletonRenderer component = (SkeletonRenderer)target; + if (!component.valid) { + component.Reset(); + component.LateUpdate(); + if (!component.valid) { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.Space(); + if (GUILayout.Button("Refresh")) component.Reset(); + EditorGUILayout.Space(); + EditorGUILayout.EndHorizontal(); + EditorGUILayout.Space(); + return; + } + } + + // Initial skin name. + { String[] skins = new String[component.skeleton.Data.Skins.Count]; int skinIndex = 0; for (int i = 0; i < skins.Length; i++) { @@ -61,15 +75,17 @@ public class SkeletonRendererInspector : Editor { } EditorGUILayout.BeginHorizontal(); - EditorGUILayout.LabelField("Initial Skin"); - EditorGUIUtility.LookLikeControls(); + EditorGUILayout.LabelField("Initial Skin", GUILayout.Width(EditorGUIUtility.labelWidth)); skinIndex = EditorGUILayout.Popup(skinIndex, skins); EditorGUILayout.EndHorizontal(); initialSkinName.stringValue = skins[skinIndex]; } - EditorGUILayout.PropertyField(meshes); + EditorGUILayout.PropertyField(meshes, + new GUIContent("Render Meshes", "Disable to optimize rendering for skeletons that don't use meshes")); + EditorGUILayout.PropertyField(immutableTriangles, + new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility")); EditorGUILayout.PropertyField(normals); EditorGUILayout.PropertyField(tangents); } diff --git a/spine-unity/Assets/Spine/SkeletonAnimation.cs b/spine-unity/Assets/Spine/SkeletonAnimation.cs index 63a4be1a5..cb490af27 100644 --- a/spine-unity/Assets/Spine/SkeletonAnimation.cs +++ b/spine-unity/Assets/Spine/SkeletonAnimation.cs @@ -44,8 +44,9 @@ public class SkeletonAnimation : SkeletonRenderer { public delegate void UpdateBonesDelegate(SkeletonAnimation skeleton); public UpdateBonesDelegate UpdateBones; - public String _animationName; - public String animationName { + [SerializeField] + private String _animationName; + public String AnimationName { get { TrackEntry entry = state.GetCurrent(0); return entry == null ? null : entry.Animation.Name; diff --git a/spine-unity/Assets/Spine/SkeletonRenderer.cs b/spine-unity/Assets/Spine/SkeletonRenderer.cs index f6e450762..e632e458c 100644 --- a/spine-unity/Assets/Spine/SkeletonRenderer.cs +++ b/spine-unity/Assets/Spine/SkeletonRenderer.cs @@ -44,10 +44,9 @@ public class SkeletonRenderer : MonoBehaviour { public SkeletonDataAsset skeletonDataAsset; public String initialSkinName; - public bool calculateNormals; - public bool calculateTangents; + public bool calculateNormals, calculateTangents; public float zSpacing; - public bool renderMeshes; + public bool renderMeshes = true, immutableTriangles; private MeshFilter meshFilter; private Mesh mesh, mesh1, mesh2; @@ -60,8 +59,7 @@ public class SkeletonRenderer : MonoBehaviour { private Material[] sharedMaterials = new Material[0]; private readonly List submeshMaterials = new List(); private readonly List submeshes = new List(); - private readonly int[] quadTriangles = {0, 2, 1, 2, 3, 1}; - + public virtual void Reset () { if (meshFilter != null) meshFilter.sharedMesh = null; if (mesh != null) DestroyImmediate(mesh); @@ -280,8 +278,7 @@ public class SkeletonRenderer : MonoBehaviour { mesh.subMeshCount = submeshCount; for (int i = 0; i < submeshCount; ++i) mesh.SetTriangles(submeshes[i].triangles, i); - mesh.RecalculateBounds(); - + if (newTriangles && calculateNormals) { Vector3[] normals = new Vector3[vertexCount]; Vector3 normal = new Vector3(0, 0, -1); @@ -309,7 +306,11 @@ public class SkeletonRenderer : MonoBehaviour { int submeshIndex = submeshMaterials.Count; submeshMaterials.Add(material); - if (submeshes.Count <= submeshIndex) submeshes.Add(new Submesh()); + if (submeshes.Count <= submeshIndex) + submeshes.Add(new Submesh()); + else if (immutableTriangles) + return; + Submesh submesh = submeshes[submeshIndex]; int[] triangles = submesh.triangles; @@ -346,12 +347,20 @@ public class SkeletonRenderer : MonoBehaviour { List drawOrder = skeleton.DrawOrder; for (int i = startSlot, triangleIndex = 0; i < endSlot; i++) { Attachment attachment = drawOrder[i].attachment; + if (attachment is RegionAttachment) { + 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; + triangleIndex += 6; + firstVertex += 4; + continue; + } int[] attachmentTriangles; int attachmentVertexCount; - if (attachment is RegionAttachment) { - attachmentVertexCount = 4; - attachmentTriangles = quadTriangles; - } else if (attachment is MeshAttachment) { + if (attachment is MeshAttachment) { MeshAttachment meshAttachment = (MeshAttachment)attachment; attachmentVertexCount = meshAttachment.vertices.Length >> 1; attachmentTriangles = meshAttachment.triangles; @@ -376,8 +385,8 @@ public class SkeletonRenderer : MonoBehaviour { Vector3 min = new Vector3(float.MaxValue, float.MaxValue, 0f); Vector3 max = new Vector3(float.MinValue, float.MinValue, 0f); foreach (Vector3 vert in vertices) { - min = Vector3.Min (min, vert); - max = Vector3.Max (max, vert); + min = Vector3.Min(min, vert); + max = Vector3.Max(max, vert); } float width = max.x - min.x; float height = max.y - min.y; diff --git a/spine-unity/Assets/examples/dragon/dragon.unity b/spine-unity/Assets/examples/dragon/dragon.unity index 939e489cf..c2859118f 100644 Binary files a/spine-unity/Assets/examples/dragon/dragon.unity and b/spine-unity/Assets/examples/dragon/dragon.unity differ diff --git a/spine-unity/Assets/examples/goblins/goblins.mat b/spine-unity/Assets/examples/goblins/goblins Material.mat similarity index 92% rename from spine-unity/Assets/examples/goblins/goblins.mat rename to spine-unity/Assets/examples/goblins/goblins Material.mat index 0300f813e..84dfab0dc 100644 Binary files a/spine-unity/Assets/examples/goblins/goblins.mat and b/spine-unity/Assets/examples/goblins/goblins Material.mat differ diff --git a/spine-unity/Assets/examples/goblins/goblins.mat.meta b/spine-unity/Assets/examples/goblins/goblins Material.mat.meta similarity index 100% rename from spine-unity/Assets/examples/goblins/goblins.mat.meta rename to spine-unity/Assets/examples/goblins/goblins Material.mat.meta diff --git a/spine-unity/Assets/examples/goblins/goblins.unity b/spine-unity/Assets/examples/goblins/goblins.unity index 7e75e436b..8eda9d9cb 100644 Binary files a/spine-unity/Assets/examples/goblins/goblins.unity and b/spine-unity/Assets/examples/goblins/goblins.unity differ diff --git a/spine-unity/Assets/examples/spineboy/spineboy.unity b/spine-unity/Assets/examples/spineboy/spineboy.unity index 71b1709c7..79364779a 100644 Binary files a/spine-unity/Assets/examples/spineboy/spineboy.unity and b/spine-unity/Assets/examples/spineboy/spineboy.unity differ