From 0687826542add28649a0f17bb4cb041e8cb47735 Mon Sep 17 00:00:00 2001 From: pharan Date: Tue, 8 Mar 2016 12:00:19 +0800 Subject: [PATCH] SpineRenderSeparator --- .../Editor/SkeletonRendererInspector.cs | 30 +- .../Editor/SpineInspectorUtility.cs | 92 +++++ .../SpineInspectorUtility.cs.meta} | 6 +- .../Mesh Generation/DoubleBuffered.cs | 15 + .../Mesh Generation/DoubleBuffered.cs.meta | 12 + .../Mesh Generation/Submeshed/Arrays.meta | 9 + .../Arrays/ArraysSingleSubmeshGenerator.cs | 315 ++++++++++++++++++ .../ArraysSingleSubmeshGenerator.cs.meta | 12 + .../ArraysSubmeshedMeshGenerator.cs | 42 +-- .../ArraysSubmeshedMeshGenerator.cs.meta | 0 .../Submeshed/ISubmeshedMeshGenerator.cs | 12 +- .../Modules/SpineRenderSeparator.meta | 9 + .../Modules/SpineRenderSeparator/Editor.meta | 9 + .../Editor/SpineRenderSeparatorInspector.cs | 36 ++ .../SpineRenderSeparatorInspector.cs.meta | 12 + .../SpineRenderSeparator.cs | 63 ++++ .../SpineRenderSeparator.cs.meta | 12 + .../spine-unity/Modules/SubmeshRenderer.meta | 9 + .../Modules/SubmeshRenderer/Editor.meta | 9 + .../Editor/SubmeshRendererInspector.cs | 22 ++ .../Editor/SubmeshRendererInspector.cs.meta | 12 + .../SubmeshRenderer/SubmeshRenderer.cs | 63 ++++ .../SubmeshRenderer/SubmeshRenderer.cs.meta | 12 + .../Assets/spine-unity/SkeletonRenderer.cs | 93 +++--- .../Editor/SkeletonUtilityInspector.cs | 9 +- ...SkeletonUtilitySubmeshRendererInspector.cs | 79 ----- .../SkeletonUtility/SkeletonUtility.cs | 20 -- .../SkeletonUtilitySubmeshRenderer.cs | 70 ---- .../SkeletonUtilitySubmeshRenderer.cs.meta | 14 - 29 files changed, 799 insertions(+), 299 deletions(-) create mode 100644 spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs rename spine-unity/Assets/spine-unity/{SkeletonUtility/Editor/SkeletonUtilitySubmeshRendererInspector.cs.meta => Editor/SpineInspectorUtility.cs.meta} (52%) create mode 100644 spine-unity/Assets/spine-unity/Mesh Generation/DoubleBuffered.cs create mode 100644 spine-unity/Assets/spine-unity/Mesh Generation/DoubleBuffered.cs.meta create mode 100644 spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays.meta create mode 100644 spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays/ArraysSingleSubmeshGenerator.cs create mode 100644 spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays/ArraysSingleSubmeshGenerator.cs.meta rename spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/{ => Arrays}/ArraysSubmeshedMeshGenerator.cs (93%) rename spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/{ => Arrays}/ArraysSubmeshedMeshGenerator.cs.meta (100%) create mode 100644 spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator.meta create mode 100644 spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/Editor.meta create mode 100644 spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/Editor/SpineRenderSeparatorInspector.cs create mode 100644 spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/Editor/SpineRenderSeparatorInspector.cs.meta create mode 100644 spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/SpineRenderSeparator.cs create mode 100644 spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/SpineRenderSeparator.cs.meta create mode 100644 spine-unity/Assets/spine-unity/Modules/SubmeshRenderer.meta create mode 100644 spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/Editor.meta create mode 100644 spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/Editor/SubmeshRendererInspector.cs create mode 100644 spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/Editor/SubmeshRendererInspector.cs.meta create mode 100644 spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/SubmeshRenderer.cs create mode 100644 spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/SubmeshRenderer.cs.meta delete mode 100644 spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilitySubmeshRendererInspector.cs delete mode 100644 spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs delete mode 100644 spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs.meta diff --git a/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs b/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs index f2e46c9bd..95ec58550 100644 --- a/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs +++ b/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs @@ -30,7 +30,6 @@ *****************************************************************************/ using System; -using System.Reflection; using UnityEditor; using UnityEngine; @@ -40,9 +39,7 @@ public class SkeletonRendererInspector : Editor { protected SerializedProperty skeletonDataAsset, initialSkinName, normals, tangents, meshes, immutableTriangles, submeshSeparators, front, zSpacing; - private static MethodInfo EditorGUILayoutSortingLayerField; - protected SerializedObject rendererSerializedObject; - protected SerializedProperty sortingLayerIDProperty; + protected SpineInspectorUtility.SerializedSortingProperties sortingProperties; protected virtual void OnEnable () { SpineEditorUtilities.ConfirmInitialization(); @@ -56,11 +53,8 @@ public class SkeletonRendererInspector : Editor { front = serializedObject.FindProperty("frontFacing"); zSpacing = serializedObject.FindProperty("zSpacing"); - if(EditorGUILayoutSortingLayerField == null) - EditorGUILayoutSortingLayerField = typeof(EditorGUILayout).GetMethod("SortingLayerField", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(GUIContent), typeof(SerializedProperty), typeof(GUIStyle) }, null); - - rendererSerializedObject = new SerializedObject(((SkeletonRenderer)target).GetComponent()); - sortingLayerIDProperty = rendererSerializedObject.FindProperty("m_SortingLayerID"); + var renderer = ((SkeletonRenderer)target).GetComponent(); + sortingProperties = new SpineInspectorUtility.SerializedSortingProperties(renderer); } protected virtual void DrawInspectorGUI () { @@ -107,23 +101,7 @@ public class SkeletonRendererInspector : Editor { // Sorting Layers { - var renderer = component.GetComponent(); - if(renderer != null) { - EditorGUI.BeginChangeCheck(); - - if(EditorGUILayoutSortingLayerField != null && sortingLayerIDProperty != null) { - EditorGUILayoutSortingLayerField.Invoke(null, new object[] { new GUIContent("Sorting Layer"), sortingLayerIDProperty, EditorStyles.popup } ); - } else { - renderer.sortingLayerID = EditorGUILayout.IntField("Sorting Layer ID", renderer.sortingLayerID); - } - - renderer.sortingOrder = EditorGUILayout.IntField("Order in Layer", renderer.sortingOrder); - - if(EditorGUI.EndChangeCheck()) { - rendererSerializedObject.ApplyModifiedProperties(); - EditorUtility.SetDirty(renderer); - } - } + SpineInspectorUtility.SortingPropertyFields(sortingProperties, applyModifiedProperties: true); } // More Render Options... diff --git a/spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs b/spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs new file mode 100644 index 000000000..17ac9551a --- /dev/null +++ b/spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs @@ -0,0 +1,92 @@ +/****************************************************************************** + * 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; +using UnityEditor; +using System.Reflection; + +public static class SpineInspectorUtility { + + #region Sorting Layer Field Helpers + static readonly GUIContent SortingLayerLabel = new GUIContent("Sorting Layer"); + static readonly GUIContent OrderInLayerLabel = new GUIContent("Order in Layer"); + + static MethodInfo m_SortingLayerFieldMethod; + static MethodInfo SortingLayerFieldMethod { + get { + if (m_SortingLayerFieldMethod == null) + m_SortingLayerFieldMethod = typeof(EditorGUILayout).GetMethod("SortingLayerField", BindingFlags.Static | BindingFlags.NonPublic, null, new System.Type[] { typeof(GUIContent), typeof(SerializedProperty), typeof(GUIStyle) }, null); + + return m_SortingLayerFieldMethod; + } + } + + public struct SerializedSortingProperties { + public SerializedObject renderer; + public SerializedProperty sortingLayerID; + public SerializedProperty sortingOrder; + + public SerializedSortingProperties (Renderer r) { + renderer = new SerializedObject(r); + sortingLayerID = renderer.FindProperty("m_SortingLayerID"); + sortingOrder = renderer.FindProperty("m_SortingOrder"); + } + + public void ApplyModifiedProperties () { + renderer.ApplyModifiedProperties(); + } + } + + public static void SortingPropertyFields (SerializedSortingProperties prop, bool applyModifiedProperties) { + if (applyModifiedProperties) { + EditorGUI.BeginChangeCheck(); + SortingPropertyFields(prop.sortingLayerID, prop.sortingOrder); + if(EditorGUI.EndChangeCheck()) { + prop.ApplyModifiedProperties(); + EditorUtility.SetDirty(prop.renderer.targetObject); + } + } else { + SortingPropertyFields(prop.sortingLayerID, prop.sortingOrder); + } + } + + public static void SortingPropertyFields (SerializedProperty m_SortingLayerID, SerializedProperty m_SortingOrder) { + if (SpineInspectorUtility.SortingLayerFieldMethod != null && m_SortingLayerID != null) { + SpineInspectorUtility.SortingLayerFieldMethod.Invoke(null, new object[] { SortingLayerLabel, m_SortingLayerID, EditorStyles.popup } ); + } else { + EditorGUILayout.PropertyField(m_SortingLayerID); + } + + EditorGUILayout.PropertyField(m_SortingOrder, OrderInLayerLabel); + } + #endregion +} diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilitySubmeshRendererInspector.cs.meta b/spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs.meta similarity index 52% rename from spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilitySubmeshRendererInspector.cs.meta rename to spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs.meta index 3b5bd3485..3219ca0b6 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilitySubmeshRendererInspector.cs.meta +++ b/spine-unity/Assets/spine-unity/Editor/SpineInspectorUtility.cs.meta @@ -1,8 +1,12 @@ fileFormatVersion: 2 -guid: 67418e462bd4dc24e8c234b92f1d4d9b +guid: 663715b5714e2db499192c8d91ef1f86 +timeCreated: 1457404957 +licenseType: Free MonoImporter: serializedVersion: 2 defaultReferences: [] executionOrder: 0 icon: {instanceID: 0} userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Mesh Generation/DoubleBuffered.cs b/spine-unity/Assets/spine-unity/Mesh Generation/DoubleBuffered.cs new file mode 100644 index 000000000..aa1ff7626 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Mesh Generation/DoubleBuffered.cs @@ -0,0 +1,15 @@ +using UnityEngine; +using System.Collections; + +namespace Spine.Unity { + public class DoubleBuffered where T : new() { + readonly T a = new T(); + readonly T b = new T(); + bool usingA; + + public T GetNext () { + usingA = !usingA; + return usingA ? a : b; + } + } +} diff --git a/spine-unity/Assets/spine-unity/Mesh Generation/DoubleBuffered.cs.meta b/spine-unity/Assets/spine-unity/Mesh Generation/DoubleBuffered.cs.meta new file mode 100644 index 000000000..2e570e48d --- /dev/null +++ b/spine-unity/Assets/spine-unity/Mesh Generation/DoubleBuffered.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 08b76da7751523448a87e528c48a5399 +timeCreated: 1457396939 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays.meta b/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays.meta new file mode 100644 index 000000000..fab1117df --- /dev/null +++ b/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ce7d323baddaa244c8f9f45b38b68193 +folderAsset: yes +timeCreated: 1457398522 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays/ArraysSingleSubmeshGenerator.cs b/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays/ArraysSingleSubmeshGenerator.cs new file mode 100644 index 000000000..2f6e74bbd --- /dev/null +++ b/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays/ArraysSingleSubmeshGenerator.cs @@ -0,0 +1,315 @@ +using UnityEngine; +using System.Collections; + +namespace Spine.Unity { + public class ArraysSingleSubmeshGenerator : ISingleSubmeshGenerator { + + public float zSpacing = 0f; + + bool premultiplyVertexColors = true; + public bool PremultiplyVertexColors { get { return this.premultiplyVertexColors; } set { this.premultiplyVertexColors = value; } } + + public Mesh GenerateMesh (SubmeshInstruction instruction) { + float zSpacing = this.zSpacing; + float[] attVertBuffer = this.attachmentVertexBuffer; + Vector2[] uvs = this.meshUVs; + Color32[] colors32 = this.meshColors32; + Color32 color; + var attachmentList = this.attachmentListBuffer; + attachmentList.Clear(); + + // Ensure correct buffer sizes. + Vector3[] vertices = this.meshVertices; + + int instructionVertexCount = instruction.vertexCount; + bool newVertices = vertices == null || instructionVertexCount > vertices.Length; + if (newVertices) { + this.meshVertices = vertices = new Vector3[instructionVertexCount]; + this.meshColors32 = colors32 = new Color32[instructionVertexCount]; + this.meshUVs = uvs = new Vector2[instructionVertexCount]; + } else { + var zero = Vector3.zero; + for (int i = instructionVertexCount, n = this.meshVertices.Length; i < n; i++) + vertices[i] = zero; + } + + Vector3 meshBoundsMin; + Vector3 meshBoundsMax; + + int attachmentCount = instruction.endSlot - instruction.startSlot; + + // Initial values for manual Mesh Bounds calculation + if (attachmentCount <= 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 * (attachmentCount - 1); + } else { + meshBoundsMin.z = zSpacing * (attachmentCount - 1); + meshBoundsMax.z = 0f; + } + } + + int vertexIndex = 0; + var skeleton = instruction.skeleton; + var skeletonDrawOrderItems = skeleton.DrawOrder.Items; + float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b; + + // Push verts in this submesh + for (int slotIndex = instruction.startSlot, endSlot = instruction.endSlot; slotIndex < endSlot; slotIndex++) { + var slot = skeletonDrawOrderItems[slotIndex]; + var attachment = slot.attachment; + float z = slotIndex * zSpacing; + + var regionAttachment = attachment as RegionAttachment; + if (regionAttachment != null) { + attachmentList.Add(attachment); + regionAttachment.ComputeWorldVertices(slot.bone, attVertBuffer); + + float x1 = attVertBuffer[RegionAttachment.X1], y1 = attVertBuffer[RegionAttachment.Y1]; + float x2 = attVertBuffer[RegionAttachment.X2], y2 = attVertBuffer[RegionAttachment.Y2]; + float x3 = attVertBuffer[RegionAttachment.X3], y3 = attVertBuffer[RegionAttachment.Y3]; + float x4 = attVertBuffer[RegionAttachment.X4], y4 = attVertBuffer[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; + + color.a = (byte)(a * slot.a * regionAttachment.a); + if (this.premultiplyVertexColors) { + 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); + } else { + color.r = (byte)(r * slot.r * regionAttachment.r); color.g = (byte)(g * slot.g * regionAttachment.g); color.b = (byte)(b * slot.b * regionAttachment.b); + } + if (slot.data.blendMode == BlendMode.additive) color.a = 0; + colors32[vertexIndex] = color; colors32[vertexIndex + 1] = color; colors32[vertexIndex + 2] = color; colors32[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; + } else { + var meshAttachment = attachment as MeshAttachment; + if (meshAttachment != null) { + attachmentList.Add(attachment); + int meshVertexCount = meshAttachment.vertices.Length; + if (attVertBuffer.Length < meshVertexCount) this.attachmentVertexBuffer = attVertBuffer = new float[meshVertexCount]; + meshAttachment.ComputeWorldVertices(slot, attVertBuffer); + + color.a = (byte)(a * slot.a * meshAttachment.a); + if (this.premultiplyVertexColors) { + 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); + } else { + color.r = (byte)(r * slot.r * meshAttachment.r); + color.g = (byte)(g * slot.g * meshAttachment.g); + color.b = (byte)(b * slot.b * meshAttachment.b); + } + if (slot.data.blendMode == BlendMode.additive) color.a = 0; + + float[] attachmentUVs = meshAttachment.uvs; + for (int iii = 0; iii < meshVertexCount; iii += 2) { + float x = attVertBuffer[iii], y = attVertBuffer[iii + 1]; + vertices[vertexIndex].x = x; vertices[vertexIndex].y = y; vertices[vertexIndex].z = z; + colors32[vertexIndex] = color; uvs[vertexIndex].x = attachmentUVs[iii]; uvs[vertexIndex].y = attachmentUVs[iii + 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; + + vertexIndex++; + } + } else { + var weightedMeshAttachment = attachment as WeightedMeshAttachment; + if (weightedMeshAttachment != null) { + attachmentList.Add(attachment); + int meshVertexCount = weightedMeshAttachment.uvs.Length; + if (attVertBuffer.Length < meshVertexCount) this.attachmentVertexBuffer = attVertBuffer = new float[meshVertexCount]; + weightedMeshAttachment.ComputeWorldVertices(slot, attVertBuffer); + + color.a = (byte)(a * slot.a * weightedMeshAttachment.a); + if (this.premultiplyVertexColors) { + 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); + } else { + color.r = (byte)(r * slot.r * weightedMeshAttachment.r); + color.g = (byte)(g * slot.g * weightedMeshAttachment.g); + color.b = (byte)(b * slot.b * weightedMeshAttachment.b); + } + if (slot.data.blendMode == BlendMode.additive) color.a = 0; + + float[] attachmentUVs = weightedMeshAttachment.uvs; + for (int iii = 0; iii < meshVertexCount; iii += 2) { + float x = attVertBuffer[iii], y = attVertBuffer[iii + 1]; + vertices[vertexIndex].x = x; vertices[vertexIndex].y = y; vertices[vertexIndex].z = z; + colors32[vertexIndex] = color; + uvs[vertexIndex].x = attachmentUVs[iii]; uvs[vertexIndex].y = attachmentUVs[iii + 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; + + vertexIndex++; + } + } + } + } + } + + var smartMesh = this.doubleBufferedSmartMesh.GetNext(); + var mesh = smartMesh.mesh; + + bool structureDoesntMatch = newVertices || smartMesh.StructureDoesntMatch(attachmentList, instruction); + + // Push triangles in this submesh + if (structureDoesntMatch) { + mesh.Clear(); + + int triangleCount = instruction.triangleCount; + + int[] thisTriangles = this.triangles; + if (triangles == null || triangles.Length < triangleCount) { + this.triangles = thisTriangles = new int[triangleCount]; + } else if (triangles.Length > triangleCount) { + for (int i = triangleCount; i < triangles.Length; i++) + thisTriangles[i] = 0; + } + + // Iterate through submesh slots and store the triangles. + int triangleIndex = 0; + int afv = 0; // attachment first vertex, for single submesh, don't use instructions.firstVertexIndex + + for (int i = instruction.startSlot, n = instruction.endSlot; i < n; i++) { + var attachment = skeletonDrawOrderItems[i].attachment; + + if (attachment is RegionAttachment) { + thisTriangles[triangleIndex] = afv; thisTriangles[triangleIndex + 1] = afv + 2; thisTriangles[triangleIndex + 2] = afv + 1; + thisTriangles[triangleIndex + 3] = afv + 2; thisTriangles[triangleIndex + 4] = afv + 3; thisTriangles[triangleIndex + 5] = afv + 1; + + triangleIndex += 6; + afv += 4; + } else { + 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; + } + + for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii++, triangleIndex++) + thisTriangles[triangleIndex] = afv + attachmentTriangles[ii]; + + afv += attachmentVertexCount; + } + } // Done adding current submesh triangles + } + + Vector3 meshBoundsExtents = (meshBoundsMax - meshBoundsMin); + Vector3 meshCenter = meshBoundsMin + meshBoundsExtents * 0.5f; + + smartMesh.Set(this.meshVertices, this.meshUVs, this.meshColors32, attachmentList, instruction); + mesh.bounds = new Bounds(meshCenter, meshBoundsExtents); + + if (structureDoesntMatch) { + mesh.triangles = triangles; + } + + return smartMesh.mesh; + } + + readonly DoubleBuffered doubleBufferedSmartMesh = new DoubleBuffered(); + readonly ExposedList attachmentListBuffer = new ExposedList(); + + float[] attachmentVertexBuffer = new float[8]; + Vector3[] meshVertices; + Color32[] meshColors32; + Vector2[] meshUVs; + int[] triangles; + + class SmartMesh { + public readonly Mesh mesh = SpineMesh.NewMesh(); + SubmeshInstruction instructionsUsed; + readonly ExposedList attachmentsUsed = new ExposedList(); + + public void Set (Vector3[] verts, Vector2[] uvs, Color32[] colors, ExposedList attachmentList, SubmeshInstruction instructions) { + mesh.vertices = verts; + mesh.uv = uvs; + mesh.colors32 = colors; + instructionsUsed = instructions; + + attachmentsUsed.Clear(); + attachmentsUsed.GrowIfNeeded(attachmentList.Capacity); + attachmentsUsed.Count = attachmentList.Count; + attachmentList.CopyTo(attachmentsUsed.Items); + } + + public bool StructureDoesntMatch (ExposedList attachmentList, SubmeshInstruction instructions) { + // Check each submesh instructions for equal arrangement. + var thisInstructions = instructionsUsed; + if ( + instructions.skeleton != thisInstructions.skeleton || + instructions.material.GetInstanceID() != thisInstructions.material.GetInstanceID() || + instructions.startSlot != thisInstructions.startSlot || + instructions.endSlot != thisInstructions.endSlot || + instructions.triangleCount != thisInstructions.triangleCount || + instructions.vertexCount != thisInstructions.vertexCount + ) return true; + //Debug.Log("structure matched"); + + // Check count inequality. + if (attachmentList.Count != this.attachmentsUsed.Count) return true; + var attachmentsPassed = attachmentList.Items; + var myAttachments = this.attachmentsUsed.Items; + for (int i = 0, n = attachmentsUsed.Count; i < n; i++) + if (attachmentsPassed[i] != myAttachments[i]) return true; + + //Debug.Log("attachments matched"); + + return false; + } + } + } +} diff --git a/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays/ArraysSingleSubmeshGenerator.cs.meta b/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays/ArraysSingleSubmeshGenerator.cs.meta new file mode 100644 index 000000000..62a4b1275 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays/ArraysSingleSubmeshGenerator.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8bde87b725a537d4d9ff09a3ec7da8b5 +timeCreated: 1456493071 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/ArraysSubmeshedMeshGenerator.cs b/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays/ArraysSubmeshedMeshGenerator.cs similarity index 93% rename from spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/ArraysSubmeshedMeshGenerator.cs rename to spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays/ArraysSubmeshedMeshGenerator.cs index 9ab49e702..46e19b78b 100644 --- a/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/ArraysSubmeshedMeshGenerator.cs +++ b/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays/ArraysSubmeshedMeshGenerator.cs @@ -15,7 +15,7 @@ public class ArraysSubmeshedMeshGenerator : Spine.Unity.ISubmeshedMeshGenerator public float zSpacing = 0f; - public SubmeshedMeshInstructions GenerateInstructions (Skeleton skeleton) { + public SubmeshedMeshInstruction GenerateInstruction (Skeleton skeleton) { if (skeleton == null) throw new System.ArgumentNullException("skeleton"); // Count vertices and submesh triangles. @@ -33,9 +33,9 @@ public class ArraysSubmeshedMeshGenerator : Spine.Unity.ISubmeshedMeshGenerator int separatorCount = separators.Count; var instructionList = this.currentInstructions.submeshInstructions; - instructionList.Clear(); + instructionList.Clear(false); - currentInstructions.attachmentList.Clear(); + currentInstructions.attachmentList.Clear(false); for (int i = 0; i < drawOrderCount; i++) { var slot = drawOrderItems[i]; @@ -70,11 +70,10 @@ public class ArraysSubmeshedMeshGenerator : Spine.Unity.ISubmeshedMeshGenerator // Populate submesh when material changes. (or when forced to separate by a submeshSeparator) if (( runningVertexCount > 0 && lastMaterial.GetInstanceID() != attachmentMaterial.GetInstanceID() ) || - //if (( lastMaterial != null && lastMaterial.GetInstanceID() != attachmentMaterial.GetInstanceID() ) || ( separatorCount > 0 && separators.Contains(slot) )) { instructionList.Add( - new SubmeshInstructions { + new SubmeshInstruction { skeleton = skeleton, material = lastMaterial, triangleCount = submeshTriangleCount, @@ -101,7 +100,7 @@ public class ArraysSubmeshedMeshGenerator : Spine.Unity.ISubmeshedMeshGenerator } instructionList.Add( - new SubmeshInstructions { + new SubmeshInstruction { skeleton = skeleton, material = lastMaterial, triangleCount = submeshTriangleCount, @@ -116,7 +115,7 @@ public class ArraysSubmeshedMeshGenerator : Spine.Unity.ISubmeshedMeshGenerator return currentInstructions; } - public SubmeshedMesh GenerateMesh (SubmeshedMeshInstructions meshInstructions) { + public SubmeshedMesh GenerateMesh (SubmeshedMeshInstruction meshInstructions) { var smartMesh = doubleBufferedSmartMesh.GetNextMesh(); var mesh = smartMesh.mesh; @@ -406,7 +405,7 @@ public class ArraysSubmeshedMeshGenerator : Spine.Unity.ISubmeshedMeshGenerator #region Internals readonly DoubleBufferedSmartMesh doubleBufferedSmartMesh = new DoubleBufferedSmartMesh(); - readonly SubmeshedMeshInstructions currentInstructions = new SubmeshedMeshInstructions(); + readonly SubmeshedMeshInstruction currentInstructions = new SubmeshedMeshInstruction(); float[] attachmentVertexBuffer = new float[8]; Vector3[] meshVertices; @@ -442,39 +441,35 @@ public class ArraysSubmeshedMeshGenerator : Spine.Unity.ISubmeshedMeshGenerator class SmartMesh { public readonly Mesh mesh = SpineMesh.NewMesh(); readonly ExposedList attachmentsUsed = new ExposedList(); - readonly ExposedList instructionsUsed = new ExposedList(); + readonly ExposedList instructionsUsed = new ExposedList(); - public void Set (Vector3[] verts, Vector2[] uvs, Color32[] colors, SubmeshedMeshInstructions instructions) { + public void Set (Vector3[] verts, Vector2[] uvs, Color32[] colors, SubmeshedMeshInstruction instruction) { mesh.vertices = verts; mesh.uv = uvs; mesh.colors32 = colors; - attachmentsUsed.Clear(); - attachmentsUsed.GrowIfNeeded(instructions.attachmentList.Capacity); - attachmentsUsed.Count = instructions.attachmentList.Count; - instructions.attachmentList.CopyTo(attachmentsUsed.Items); + attachmentsUsed.Clear(false); + attachmentsUsed.GrowIfNeeded(instruction.attachmentList.Capacity); + attachmentsUsed.Count = instruction.attachmentList.Count; + instruction.attachmentList.CopyTo(attachmentsUsed.Items); - instructionsUsed.Clear(); - instructionsUsed.GrowIfNeeded(instructions.submeshInstructions.Capacity); - instructionsUsed.Count = instructions.submeshInstructions.Count; - instructions.submeshInstructions.CopyTo(instructionsUsed.Items); + instructionsUsed.Clear(false); + instructionsUsed.GrowIfNeeded(instruction.submeshInstructions.Capacity); + instructionsUsed.Count = instruction.submeshInstructions.Count; + instruction.submeshInstructions.CopyTo(instructionsUsed.Items); } - public bool StructureDoesntMatch (SubmeshedMeshInstructions instructions) { + public bool StructureDoesntMatch (SubmeshedMeshInstruction instructions) { // Check count inequality. if (instructions.attachmentList.Count != this.attachmentsUsed.Count) return true; if (instructions.submeshInstructions.Count != this.instructionsUsed.Count) return true; - //Debug.Log("broadphase matched"); - // Check each attachment. var attachmentsPassed = instructions.attachmentList.Items; var myAttachments = this.attachmentsUsed.Items; for (int i = 0, n = attachmentsUsed.Count; i < n; i++) if (attachmentsPassed[i] != myAttachments[i]) return true; - //Debug.Log("attachments matched"); - // Check each submesh for equal arrangement. var instructionListItems = instructions.submeshInstructions.Items; var myInstructions = this.instructionsUsed.Items; @@ -482,7 +477,6 @@ public class ArraysSubmeshedMeshGenerator : Spine.Unity.ISubmeshedMeshGenerator var lhs = instructionListItems[i]; var rhs = myInstructions[i]; if ( - lhs.skeleton != rhs.skeleton || lhs.material.GetInstanceID() != rhs.material.GetInstanceID() || lhs.startSlot != rhs.startSlot || lhs.endSlot != rhs.endSlot || diff --git a/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/ArraysSubmeshedMeshGenerator.cs.meta b/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays/ArraysSubmeshedMeshGenerator.cs.meta similarity index 100% rename from spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/ArraysSubmeshedMeshGenerator.cs.meta rename to spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/Arrays/ArraysSubmeshedMeshGenerator.cs.meta diff --git a/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/ISubmeshedMeshGenerator.cs b/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/ISubmeshedMeshGenerator.cs index 82030c6e2..87c0f869e 100644 --- a/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/ISubmeshedMeshGenerator.cs +++ b/spine-unity/Assets/spine-unity/Mesh Generation/Submeshed/ISubmeshedMeshGenerator.cs @@ -5,18 +5,18 @@ namespace Spine.Unity { public interface ISubmeshedMeshGenerator { /// Generates instructions for how to generate the submeshed mesh based on the given state of the /// skeleton. The returned instructions can be used to generate a whole submeshed mesh or individual submeshes. - SubmeshedMeshInstructions GenerateInstructions (Skeleton skeleton); + SubmeshedMeshInstruction GenerateInstruction (Skeleton skeleton); /// Returns a SubmeshedMesh (a mesh and a material array coupled in a struct). /// Call GenerateInstructions to get the SubmeshedMeshInstructions to pass into this. - SubmeshedMesh GenerateMesh (SubmeshedMeshInstructions wholeMeshInstruction); + SubmeshedMesh GenerateMesh (SubmeshedMeshInstruction wholeMeshInstruction); /// A list of slots that mark the end of a submesh. The slot after it will be the start of a new submesh. List Separators { get; } } public interface ISingleSubmeshGenerator { - void FillMesh (SubmeshInstructions instructions, Mesh meshToFill); + Mesh GenerateMesh (SubmeshInstruction instruction); } /// A Submeshed mesh is a return type so the mesh with @@ -31,8 +31,8 @@ namespace Spine.Unity { } /// Primarily a collection of Submesh Instructions. This constitutes instructions for how to construct a mesh containing submeshes. - public class SubmeshedMeshInstructions { - public readonly ExposedList submeshInstructions = new ExposedList(); + public class SubmeshedMeshInstruction { + public readonly ExposedList submeshInstructions = new ExposedList(); public readonly ExposedList attachmentList = new ExposedList(); public int vertexCount = -1; @@ -52,7 +52,7 @@ namespace Spine.Unity { } /// Instructions for how to generate a mesh or submesh out of a range of slots in a given skeleton. - public struct SubmeshInstructions { + public struct SubmeshInstruction { public Skeleton skeleton; public int startSlot; public int endSlot; diff --git a/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator.meta b/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator.meta new file mode 100644 index 000000000..72398a418 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3a361f5ac799a5149b340f9e20da27d1 +folderAsset: yes +timeCreated: 1457405502 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/Editor.meta b/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/Editor.meta new file mode 100644 index 000000000..1d2ca48c6 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 211465c9f045fd142abe552a6ffdc799 +folderAsset: yes +timeCreated: 1457405813 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/Editor/SpineRenderSeparatorInspector.cs b/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/Editor/SpineRenderSeparatorInspector.cs new file mode 100644 index 000000000..926587636 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/Editor/SpineRenderSeparatorInspector.cs @@ -0,0 +1,36 @@ +using UnityEngine; +using System.Collections; +using UnityEditor; +using Spine.Unity; + +[CustomEditor(typeof(SpineRenderSeparator))] +public class SpineRenderSeparatorInspector : Editor { + + SpineRenderSeparator component; + + void OnEnable () { + component = target as SpineRenderSeparator; + } + + public override void OnInspectorGUI () { + base.OnInspectorGUI(); + if (GUILayout.Button("Destroy Submesh Renderers")) { + if (EditorUtility.DisplayDialog("Destroy Submesh Renderers", "Do you really want to destroy all the SubmeshRenderer GameObjects in the list?", "Destroy", "Cancel")) { + + for (int i = 0; i < component.submeshRenderers.Count; i++) { + Debug.LogFormat("Destroying {0}", component.submeshRenderers[i].gameObject.name); + DestroyImmediate(component.submeshRenderers[i].gameObject); + } + + component.submeshRenderers.Clear(); + } + } + + if (GUILayout.Button("Add SubmeshRenderer")) { + int index = component.submeshRenderers.Count; + var smr = SubmeshRenderer.NewSubmeshRendererGameObject(component.transform, index.ToString()); + component.submeshRenderers.Add(smr); + } + } + +} diff --git a/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/Editor/SpineRenderSeparatorInspector.cs.meta b/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/Editor/SpineRenderSeparatorInspector.cs.meta new file mode 100644 index 000000000..d8ac8aa91 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/Editor/SpineRenderSeparatorInspector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d8742ee1d54c9954d95c9e6508806ac2 +timeCreated: 1457405832 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/SpineRenderSeparator.cs b/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/SpineRenderSeparator.cs new file mode 100644 index 000000000..b4dc1e4ca --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/SpineRenderSeparator.cs @@ -0,0 +1,63 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using Spine.Unity; + +[ExecuteInEditMode] +public class SpineRenderSeparator : MonoBehaviour { + [SerializeField] + protected SkeletonRenderer skeletonRenderer; + public SkeletonRenderer SkeletonRenderer { + get { return skeletonRenderer; } + set { + if (skeletonRenderer != null) + skeletonRenderer.GenerateMeshOverride -= SeparatelyRenderSubmeshes; + skeletonRenderer = value; + } + } + + MeshRenderer masterMeshRenderer; + + public List submeshRenderers = new List(); + public bool propagateMaterialPropertyBlock = false; + + void OnEnable () { + if (skeletonRenderer == null) return; + if (block == null) block = new MaterialPropertyBlock(); + masterMeshRenderer = skeletonRenderer.GetComponent(); + masterMeshRenderer.enabled = false; + skeletonRenderer.GenerateMeshOverride -= SeparatelyRenderSubmeshes; + skeletonRenderer.GenerateMeshOverride += SeparatelyRenderSubmeshes; + } + + void OnDisable () { + if (skeletonRenderer == null) return; + + masterMeshRenderer.enabled = true; + skeletonRenderer.GenerateMeshOverride -= SeparatelyRenderSubmeshes; + + foreach (var s in submeshRenderers) + s.ClearMesh(); + } + + MaterialPropertyBlock block; + + void SeparatelyRenderSubmeshes (SkeletonRenderer.SmartMesh.Instruction instruction) { + var submeshInstructions = instruction.submeshInstructions; + var submeshInstructionsItems = submeshInstructions.Items; + for (int i = 0; i < instruction.submeshInstructions.Count; i++) { + if (i >= submeshRenderers.Count) return; + var submeshRenderer = submeshRenderers[i]; + submeshRenderer.RenderSubmesh(submeshInstructionsItems[i]); + + if (propagateMaterialPropertyBlock) { + masterMeshRenderer.GetPropertyBlock(block); + submeshRenderer.SetPropertyBlock(block); + } + + } + } + + + +} diff --git a/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/SpineRenderSeparator.cs.meta b/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/SpineRenderSeparator.cs.meta new file mode 100644 index 000000000..0c344f753 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SpineRenderSeparator/SpineRenderSeparator.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5c70a5b35f6ff2541aed8e8346b7e4d5 +timeCreated: 1457405791 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer.meta b/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer.meta new file mode 100644 index 000000000..e72d52624 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 792af191c395561459cc0cc03a517ae8 +folderAsset: yes +timeCreated: 1457401769 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/Editor.meta b/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/Editor.meta new file mode 100644 index 000000000..589b9b4b2 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5eec1664658bb4344909619707652674 +folderAsset: yes +timeCreated: 1457405608 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/Editor/SubmeshRendererInspector.cs b/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/Editor/SubmeshRendererInspector.cs new file mode 100644 index 000000000..3fbceb67f --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/Editor/SubmeshRendererInspector.cs @@ -0,0 +1,22 @@ +using UnityEngine; +using System.Collections; +using UnityEditor; +using Spine.Unity; + +[CustomEditor(typeof(SubmeshRenderer))] +public class SubmeshRendererInspector : Editor { + + SpineInspectorUtility.SerializedSortingProperties sortingProperties; + SubmeshRenderer component; + + void OnEnable () { + component = target as SubmeshRenderer; + sortingProperties = new SpineInspectorUtility.SerializedSortingProperties(component.GetComponent()); + } + + public override void OnInspectorGUI () { + DrawDefaultInspector(); + SpineInspectorUtility.SortingPropertyFields(sortingProperties, true); + } + +} diff --git a/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/Editor/SubmeshRendererInspector.cs.meta b/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/Editor/SubmeshRendererInspector.cs.meta new file mode 100644 index 000000000..8a47d2273 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/Editor/SubmeshRendererInspector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 15418e02758268b488e9ab86f805330c +timeCreated: 1457407060 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/SubmeshRenderer.cs b/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/SubmeshRenderer.cs new file mode 100644 index 000000000..5a6eefe5c --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/SubmeshRenderer.cs @@ -0,0 +1,63 @@ +using UnityEngine; +using System.Collections; + +using UnityEngine.Assertions; + +namespace Spine.Unity { + [RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))] + public class SubmeshRenderer : MonoBehaviour { + ISingleSubmeshGenerator meshGenerator; + public ISingleSubmeshGenerator MeshGenerator { + get { + LazyIntialize(); + return meshGenerator; + } + } + + MeshRenderer meshRenderer; + public MeshRenderer MeshRenderer { + get { + LazyIntialize(); + return meshRenderer; + } + } + + MeshFilter meshFilter; + public MeshFilter MeshFilter { + get { + LazyIntialize(); + return meshFilter; + } + } + + void LazyIntialize () { + if (meshGenerator != null) return; + meshGenerator = new ArraysSingleSubmeshGenerator(); // swap this out with your custom ISingleSubmeshGenerator code. + meshFilter = GetComponent(); + meshRenderer = GetComponent(); + } + + public void ClearMesh () { + meshFilter.sharedMesh = null; + } + + public void RenderSubmesh (SubmeshInstruction instruction) { + LazyIntialize(); + meshRenderer.sharedMaterial = instruction.material; + meshFilter.sharedMesh = meshGenerator.GenerateMesh(instruction); + } + + public void SetPropertyBlock (MaterialPropertyBlock block) { + LazyIntialize(); + meshRenderer.SetPropertyBlock(block); + } + + public static SubmeshRenderer NewSubmeshRendererGameObject (Transform parent, string name) { + var go = new GameObject(name, typeof(MeshFilter), typeof(MeshRenderer)); + go.transform.SetParent(parent, false); + var returnComponent = go.AddComponent(); + + return returnComponent; + } + } +} diff --git a/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/SubmeshRenderer.cs.meta b/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/SubmeshRenderer.cs.meta new file mode 100644 index 000000000..a53a783d6 --- /dev/null +++ b/spine-unity/Assets/spine-unity/Modules/SubmeshRenderer/SubmeshRenderer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5273e5c60bd84a44db5a4e8f3252eef0 +timeCreated: 1457396525 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs index ac9da0756..346c3e8f9 100644 --- a/spine-unity/Assets/spine-unity/SkeletonRenderer.cs +++ b/spine-unity/Assets/spine-unity/SkeletonRenderer.cs @@ -32,6 +32,7 @@ using System; using System.Collections.Generic; using UnityEngine; using Spine; +using Spine.Unity; /// Renders a skeleton. [ExecuteInEditMode, RequireComponent(typeof(MeshFilter), typeof(MeshRenderer)), DisallowMultipleComponent] @@ -52,11 +53,15 @@ public class SkeletonRenderer : MonoBehaviour { // Submesh Separation [SpineSlot] public string[] submeshSeparators = new string[0]; - [HideInInspector] public List submeshSeparatorSlots = new List(); + [System.NonSerialized] public List submeshSeparatorSlots = new List(); // Custom Slot Material - [System.NonSerialized] private readonly Dictionary customSlotMaterials = new Dictionary(); + [System.NonSerialized] readonly Dictionary customSlotMaterials = new Dictionary(); public Dictionary CustomSlotMaterials { get { return customSlotMaterials; } } + + // Custom Mesh Generation Override + public delegate void InstructionDelegate (SkeletonRenderer.SmartMesh.Instruction instruction); + public event InstructionDelegate GenerateMeshOverride; #endregion [System.NonSerialized] public bool valid; @@ -65,7 +70,7 @@ public class SkeletonRenderer : MonoBehaviour { MeshRenderer meshRenderer; MeshFilter meshFilter; - DoubleBufferedSmartMesh doubleBufferedMesh; + Spine.Unity.DoubleBuffered doubleBufferedMesh; readonly SmartMesh.Instruction currentInstructions = new SmartMesh.Instruction(); readonly ExposedList submeshes = new ExposedList(); @@ -80,8 +85,6 @@ public class SkeletonRenderer : MonoBehaviour { Vector3[] normals; Vector4[] tangents; - SkeletonUtilitySubmeshRenderer[] submeshRenderers; - #region Runtime Instantiation public static T NewSpineGameObject (SkeletonDataAsset skeletonDataAsset) where T : SkeletonRenderer { return SkeletonRenderer.AddSpineComponent(new GameObject("New Spine GameObject"), skeletonDataAsset); @@ -140,7 +143,7 @@ public class SkeletonRenderer : MonoBehaviour { meshFilter = GetComponent(); meshRenderer = GetComponent(); - doubleBufferedMesh = new DoubleBufferedSmartMesh(); + doubleBufferedMesh = new DoubleBuffered(); vertices = new Vector3[0]; skeleton = new Skeleton(skeletonData); @@ -152,23 +155,17 @@ public class SkeletonRenderer : MonoBehaviour { submeshSeparatorSlots.Add(skeleton.FindSlot(submeshSeparators[i])); } - CollectSubmeshRenderers(); - LateUpdate(); if (OnRebuild != null) OnRebuild(this); } - public void CollectSubmeshRenderers () { - submeshRenderers = GetComponentsInChildren(); - } - public virtual void LateUpdate () { if (!valid) return; - if (!meshRenderer.enabled && submeshRenderers.Length == 0) + if (!meshRenderer.enabled && GenerateMeshOverride == null) return; // Step 1. Determine a SmartMesh.Instruction. Split up instructions into submeshes. @@ -202,6 +199,7 @@ public class SkeletonRenderer : MonoBehaviour { 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++) { @@ -261,16 +259,19 @@ public class SkeletonRenderer : MonoBehaviour { (submeshSeparatorSlotsCount > 0 && submeshSeparatorSlots.Contains(slot))) { workingSubmeshInstructions.Add( - new SmartMesh.Instruction.SubmeshInstruction { + new Spine.Unity.SubmeshInstruction { + skeleton = this.skeleton, material = lastMaterial, startSlot = submeshStartSlotIndex, endSlot = i, triangleCount = submeshTriangleCount, - firstVertex = submeshFirstVertex, + firstVertexIndex = submeshFirstVertex, + vertexCount = submeshVertexCount } ); submeshTriangleCount = 0; + submeshVertexCount = 0; submeshFirstVertex = vertexCount; submeshStartSlotIndex = i; } @@ -278,15 +279,18 @@ public class SkeletonRenderer : MonoBehaviour { submeshTriangleCount += attachmentTriangleCount; vertexCount += attachmentVertexCount; + submeshVertexCount += attachmentVertexCount; } workingSubmeshInstructions.Add( - new SmartMesh.Instruction.SubmeshInstruction { + new Spine.Unity.SubmeshInstruction { + skeleton = this.skeleton, material = lastMaterial, startSlot = submeshStartSlotIndex, endSlot = drawOrderCount, triangleCount = submeshTriangleCount, - firstVertex = submeshFirstVertex, + firstVertexIndex = submeshFirstVertex, + vertexCount = submeshVertexCount } ); @@ -294,6 +298,10 @@ public class SkeletonRenderer : MonoBehaviour { workingInstruction.immutableTriangles = this.immutableTriangles; workingInstruction.frontFacing = this.frontFacing; + if (GenerateMeshOverride != null) { + GenerateMeshOverride(workingInstruction); + return; + } // Step 2. Update vertex buffer based on verts from the attachments. // Uses values that were also stored in workingInstruction. @@ -509,7 +517,7 @@ public class SkeletonRenderer : MonoBehaviour { } // Step 3. Move the mesh data into a UnityEngine.Mesh - var currentSmartMesh = doubleBufferedMesh.GetNextMesh(); // Double-buffer for performance. + var currentSmartMesh = doubleBufferedMesh.GetNext(); // Double-buffer for performance. var currentMesh = currentSmartMesh.mesh; currentMesh.vertices = vertices; @@ -590,20 +598,7 @@ public class SkeletonRenderer : MonoBehaviour { // Step 5. Miscellaneous - // Submesh Renderers - if (submeshRenderers.Length > 0) { - var thisSharedMaterials = this.sharedMaterials; - for (int i = 0; i < submeshRenderers.Length; i++) { - SkeletonUtilitySubmeshRenderer submeshRenderer = submeshRenderers[i]; - if (submeshRenderer.submeshIndex < thisSharedMaterials.Length) { - submeshRenderer.SetMesh(meshRenderer, currentMesh, thisSharedMaterials[submeshRenderer.submeshIndex]); - } else { - submeshRenderer.GetComponent().enabled = false; - } - } - } - - + // Add stuff here if you want } static bool CheckIfMustUpdateMeshStructure (SmartMesh.Instruction a, SmartMesh.Instruction b) { @@ -613,6 +608,9 @@ public class SkeletonRenderer : MonoBehaviour { return true; #endif + if (a.vertexCount != b.vertexCount) + return true; + if (a.immutableTriangles != b.immutableTriangles) return true; @@ -652,22 +650,25 @@ public class SkeletonRenderer : MonoBehaviour { var submeshA = submeshInstructionsItemsA[i]; var submeshB = submeshInstructionsItemsB[i]; - if (!(submeshA.startSlot == submeshB.startSlot && + if (!( + submeshA.vertexCount == submeshB.vertexCount && + submeshA.startSlot == submeshB.startSlot && submeshA.endSlot == submeshB.endSlot && submeshA.triangleCount == submeshB.triangleCount && - submeshA.firstVertex == submeshB.firstVertex)) + submeshA.firstVertexIndex == submeshB.firstVertexIndex + )) return true; } return false; } - void SetSubmesh (int submeshIndex, SmartMesh.Instruction.SubmeshInstruction submeshInstructions, ExposedList flipStates, bool isLastSubmesh) { + void SetSubmesh (int submeshIndex, Spine.Unity.SubmeshInstruction submeshInstructions, ExposedList flipStates, bool isLastSubmesh) { SubmeshTriangleBuffer currentSubmesh = submeshes.Items[submeshIndex]; int[] triangles = currentSubmesh.triangles; int triangleCount = submeshInstructions.triangleCount; - int firstVertex = submeshInstructions.firstVertex; + int firstVertex = submeshInstructions.firstVertexIndex; int trianglesCapacity = triangles.Length; if (isLastSubmesh && trianglesCapacity > triangleCount) { @@ -787,19 +788,8 @@ public class SkeletonRenderer : MonoBehaviour { } #endif - class DoubleBufferedSmartMesh { - readonly SmartMesh mesh1 = new SmartMesh(); - readonly SmartMesh mesh2 = new SmartMesh(); - bool usingMesh1; - - public SmartMesh GetNextMesh () { - usingMesh1 = !usingMesh1; - return usingMesh1 ? mesh1 : mesh2; - } - } - ///This is a Mesh that also stores the instructions SkeletonRenderer generated for it. - class SmartMesh { + public class SmartMesh { public Mesh mesh = Spine.Unity.SpineMesh.NewMesh(); public SmartMesh.Instruction instructionUsed = new SmartMesh.Instruction(); @@ -809,11 +799,7 @@ public class SkeletonRenderer : MonoBehaviour { public int vertexCount = -1; public readonly ExposedList attachments = new ExposedList(); public readonly ExposedList attachmentFlips = new ExposedList(); - public readonly ExposedList submeshInstructions = new ExposedList(); - public struct SubmeshInstruction { - public Material material; - public int firstVertex, startSlot, endSlot, triangleCount; - } + public readonly ExposedList submeshInstructions = new ExposedList(); public void Clear () { this.attachments.Clear(false); @@ -824,7 +810,6 @@ public class SkeletonRenderer : MonoBehaviour { public void Set (Instruction other) { this.immutableTriangles = other.immutableTriangles; this.frontFacing = other.frontFacing; - //this.requiresUpdate = other.requiresUpdate; this.vertexCount = other.vertexCount; this.attachments.Clear(false); diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs index e6af51945..94079c6ad 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilityInspector.cs @@ -35,9 +35,7 @@ public class SkeletonUtilityInspector : Editor { break; } } - - - + typeof(EditorGUIUtility).InvokeMember("SetIconForObject", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic, null, null, new object[2] { utilityBone.gameObject, icon @@ -170,8 +168,9 @@ public class SkeletonUtilityInspector : Editor { } EditorGUI.EndDisabledGroup(); - if (GUILayout.Button(new GUIContent("Spawn Submeshes", SpineEditorUtilities.Icons.subMeshRenderer), GUILayout.Width(150), GUILayout.Height(24))) - skeletonUtility.SpawnSubRenderers(true); +// if (GUILayout.Button(new GUIContent("Spawn Submeshes", SpineEditorUtilities.Icons.subMeshRenderer), GUILayout.Width(150), GUILayout.Height(24))) +// skeletonUtility.SpawnSubRenderers(true); + GUILayout.EndHorizontal(); EditorGUI.BeginChangeCheck(); diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilitySubmeshRendererInspector.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilitySubmeshRendererInspector.cs deleted file mode 100644 index bcbaca61e..000000000 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/Editor/SkeletonUtilitySubmeshRendererInspector.cs +++ /dev/null @@ -1,79 +0,0 @@ -/****************************************************************************** - * 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 System; -using System.Collections; -using System.Reflection; - -[CustomEditor(typeof(SkeletonUtilitySubmeshRenderer))] -public class SkeletonUtilitySubmeshRendererInspector : Editor { - - private static MethodInfo EditorGUILayoutSortingLayerField; - protected SerializedObject rendererSerializedObject; - protected SerializedProperty sortingLayerIDProperty; - - SkeletonUtilitySubmeshRenderer component; - - void OnEnable () { - component = (SkeletonUtilitySubmeshRenderer)target; - - if (EditorGUILayoutSortingLayerField == null) - EditorGUILayoutSortingLayerField = typeof(EditorGUILayout).GetMethod("SortingLayerField", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[] { typeof(GUIContent), typeof(SerializedProperty), typeof(GUIStyle) }, null); - - rendererSerializedObject = new SerializedObject(((SkeletonUtilitySubmeshRenderer)target).GetComponent()); - sortingLayerIDProperty = rendererSerializedObject.FindProperty("m_SortingLayerID"); - } - - public override void OnInspectorGUI () { - // Sorting Layers - { - var renderer = component.GetComponent(); - if (renderer != null) { - EditorGUI.BeginChangeCheck(); - - if (EditorGUILayoutSortingLayerField != null && sortingLayerIDProperty != null) { - EditorGUILayoutSortingLayerField.Invoke(null, new object[] { new GUIContent("Sorting Layer"), sortingLayerIDProperty, EditorStyles.popup }); - } else { - renderer.sortingLayerID = EditorGUILayout.IntField("Sorting Layer ID", renderer.sortingLayerID); - } - - renderer.sortingOrder = EditorGUILayout.IntField("Order in Layer", renderer.sortingOrder); - - if (EditorGUI.EndChangeCheck()) { - rendererSerializedObject.ApplyModifiedProperties(); - EditorUtility.SetDirty(renderer); - } - } - } - } -} diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs index 2ff91eccd..5b95dc74d 100644 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs +++ b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtility.cs @@ -381,24 +381,4 @@ public class SkeletonUtility : MonoBehaviour { return go; } - public void SpawnSubRenderers (bool disablePrimaryRenderer) { - int submeshCount = GetComponent().sharedMesh.subMeshCount; - - for (int i = 0; i < submeshCount; i++) { - GameObject go = new GameObject("Submesh " + i, typeof(MeshFilter), typeof(MeshRenderer)); - go.transform.parent = transform; - go.transform.localPosition = Vector3.zero; - go.transform.localRotation = Quaternion.identity; - go.transform.localScale = Vector3.one; - - SkeletonUtilitySubmeshRenderer s = go.AddComponent(); - s.GetComponent().sortingOrder = i * 10; - s.submeshIndex = i; - } - - skeletonRenderer.CollectSubmeshRenderers(); - - if (disablePrimaryRenderer) - GetComponent().enabled = false; - } } diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs deleted file mode 100644 index a756314ba..000000000 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs +++ /dev/null @@ -1,70 +0,0 @@ -/****************************************************************************** - * 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; - -[ExecuteInEditMode] -public class SkeletonUtilitySubmeshRenderer : MonoBehaviour { - [System.NonSerialized] - public Mesh mesh; - public int submeshIndex = 0; - public Material hiddenPassMaterial; - Renderer cachedRenderer; - MeshFilter filter; - Material[] sharedMaterials; - - void Awake () { - cachedRenderer = GetComponent(); - filter = GetComponent(); - sharedMaterials = new Material[0]; - } - - public void SetMesh (Renderer parentRenderer, Mesh mesh, Material mat) { - if (cachedRenderer == null) - return; - - cachedRenderer.enabled = true; - filter.sharedMesh = mesh; - if (cachedRenderer.sharedMaterials.Length != parentRenderer.sharedMaterials.Length) { - sharedMaterials = parentRenderer.sharedMaterials; - } - - for (int i = 0; i < sharedMaterials.Length; i++) { - if (i == submeshIndex) - sharedMaterials[i] = mat; - else - sharedMaterials[i] = hiddenPassMaterial; - } - - cachedRenderer.sharedMaterials = sharedMaterials; - } -} diff --git a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs.meta b/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs.meta deleted file mode 100644 index a58d557e9..000000000 --- a/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilitySubmeshRenderer.cs.meta +++ /dev/null @@ -1,14 +0,0 @@ -fileFormatVersion: 2 -guid: 7820c1c2b0e52c6408de899d6939996e -MonoImporter: - serializedVersion: 2 - defaultReferences: - - parentRenderer: {instanceID: 0} - - mesh: {instanceID: 0} - - hiddenPassMaterial: {fileID: 2100000, guid: 43227e5adadc6f24bb4bf74b92a56fb4, - type: 2} - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: