|
@@ -30,7 +30,6 @@
|
|
*****************************************************************************/
|
|
*****************************************************************************/
|
|
|
|
|
|
using System;
|
|
using System;
|
|
-using System.IO;
|
|
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine;
|
|
using Spine;
|
|
using Spine;
|
|
@@ -65,14 +64,14 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
private Mesh mesh1, mesh2;
|
|
private Mesh mesh1, mesh2;
|
|
private bool useMesh1;
|
|
private bool useMesh1;
|
|
private float[] tempVertices = new float[8];
|
|
private float[] tempVertices = new float[8];
|
|
- private int lastVertexCount;
|
|
|
|
private Vector3[] vertices;
|
|
private Vector3[] vertices;
|
|
private Color32[] colors;
|
|
private Color32[] colors;
|
|
private Vector2[] uvs;
|
|
private Vector2[] uvs;
|
|
private Material[] sharedMaterials = new Material[0];
|
|
private Material[] sharedMaterials = new Material[0];
|
|
- private readonly List<Material> submeshMaterials = new List<Material>();
|
|
|
|
- private readonly List<Submesh> submeshes = new List<Submesh>();
|
|
|
|
|
|
+ private readonly ExposedList<Material> submeshMaterials = new ExposedList<Material>();
|
|
|
|
+ private readonly ExposedList<Submesh> submeshes = new ExposedList<Submesh>();
|
|
private SkeletonUtilitySubmeshRenderer[] submeshRenderers;
|
|
private SkeletonUtilitySubmeshRenderer[] submeshRenderers;
|
|
|
|
+ private LastState lastState = new LastState();
|
|
|
|
|
|
public virtual void Reset () {
|
|
public virtual void Reset () {
|
|
if (meshFilter != null)
|
|
if (meshFilter != null)
|
|
@@ -95,9 +94,9 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
DestroyImmediate(mesh2);
|
|
DestroyImmediate(mesh2);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ lastState = new LastState();
|
|
mesh1 = null;
|
|
mesh1 = null;
|
|
mesh2 = null;
|
|
mesh2 = null;
|
|
- lastVertexCount = 0;
|
|
|
|
vertices = null;
|
|
vertices = null;
|
|
colors = null;
|
|
colors = null;
|
|
uvs = null;
|
|
uvs = null;
|
|
@@ -119,6 +118,7 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
valid = true;
|
|
valid = true;
|
|
|
|
|
|
meshFilter = GetComponent<MeshFilter>();
|
|
meshFilter = GetComponent<MeshFilter>();
|
|
|
|
+ meshRenderer = GetComponent<MeshRenderer>();
|
|
mesh1 = newMesh();
|
|
mesh1 = newMesh();
|
|
mesh2 = newMesh();
|
|
mesh2 = newMesh();
|
|
vertices = new Vector3[0];
|
|
vertices = new Vector3[0];
|
|
@@ -178,40 +178,67 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
public virtual void LateUpdate () {
|
|
public virtual void LateUpdate () {
|
|
if (!valid)
|
|
if (!valid)
|
|
return;
|
|
return;
|
|
|
|
+
|
|
|
|
+ // Exit early if there is nothing to render
|
|
|
|
+ if (!meshRenderer.enabled && submeshRenderers.Length == 0)
|
|
|
|
+ return;
|
|
|
|
+
|
|
// Count vertices and submesh triangles.
|
|
// Count vertices and submesh triangles.
|
|
int vertexCount = 0;
|
|
int vertexCount = 0;
|
|
int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;
|
|
int submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;
|
|
Material lastMaterial = null;
|
|
Material lastMaterial = null;
|
|
- submeshMaterials.Clear();
|
|
|
|
- List<Slot> drawOrder = skeleton.DrawOrder;
|
|
|
|
|
|
+ ExposedList<Slot> drawOrder = skeleton.drawOrder;
|
|
int drawOrderCount = drawOrder.Count;
|
|
int drawOrderCount = drawOrder.Count;
|
|
|
|
+ int submeshSeparatorSlotsCount = submeshSeparatorSlots.Count;
|
|
bool renderMeshes = this.renderMeshes;
|
|
bool renderMeshes = this.renderMeshes;
|
|
|
|
+
|
|
|
|
+ // Clear last state of attachments and submeshes
|
|
|
|
+ ExposedList<int> attachmentsTriangleCountTemp = lastState.attachmentsTriangleCountTemp;
|
|
|
|
+ attachmentsTriangleCountTemp.GrowIfNeeded(drawOrderCount);
|
|
|
|
+ attachmentsTriangleCountTemp.Count = drawOrderCount;
|
|
|
|
+ ExposedList<bool> attachmentsFlipStateTemp = lastState.attachmentsFlipStateTemp;
|
|
|
|
+ attachmentsFlipStateTemp.GrowIfNeeded(drawOrderCount);
|
|
|
|
+ attachmentsFlipStateTemp.Count = drawOrderCount;
|
|
|
|
+
|
|
|
|
+ ExposedList<LastState.AddSubmeshArguments> addSubmeshArgumentsTemp = lastState.addSubmeshArgumentsTemp;
|
|
|
|
+ addSubmeshArgumentsTemp.Clear(false);
|
|
for (int i = 0; i < drawOrderCount; i++) {
|
|
for (int i = 0; i < drawOrderCount; i++) {
|
|
- Slot slot = drawOrder[i];
|
|
|
|
|
|
+ Slot slot = drawOrder.Items[i];
|
|
|
|
+ Bone bone = slot.bone;
|
|
Attachment attachment = slot.attachment;
|
|
Attachment attachment = slot.attachment;
|
|
|
|
|
|
object rendererObject;
|
|
object rendererObject;
|
|
int attachmentVertexCount, attachmentTriangleCount;
|
|
int attachmentVertexCount, attachmentTriangleCount;
|
|
-
|
|
|
|
- if (attachment is RegionAttachment) {
|
|
|
|
- rendererObject = ((RegionAttachment)attachment).RendererObject;
|
|
|
|
|
|
+ bool worldScaleXIsPositive = bone.worldScaleX >= 0f;
|
|
|
|
+ bool worldScaleYIsPositive = bone.worldScaleY >= 0f;
|
|
|
|
+ bool worldScaleIsSameSigns = (worldScaleXIsPositive && worldScaleYIsPositive) ||
|
|
|
|
+ (!worldScaleXIsPositive && !worldScaleYIsPositive);
|
|
|
|
+ bool flip = frontFacing && ((bone.worldFlipX != bone.worldFlipY) == worldScaleIsSameSigns);
|
|
|
|
+ attachmentsFlipStateTemp.Items[i] = flip;
|
|
|
|
+
|
|
|
|
+ attachmentsTriangleCountTemp.Items[i] = -1;
|
|
|
|
+ RegionAttachment regionAttachment = attachment as RegionAttachment;
|
|
|
|
+ if (regionAttachment != null) {
|
|
|
|
+ rendererObject = regionAttachment.RendererObject;
|
|
attachmentVertexCount = 4;
|
|
attachmentVertexCount = 4;
|
|
attachmentTriangleCount = 6;
|
|
attachmentTriangleCount = 6;
|
|
} else {
|
|
} else {
|
|
if (!renderMeshes)
|
|
if (!renderMeshes)
|
|
continue;
|
|
continue;
|
|
- if (attachment is MeshAttachment) {
|
|
|
|
- MeshAttachment meshAttachment = (MeshAttachment)attachment;
|
|
|
|
|
|
+ MeshAttachment meshAttachment = attachment as MeshAttachment;
|
|
|
|
+ if (meshAttachment != null) {
|
|
rendererObject = meshAttachment.RendererObject;
|
|
rendererObject = meshAttachment.RendererObject;
|
|
attachmentVertexCount = meshAttachment.vertices.Length >> 1;
|
|
attachmentVertexCount = meshAttachment.vertices.Length >> 1;
|
|
attachmentTriangleCount = meshAttachment.triangles.Length;
|
|
attachmentTriangleCount = meshAttachment.triangles.Length;
|
|
- } else if (attachment is SkinnedMeshAttachment) {
|
|
|
|
- SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
|
|
|
|
- rendererObject = meshAttachment.RendererObject;
|
|
|
|
- attachmentVertexCount = meshAttachment.uvs.Length >> 1;
|
|
|
|
- attachmentTriangleCount = meshAttachment.triangles.Length;
|
|
|
|
- } else
|
|
|
|
- continue;
|
|
|
|
|
|
+ } else {
|
|
|
|
+ SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment;
|
|
|
|
+ if (skinnedMeshAttachment != null) {
|
|
|
|
+ rendererObject = skinnedMeshAttachment.RendererObject;
|
|
|
|
+ attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1;
|
|
|
|
+ attachmentTriangleCount = skinnedMeshAttachment.triangles.Length;
|
|
|
|
+ } else
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// Populate submesh when material changes.
|
|
// Populate submesh when material changes.
|
|
@@ -220,9 +247,11 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
#else
|
|
#else
|
|
Material material = (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject;
|
|
Material material = (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject;
|
|
#endif
|
|
#endif
|
|
-
|
|
|
|
- if ((lastMaterial != material && lastMaterial != null) || submeshSeparatorSlots.Contains(slot)) {
|
|
|
|
- AddSubmesh(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false);
|
|
|
|
|
|
+ if ((lastMaterial != null && lastMaterial.GetInstanceID() != material.GetInstanceID()) ||
|
|
|
|
+ (submeshSeparatorSlotsCount > 0 && submeshSeparatorSlots.Contains(slot))) {
|
|
|
|
+ addSubmeshArgumentsTemp.Add(
|
|
|
|
+ new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false)
|
|
|
|
+ );
|
|
submeshTriangleCount = 0;
|
|
submeshTriangleCount = 0;
|
|
submeshFirstVertex = vertexCount;
|
|
submeshFirstVertex = vertexCount;
|
|
submeshStartSlotIndex = i;
|
|
submeshStartSlotIndex = i;
|
|
@@ -231,15 +260,37 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
|
|
|
|
submeshTriangleCount += attachmentTriangleCount;
|
|
submeshTriangleCount += attachmentTriangleCount;
|
|
vertexCount += attachmentVertexCount;
|
|
vertexCount += attachmentVertexCount;
|
|
|
|
+
|
|
|
|
+ attachmentsTriangleCountTemp.Items[i] = attachmentTriangleCount;
|
|
}
|
|
}
|
|
- AddSubmesh(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true);
|
|
|
|
|
|
+ addSubmeshArgumentsTemp.Add(
|
|
|
|
+ new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true)
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ bool mustUpdateMeshStructure = CheckIfMustUpdateMeshStructure(attachmentsTriangleCountTemp, attachmentsFlipStateTemp, addSubmeshArgumentsTemp);
|
|
|
|
+ if (mustUpdateMeshStructure) {
|
|
|
|
+ submeshMaterials.Clear();
|
|
|
|
+ for (int i = 0, n = addSubmeshArgumentsTemp.Count; i < n; i++) {
|
|
|
|
+ LastState.AddSubmeshArguments arguments = addSubmeshArgumentsTemp.Items[i];
|
|
|
|
+ AddSubmesh(
|
|
|
|
+ arguments.material,
|
|
|
|
+ arguments.startSlot,
|
|
|
|
+ arguments.endSlot,
|
|
|
|
+ arguments.triangleCount,
|
|
|
|
+ arguments.firstVertex,
|
|
|
|
+ arguments.lastSubmesh,
|
|
|
|
+ attachmentsFlipStateTemp
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Set materials.
|
|
|
|
+ if (submeshMaterials.Count == sharedMaterials.Length)
|
|
|
|
+ submeshMaterials.CopyTo(sharedMaterials);
|
|
|
|
+ else
|
|
|
|
+ sharedMaterials = submeshMaterials.ToArray();
|
|
|
|
|
|
- // Set materials.
|
|
|
|
- if (submeshMaterials.Count == sharedMaterials.Length)
|
|
|
|
- submeshMaterials.CopyTo(sharedMaterials);
|
|
|
|
- else
|
|
|
|
- sharedMaterials = submeshMaterials.ToArray();
|
|
|
|
- meshRenderer.sharedMaterials = sharedMaterials;
|
|
|
|
|
|
+ meshRenderer.sharedMaterials = sharedMaterials;
|
|
|
|
+ }
|
|
|
|
|
|
// Ensure mesh data is the right size.
|
|
// Ensure mesh data is the right size.
|
|
Vector3[] vertices = this.vertices;
|
|
Vector3[] vertices = this.vertices;
|
|
@@ -254,31 +305,48 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
} else {
|
|
} else {
|
|
// Too many vertices, zero the extra.
|
|
// Too many vertices, zero the extra.
|
|
Vector3 zero = Vector3.zero;
|
|
Vector3 zero = Vector3.zero;
|
|
- for (int i = vertexCount, n = lastVertexCount; i < n; i++)
|
|
|
|
|
|
+ for (int i = vertexCount, n = lastState.vertexCount ; i < n; i++)
|
|
vertices[i] = zero;
|
|
vertices[i] = zero;
|
|
}
|
|
}
|
|
- lastVertexCount = vertexCount;
|
|
|
|
|
|
+ lastState.vertexCount = vertexCount;
|
|
|
|
|
|
// Setup mesh.
|
|
// Setup mesh.
|
|
|
|
+ float zSpacing = this.zSpacing;
|
|
float[] tempVertices = this.tempVertices;
|
|
float[] tempVertices = this.tempVertices;
|
|
Vector2[] uvs = this.uvs;
|
|
Vector2[] uvs = this.uvs;
|
|
Color32[] colors = this.colors;
|
|
Color32[] colors = this.colors;
|
|
int vertexIndex = 0;
|
|
int vertexIndex = 0;
|
|
- Color32 color = new Color32();
|
|
|
|
- float zSpacing = this.zSpacing;
|
|
|
|
|
|
+ Color32 color;
|
|
float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b;
|
|
float a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b;
|
|
|
|
+
|
|
|
|
+ Vector3 meshBoundsMin;
|
|
|
|
+ meshBoundsMin.x = float.MaxValue;
|
|
|
|
+ meshBoundsMin.y = float.MaxValue;
|
|
|
|
+ meshBoundsMin.z = zSpacing > 0f ? 0f : zSpacing * (drawOrderCount - 1);
|
|
|
|
+ Vector3 meshBoundsMax;
|
|
|
|
+ meshBoundsMax.x = float.MinValue;
|
|
|
|
+ meshBoundsMax.y = float.MinValue;
|
|
|
|
+ meshBoundsMax.z = zSpacing < 0f ? 0f : zSpacing * (drawOrderCount - 1);
|
|
for (int i = 0; i < drawOrderCount; i++) {
|
|
for (int i = 0; i < drawOrderCount; i++) {
|
|
- Slot slot = drawOrder[i];
|
|
|
|
|
|
+ Slot slot = drawOrder.Items[i];
|
|
Attachment attachment = slot.attachment;
|
|
Attachment attachment = slot.attachment;
|
|
- if (attachment is RegionAttachment) {
|
|
|
|
- RegionAttachment regionAttachment = (RegionAttachment)attachment;
|
|
|
|
|
|
+ RegionAttachment regionAttachment = attachment as RegionAttachment;
|
|
|
|
+ if (regionAttachment != null) {
|
|
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 + 1] = new Vector3(tempVertices[RegionAttachment.X4], tempVertices[RegionAttachment.Y4], 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].x = tempVertices[RegionAttachment.X1];
|
|
|
|
+ vertices[vertexIndex].y = tempVertices[RegionAttachment.Y1];
|
|
|
|
+ vertices[vertexIndex].z = z;
|
|
|
|
+ vertices[vertexIndex + 1].x = tempVertices[RegionAttachment.X4];
|
|
|
|
+ vertices[vertexIndex + 1].y = tempVertices[RegionAttachment.Y4];
|
|
|
|
+ vertices[vertexIndex + 1].z = z;
|
|
|
|
+ vertices[vertexIndex + 2].x = tempVertices[RegionAttachment.X2];
|
|
|
|
+ vertices[vertexIndex + 2].y = tempVertices[RegionAttachment.Y2];
|
|
|
|
+ vertices[vertexIndex + 2].z = z;
|
|
|
|
+ vertices[vertexIndex + 3].x = tempVertices[RegionAttachment.X3];
|
|
|
|
+ vertices[vertexIndex + 3].y = tempVertices[RegionAttachment.Y3];
|
|
|
|
+ vertices[vertexIndex + 3].z = 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);
|
|
@@ -291,17 +359,57 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
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 + 1] = new Vector2(regionUVs[RegionAttachment.X4], regionUVs[RegionAttachment.Y4]);
|
|
|
|
- uvs[vertexIndex + 2] = new Vector2(regionUVs[RegionAttachment.X2], regionUVs[RegionAttachment.Y2]);
|
|
|
|
- uvs[vertexIndex + 3] = new Vector2(regionUVs[RegionAttachment.X3], regionUVs[RegionAttachment.Y3]);
|
|
|
|
|
|
+ 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 (tempVertices[RegionAttachment.X1] < meshBoundsMin.x)
|
|
|
|
+ meshBoundsMin.x = tempVertices[RegionAttachment.X1];
|
|
|
|
+ else if (tempVertices[RegionAttachment.X1] > meshBoundsMax.x)
|
|
|
|
+ meshBoundsMax.x = tempVertices[RegionAttachment.X1];
|
|
|
|
+ if (tempVertices[RegionAttachment.X2] < meshBoundsMin.x)
|
|
|
|
+ meshBoundsMin.x = tempVertices[RegionAttachment.X2];
|
|
|
|
+ else if (tempVertices[RegionAttachment.X2] > meshBoundsMax.x)
|
|
|
|
+ meshBoundsMax.x = tempVertices[RegionAttachment.X2];
|
|
|
|
+ if (tempVertices[RegionAttachment.X3] < meshBoundsMin.x)
|
|
|
|
+ meshBoundsMin.x = tempVertices[RegionAttachment.X3];
|
|
|
|
+ else if (tempVertices[RegionAttachment.X3] > meshBoundsMax.x)
|
|
|
|
+ meshBoundsMax.x = tempVertices[RegionAttachment.X3];
|
|
|
|
+ if (tempVertices[RegionAttachment.X4] < meshBoundsMin.x)
|
|
|
|
+ meshBoundsMin.x = tempVertices[RegionAttachment.X4];
|
|
|
|
+ else if (tempVertices[RegionAttachment.X4] > meshBoundsMax.x)
|
|
|
|
+ meshBoundsMax.x = tempVertices[RegionAttachment.X4];
|
|
|
|
+
|
|
|
|
+ // Calculate min/max Y
|
|
|
|
+ if (tempVertices[RegionAttachment.Y1] < meshBoundsMin.y)
|
|
|
|
+ meshBoundsMin.y = tempVertices[RegionAttachment.Y1];
|
|
|
|
+ else if (tempVertices[RegionAttachment.Y1] > meshBoundsMax.y)
|
|
|
|
+ meshBoundsMax.y = tempVertices[RegionAttachment.Y1];
|
|
|
|
+ if (tempVertices[RegionAttachment.Y2] < meshBoundsMin.y)
|
|
|
|
+ meshBoundsMin.y = tempVertices[RegionAttachment.Y2];
|
|
|
|
+ else if (tempVertices[RegionAttachment.Y2] > meshBoundsMax.y)
|
|
|
|
+ meshBoundsMax.y = tempVertices[RegionAttachment.Y2];
|
|
|
|
+ if (tempVertices[RegionAttachment.Y3] < meshBoundsMin.y)
|
|
|
|
+ meshBoundsMin.y = tempVertices[RegionAttachment.Y3];
|
|
|
|
+ else if (tempVertices[RegionAttachment.Y3] > meshBoundsMax.y)
|
|
|
|
+ meshBoundsMax.y = tempVertices[RegionAttachment.Y3];
|
|
|
|
+ if (tempVertices[RegionAttachment.Y4] < meshBoundsMin.y)
|
|
|
|
+ meshBoundsMin.y = tempVertices[RegionAttachment.Y4];
|
|
|
|
+ else if (tempVertices[RegionAttachment.Y4] > meshBoundsMax.y)
|
|
|
|
+ meshBoundsMax.y = tempVertices[RegionAttachment.Y4];
|
|
|
|
|
|
vertexIndex += 4;
|
|
vertexIndex += 4;
|
|
} else {
|
|
} else {
|
|
if (!renderMeshes)
|
|
if (!renderMeshes)
|
|
continue;
|
|
continue;
|
|
- if (attachment is MeshAttachment) {
|
|
|
|
- MeshAttachment meshAttachment = (MeshAttachment)attachment;
|
|
|
|
|
|
+ MeshAttachment meshAttachment = attachment as MeshAttachment;
|
|
|
|
+ if (meshAttachment != null) {
|
|
int meshVertexCount = meshAttachment.vertices.Length;
|
|
int meshVertexCount = meshAttachment.vertices.Length;
|
|
if (tempVertices.Length < meshVertexCount)
|
|
if (tempVertices.Length < meshVertexCount)
|
|
this.tempVertices = tempVertices = new float[meshVertexCount];
|
|
this.tempVertices = tempVertices = new float[meshVertexCount];
|
|
@@ -316,29 +424,55 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
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].x = tempVertices[ii];
|
|
|
|
+ vertices[vertexIndex].y = tempVertices[ii + 1];
|
|
|
|
+ vertices[vertexIndex].z = z;
|
|
colors[vertexIndex] = color;
|
|
colors[vertexIndex] = color;
|
|
- uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]);
|
|
|
|
|
|
+ uvs[vertexIndex].x = meshUVs[ii];
|
|
|
|
+ uvs[vertexIndex].y = meshUVs[ii + 1];
|
|
|
|
+
|
|
|
|
+ if (tempVertices[ii] < meshBoundsMin.x)
|
|
|
|
+ meshBoundsMin.x = tempVertices[ii];
|
|
|
|
+ else if (tempVertices[ii] > meshBoundsMax.x)
|
|
|
|
+ meshBoundsMax.x = tempVertices[ii];
|
|
|
|
+ if (tempVertices[ii + 1]< meshBoundsMin.y)
|
|
|
|
+ meshBoundsMin.y = tempVertices[ii + 1];
|
|
|
|
+ else if (tempVertices[ii + 1] > meshBoundsMax.y)
|
|
|
|
+ meshBoundsMax.y = tempVertices[ii + 1];
|
|
}
|
|
}
|
|
- } else if (attachment is SkinnedMeshAttachment) {
|
|
|
|
- SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
|
|
|
|
- int meshVertexCount = meshAttachment.uvs.Length;
|
|
|
|
- if (tempVertices.Length < meshVertexCount)
|
|
|
|
- this.tempVertices = tempVertices = new float[meshVertexCount];
|
|
|
|
- meshAttachment.ComputeWorldVertices(slot, tempVertices);
|
|
|
|
-
|
|
|
|
- color.a = (byte)(a * slot.a * meshAttachment.a);
|
|
|
|
- color.r = (byte)(r * slot.r * meshAttachment.r * color.a);
|
|
|
|
- color.g = (byte)(g * slot.g * meshAttachment.g * color.a);
|
|
|
|
- color.b = (byte)(b * slot.b * meshAttachment.b * color.a);
|
|
|
|
- if (slot.data.blendMode == BlendMode.additive) color.a = 0;
|
|
|
|
-
|
|
|
|
- float[] meshUVs = meshAttachment.uvs;
|
|
|
|
- float z = i * zSpacing;
|
|
|
|
- for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {
|
|
|
|
- vertices[vertexIndex] = new Vector3(tempVertices[ii], tempVertices[ii + 1], z);
|
|
|
|
- colors[vertexIndex] = color;
|
|
|
|
- uvs[vertexIndex] = new Vector2(meshUVs[ii], meshUVs[ii + 1]);
|
|
|
|
|
|
+ } else {
|
|
|
|
+ SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment;
|
|
|
|
+ if (skinnedMeshAttachment != null) {
|
|
|
|
+ int meshVertexCount = skinnedMeshAttachment.uvs.Length;
|
|
|
|
+ if (tempVertices.Length < meshVertexCount)
|
|
|
|
+ this.tempVertices = tempVertices = new float[meshVertexCount];
|
|
|
|
+ skinnedMeshAttachment.ComputeWorldVertices(slot, tempVertices);
|
|
|
|
+
|
|
|
|
+ color.a = (byte)(a * slot.a * skinnedMeshAttachment.a);
|
|
|
|
+ color.r = (byte)(r * slot.r * skinnedMeshAttachment.r * color.a);
|
|
|
|
+ color.g = (byte)(g * slot.g * skinnedMeshAttachment.g * color.a);
|
|
|
|
+ color.b = (byte)(b * slot.b * skinnedMeshAttachment.b * color.a);
|
|
|
|
+ if (slot.data.blendMode == BlendMode.additive) color.a = 0;
|
|
|
|
+
|
|
|
|
+ float[] meshUVs = skinnedMeshAttachment.uvs;
|
|
|
|
+ float z = i * zSpacing;
|
|
|
|
+ for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++) {
|
|
|
|
+ vertices[vertexIndex].x = tempVertices[ii];
|
|
|
|
+ vertices[vertexIndex].y = tempVertices[ii + 1];
|
|
|
|
+ vertices[vertexIndex].z = z;
|
|
|
|
+ colors[vertexIndex] = color;
|
|
|
|
+ uvs[vertexIndex].x = meshUVs[ii];
|
|
|
|
+ uvs[vertexIndex].y = meshUVs[ii + 1];
|
|
|
|
+
|
|
|
|
+ if (tempVertices[ii] < meshBoundsMin.x)
|
|
|
|
+ meshBoundsMin.x = tempVertices[ii];
|
|
|
|
+ else if (tempVertices[ii] > meshBoundsMax.x)
|
|
|
|
+ meshBoundsMax.x = tempVertices[ii];
|
|
|
|
+ if (tempVertices[ii + 1]< meshBoundsMin.y)
|
|
|
|
+ meshBoundsMin.y = tempVertices[ii + 1];
|
|
|
|
+ else if (tempVertices[ii + 1] > meshBoundsMax.y)
|
|
|
|
+ meshBoundsMax.y = tempVertices[ii + 1];
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -352,11 +486,16 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
mesh.colors32 = colors;
|
|
mesh.colors32 = colors;
|
|
mesh.uv = uvs;
|
|
mesh.uv = uvs;
|
|
|
|
|
|
- int submeshCount = submeshMaterials.Count;
|
|
|
|
- mesh.subMeshCount = submeshCount;
|
|
|
|
- for (int i = 0; i < submeshCount; ++i)
|
|
|
|
- mesh.SetTriangles(submeshes[i].triangles, i);
|
|
|
|
- mesh.RecalculateBounds();
|
|
|
|
|
|
+ if (mustUpdateMeshStructure) {
|
|
|
|
+ int submeshCount = submeshMaterials.Count;
|
|
|
|
+ mesh.subMeshCount = submeshCount;
|
|
|
|
+ for (int i = 0; i < submeshCount; ++i)
|
|
|
|
+ mesh.SetTriangles(submeshes.Items[i].triangles, i);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin;
|
|
|
|
+ Vector3 meshBoundsCenter = meshBoundsMin + meshBoundsExtents * 0.5f;
|
|
|
|
+ mesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents);
|
|
|
|
|
|
if (newTriangles && calculateNormals) {
|
|
if (newTriangles && calculateNormals) {
|
|
Vector3[] normals = new Vector3[vertexCount];
|
|
Vector3[] normals = new Vector3[vertexCount];
|
|
@@ -377,21 +516,105 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // Update previous state
|
|
|
|
+ ExposedList<int> attachmentsTriangleCountCurrentMesh;
|
|
|
|
+ ExposedList<bool> attachmentsFlipStateCurrentMesh;
|
|
|
|
+ ExposedList<LastState.AddSubmeshArguments> addSubmeshArgumentsCurrentMesh;
|
|
|
|
+ if (useMesh1) {
|
|
|
|
+ attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh1;
|
|
|
|
+ addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh1;
|
|
|
|
+ attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh1;
|
|
|
|
+ lastState.immutableTrianglesMesh1 = immutableTriangles;
|
|
|
|
+ } else {
|
|
|
|
+ attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh2;
|
|
|
|
+ addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh2;
|
|
|
|
+ attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh2;
|
|
|
|
+ lastState.immutableTrianglesMesh2 = immutableTriangles;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ attachmentsTriangleCountCurrentMesh.GrowIfNeeded(attachmentsTriangleCountTemp.Capacity);
|
|
|
|
+ attachmentsTriangleCountCurrentMesh.Count = attachmentsTriangleCountTemp.Count;
|
|
|
|
+ attachmentsTriangleCountTemp.CopyTo(attachmentsTriangleCountCurrentMesh.Items, 0);
|
|
|
|
+
|
|
|
|
+ attachmentsFlipStateCurrentMesh.GrowIfNeeded(attachmentsFlipStateTemp.Capacity);
|
|
|
|
+ attachmentsFlipStateCurrentMesh.Count = attachmentsFlipStateTemp.Count;
|
|
|
|
+ attachmentsFlipStateTemp.CopyTo(attachmentsFlipStateCurrentMesh.Items, 0);
|
|
|
|
+
|
|
|
|
+ addSubmeshArgumentsCurrentMesh.GrowIfNeeded(addSubmeshArgumentsTemp.Count);
|
|
|
|
+ addSubmeshArgumentsCurrentMesh.Count = addSubmeshArgumentsTemp.Count;
|
|
|
|
+ addSubmeshArgumentsTemp.CopyTo(addSubmeshArgumentsCurrentMesh.Items);
|
|
|
|
+
|
|
if (submeshRenderers.Length > 0) {
|
|
if (submeshRenderers.Length > 0) {
|
|
- foreach (var submeshRenderer in submeshRenderers) {
|
|
|
|
- if (submeshRenderer.submeshIndex < sharedMaterials.Length)
|
|
|
|
|
|
+ for (int i = 0; i < submeshRenderers.Length; i++) {
|
|
|
|
+ SkeletonUtilitySubmeshRenderer submeshRenderer = submeshRenderers[i];
|
|
|
|
+ if (submeshRenderer.submeshIndex < sharedMaterials.Length) {
|
|
submeshRenderer.SetMesh(meshRenderer, useMesh1 ? mesh1 : mesh2, sharedMaterials[submeshRenderer.submeshIndex]);
|
|
submeshRenderer.SetMesh(meshRenderer, useMesh1 ? mesh1 : mesh2, sharedMaterials[submeshRenderer.submeshIndex]);
|
|
- else
|
|
|
|
|
|
+ } else {
|
|
submeshRenderer.GetComponent<Renderer>().enabled = false;
|
|
submeshRenderer.GetComponent<Renderer>().enabled = false;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
useMesh1 = !useMesh1;
|
|
useMesh1 = !useMesh1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private bool CheckIfMustUpdateMeshStructure(ExposedList<int> attachmentsTriangleCountTemp, ExposedList<bool> attachmentsFlipStateTemp, ExposedList<LastState.AddSubmeshArguments> addSubmeshArgumentsTemp) {
|
|
|
|
+ // Check if any mesh settings were changed
|
|
|
|
+ bool mustUpdateMeshStructure =
|
|
|
|
+ immutableTriangles != (useMesh1 ? lastState.immutableTrianglesMesh1 : lastState.immutableTrianglesMesh2);
|
|
|
|
+#if UNITY_EDITOR
|
|
|
|
+ mustUpdateMeshStructure |= !Application.isPlaying;
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ if (mustUpdateMeshStructure)
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+ // Check if any attachments were enabled/disabled
|
|
|
|
+ // or submesh structures has changed
|
|
|
|
+ ExposedList<int> attachmentsTriangleCountCurrentMesh;
|
|
|
|
+ ExposedList<bool> attachmentsFlipStateCurrentMesh;
|
|
|
|
+ ExposedList<LastState.AddSubmeshArguments> addSubmeshArgumentsCurrentMesh;
|
|
|
|
+ if (useMesh1) {
|
|
|
|
+ attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh1;
|
|
|
|
+ addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh1;
|
|
|
|
+ attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh1;
|
|
|
|
+ } else {
|
|
|
|
+ attachmentsTriangleCountCurrentMesh = lastState.attachmentsTriangleCountMesh2;
|
|
|
|
+ addSubmeshArgumentsCurrentMesh = lastState.addSubmeshArgumentsMesh2;
|
|
|
|
+ attachmentsFlipStateCurrentMesh = lastState.attachmentsFlipStateMesh2;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Check attachments
|
|
|
|
+ int attachmentCount = attachmentsTriangleCountTemp.Count;
|
|
|
|
+ if (attachmentsTriangleCountCurrentMesh.Count != attachmentCount)
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < attachmentCount; i++) {
|
|
|
|
+ if (attachmentsTriangleCountCurrentMesh.Items[i] != attachmentsTriangleCountTemp.Items[i])
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Check flip state
|
|
|
|
+ for (int i = 0; i < attachmentCount; i++) {
|
|
|
|
+ if (attachmentsFlipStateCurrentMesh.Items[i] != attachmentsFlipStateTemp.Items[i])
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Check submeshes
|
|
|
|
+ int submeshCount = addSubmeshArgumentsTemp.Count;
|
|
|
|
+ if (addSubmeshArgumentsCurrentMesh.Count != submeshCount)
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < submeshCount; i++) {
|
|
|
|
+ if (!addSubmeshArgumentsCurrentMesh.Items[i].Equals(ref addSubmeshArgumentsTemp.Items[i]))
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
/** 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, ExposedList<bool> flipStates) {
|
|
int submeshIndex = submeshMaterials.Count;
|
|
int submeshIndex = submeshMaterials.Count;
|
|
submeshMaterials.Add(material);
|
|
submeshMaterials.Add(material);
|
|
|
|
|
|
@@ -400,7 +623,7 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
else if (immutableTriangles)
|
|
else if (immutableTriangles)
|
|
return;
|
|
return;
|
|
|
|
|
|
- Submesh submesh = submeshes[submeshIndex];
|
|
|
|
|
|
+ Submesh submesh = submeshes.Items[submeshIndex];
|
|
|
|
|
|
int[] triangles = submesh.triangles;
|
|
int[] triangles = submesh.triangles;
|
|
int trianglesCapacity = triangles.Length;
|
|
int trianglesCapacity = triangles.Length;
|
|
@@ -434,12 +657,12 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
}
|
|
}
|
|
|
|
|
|
// Store triangles.
|
|
// Store triangles.
|
|
- List<Slot> drawOrder = skeleton.DrawOrder;
|
|
|
|
|
|
+ ExposedList<Slot> drawOrder = skeleton.DrawOrder;
|
|
for (int i = startSlot, triangleIndex = 0; i < endSlot; i++) {
|
|
for (int i = startSlot, triangleIndex = 0; i < endSlot; i++) {
|
|
- Slot slot = drawOrder[i];
|
|
|
|
|
|
+ Slot slot = drawOrder.Items[i];
|
|
Attachment attachment = slot.attachment;
|
|
Attachment attachment = slot.attachment;
|
|
- Bone bone = slot.bone;
|
|
|
|
- bool flip = frontFacing && ((bone.WorldFlipX != bone.WorldFlipY) != (Mathf.Sign(bone.WorldScaleX) != Mathf.Sign(bone.WorldScaleY)));
|
|
|
|
|
|
+
|
|
|
|
+ bool flip = flipStates.Items[i];
|
|
|
|
|
|
if (attachment is RegionAttachment) {
|
|
if (attachment is RegionAttachment) {
|
|
if (!flip) {
|
|
if (!flip) {
|
|
@@ -464,16 +687,18 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
}
|
|
}
|
|
int[] attachmentTriangles;
|
|
int[] attachmentTriangles;
|
|
int attachmentVertexCount;
|
|
int attachmentVertexCount;
|
|
- if (attachment is MeshAttachment) {
|
|
|
|
- MeshAttachment meshAttachment = (MeshAttachment)attachment;
|
|
|
|
|
|
+ MeshAttachment meshAttachment = attachment as MeshAttachment;
|
|
|
|
+ if (meshAttachment != null) {
|
|
attachmentVertexCount = meshAttachment.vertices.Length >> 1;
|
|
attachmentVertexCount = meshAttachment.vertices.Length >> 1;
|
|
attachmentTriangles = meshAttachment.triangles;
|
|
attachmentTriangles = meshAttachment.triangles;
|
|
- } else if (attachment is SkinnedMeshAttachment) {
|
|
|
|
- SkinnedMeshAttachment meshAttachment = (SkinnedMeshAttachment)attachment;
|
|
|
|
- attachmentVertexCount = meshAttachment.uvs.Length >> 1;
|
|
|
|
- attachmentTriangles = meshAttachment.triangles;
|
|
|
|
- } else
|
|
|
|
- continue;
|
|
|
|
|
|
+ } else {
|
|
|
|
+ SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment;
|
|
|
|
+ if (skinnedMeshAttachment != null) {
|
|
|
|
+ attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1;
|
|
|
|
+ attachmentTriangles = skinnedMeshAttachment.triangles;
|
|
|
|
+ } else
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
|
|
if (flip) {
|
|
if (flip) {
|
|
for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii += 3, triangleIndex += 3) {
|
|
for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii += 3, triangleIndex += 3) {
|
|
@@ -494,24 +719,62 @@ public class SkeletonRenderer : MonoBehaviour {
|
|
#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.
|
|
- if (vertices == null) return;
|
|
|
|
- Vector3 gizmosCenter = new Vector3();
|
|
|
|
- Vector3 gizmosSize = new Vector3();
|
|
|
|
- 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);
|
|
|
|
- }
|
|
|
|
- float width = max.x - min.x;
|
|
|
|
- float height = max.y - min.y;
|
|
|
|
- gizmosCenter = new Vector3(min.x + (width / 2f), min.y + (height / 2f), 0f);
|
|
|
|
- gizmosSize = new Vector3(width, height, 1f);
|
|
|
|
|
|
+ meshFilter = GetComponent<MeshFilter>();
|
|
|
|
+ if (meshFilter == null) return;
|
|
|
|
+
|
|
|
|
+ Mesh mesh = meshFilter.sharedMesh;
|
|
|
|
+ if (mesh == null) return;
|
|
|
|
+
|
|
|
|
+ Bounds meshBounds = mesh.bounds;
|
|
Gizmos.color = Color.clear;
|
|
Gizmos.color = Color.clear;
|
|
Gizmos.matrix = transform.localToWorldMatrix;
|
|
Gizmos.matrix = transform.localToWorldMatrix;
|
|
- Gizmos.DrawCube(gizmosCenter, gizmosSize);
|
|
|
|
|
|
+ Gizmos.DrawCube(meshBounds.center, meshBounds.size);
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
|
|
+ private class LastState {
|
|
|
|
+ public bool immutableTrianglesMesh1;
|
|
|
|
+ public bool immutableTrianglesMesh2;
|
|
|
|
+ public int vertexCount;
|
|
|
|
+ public readonly ExposedList<bool> attachmentsFlipStateTemp = new ExposedList<bool>();
|
|
|
|
+ public readonly ExposedList<bool> attachmentsFlipStateMesh1 = new ExposedList<bool>();
|
|
|
|
+ public readonly ExposedList<bool> attachmentsFlipStateMesh2 = new ExposedList<bool>();
|
|
|
|
+ public readonly ExposedList<int> attachmentsTriangleCountTemp = new ExposedList<int>();
|
|
|
|
+ public readonly ExposedList<int> attachmentsTriangleCountMesh1 = new ExposedList<int>();
|
|
|
|
+ public readonly ExposedList<int> attachmentsTriangleCountMesh2 = new ExposedList<int>();
|
|
|
|
+ public readonly ExposedList<AddSubmeshArguments> addSubmeshArgumentsTemp = new ExposedList<AddSubmeshArguments>();
|
|
|
|
+ public readonly ExposedList<AddSubmeshArguments> addSubmeshArgumentsMesh1 = new ExposedList<AddSubmeshArguments>();
|
|
|
|
+ public readonly ExposedList<AddSubmeshArguments> addSubmeshArgumentsMesh2 = new ExposedList<AddSubmeshArguments>();
|
|
|
|
+
|
|
|
|
+ public struct AddSubmeshArguments {
|
|
|
|
+ public Material material;
|
|
|
|
+ public int startSlot;
|
|
|
|
+ public int endSlot;
|
|
|
|
+ public int triangleCount;
|
|
|
|
+ public int firstVertex;
|
|
|
|
+ public bool lastSubmesh;
|
|
|
|
+
|
|
|
|
+ public AddSubmeshArguments(Material material, int startSlot, int endSlot, int triangleCount, int firstVertex, bool lastSubmesh) {
|
|
|
|
+ this.material = material;
|
|
|
|
+ this.startSlot = startSlot;
|
|
|
|
+ this.endSlot = endSlot;
|
|
|
|
+ this.triangleCount = triangleCount;
|
|
|
|
+ this.firstVertex = firstVertex;
|
|
|
|
+ this.lastSubmesh = lastSubmesh;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public bool Equals(ref AddSubmeshArguments other) {
|
|
|
|
+ return
|
|
|
|
+ !ReferenceEquals(material, null) &&
|
|
|
|
+ !ReferenceEquals(other.material, null) &&
|
|
|
|
+ material.GetInstanceID() == other.material.GetInstanceID() &&
|
|
|
|
+ startSlot == other.startSlot &&
|
|
|
|
+ endSlot == other.endSlot &&
|
|
|
|
+ triangleCount == other.triangleCount &&
|
|
|
|
+ firstVertex == other.firstVertex;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
class Submesh {
|
|
class Submesh {
|