private void AddSubmesh(MeshState.AddSubmeshArguments submeshArguments, ExposedList <bool> flipStates)
    {
        int submeshIndex = submeshMaterials.Count;

        submeshMaterials.Add(submeshArguments.material);

        if (submeshes.Count <= submeshIndex)
        {
            submeshes.Add(new Submesh());
        }
        else if (immutableTriangles)
        {
            return;
        }

        Submesh submesh = submeshes.Items[submeshIndex];

        int[] triangles = submesh.triangles;

        int triangleCount = submeshArguments.triangleCount;
        int firstVertex   = submeshArguments.firstVertex;

        int trianglesCapacity = triangles.Length;

        if (submeshArguments.isLastSubmesh && trianglesCapacity > triangleCount)
        {
            // Last submesh may have more triangles than required, so zero triangles to the end.
            for (int i = triangleCount; i < trianglesCapacity; i++)
            {
                triangles[i] = 0;
            }
            submesh.triangleCount = triangleCount;
        }
        else if (trianglesCapacity != triangleCount)
        {
            // Reallocate triangles when not the exact size needed.
            submesh.triangles     = triangles = new int[triangleCount];
            submesh.triangleCount = 0;
        }

        if (!renderMeshes && !frontFacing)
        {
            // Use stored triangles if possible.
            if (submesh.firstVertex != firstVertex || submesh.triangleCount < triangleCount)
            {
                submesh.triangleCount = triangleCount;
                submesh.firstVertex   = firstVertex;
                //int drawOrderIndex = 0;
                for (int i = 0; i < triangleCount; i += 6, firstVertex += 4 /*, drawOrderIndex++*/)
                {
                    triangles[i]     = firstVertex;
                    triangles[i + 1] = firstVertex + 2;
                    triangles[i + 2] = firstVertex + 1;
                    triangles[i + 3] = firstVertex + 2;
                    triangles[i + 4] = firstVertex + 3;
                    triangles[i + 5] = firstVertex + 1;
                }
            }
            return;
        }

        // Iterate through all slots and store their triangles.
        ExposedList <Slot> drawOrder = skeleton.DrawOrder;
        int triangleIndex            = 0; // Modified by loop

        for (int i = submeshArguments.startSlot, n = submeshArguments.endSlot; i < n; i++)
        {
            Slot       slot       = drawOrder.Items[i];
            Attachment attachment = slot.attachment;

            bool flip = flipStates.Items[i];

            // Add RegionAttachment triangles
            if (attachment is RegionAttachment)
            {
                if (!flip)
                {
                    triangles[triangleIndex]     = firstVertex;
                    triangles[triangleIndex + 1] = firstVertex + 2;
                    triangles[triangleIndex + 2] = firstVertex + 1;
                    triangles[triangleIndex + 3] = firstVertex + 2;
                    triangles[triangleIndex + 4] = firstVertex + 3;
                    triangles[triangleIndex + 5] = firstVertex + 1;
                }
                else
                {
                    triangles[triangleIndex]     = firstVertex + 1;
                    triangles[triangleIndex + 1] = firstVertex + 2;
                    triangles[triangleIndex + 2] = firstVertex;
                    triangles[triangleIndex + 3] = firstVertex + 1;
                    triangles[triangleIndex + 4] = firstVertex + 3;
                    triangles[triangleIndex + 5] = firstVertex + 2;
                }

                triangleIndex += 6;
                firstVertex   += 4;
                continue;
            }

            // Add (Skinned)MeshAttachment triangles
            int[]          attachmentTriangles;
            int            attachmentVertexCount;
            MeshAttachment meshAttachment = attachment as MeshAttachment;
            if (meshAttachment != null)
            {
                attachmentVertexCount = meshAttachment.vertices.Length >> 1;                 //  length/2
                attachmentTriangles   = meshAttachment.triangles;
            }
            else
            {
                SkinnedMeshAttachment skinnedMeshAttachment = attachment as SkinnedMeshAttachment;
                if (skinnedMeshAttachment != null)
                {
                    attachmentVertexCount = skinnedMeshAttachment.uvs.Length >> 1;                     // length/2
                    attachmentTriangles   = skinnedMeshAttachment.triangles;
                }
                else
                {
                    continue;
                }
            }

            if (flip)
            {
                for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii += 3, triangleIndex += 3)
                {
                    triangles[triangleIndex + 2] = firstVertex + attachmentTriangles[ii];
                    triangles[triangleIndex + 1] = firstVertex + attachmentTriangles[ii + 1];
                    triangles[triangleIndex]     = firstVertex + attachmentTriangles[ii + 2];
                }
            }
            else
            {
                for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii++, triangleIndex++)
                {
                    triangles[triangleIndex] = firstVertex + attachmentTriangles[ii];
                }
            }

            firstVertex += attachmentVertexCount;
        }
    }
    private void AddSubmesh(MeshState.AddSubmeshArguments submeshArguments, ExposedList <bool> flipStates)
    {
        int submeshIndex = submeshMaterials.Count;

        submeshMaterials.Add(submeshArguments.material);

        if (submeshes.Count <= submeshIndex)
        {
            submeshes.Add(new Submesh());
        }
        else if (immutableTriangles)
        {
            return;
        }

        Submesh currentSubmesh = submeshes.Items[submeshIndex];

        int[] triangles = currentSubmesh.triangles;

        int triangleCount = submeshArguments.triangleCount;
        int firstVertex   = submeshArguments.firstVertex;

        int trianglesCapacity = triangles.Length;

        if (submeshArguments.isLastSubmesh && trianglesCapacity > triangleCount)
        {
            // Last submesh may have more triangles than required, so zero triangles to the end.
            for (int i = triangleCount; i < trianglesCapacity; i++)
            {
                triangles[i] = 0;
            }
            currentSubmesh.triangleCount = triangleCount;
        }
        else if (trianglesCapacity != triangleCount)
        {
            // Reallocate triangles when not the exact size needed.
            currentSubmesh.triangles     = triangles = new int[triangleCount];
            currentSubmesh.triangleCount = 0;
        }

        if (!this.renderMeshes && !this.frontFacing)
        {
            // Use stored triangles if possible.
            if (currentSubmesh.firstVertex != firstVertex || currentSubmesh.triangleCount < triangleCount)               //|| currentSubmesh.triangleCount == 0
            {
                currentSubmesh.triangleCount = triangleCount;
                currentSubmesh.firstVertex   = firstVertex;

                for (int i = 0; i < triangleCount; i += 6, firstVertex += 4)
                {
                    triangles[i]     = firstVertex;
                    triangles[i + 1] = firstVertex + 2;
                    triangles[i + 2] = firstVertex + 1;
                    triangles[i + 3] = firstVertex + 2;
                    triangles[i + 4] = firstVertex + 3;
                    triangles[i + 5] = firstVertex + 1;
                }
            }
            return;
        }

        // This method caches several .Items arrays. Whenever it does, there should be no mutations done on the overlying ExposedList object.
        // Iterate through all slots and store their triangles.
        var drawOrderItems  = skeleton.DrawOrder.Items;
        var flipStatesItems = flipStates.Items;

        int triangleIndex = 0;         // Modified by loop

        for (int i = submeshArguments.startSlot, n = submeshArguments.endSlot; i < n; i++)
        {
            Attachment attachment = drawOrderItems[i].attachment;

            bool flip = flipStatesItems[i];

            // Add RegionAttachment triangles
            if (attachment is RegionAttachment)
            {
                if (!flip)
                {
                    triangles[triangleIndex]     = firstVertex;
                    triangles[triangleIndex + 1] = firstVertex + 2;
                    triangles[triangleIndex + 2] = firstVertex + 1;
                    triangles[triangleIndex + 3] = firstVertex + 2;
                    triangles[triangleIndex + 4] = firstVertex + 3;
                    triangles[triangleIndex + 5] = firstVertex + 1;
                }
                else
                {
                    triangles[triangleIndex]     = firstVertex + 1;
                    triangles[triangleIndex + 1] = firstVertex + 2;
                    triangles[triangleIndex + 2] = firstVertex;
                    triangles[triangleIndex + 3] = firstVertex + 1;
                    triangles[triangleIndex + 4] = firstVertex + 3;
                    triangles[triangleIndex + 5] = firstVertex + 2;
                }

                triangleIndex += 6;
                firstVertex   += 4;
                continue;
            }

            // Add (Weighted)MeshAttachment triangles
            int[] attachmentTriangles;
            int   attachmentVertexCount;
            var   meshAttachment = attachment as MeshAttachment;
            if (meshAttachment != null)
            {
                attachmentVertexCount = meshAttachment.vertices.Length >> 1;                 // length/2
                attachmentTriangles   = meshAttachment.triangles;
            }
            else
            {
                var weightedMeshAttachment = attachment as WeightedMeshAttachment;
                if (weightedMeshAttachment != null)
                {
                    attachmentVertexCount = weightedMeshAttachment.uvs.Length >> 1;                     // length/2
                    attachmentTriangles   = weightedMeshAttachment.triangles;
                }
                else
                {
                    continue;
                }
            }

            if (flip)
            {
                for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii += 3, triangleIndex += 3)
                {
                    triangles[triangleIndex + 2] = firstVertex + attachmentTriangles[ii];
                    triangles[triangleIndex + 1] = firstVertex + attachmentTriangles[ii + 1];
                    triangles[triangleIndex]     = firstVertex + attachmentTriangles[ii + 2];
                }
            }
            else
            {
                for (int ii = 0, nn = attachmentTriangles.Length; ii < nn; ii++, triangleIndex++)
                {
                    triangles[triangleIndex] = firstVertex + attachmentTriangles[ii];
                }
            }

            firstVertex += attachmentVertexCount;
        }
    }
    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
        MeshState.SingleMeshState stateTemp = meshState.stateTemp;
        stateTemp.attachments.Clear(true);
        stateTemp.UpdateDrawOrderCount(drawOrderCount);

        stateTemp.addSubmeshArguments.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);
            stateTemp.attachmentsFlipState.Items[i] = flip;

            stateTemp.attachments.Items[i] = attachment;
            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)))
            {
                stateTemp.addSubmeshArguments.Add(
                    new MeshState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, i, submeshTriangleCount, submeshFirstVertex, false)
                    );
                submeshTriangleCount  = 0;
                submeshFirstVertex    = vertexCount;
                submeshStartSlotIndex = i;
            }
            lastMaterial = material;

            submeshTriangleCount += attachmentTriangleCount;
            vertexCount          += attachmentVertexCount;
        }
        stateTemp.addSubmeshArguments.Add(
            new MeshState.AddSubmeshArguments(lastMaterial, submeshStartSlotIndex, drawOrderCount, submeshTriangleCount, submeshFirstVertex, true)
            );

        bool mustUpdateMeshStructure = CheckIfMustUpdateMeshStructure(stateTemp.attachments, stateTemp.attachmentsFlipState, stateTemp.addSubmeshArguments);
        if (mustUpdateMeshStructure)
        {
            submeshMaterials.Clear();
            for (int i = 0, n = stateTemp.addSubmeshArguments.Count; i < n; i++)
            {
                MeshState.AddSubmeshArguments arguments = stateTemp.addSubmeshArguments.Items[i];
                AddSubmesh(
                    arguments.material,
                    arguments.startSlot,
                    arguments.endSlot,
                    arguments.triangleCount,
                    arguments.firstVertex,
                    arguments.lastSubmesh,
                    stateTemp.attachmentsFlipState
                    );
            }

            // 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 = 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             = 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
        MeshState.SingleMeshState currentMeshState = useMesh1 ? meshState.stateMesh1 : meshState.stateMesh2;
        currentMeshState.immutableTriangles = immutableTriangles;

        currentMeshState.attachments.Clear(true);
        currentMeshState.attachments.GrowIfNeeded(stateTemp.attachments.Capacity);
        currentMeshState.attachments.Count = stateTemp.attachments.Count;
        stateTemp.attachments.CopyTo(currentMeshState.attachments.Items);

        currentMeshState.attachmentsFlipState.GrowIfNeeded(stateTemp.attachmentsFlipState.Capacity);
        currentMeshState.attachmentsFlipState.Count = stateTemp.attachmentsFlipState.Count;
        stateTemp.attachmentsFlipState.CopyTo(currentMeshState.attachmentsFlipState.Items);

        currentMeshState.addSubmeshArguments.GrowIfNeeded(stateTemp.addSubmeshArguments.Capacity);
        currentMeshState.addSubmeshArguments.Count = stateTemp.addSubmeshArguments.Count;
        stateTemp.addSubmeshArguments.CopyTo(currentMeshState.addSubmeshArguments.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;
    }