Example #1
0
    public void SpawnSubRenderers(bool disablePrimaryRenderer)
    {
        int subMeshCount = base.GetComponent <MeshFilter>().get_sharedMesh().get_subMeshCount();

        for (int i = 0; i < subMeshCount; i++)
        {
            GameObject gameObject = new GameObject("Submesh " + i, new Type[]
            {
                typeof(MeshFilter),
                typeof(MeshRenderer)
            });
            gameObject.get_transform().set_parent(base.get_transform());
            gameObject.get_transform().set_localPosition(Vector3.get_zero());
            gameObject.get_transform().set_localRotation(Quaternion.get_identity());
            gameObject.get_transform().set_localScale(Vector3.get_one());
            SkeletonUtilitySubmeshRenderer skeletonUtilitySubmeshRenderer = gameObject.AddComponent <SkeletonUtilitySubmeshRenderer>();
            skeletonUtilitySubmeshRenderer.GetComponent <Renderer>().set_sortingOrder(i * 10);
            skeletonUtilitySubmeshRenderer.submeshIndex = i;
        }
        this.skeletonRenderer.CollectSubmeshRenderers();
        if (disablePrimaryRenderer)
        {
            base.GetComponent <Renderer>().set_enabled(false);
        }
    }
	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<Renderer>());
		sortingLayerIDProperty = rendererSerializedObject.FindProperty("m_SortingLayerID");
	}
    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 <Renderer>());
        sortingLayerIDProperty   = rendererSerializedObject.FindProperty("m_SortingLayerID");
    }
    public void SpawnSubRenderers(bool disablePrimaryRenderer)
    {
        int submeshCount = GetComponent <MeshFilter>().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 <SkeletonUtilitySubmeshRenderer>();
            s.GetComponent <Renderer>().sortingOrder = i * 10;
            s.submeshIndex = i;
        }

        skeletonRenderer.CollectSubmeshRenderers();

        if (disablePrimaryRenderer)
        {
            GetComponent <Renderer>().enabled = false;
        }
    }
Example #5
0
    public virtual void LateUpdate()
    {
        if (!valid)
        {
            return;
        }

        // Exit early if there is nothing to render
        if (!meshRenderer.enabled && submeshRenderers.Length == 0)
        {
            return;
        }

        // This method caches several .Items arrays. Whenever it does, there should be no mutations done on the overlying ExposedList object.

        // Count vertices and submesh triangles.
        int vertexCount = 0;

        int                submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;
        Material           lastMaterial               = null;
        ExposedList <Slot> drawOrder                  = skeleton.drawOrder;
        var                drawOrderItems             = drawOrder.Items;
        int                drawOrderCount             = drawOrder.Count;
        int                submeshSeparatorSlotsCount = submeshSeparatorSlots.Count;
        bool               renderMeshes               = this.renderMeshes;

        // Clear last state of attachments and submeshes
        MeshState.SingleMeshState workingState = meshState.buffer;
        var workingAttachments = workingState.attachments;

        workingAttachments.Clear(true);
        workingState.UpdateAttachmentCount(drawOrderCount);
        var workingAttachmentsItems = workingAttachments.Items;

        var workingFlips      = workingState.attachmentsFlipState;
        var workingFlipsItems = workingState.attachmentsFlipState.Items;

        var workingSubmeshArguments = workingState.addSubmeshArguments;         // Items array should not be cached. There is dynamic writing to this object.

        workingSubmeshArguments.Clear(false);

        MeshState.SingleMeshState storedState = useMesh1 ? meshState.stateMesh1 : meshState.stateMesh2;
        var storedAttachments      = storedState.attachments;
        var storedAttachmentsItems = storedAttachments.Items;

        var storedFlips      = storedState.attachmentsFlipState;
        var storedFlipsItems = storedFlips.Items;

        bool mustUpdateMeshStructure = storedState.requiresUpdate ||                         // Force update if the mesh was cleared. (prevents flickering due to incorrect state)
                                       drawOrderCount != storedAttachments.Count ||          // Number of slots changed (when does this happen?)
                                       immutableTriangles != storedState.immutableTriangles; // Immutable Triangles flag changed.

        bool isCustomMaterialsPopulated = customSlotMaterials.Count > 0;

        for (int i = 0; i < drawOrderCount; i++)
        {
            Slot       slot       = drawOrderItems[i];
            Bone       bone       = slot.bone;
            Attachment attachment = slot.attachment;

            object rendererObject;             // An AtlasRegion in plain Spine-Unity. Spine-TK2D hooks into TK2D's system. eventual source of Material object.
            int    attachmentVertexCount, attachmentTriangleCount;

            // Handle flipping for triangle winding (for lighting?).
            bool flip = frontFacing && (bone.WorldSignX != bone.WorldSignY);

            workingFlipsItems[i]       = flip;
            workingAttachmentsItems[i] = attachment;

            mustUpdateMeshStructure = mustUpdateMeshStructure ||                   // Always prefer short circuited or. || and not |=.
                                      (attachment != storedAttachmentsItems[i]) || // Attachment order changed. // This relies on the drawOrder.Count != storedAttachments.Count check above as a bounds check.
                                      (flip != storedFlipsItems[i]);               // Flip states changed.

            var regionAttachment = attachment as RegionAttachment;
            if (regionAttachment != null)
            {
                rendererObject          = regionAttachment.RendererObject;
                attachmentVertexCount   = 4;
                attachmentTriangleCount = 6;
            }
            else
            {
                if (!renderMeshes)
                {
                    continue;
                }
                var meshAttachment = attachment as MeshAttachment;
                if (meshAttachment != null)
                {
                    rendererObject          = meshAttachment.RendererObject;
                    attachmentVertexCount   = meshAttachment.vertices.Length >> 1;
                    attachmentTriangleCount = meshAttachment.triangles.Length;
                }
                else
                {
                    var skinnedMeshAttachment = attachment as WeightedMeshAttachment;
                    if (skinnedMeshAttachment != null)
                    {
                        rendererObject          = skinnedMeshAttachment.RendererObject;
                        attachmentVertexCount   = skinnedMeshAttachment.uvs.Length >> 1;
                        attachmentTriangleCount = skinnedMeshAttachment.triangles.Length;
                    }
                    else
                    {
                        continue;
                    }
                }
            }

                        #if !SPINE_TK2D
            // Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject; // For no customSlotMaterials

            Material material;
            if (isCustomMaterialsPopulated)
            {
                if (!customSlotMaterials.TryGetValue(slot, out material))
                {
                    material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
                }
            }
            else
            {
                material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
            }
                        #else
            Material material = (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject;
                        #endif

            // Populate submesh when material changes. (or when forced to separate by a submeshSeparator)
            if ((vertexCount > 0 && lastMaterial.GetInstanceID() != material.GetInstanceID()) ||
                (submeshSeparatorSlotsCount > 0 && submeshSeparatorSlots.Contains(slot)))
            {
                workingSubmeshArguments.Add(
                    new MeshState.AddSubmeshArguments {
                    material      = lastMaterial,
                    startSlot     = submeshStartSlotIndex,
                    endSlot       = i,
                    triangleCount = submeshTriangleCount,
                    firstVertex   = submeshFirstVertex,
                    isLastSubmesh = false
                }
                    );

                submeshTriangleCount  = 0;
                submeshFirstVertex    = vertexCount;
                submeshStartSlotIndex = i;
            }
            lastMaterial = material;

            submeshTriangleCount += attachmentTriangleCount;
            vertexCount          += attachmentVertexCount;
        }


        workingSubmeshArguments.Add(
            new MeshState.AddSubmeshArguments {
            material      = lastMaterial,
            startSlot     = submeshStartSlotIndex,
            endSlot       = drawOrderCount,
            triangleCount = submeshTriangleCount,
            firstVertex   = submeshFirstVertex,
            isLastSubmesh = true
        }
            );

        mustUpdateMeshStructure = mustUpdateMeshStructure ||
                                  this.sharedMaterials.Length != workingSubmeshArguments.Count || // Material array changed in size
                                  CheckIfMustUpdateMeshStructure(workingSubmeshArguments);        // Submesh Argument Array changed.

        // CheckIfMustUpdateMaterialArray (workingMaterials, sharedMaterials)
        if (!mustUpdateMeshStructure)
        {
            // Narrow phase material array check.
            var workingMaterials = workingSubmeshArguments.Items;
            for (int i = 0, n = sharedMaterials.Length; i < n; i++)
            {
                if (this.sharedMaterials[i] != workingMaterials[i].material)                    // Bounds check is implied above.
                {
                    mustUpdateMeshStructure = true;
                    break;
                }
            }
        }

        // NOT ELSE

        if (mustUpdateMeshStructure)
        {
            this.submeshMaterials.Clear();

            var workingSubmeshArgumentsItems = workingSubmeshArguments.Items;
            for (int i = 0, n = workingSubmeshArguments.Count; i < n; i++)
            {
                AddSubmesh(workingSubmeshArgumentsItems[i], workingFlips);
            }

            // Set materials.
            if (submeshMaterials.Count == sharedMaterials.Length)
            {
                submeshMaterials.CopyTo(sharedMaterials);
            }
            else
            {
                sharedMaterials = submeshMaterials.ToArray();
            }

            meshRenderer.sharedMaterials = sharedMaterials;
        }


        // Ensure mesh data is the right size.
        Vector3[] vertices     = this.vertices;
        bool      newTriangles = vertexCount > vertices.Length;
        if (newTriangles)
        {
            // Not enough vertices, increase size.
            this.vertices = vertices = new Vector3[vertexCount];
            this.colors   = new Color32[vertexCount];
            this.uvs      = new Vector2[vertexCount];

            mesh1.Clear();
            mesh2.Clear();
            meshState.stateMesh1.requiresUpdate = true;
            meshState.stateMesh2.requiresUpdate = true;
        }
        else
        {
            // Too many vertices, zero the extra.
            Vector3 zero = Vector3.zero;
            for (int i = vertexCount, n = meshState.vertexCount; i < n; i++)
            {
                vertices[i] = zero;
            }
        }
        meshState.vertexCount = vertexCount;

        // Setup mesh.
        float     zSpacing     = this.zSpacing;
        float[]   tempVertices = this.tempVertices;
        Vector2[] uvs          = this.uvs;
        Color32[] colors       = this.colors;
        int       vertexIndex  = 0;
        Color32   color;
        float     a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b;

        Vector3 meshBoundsMin;
        Vector3 meshBoundsMax;
        if (vertexCount == 0)
        {
            meshBoundsMin = new Vector3(0, 0, 0);
            meshBoundsMax = new Vector3(0, 0, 0);
        }
        else
        {
            meshBoundsMin.x = int.MaxValue;
            meshBoundsMin.y = int.MaxValue;
            meshBoundsMax.x = int.MinValue;
            meshBoundsMax.y = int.MinValue;
            if (zSpacing > 0f)
            {
                meshBoundsMin.z = 0f;
                meshBoundsMax.z = zSpacing * (drawOrderCount - 1);
            }
            else
            {
                meshBoundsMin.z = zSpacing * (drawOrderCount - 1);
                meshBoundsMax.z = 0f;
            }
            int i = 0;
            do
            {
                Slot             slot             = drawOrderItems[i];
                Attachment       attachment       = slot.attachment;
                RegionAttachment regionAttachment = attachment as RegionAttachment;
                if (regionAttachment != null)
                {
                    regionAttachment.ComputeWorldVertices(slot.bone, tempVertices);

                    float z = i * zSpacing;
                    float x1 = tempVertices[RegionAttachment.X1], y1 = tempVertices[RegionAttachment.Y1];
                    float x2 = tempVertices[RegionAttachment.X2], y2 = tempVertices[RegionAttachment.Y2];
                    float x3 = tempVertices[RegionAttachment.X3], y3 = tempVertices[RegionAttachment.Y3];
                    float x4 = tempVertices[RegionAttachment.X4], y4 = tempVertices[RegionAttachment.Y4];
                    vertices[vertexIndex].x     = x1;
                    vertices[vertexIndex].y     = y1;
                    vertices[vertexIndex].z     = z;
                    vertices[vertexIndex + 1].x = x4;
                    vertices[vertexIndex + 1].y = y4;
                    vertices[vertexIndex + 1].z = z;
                    vertices[vertexIndex + 2].x = x2;
                    vertices[vertexIndex + 2].y = y2;
                    vertices[vertexIndex + 2].z = z;
                    vertices[vertexIndex + 3].x = x3;
                    vertices[vertexIndex + 3].y = y3;
                    vertices[vertexIndex + 3].z = z;

                    color.a = (byte)(a * slot.a * regionAttachment.a);
                    color.r = (byte)(r * slot.r * regionAttachment.r * color.a);
                    color.g = (byte)(g * slot.g * regionAttachment.g * color.a);
                    color.b = (byte)(b * slot.b * regionAttachment.b * color.a);
                    if (slot.data.blendMode == BlendMode.additive)
                    {
                        color.a = 0;
                    }
                    colors[vertexIndex]     = color;
                    colors[vertexIndex + 1] = color;
                    colors[vertexIndex + 2] = color;
                    colors[vertexIndex + 3] = color;

                    float[] regionUVs = regionAttachment.uvs;
                    uvs[vertexIndex].x     = regionUVs[RegionAttachment.X1];
                    uvs[vertexIndex].y     = regionUVs[RegionAttachment.Y1];
                    uvs[vertexIndex + 1].x = regionUVs[RegionAttachment.X4];
                    uvs[vertexIndex + 1].y = regionUVs[RegionAttachment.Y4];
                    uvs[vertexIndex + 2].x = regionUVs[RegionAttachment.X2];
                    uvs[vertexIndex + 2].y = regionUVs[RegionAttachment.Y2];
                    uvs[vertexIndex + 3].x = regionUVs[RegionAttachment.X3];
                    uvs[vertexIndex + 3].y = regionUVs[RegionAttachment.Y3];

                    // Calculate min/max X
                    if (x1 < meshBoundsMin.x)
                    {
                        meshBoundsMin.x = x1;
                    }
                    else if (x1 > meshBoundsMax.x)
                    {
                        meshBoundsMax.x = x1;
                    }
                    if (x2 < meshBoundsMin.x)
                    {
                        meshBoundsMin.x = x2;
                    }
                    else if (x2 > meshBoundsMax.x)
                    {
                        meshBoundsMax.x = x2;
                    }
                    if (x3 < meshBoundsMin.x)
                    {
                        meshBoundsMin.x = x3;
                    }
                    else if (x3 > meshBoundsMax.x)
                    {
                        meshBoundsMax.x = x3;
                    }
                    if (x4 < meshBoundsMin.x)
                    {
                        meshBoundsMin.x = x4;
                    }
                    else if (x4 > meshBoundsMax.x)
                    {
                        meshBoundsMax.x = x4;
                    }

                    // Calculate min/max Y
                    if (y1 < meshBoundsMin.y)
                    {
                        meshBoundsMin.y = y1;
                    }
                    else if (y1 > meshBoundsMax.y)
                    {
                        meshBoundsMax.y = y1;
                    }
                    if (y2 < meshBoundsMin.y)
                    {
                        meshBoundsMin.y = y2;
                    }
                    else if (y2 > meshBoundsMax.y)
                    {
                        meshBoundsMax.y = y2;
                    }
                    if (y3 < meshBoundsMin.y)
                    {
                        meshBoundsMin.y = y3;
                    }
                    else if (y3 > meshBoundsMax.y)
                    {
                        meshBoundsMax.y = y3;
                    }
                    if (y4 < meshBoundsMin.y)
                    {
                        meshBoundsMin.y = y4;
                    }
                    else if (y4 > meshBoundsMax.y)
                    {
                        meshBoundsMax.y = y4;
                    }

                    vertexIndex += 4;
                }
                else
                {
                    if (!renderMeshes)
                    {
                        continue;
                    }
                    MeshAttachment meshAttachment = attachment as MeshAttachment;
                    if (meshAttachment != null)
                    {
                        int meshVertexCount = meshAttachment.vertices.Length;
                        if (tempVertices.Length < meshVertexCount)
                        {
                            this.tempVertices = tempVertices = new float[meshVertexCount];
                        }
                        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++)
                        {
                            float x = tempVertices[ii], y = tempVertices[ii + 1];
                            vertices[vertexIndex].x = x;
                            vertices[vertexIndex].y = y;
                            vertices[vertexIndex].z = z;
                            colors[vertexIndex]     = color;
                            uvs[vertexIndex].x      = meshUVs[ii];
                            uvs[vertexIndex].y      = meshUVs[ii + 1];

                            if (x < meshBoundsMin.x)
                            {
                                meshBoundsMin.x = x;
                            }
                            else if (x > meshBoundsMax.x)
                            {
                                meshBoundsMax.x = x;
                            }
                            if (y < meshBoundsMin.y)
                            {
                                meshBoundsMin.y = y;
                            }
                            else if (y > meshBoundsMax.y)
                            {
                                meshBoundsMax.y = y;
                            }
                        }
                    }
                    else
                    {
                        WeightedMeshAttachment weightedMeshAttachment = attachment as WeightedMeshAttachment;
                        if (weightedMeshAttachment != null)
                        {
                            int meshVertexCount = weightedMeshAttachment.uvs.Length;
                            if (tempVertices.Length < meshVertexCount)
                            {
                                this.tempVertices = tempVertices = new float[meshVertexCount];
                            }
                            weightedMeshAttachment.ComputeWorldVertices(slot, tempVertices);

                            color.a = (byte)(a * slot.a * weightedMeshAttachment.a);
                            color.r = (byte)(r * slot.r * weightedMeshAttachment.r * color.a);
                            color.g = (byte)(g * slot.g * weightedMeshAttachment.g * color.a);
                            color.b = (byte)(b * slot.b * weightedMeshAttachment.b * color.a);
                            if (slot.data.blendMode == BlendMode.additive)
                            {
                                color.a = 0;
                            }

                            float[] meshUVs = weightedMeshAttachment.uvs;
                            float   z       = i * zSpacing;
                            for (int ii = 0; ii < meshVertexCount; ii += 2, vertexIndex++)
                            {
                                float x = tempVertices[ii], y = tempVertices[ii + 1];
                                vertices[vertexIndex].x = x;
                                vertices[vertexIndex].y = y;
                                vertices[vertexIndex].z = z;
                                colors[vertexIndex]     = color;
                                uvs[vertexIndex].x      = meshUVs[ii];
                                uvs[vertexIndex].y      = meshUVs[ii + 1];

                                if (x < meshBoundsMin.x)
                                {
                                    meshBoundsMin.x = x;
                                }
                                else if (x > meshBoundsMax.x)
                                {
                                    meshBoundsMax.x = x;
                                }
                                if (y < meshBoundsMin.y)
                                {
                                    meshBoundsMin.y = y;
                                }
                                else if (y > meshBoundsMax.y)
                                {
                                    meshBoundsMax.y = y;
                                }
                            }
                        }
                    }
                }
            } while (++i < drawOrderCount);
        }

        // Double buffer mesh.
        Mesh mesh = useMesh1 ? mesh1 : mesh2;
        meshFilter.sharedMesh = mesh;

        mesh.vertices = vertices;
        mesh.colors32 = colors;
        mesh.uv       = uvs;

        if (mustUpdateMeshStructure)
        {
            int submeshCount = submeshMaterials.Count;
            mesh.subMeshCount = submeshCount;
            for (int i = 0; i < submeshCount; ++i)
            {
                mesh.SetTriangles(submeshes.Items[i].triangles, i);
            }

            // Done updating mesh.
            storedState.requiresUpdate = false;
        }

        Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin;
        Vector3 meshBoundsCenter  = meshBoundsMin + meshBoundsExtents * 0.5f;
        mesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents);

        if (newTriangles && calculateNormals)
        {
            Vector3[] normals = new Vector3[vertexCount];
            Vector3   normal  = new Vector3(0, 0, -1);
            for (int i = 0; i < vertexCount; i++)
            {
                normals[i] = normal;
            }
            (useMesh1 ? mesh2 : mesh1).vertices = vertices;             // Set other mesh vertices.
            mesh1.normals = normals;
            mesh2.normals = normals;

            if (calculateTangents)
            {
                Vector4[] tangents = new Vector4[vertexCount];
                Vector4   tangent  = new Vector4(1, 0, 0, -1);
                for (int i = 0; i < vertexCount; i++)
                {
                    tangents[i] = tangent;
                }
                mesh1.tangents = tangents;
                mesh2.tangents = tangents;
            }
        }

        // Update previous state
        storedState.immutableTriangles = immutableTriangles;

        storedAttachments.Clear(true);
        storedAttachments.GrowIfNeeded(workingAttachments.Capacity);
        storedAttachments.Count = workingAttachments.Count;
        workingAttachments.CopyTo(storedAttachments.Items);

        storedFlips.GrowIfNeeded(workingFlips.Capacity);
        storedFlips.Count = workingFlips.Count;
        workingFlips.CopyTo(storedFlips.Items);

        storedState.addSubmeshArguments.GrowIfNeeded(workingSubmeshArguments.Capacity);
        storedState.addSubmeshArguments.Count = workingSubmeshArguments.Count;
        workingSubmeshArguments.CopyTo(storedState.addSubmeshArguments.Items);


        // Submesh Renderers
        if (submeshRenderers.Length > 0)
        {
            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]);
                }
                else
                {
                    submeshRenderer.GetComponent <Renderer>().enabled = false;
                }
            }
        }

        useMesh1 = !useMesh1;
    }
    public virtual void LateUpdate()
    {
        if (!valid)
        {
            return;
        }

        // Exit early if there is nothing to render
        if (!meshRenderer.enabled && submeshRenderers.Length == 0)
        {
            return;
        }

        // Count vertices and submesh triangles.
        int                vertexCount = 0;
        int                submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;
        Material           lastMaterial               = null;
        ExposedList <Slot> drawOrder                  = skeleton.drawOrder;
        int                drawOrderCount             = drawOrder.Count;
        int                submeshSeparatorSlotsCount = submeshSeparatorSlots.Count;
        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++)
        {
            Slot       slot       = drawOrder.Items[i];
            Bone       bone       = slot.bone;
            Attachment attachment = slot.attachment;

            object rendererObject;
            int    attachmentVertexCount, attachmentTriangleCount;
            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;
                attachmentTriangleCount = 6;
            }
            else
            {
                if (!renderMeshes)
                {
                    continue;
                }
                MeshAttachment meshAttachment = attachment as MeshAttachment;
                if (meshAttachment != null)
                {
                    rendererObject          = meshAttachment.RendererObject;
                    attachmentVertexCount   = meshAttachment.vertices.Length >> 1;
                    attachmentTriangleCount = meshAttachment.triangles.Length;
                }
                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.
#if !SPINE_TK2D
            Material material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
#else
            Material material = (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject;
#endif
            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;
                submeshFirstVertex    = vertexCount;
                submeshStartSlotIndex = i;
            }
            lastMaterial = material;

            submeshTriangleCount += attachmentTriangleCount;
            vertexCount          += attachmentVertexCount;

            attachmentsTriangleCountTemp.Items[i] = attachmentTriangleCount;
        }
        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();
            }

            meshRenderer.sharedMaterials = sharedMaterials;
        }

        // Ensure mesh data is the right size.
        Vector3[] vertices     = this.vertices;
        bool      newTriangles = vertexCount > vertices.Length;
        if (newTriangles)
        {
            // Not enough vertices, increase size.
            this.vertices = vertices = new Vector3[vertexCount];
            this.colors   = new Color32[vertexCount];
            this.uvs      = new Vector2[vertexCount];
            mesh1.Clear();
            mesh2.Clear();
        }
        else
        {
            // Too many vertices, zero the extra.
            Vector3 zero = Vector3.zero;
            for (int i = vertexCount, n = lastState.vertexCount; i < n; i++)
            {
                vertices[i] = zero;
            }
        }
        lastState.vertexCount = vertexCount;

        // Setup mesh.
        float     zSpacing     = this.zSpacing;
        float[]   tempVertices = this.tempVertices;
        Vector2[] uvs          = this.uvs;
        Color32[] colors       = this.colors;
        int       vertexIndex  = 0;
        Color32   color;
        float     a = skeleton.a * 255, r = skeleton.r, g = skeleton.g, b = skeleton.b;

        Vector3 meshBoundsMin;
        Vector3 meshBoundsMax;
        if (vertexCount == 0)
        {
            meshBoundsMin = new Vector3(0, 0, 0);
            meshBoundsMax = new Vector3(0, 0, 0);
        }
        else
        {
            meshBoundsMin.x = int.MaxValue;
            meshBoundsMin.y = int.MaxValue;
            meshBoundsMax.x = int.MinValue;
            meshBoundsMax.y = int.MinValue;
            if (zSpacing > 0f)
            {
                meshBoundsMin.z = 0f;
                meshBoundsMax.z = zSpacing * (drawOrderCount - 1);
            }
            else
            {
                meshBoundsMin.z = zSpacing * (drawOrderCount - 1);
                meshBoundsMax.z = 0f;
            }
            int i = 0;
            do
            {
                Slot             slot             = drawOrder.Items[i];
                Attachment       attachment       = slot.attachment;
                RegionAttachment regionAttachment = attachment as RegionAttachment;
                if (regionAttachment != null)
                {
                    regionAttachment.ComputeWorldVertices(slot.bone, tempVertices);

                    float z = i * zSpacing;
                    float x1 = tempVertices[RegionAttachment.X1], y1 = tempVertices[RegionAttachment.Y1];
                    float x2 = tempVertices[RegionAttachment.X2], y2 = tempVertices[RegionAttachment.Y2];
                    float x3 = tempVertices[RegionAttachment.X3], y3 = tempVertices[RegionAttachment.Y3];
                    float x4 = tempVertices[RegionAttachment.X4], y4 = tempVertices[RegionAttachment.Y4];
                    vertices[vertexIndex].x     = x1;
                    vertices[vertexIndex].y     = y1;
                    vertices[vertexIndex].z     = z;
                    vertices[vertexIndex + 1].x = x4;
                    vertices[vertexIndex + 1].y = y4;
                    vertices[vertexIndex + 1].z = z;
                    vertices[vertexIndex + 2].x = x2;
                    vertices[vertexIndex + 2].y = y2;
                    vertices[vertexIndex + 2].z = z;
                    vertices[vertexIndex + 3].x = x3;
                    vertices[vertexIndex + 3].y = y3;
                    vertices[vertexIndex + 3].z = z;

                    color.a = (byte)(a * slot.a * regionAttachment.a);
                    color.r = (byte)(r * slot.r * regionAttachment.r * color.a);
                    color.g = (byte)(g * slot.g * regionAttachment.g * color.a);
                    color.b = (byte)(b * slot.b * regionAttachment.b * color.a);
                    if (slot.data.blendMode == BlendMode.additive)
                    {
                        color.a = 0;
                    }
                    colors[vertexIndex]     = color;
                    colors[vertexIndex + 1] = color;
                    colors[vertexIndex + 2] = color;
                    colors[vertexIndex + 3] = color;

                    float[] regionUVs = regionAttachment.uvs;
                    uvs[vertexIndex].x     = regionUVs[RegionAttachment.X1];
                    uvs[vertexIndex].y     = regionUVs[RegionAttachment.Y1];
                    uvs[vertexIndex + 1].x = regionUVs[RegionAttachment.X4];
                    uvs[vertexIndex + 1].y = regionUVs[RegionAttachment.Y4];
                    uvs[vertexIndex + 2].x = regionUVs[RegionAttachment.X2];
                    uvs[vertexIndex + 2].y = regionUVs[RegionAttachment.Y2];
                    uvs[vertexIndex + 3].x = regionUVs[RegionAttachment.X3];
                    uvs[vertexIndex + 3].y = regionUVs[RegionAttachment.Y3];

                    // Calculate min/max X
                    if (x1 < meshBoundsMin.x)
                    {
                        meshBoundsMin.x = x1;
                    }
                    else if (x1 > meshBoundsMax.x)
                    {
                        meshBoundsMax.x = x1;
                    }
                    if (x2 < meshBoundsMin.x)
                    {
                        meshBoundsMin.x = x2;
                    }
                    else if (x2 > meshBoundsMax.x)
                    {
                        meshBoundsMax.x = x2;
                    }
                    if (x3 < meshBoundsMin.x)
                    {
                        meshBoundsMin.x = x3;
                    }
                    else if (x3 > meshBoundsMax.x)
                    {
                        meshBoundsMax.x = x3;
                    }
                    if (x4 < meshBoundsMin.x)
                    {
                        meshBoundsMin.x = x4;
                    }
                    else if (x4 > meshBoundsMax.x)
                    {
                        meshBoundsMax.x = x4;
                    }

                    // Calculate min/max Y
                    if (y1 < meshBoundsMin.y)
                    {
                        meshBoundsMin.y = y1;
                    }
                    else if (y1 > meshBoundsMax.y)
                    {
                        meshBoundsMax.y = y1;
                    }
                    if (y2 < meshBoundsMin.y)
                    {
                        meshBoundsMin.y = y2;
                    }
                    else if (y2 > meshBoundsMax.y)
                    {
                        meshBoundsMax.y = y2;
                    }
                    if (y3 < meshBoundsMin.y)
                    {
                        meshBoundsMin.y = y3;
                    }
                    else if (y3 > meshBoundsMax.y)
                    {
                        meshBoundsMax.y = y3;
                    }
                    if (y4 < meshBoundsMin.y)
                    {
                        meshBoundsMin.y = y4;
                    }
                    else if (y4 > meshBoundsMax.y)
                    {
                        meshBoundsMax.y = y4;
                    }

                    vertexIndex += 4;
                }
                else
                {
                    if (!renderMeshes)
                    {
                        continue;
                    }
                    MeshAttachment meshAttachment = attachment as MeshAttachment;
                    if (meshAttachment != null)
                    {
                        int meshVertexCount = meshAttachment.vertices.Length;
                        if (tempVertices.Length < meshVertexCount)
                        {
                            this.tempVertices = tempVertices = new float[meshVertexCount];
                        }
                        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++)
                        {
                            float x = tempVertices[ii], y = tempVertices[ii + 1];
                            vertices[vertexIndex].x = x;
                            vertices[vertexIndex].y = y;
                            vertices[vertexIndex].z = z;
                            colors[vertexIndex]     = color;
                            uvs[vertexIndex].x      = meshUVs[ii];
                            uvs[vertexIndex].y      = meshUVs[ii + 1];

                            if (x < meshBoundsMin.x)
                            {
                                meshBoundsMin.x = x;
                            }
                            else if (x > meshBoundsMax.x)
                            {
                                meshBoundsMax.x = x;
                            }
                            if (y < meshBoundsMin.y)
                            {
                                meshBoundsMin.y = y;
                            }
                            else if (y > meshBoundsMax.y)
                            {
                                meshBoundsMax.y = y;
                            }
                        }
                    }
                    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++)
                            {
                                float x = tempVertices[ii], y = tempVertices[ii + 1];
                                vertices[vertexIndex].x = x;
                                vertices[vertexIndex].y = y;
                                vertices[vertexIndex].z = z;
                                colors[vertexIndex]     = color;
                                uvs[vertexIndex].x      = meshUVs[ii];
                                uvs[vertexIndex].y      = meshUVs[ii + 1];

                                if (x < meshBoundsMin.x)
                                {
                                    meshBoundsMin.x = x;
                                }
                                else if (x > meshBoundsMax.x)
                                {
                                    meshBoundsMax.x = x;
                                }
                                if (y < meshBoundsMin.y)
                                {
                                    meshBoundsMin.y = y;
                                }
                                else if (y > meshBoundsMax.y)
                                {
                                    meshBoundsMax.y = y;
                                }
                            }
                        }
                    }
                }
            } while (++i < drawOrderCount);
        }

        // Double buffer mesh.
        Mesh mesh = useMesh1 ? mesh1 : mesh2;
        meshFilter.sharedMesh = mesh;

        mesh.vertices = vertices;
        mesh.colors32 = colors;
        mesh.uv       = uvs;

        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)
        {
            Vector3[] normals = new Vector3[vertexCount];
            Vector3   normal  = new Vector3(0, 0, -1);
            for (int i = 0; i < vertexCount; i++)
            {
                normals[i] = normal;
            }
            (useMesh1 ? mesh2 : mesh1).vertices = vertices;             // Set other mesh vertices.
            mesh1.normals = normals;
            mesh2.normals = normals;

            if (calculateTangents)
            {
                Vector4[] tangents = new Vector4[vertexCount];
                Vector3   tangent  = new Vector3(0, 0, 1);
                for (int i = 0; i < vertexCount; i++)
                {
                    tangents[i] = tangent;
                }
                mesh1.tangents = tangents;
                mesh2.tangents = tangents;
            }
        }

        // 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)
        {
            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]);
                }
                else
                {
                    submeshRenderer.GetComponent <Renderer>().enabled = false;
                }
            }
        }

        useMesh1 = !useMesh1;
    }
Example #7
0
    public virtual void LateUpdate()
    {
        if (!valid)
        {
            return;
        }

        // Exit early if there is nothing to render
        if (!meshRenderer.enabled && submeshRenderers.Length == 0)
        {
            return;
        }

        // Count vertices and submesh triangles.
        int                vertexCount = 0;
        int                submeshTriangleCount = 0, submeshFirstVertex = 0, submeshStartSlotIndex = 0;
        Material           lastMaterial               = null;
        ExposedList <Slot> drawOrder                  = skeleton.drawOrder;
        int                drawOrderCount             = drawOrder.Count;
        int                submeshSeparatorSlotsCount = submeshSeparatorSlots.Count;
        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);
        bool noRender = false;

        for (int i = 0; i < drawOrderCount; i++)
        {
            Slot       slot       = drawOrder.Items[i];
            Bone       bone       = slot.bone;
            Attachment attachment = slot.attachment;

            object rendererObject;
            int    attachmentVertexCount, attachmentTriangleCount;
            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;
                attachmentTriangleCount = 6;
            }
            else
            {
                if (!renderMeshes)
                {
                    continue;
                }
                MeshAttachment meshAttachment = attachment as MeshAttachment;
                if (meshAttachment != null)
                {
                    rendererObject          = meshAttachment.RendererObject;
                    attachmentVertexCount   = meshAttachment.vertices.Length >> 1;
                    attachmentTriangleCount = meshAttachment.triangles.Length;
                }
                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.

            // tsteil - added support for mask material
            Material material = null;
            if (useMaskMaterial)
            {
                if (maskProvider != null)
                {
                    if (maskMaterial == null)
                    {
                        var prefabMat = (Material)((AtlasRegion)rendererObject).page.rendererObjectMask;
                        material           = new Material(prefabMat);
                        material.hideFlags = HideFlags.HideAndDontSave;
                        maskMaterial       = material;
                        SetMaskId();
                    }
                    else
                    {
                        material = maskMaterial;
                    }
                }
                else
                {
                    material = (Material)((AtlasRegion)rendererObject).page.rendererObjectMask;
                }
            }
            else
            {
#if !SPINE_TK2D
                material = (Material)((AtlasRegion)rendererObject).page.rendererObject;
#else
                material = (rendererObject.GetType() == typeof(Material)) ? (Material)rendererObject : (Material)((AtlasRegion)rendererObject).page.rendererObject;
#endif
            }
            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;
                submeshFirstVertex    = vertexCount;
                submeshStartSlotIndex = i;
            }
            lastMaterial = material;

            submeshTriangleCount += attachmentTriangleCount;
            vertexCount          += attachmentVertexCount;

            attachmentsTriangleCountTemp.Items[i] = attachmentTriangleCount;
        }

        // tsteil - we need to keep track if we're rendering or not
        if (lastMaterial == null)
        {
            noRender = true;
        }

        addSubmeshArgumentsTemp.Add(
            new LastState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true)
            );

        bool mustUpdateMeshStructure = CheckIfMustUpdateMeshStructure(attachmentsTriangleCountTemp, attachmentsFlipStateTemp, addSubmeshArgumentsTemp);
        var  submeshMatCount         = 0;
        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.
            submeshMatCount = submeshMaterials.Count;
            if (submeshMatCount == sharedMaterials.Length)
            {
                submeshMaterials.CopyTo(sharedMaterials);
            }
            else
            {
                sharedMaterials = submeshMaterials.ToArray();
            }
            meshRenderer.sharedMaterials = sharedMaterials;
        }

        // Ensure mesh data is the right size.
        Vector3[] vertices     = this.vertices;
        bool      newTriangles = vertexCount > vertices.Length;
        if (newTriangles)
        {
            // Not enough vertices, increase size.
            this.vertices = vertices = new Vector3[vertexCount];
            this.colors   = new Color32[vertexCount];
            this.uvs      = new Vector2[vertexCount];
            if (setupUv2)
            {
                this.uvs2 = new Vector2[vertexCount];
            }
            mesh1.Clear();
            mesh2.Clear();
        }
        else
        {
            // Too many vertices, zero the extra.
            Vector3 zero = Vector3.zero;
            for (int i = vertexCount, n = lastState.vertexCount; i < n; i++)
            {
                vertices[i] = zero;
            }
        }
        lastState.vertexCount = vertexCount;

        // Setup mesh.
        float     zSpacing     = this.zSpacing;
        float[]   tempVertices = this.tempVertices;
        Vector2[] uvs          = this.uvs;
        Vector2[] uvs2         = this.uvs2;
        Color32[] colors       = this.colors;
        int       vertexIndex  = 0;
        Color32   color;
        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++)
        {
            Slot             slot             = drawOrder.Items[i];
            Attachment       attachment       = slot.attachment;
            RegionAttachment regionAttachment = attachment as RegionAttachment;
            if (regionAttachment != null)
            {
                regionAttachment.ComputeWorldVertices(slot.bone, tempVertices);

                float z = i * zSpacing;
                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;

                // Eugene - added
                if (overrideVertexColor)
                {
                    color = vertexColor;

                    colors[vertexIndex]     = color;
                    colors[vertexIndex + 1] = color;
                    colors[vertexIndex + 2] = color;
                    colors[vertexIndex + 3] = color;
                }
                else
                {
                    color.a = (byte)(a * slot.a * regionAttachment.a);
                    color.r = (byte)(r * slot.r * regionAttachment.r * color.a);
                    color.g = (byte)(g * slot.g * regionAttachment.g * color.a);
                    color.b = (byte)(b * slot.b * regionAttachment.b * color.a);
                    if (slot.data.blendMode == BlendMode.additive)
                    {
                        color.a = 0;
                    }
                    colors[vertexIndex]     = color;
                    colors[vertexIndex + 1] = color;
                    colors[vertexIndex + 2] = color;
                    colors[vertexIndex + 3] = color;
                }

                float[] regionUVs = regionAttachment.uvs;
                uvs[vertexIndex].x     = regionUVs[RegionAttachment.X1];
                uvs[vertexIndex].y     = regionUVs[RegionAttachment.Y1];
                uvs[vertexIndex + 1].x = regionUVs[RegionAttachment.X4];
                uvs[vertexIndex + 1].y = regionUVs[RegionAttachment.Y4];
                uvs[vertexIndex + 2].x = regionUVs[RegionAttachment.X2];
                uvs[vertexIndex + 2].y = regionUVs[RegionAttachment.Y2];
                uvs[vertexIndex + 3].x = regionUVs[RegionAttachment.X3];
                uvs[vertexIndex + 3].y = regionUVs[RegionAttachment.Y3];

                // Calculate min/max X
                if (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;
            }
            else
            {
                if (!renderMeshes)
                {
                    continue;
                }
                MeshAttachment meshAttachment = attachment as MeshAttachment;
                if (meshAttachment != null)
                {
                    int meshVertexCount = meshAttachment.vertices.Length;
                    if (tempVertices.Length < meshVertexCount)
                    {
                        this.tempVertices = tempVertices = new float[meshVertexCount];
                    }
                    meshAttachment.ComputeWorldVertices(slot, tempVertices);

                    // Eugene - added
                    if (overrideVertexColor)
                    {
                        color = vertexColor;
                    }
                    else
                    {
                        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].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];
                        }
                    }
                }
                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);

                        // Eugene - added
                        if (overrideVertexColor)
                        {
                            color = vertexColor;
                        }
                        else
                        {
                            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];
                            }
                        }
                    }
                }
            }
        }

        // Double buffer mesh.
        Mesh mesh = useMesh1 ? mesh1 : mesh2;
        meshFilter.sharedMesh = mesh;

        mesh.vertices = vertices;
        mesh.colors32 = colors;
        mesh.uv       = uvs;

        // tsteil - added UV2 stuff
        if (setupUv2)
        {
            float minX  = 1f;
            float minY  = 1f;
            float maxX  = 0f;
            float maxY  = 0f;
            float sizeX = 0f;
            float sizeY = 0f;

            // go through our vertices and find the min and max so we can normalize the UVs against it
            for (int i = 0; i < vertexCount; ++i)
            {
                var x = vertices[i].x;
                var y = vertices[i].y;
                if (x < minX)
                {
                    minX = x;
                }
                else if (x > maxX)
                {
                    maxX = x;
                }
                if (y < minY)
                {
                    minY = y;
                }
                else if (y > maxY)
                {
                    maxY = y;
                }
            }
            sizeX = maxX - minX;
            sizeY = maxY - minY;

            // now set the uvs2
            for (int i = 0; i < vertexCount; ++i)
            {
                uvs2[i].x = (vertices[i].x - minX) / sizeX;
                uvs2[i].y = (vertices[i].y - minY) / sizeY;
            }
            mesh.uv2 = uvs2;
        }

        if (mustUpdateMeshStructure)
        {
            int submeshCount = submeshMatCount;
            mesh.subMeshCount = submeshCount;
            for (int i = 0; i < submeshCount; ++i)
            {
                mesh.SetTriangles(submeshes.Items[i].triangles, i);
            }
        }

        // tsteil: if we're not rendering, we dont need to calculate the bounds (this fixes the crazy AABB math errors)
        if (noRender == false)
        {
            Vector3 meshBoundsExtents = meshBoundsMax - meshBoundsMin;
            Vector3 meshBoundsCenter  = meshBoundsMin + meshBoundsExtents * 0.5f;
            mesh.bounds = new Bounds(meshBoundsCenter, meshBoundsExtents);
        }

        if (newTriangles && calculateNormals)
        {
            Vector3[] normals = new Vector3[vertexCount];
            Vector3   normal  = new Vector3(0, 0, -1);
            for (int i = 0; i < vertexCount; i++)
            {
                normals[i] = normal;
            }
            (useMesh1 ? mesh2 : mesh1).vertices = vertices;             // Set other mesh vertices.
            mesh1.normals = normals;
            mesh2.normals = normals;

            if (calculateTangents)
            {
                Vector4[] tangents = new Vector4[vertexCount];
                Vector3   tangent  = new Vector3(0, 0, 1);
                for (int i = 0; i < vertexCount; i++)
                {
                    tangents[i] = tangent;
                }
                mesh1.tangents = tangents;
                mesh2.tangents = tangents;
            }
        }

        // 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)
        {
            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]);
                }
                else
                {
                    submeshRenderer.GetComponent <Renderer>().enabled = false;
                }
            }
        }

        useMesh1 = !useMesh1;
    }