Merge pull request #351 from Fenrisul/master

Null mesh cleanup fixed in SkeletonRenderer
This commit is contained in:
Fenrisul 2015-01-29 17:42:35 -08:00
commit 5275e921c8
2 changed files with 122 additions and 83 deletions

View File

@ -33,7 +33,7 @@ using UnityEngine;
[CustomEditor(typeof(SkeletonRenderer))] [CustomEditor(typeof(SkeletonRenderer))]
public class SkeletonRendererInspector : Editor { public class SkeletonRendererInspector : Editor {
protected SerializedProperty skeletonDataAsset, initialSkinName, normals, tangents, meshes, immutableTriangles, submeshSeparators; protected SerializedProperty skeletonDataAsset, initialSkinName, normals, tangents, meshes, immutableTriangles, submeshSeparators, front;
protected virtual void OnEnable () { protected virtual void OnEnable () {
SpineEditorUtilities.ConfirmInitialization(); SpineEditorUtilities.ConfirmInitialization();
@ -44,6 +44,7 @@ public class SkeletonRendererInspector : Editor {
meshes = serializedObject.FindProperty("renderMeshes"); meshes = serializedObject.FindProperty("renderMeshes");
immutableTriangles = serializedObject.FindProperty("immutableTriangles"); immutableTriangles = serializedObject.FindProperty("immutableTriangles");
submeshSeparators = serializedObject.FindProperty("submeshSeparators"); submeshSeparators = serializedObject.FindProperty("submeshSeparators");
front = serializedObject.FindProperty("frontFacing");
} }
protected virtual void gui () { protected virtual void gui () {
@ -97,6 +98,7 @@ public class SkeletonRendererInspector : Editor {
new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility")); new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility"));
EditorGUILayout.PropertyField(normals); EditorGUILayout.PropertyField(normals);
EditorGUILayout.PropertyField(tangents); EditorGUILayout.PropertyField(tangents);
EditorGUILayout.PropertyField(front);
EditorGUILayout.PropertyField(submeshSeparators, true); EditorGUILayout.PropertyField(submeshSeparators, true);
} }

View File

@ -38,7 +38,7 @@ using Spine;
[ExecuteInEditMode, RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))] [ExecuteInEditMode, RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class SkeletonRenderer : MonoBehaviour { public class SkeletonRenderer : MonoBehaviour {
public delegate void SkeletonRendererDelegate (SkeletonRenderer skeletonRenderer); public delegate void SkeletonRendererDelegate(SkeletonRenderer skeletonRenderer);
public SkeletonRendererDelegate OnReset; public SkeletonRendererDelegate OnReset;
[System.NonSerialized] [System.NonSerialized]
@ -50,6 +50,7 @@ public class SkeletonRenderer : MonoBehaviour {
public bool calculateNormals, calculateTangents; public bool calculateNormals, calculateTangents;
public float zSpacing; public float zSpacing;
public bool renderMeshes = true, immutableTriangles; public bool renderMeshes = true, immutableTriangles;
public bool frontFacing;
public bool logErrors = false; public bool logErrors = false;
[SpineSlot] [SpineSlot]
@ -70,9 +71,9 @@ public class SkeletonRenderer : MonoBehaviour {
private Material[] sharedMaterials = new Material[0]; private Material[] sharedMaterials = new Material[0];
private readonly List<Material> submeshMaterials = new List<Material>(); private readonly List<Material> submeshMaterials = new List<Material>();
private readonly List<Submesh> submeshes = new List<Submesh>(); private readonly List<Submesh> submeshes = new List<Submesh>();
public virtual void Reset () {
public virtual void Reset() {
if (meshFilter != null) if (meshFilter != null)
meshFilter.sharedMesh = null; meshFilter.sharedMesh = null;
if (renderer != null) if (renderer != null)
@ -99,12 +100,12 @@ public class SkeletonRenderer : MonoBehaviour {
if (skeletonData == null) if (skeletonData == null)
return; return;
valid = true; valid = true;
meshFilter = GetComponent<MeshFilter>(); meshFilter = GetComponent<MeshFilter>();
mesh1 = newMesh(); mesh1 = newMesh();
mesh2 = newMesh(); mesh2 = newMesh();
vertices = new Vector3[0]; vertices = new Vector3[0];
skeleton = new Skeleton(skeletonData); skeleton = new Skeleton(skeletonData);
if (initialSkinName != null && initialSkinName.Length > 0 && initialSkinName != "default") if (initialSkinName != null && initialSkinName.Length > 0 && initialSkinName != "default")
skeleton.SetSkin(initialSkinName); skeleton.SetSkin(initialSkinName);
@ -114,33 +115,44 @@ public class SkeletonRenderer : MonoBehaviour {
submeshSeparatorSlots.Add(skeleton.FindSlot(submeshSeparators[i])); submeshSeparatorSlots.Add(skeleton.FindSlot(submeshSeparators[i]));
} }
// Store flipped triangles for meshes
if (OnReset != null) if (OnReset != null)
OnReset(this); OnReset(this);
} }
public virtual void OnEnable() { public virtual void OnEnable() {
if(mesh1 == null || mesh2 == null) if (mesh1 == null || mesh2 == null)
Reset(); Reset();
} }
public virtual void OnDisable() { public virtual void OnDisable() {
if (Application.isPlaying && gameObject.activeInHierarchy == false) { if (Application.isPlaying && gameObject.activeInHierarchy == false) {
if (mesh1 != null) if (mesh1 != null) {
Destroy(mesh1); Destroy(mesh1);
if (mesh2 != null) mesh1 = null;
}
if (mesh2 != null) {
Destroy(mesh2); Destroy(mesh2);
mesh2 = null;
}
} }
} }
private Mesh newMesh () { private Mesh newMesh() {
Mesh mesh = new Mesh(); Mesh mesh = new Mesh();
mesh.name = "Skeleton Mesh"; mesh.name = "Skeleton Mesh";
mesh.hideFlags = HideFlags.HideAndDontSave; mesh.hideFlags = HideFlags.HideAndDontSave;
mesh.MarkDynamic(); mesh.MarkDynamic();
return mesh; return mesh;
} }
public virtual void LateUpdate () { public virtual void LateUpdate() {
if (!valid) if (!valid)
return; return;
// Count vertices and submesh triangles. // Count vertices and submesh triangles.
@ -154,10 +166,10 @@ public class SkeletonRenderer : MonoBehaviour {
for (int i = 0; i < drawOrderCount; i++) { for (int i = 0; i < drawOrderCount; i++) {
Slot slot = drawOrder[i]; Slot slot = drawOrder[i];
Attachment attachment = slot.attachment; Attachment attachment = slot.attachment;
object rendererObject; object rendererObject;
int attachmentVertexCount, attachmentTriangleCount; int attachmentVertexCount, attachmentTriangleCount;
if (attachment is RegionAttachment) { if (attachment is RegionAttachment) {
rendererObject = ((RegionAttachment)attachment).RendererObject; rendererObject = ((RegionAttachment)attachment).RendererObject;
attachmentVertexCount = 4; attachmentVertexCount = 4;
@ -171,12 +183,12 @@ public class SkeletonRenderer : MonoBehaviour {
attachmentVertexCount = meshAttachment.vertices.Length >> 1; attachmentVertexCount = meshAttachment.vertices.Length >> 1;
attachmentTriangleCount = meshAttachment.triangles.Length; attachmentTriangleCount = meshAttachment.triangles.Length;
} else if (attachment is SkinnedMeshAttachment) { } else if (attachment is SkinnedMeshAttachment) {
SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
rendererObject = meshAttachment.RendererObject; rendererObject = meshAttachment.RendererObject;
attachmentVertexCount = meshAttachment.uvs.Length >> 1; attachmentVertexCount = meshAttachment.uvs.Length >> 1;
attachmentTriangleCount = meshAttachment.triangles.Length; attachmentTriangleCount = meshAttachment.triangles.Length;
} else } else
continue; continue;
} }
// Populate submesh when material changes. // Populate submesh when material changes.
@ -189,19 +201,19 @@ public class SkeletonRenderer : MonoBehaviour {
submeshStartSlotIndex = i; submeshStartSlotIndex = i;
} }
lastMaterial = material; lastMaterial = material;
submeshTriangleCount += attachmentTriangleCount; submeshTriangleCount += attachmentTriangleCount;
vertexCount += attachmentVertexCount; vertexCount += attachmentVertexCount;
} }
AddSubmesh(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true); AddSubmesh(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true);
// Set materials. // Set materials.
if (submeshMaterials.Count == sharedMaterials.Length) if (submeshMaterials.Count == sharedMaterials.Length)
submeshMaterials.CopyTo(sharedMaterials); submeshMaterials.CopyTo(sharedMaterials);
else else
sharedMaterials = submeshMaterials.ToArray(); sharedMaterials = submeshMaterials.ToArray();
renderer.sharedMaterials = sharedMaterials; renderer.sharedMaterials = sharedMaterials;
// Ensure mesh data is the right size. // Ensure mesh data is the right size.
Vector3[] vertices = this.vertices; Vector3[] vertices = this.vertices;
bool newTriangles = vertexCount > vertices.Length; bool newTriangles = vertexCount > vertices.Length;
@ -219,7 +231,7 @@ public class SkeletonRenderer : MonoBehaviour {
vertices[i] = zero; vertices[i] = zero;
} }
lastVertexCount = vertexCount; lastVertexCount = vertexCount;
// Setup mesh. // Setup mesh.
float[] tempVertices = this.tempVertices; float[] tempVertices = this.tempVertices;
Vector2[] uvs = this.uvs; Vector2[] uvs = this.uvs;
@ -234,13 +246,13 @@ public class SkeletonRenderer : MonoBehaviour {
if (attachment is RegionAttachment) { if (attachment is RegionAttachment) {
RegionAttachment regionAttachment = (RegionAttachment)attachment; RegionAttachment regionAttachment = (RegionAttachment)attachment;
regionAttachment.ComputeWorldVertices(slot.bone, tempVertices); regionAttachment.ComputeWorldVertices(slot.bone, tempVertices);
float z = i * zSpacing; float z = i * zSpacing;
vertices[vertexIndex] = new Vector3(tempVertices[RegionAttachment.X1], tempVertices[RegionAttachment.Y1], z); vertices[vertexIndex] = new Vector3(tempVertices[RegionAttachment.X1], tempVertices[RegionAttachment.Y1], z);
vertices[vertexIndex + 1] = new Vector3(tempVertices[RegionAttachment.X4], tempVertices[RegionAttachment.Y4], z); vertices[vertexIndex + 1] = new Vector3(tempVertices[RegionAttachment.X4], tempVertices[RegionAttachment.Y4], z);
vertices[vertexIndex + 2] = new Vector3(tempVertices[RegionAttachment.X2], tempVertices[RegionAttachment.Y2], z); vertices[vertexIndex + 2] = new Vector3(tempVertices[RegionAttachment.X2], tempVertices[RegionAttachment.Y2], z);
vertices[vertexIndex + 3] = new Vector3(tempVertices[RegionAttachment.X3], tempVertices[RegionAttachment.Y3], z); vertices[vertexIndex + 3] = new Vector3(tempVertices[RegionAttachment.X3], tempVertices[RegionAttachment.Y3], z);
color.a = (byte)(a * slot.a * regionAttachment.a); color.a = (byte)(a * slot.a * regionAttachment.a);
color.r = (byte)(r * slot.r * regionAttachment.r * color.a); color.r = (byte)(r * slot.r * regionAttachment.r * color.a);
color.g = (byte)(g * slot.g * regionAttachment.g * color.a); color.g = (byte)(g * slot.g * regionAttachment.g * color.a);
@ -251,13 +263,13 @@ public class SkeletonRenderer : MonoBehaviour {
colors[vertexIndex + 1] = color; colors[vertexIndex + 1] = color;
colors[vertexIndex + 2] = color; colors[vertexIndex + 2] = color;
colors[vertexIndex + 3] = color; colors[vertexIndex + 3] = color;
float[] regionUVs = regionAttachment.uvs; float[] regionUVs = regionAttachment.uvs;
uvs[vertexIndex] = new Vector2(regionUVs[RegionAttachment.X1], regionUVs[RegionAttachment.Y1]); uvs[vertexIndex] = new Vector2(regionUVs[RegionAttachment.X1], regionUVs[RegionAttachment.Y1]);
uvs[vertexIndex + 1] = new Vector2(regionUVs[RegionAttachment.X4], regionUVs[RegionAttachment.Y4]); uvs[vertexIndex + 1] = new Vector2(regionUVs[RegionAttachment.X4], regionUVs[RegionAttachment.Y4]);
uvs[vertexIndex + 2] = new Vector2(regionUVs[RegionAttachment.X2], regionUVs[RegionAttachment.Y2]); uvs[vertexIndex + 2] = new Vector2(regionUVs[RegionAttachment.X2], regionUVs[RegionAttachment.Y2]);
uvs[vertexIndex + 3] = new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3]); uvs[vertexIndex + 3] = new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3]);
vertexIndex += 4; vertexIndex += 4;
} else { } else {
if (!renderMeshes) if (!renderMeshes)
@ -268,14 +280,14 @@ public class SkeletonRenderer : MonoBehaviour {
if (tempVertices.Length < meshVertexCount) if (tempVertices.Length < meshVertexCount)
this.tempVertices = tempVertices = new float[meshVertexCount]; this.tempVertices = tempVertices = new float[meshVertexCount];
meshAttachment.ComputeWorldVertices(slot, tempVertices); meshAttachment.ComputeWorldVertices(slot, tempVertices);
color.a = (byte)(a * slot.a * meshAttachment.a); color.a = (byte)(a * slot.a * meshAttachment.a);
color.r = (byte)(r * slot.r * meshAttachment.r * color.a); color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
color.b = (byte)(b * slot.b * meshAttachment.b * color.a); color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
if (slot.data.additiveBlending) if (slot.data.additiveBlending)
color.a = 0; color.a = 0;
float[] meshUVs = meshAttachment.uvs; float[] meshUVs = meshAttachment.uvs;
float z = i * zSpacing; float z = i * zSpacing;
for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {
@ -284,38 +296,38 @@ public class SkeletonRenderer : MonoBehaviour {
uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]); uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]);
} }
} else if (attachment is SkinnedMeshAttachment) { } else if (attachment is SkinnedMeshAttachment) {
SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
int meshVertexCount = meshAttachment.uvs.Length; int meshVertexCount = meshAttachment.uvs.Length;
if (tempVertices.Length < meshVertexCount) if (tempVertices.Length < meshVertexCount)
this.tempVertices = tempVertices = new float[meshVertexCount]; this.tempVertices = tempVertices = new float[meshVertexCount];
meshAttachment.ComputeWorldVertices(slot, tempVertices); meshAttachment.ComputeWorldVertices(slot, tempVertices);
color.a = (byte)(a * slot.a * meshAttachment.a); color.a = (byte)(a * slot.a * meshAttachment.a);
color.r = (byte)(r * slot.r * meshAttachment.r * color.a); color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
color.g = (byte)(g * slot.g * meshAttachment.g * color.a); color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
color.b = (byte)(b * slot.b * meshAttachment.b * color.a); color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
if (slot.data.additiveBlending) if (slot.data.additiveBlending)
color.a = 0; color.a = 0;
float[] meshUVs = meshAttachment.uvs; float[] meshUVs = meshAttachment.uvs;
float z = i * zSpacing; float z = i * zSpacing;
for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) { for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {
vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z); vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z);
colors[vertexIndex] = color; colors[vertexIndex] = color;
uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]); uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]);
}
} }
}
} }
} }
// Double buffer mesh. // Double buffer mesh.
Mesh mesh = useMesh1 ? mesh1 : mesh2; Mesh mesh = useMesh1 ? mesh1 : mesh2;
meshFilter.sharedMesh = mesh; meshFilter.sharedMesh = mesh;
mesh.vertices = vertices; mesh.vertices = vertices;
mesh.colors32 = colors; mesh.colors32 = colors;
mesh.uv = uvs; mesh.uv = uvs;
int submeshCount = submeshMaterials.Count; int submeshCount = submeshMaterials.Count;
mesh.subMeshCount = submeshCount; mesh.subMeshCount = submeshCount;
for (int i = 0; i < submeshCount; ++i) for (int i = 0; i < submeshCount; ++i)
@ -330,7 +342,7 @@ public class SkeletonRenderer : MonoBehaviour {
(useMesh1 ? mesh2 : mesh1).vertices = vertices; // Set other mesh vertices. (useMesh1 ? mesh2 : mesh1).vertices = vertices; // Set other mesh vertices.
mesh1.normals = normals; mesh1.normals = normals;
mesh2.normals = normals; mesh2.normals = normals;
if (calculateTangents) { if (calculateTangents) {
Vector4[] tangents = new Vector4[vertexCount]; Vector4[] tangents = new Vector4[vertexCount];
Vector3 tangent = new Vector3(0, 0, 1); Vector3 tangent = new Vector3(0, 0, 1);
@ -340,22 +352,22 @@ public class SkeletonRenderer : MonoBehaviour {
mesh2.tangents = tangents; mesh2.tangents = tangents;
} }
} }
useMesh1 = !useMesh1; useMesh1 = !useMesh1;
} }
/** Stores vertices and triangles for a single material. */ /** Stores vertices and triangles for a single material. */
private void AddSubmesh (Material material, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh) { private void AddSubmesh(Material material, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh) {
int submeshIndex = submeshMaterials.Count; int submeshIndex = submeshMaterials.Count;
submeshMaterials.Add(material); submeshMaterials.Add(material);
if (submeshes.Count <= submeshIndex) if (submeshes.Count <= submeshIndex)
submeshes.Add(new Submesh()); submeshes.Add(new Submesh());
else if (immutableTriangles) else if (immutableTriangles)
return; return;
Submesh submesh = submeshes[submeshIndex]; Submesh submesh = submeshes[submeshIndex];
int[] triangles = submesh.triangles; int[] triangles = submesh.triangles;
int trianglesCapacity = triangles.Length; int trianglesCapacity = triangles.Length;
if (lastSubmesh && trianglesCapacity > triangleCount) { if (lastSubmesh && trianglesCapacity > triangleCount) {
@ -364,17 +376,18 @@ public class SkeletonRenderer : MonoBehaviour {
triangles[i] = 0; triangles[i] = 0;
submesh.triangleCount = triangleCount; submesh.triangleCount = triangleCount;
} else if (trianglesCapacity != triangleCount) { } else if (trianglesCapacity != triangleCount) {
// Reallocate triangles when not the exact size needed. // Reallocate triangles when not the exact size needed.
submesh.triangles = triangles = new int[triangleCount]; submesh.triangles = triangles = new int[triangleCount];
submesh.triangleCount = 0; submesh.triangleCount = 0;
} }
if (!renderMeshes) { if (!renderMeshes && !frontFacing) {
// Use stored triangles if possible. // Use stored triangles if possible.
if (submesh.firstVertex != firstVertex || submesh.triangleCount < triangleCount) { if (submesh.firstVertex != firstVertex || submesh.triangleCount < triangleCount) {
submesh.triangleCount = triangleCount; submesh.triangleCount = triangleCount;
submesh.firstVertex = firstVertex; submesh.firstVertex = firstVertex;
for (int i = 0; i < triangleCount; i += 6, firstVertex += 4) { int drawOrderIndex = 0;
for (int i = 0; i < triangleCount; i += 6, firstVertex += 4, drawOrderIndex++) {
triangles[i] = firstVertex; triangles[i] = firstVertex;
triangles[i + 1] = firstVertex + 2; triangles[i + 1] = firstVertex + 2;
triangles[i + 2] = firstVertex + 1; triangles[i + 2] = firstVertex + 1;
@ -389,14 +402,27 @@ public class SkeletonRenderer : MonoBehaviour {
// Store triangles. // Store triangles.
List<Slot> drawOrder = skeleton.DrawOrder; List<Slot> drawOrder = skeleton.DrawOrder;
for (int i = startSlot, triangleIndex = 0; i < endSlot; i++) { for (int i = startSlot, triangleIndex = 0; i < endSlot; i++) {
Attachment attachment = drawOrder[i].attachment; Slot slot = drawOrder[i];
Attachment attachment = slot.attachment;
bool flip = frontFacing && ((slot.Bone.WorldFlipX != slot.Bone.WorldFlipY) != (Mathf.Sign(slot.Bone.WorldScaleX) != Mathf.Sign(slot.bone.WorldScaleY)));
if (attachment is RegionAttachment) { if (attachment is RegionAttachment) {
triangles[triangleIndex] = firstVertex; if (!flip) {
triangles[triangleIndex + 1] = firstVertex + 2; triangles[triangleIndex] = firstVertex;
triangles[triangleIndex + 2] = firstVertex + 1; triangles[triangleIndex + 1] = firstVertex + 2;
triangles[triangleIndex + 3] = firstVertex + 2; triangles[triangleIndex + 2] = firstVertex + 1;
triangles[triangleIndex + 4] = firstVertex + 3; triangles[triangleIndex + 3] = firstVertex + 2;
triangles[triangleIndex + 5] = firstVertex + 1; 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; triangleIndex += 6;
firstVertex += 4; firstVertex += 4;
continue; continue;
@ -408,17 +434,28 @@ public class SkeletonRenderer : MonoBehaviour {
attachmentVertexCount = meshAttachment.vertices.Length >> 1; attachmentVertexCount = meshAttachment.vertices.Length >> 1;
attachmentTriangles = meshAttachment.triangles; attachmentTriangles = meshAttachment.triangles;
} else if (attachment is SkinnedMeshAttachment) { } else if (attachment is SkinnedMeshAttachment) {
SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment; SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
attachmentVertexCount = meshAttachment.uvs.Length >> 1; attachmentVertexCount = meshAttachment.uvs.Length >> 1;
attachmentTriangles = meshAttachment.triangles; attachmentTriangles = meshAttachment.triangles;
} else } else
continue; continue;
for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii++, triangleIndex++)
triangles[triangleIndex] = firstVertex + attachmentTriangles[ii]; 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];
}
}
firstVertex += attachmentVertexCount; firstVertex += attachmentVertexCount;
} }
} }
#if UNITY_EDITOR #if UNITY_EDITOR
void OnDrawGizmos() { void OnDrawGizmos() {
// Make selection easier by drawing a clear gizmo over the skeleton. // Make selection easier by drawing a clear gizmo over the skeleton.
@ -434,7 +471,7 @@ public class SkeletonRenderer : MonoBehaviour {
float width = max.x - min.x; float width = max.x - min.x;
float height = max.y - min.y; float height = max.y - min.y;
gizmosCenter = new Vector3(min.x + (width / 2f), min.y + (height / 2f), 0f); gizmosCenter = new Vector3(min.x + (width / 2f), min.y + (height / 2f), 0f);
gizmosSize = new Vector3(width, height, 1f); gizmosSize = new Vector3(width, height, 1f);
Gizmos.color = Color.clear; Gizmos.color = Color.clear;
Gizmos.matrix = transform.localToWorldMatrix; Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.DrawCube(gizmosCenter, gizmosSize); Gizmos.DrawCube(gizmosCenter, gizmosSize);