/// <summary>Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.</summary>
        /// <param name="x">The horizontal distance between the skeleton origin and the left side of the AABB.</param>
        /// <param name="y">The vertical distance between the skeleton origin and the bottom side of the AABB.</param>
        /// <param name="width">The width of the AABB</param>
        /// <param name="height">The height of the AABB.</param>
        /// <param name="vertexBuffer">Reference to hold a float[]. May be a null reference. This method will assign it a new float[] with the appropriate size as needed.</param>
        public void GetBounds(out float x, out float y, out float width, out float height, ref float[] vertexBuffer)
        {
            float[] temp = vertexBuffer;
            temp = temp ?? new float[8];
            var   drawOrderItems = this.drawOrder.Items;
            float minX = int.MaxValue, minY = int.MaxValue, maxX = int.MinValue, maxY = int.MinValue;

            for (int i = 0, n = this.drawOrder.Count; i < n; i++)
            {
                Slot       slot             = drawOrderItems[i];
                int        verticesLength   = 0;
                float[]    vertices         = null;
                Attachment attachment       = slot.attachment;
                var        regionAttachment = attachment as RegionAttachment;
                if (regionAttachment != null)
                {
                    verticesLength = 8;
                    if (temp.Length < 8)
                    {
                        temp = new float[8];
                    }
                    regionAttachment.ComputeWorldVertices(slot.bone, temp, 0);
                }
                else
                {
                    var meshAttachment = attachment as MeshAttachment;
                    if (meshAttachment != null)
                    {
                        MeshAttachment mesh = meshAttachment;
                        verticesLength = mesh.WorldVerticesLength;
                        if (temp.Length < verticesLength)
                        {
                            temp = new float[verticesLength];
                        }
                        mesh.ComputeWorldVertices(slot, 0, verticesLength, temp, 0);
                    }
                }

                if (vertices != null)
                {
                    for (int ii = 0; ii < verticesLength; ii += 2)
                    {
                        float vx = vertices[ii], vy = vertices[ii + 1];
                        minX = Math.Min(minX, vx);
                        minY = Math.Min(minY, vy);
                        maxX = Math.Max(maxX, vx);
                        maxY = Math.Max(maxY, vy);
                    }
                }
            }
            x            = minX;
            y            = minY;
            width        = maxX - minX;
            height       = maxY - minY;
            vertexBuffer = temp;
        }
        public void Draw(Skeleton skeleton)
        {
            var   drawOrder = skeleton.DrawOrder;
            var   drawOrderItems = skeleton.DrawOrder.Items;
            float skeletonR = skeleton.R, skeletonG = skeleton.G, skeletonB = skeleton.B, skeletonA = skeleton.A;
            Color color = new Color();

            for (int i = 0, n = drawOrder.Count; i < n; i++)
            {
                Slot       slot       = drawOrderItems[i];
                Attachment attachment = slot.Attachment;

                float     attachmentColorR, attachmentColorG, attachmentColorB, attachmentColorA;
                Texture2D texture       = null;
                int       verticesCount = 0;
                float[]   vertices      = this.vertices;
                int       indicesCount  = 0;
                int[]     indices       = null;
                float[]   uvs           = null;

                if (attachment is RegionAttachment)
                {
                    RegionAttachment regionAttachment = (RegionAttachment)attachment;
                    attachmentColorR = regionAttachment.R; attachmentColorG = regionAttachment.G; attachmentColorB = regionAttachment.B; attachmentColorA = regionAttachment.A;
                    AtlasRegion region = (AtlasRegion)regionAttachment.RendererObject;
                    texture       = (Texture2D)region.page.rendererObject;
                    verticesCount = 4;
                    regionAttachment.ComputeWorldVertices(slot.Bone, vertices, 0, 2);
                    indicesCount = 6;
                    indices      = quadTriangles;
                    uvs          = regionAttachment.UVs;
                }
                else if (attachment is MeshAttachment)
                {
                    MeshAttachment mesh = (MeshAttachment)attachment;
                    attachmentColorR = mesh.R; attachmentColorG = mesh.G; attachmentColorB = mesh.B; attachmentColorA = mesh.A;
                    AtlasRegion region = (AtlasRegion)mesh.RendererObject;
                    texture = (Texture2D)region.page.rendererObject;
                    int vertexCount = mesh.WorldVerticesLength;
                    if (vertices.Length < vertexCount)
                    {
                        vertices = new float[vertexCount];
                    }
                    verticesCount = vertexCount >> 1;
                    mesh.ComputeWorldVertices(slot, vertices);
                    indicesCount = mesh.Triangles.Length;
                    indices      = mesh.Triangles;
                    uvs          = mesh.UVs;
                }
                else if (attachment is ClippingAttachment)
                {
                    ClippingAttachment clip = (ClippingAttachment)attachment;
                    clipper.ClipStart(slot, clip);
                    continue;
                }
                else
                {
                    continue;
                }

                // set blend state
                BlendState blend = slot.Data.BlendMode == BlendMode.Additive ? BlendState.Additive : defaultBlendState;
                if (device.BlendState != blend)
                {
                    End();
                    device.BlendState = blend;
                }

                // calculate color
                float a = skeletonA * slot.A * attachmentColorA;
                if (premultipliedAlpha)
                {
                    color = new Color(
                        skeletonR * slot.R * attachmentColorR * a,
                        skeletonG * slot.G * attachmentColorG * a,
                        skeletonB * slot.B * attachmentColorB * a, a);
                }
                else
                {
                    color = new Color(
                        skeletonR * slot.R * attachmentColorR,
                        skeletonG * slot.G * attachmentColorG,
                        skeletonB * slot.B * attachmentColorB, a);
                }

                Color darkColor = new Color();
                if (slot.HasSecondColor)
                {
                    darkColor = new Color(slot.R2, slot.G2, slot.B2);
                }

                // clip
                if (clipper.IsClipping())
                {
                    clipper.ClipTriangles(vertices, verticesCount << 1, indices, indicesCount, uvs);
                    vertices      = clipper.ClippedVertices.Items;
                    verticesCount = clipper.ClippedVertices.Count >> 1;
                    indices       = clipper.ClippedTriangles.Items;
                    indicesCount  = clipper.ClippedTriangles.Count;
                    uvs           = clipper.ClippedUVs.Items;
                }

                if (verticesCount == 0 || indicesCount == 0)
                {
                    continue;
                }

                // submit to batch
                MeshItem item = batcher.NextItem(verticesCount, indicesCount);
                item.texture = texture;
                for (int ii = 0, nn = indicesCount; ii < nn; ii++)
                {
                    item.triangles[ii] = indices[ii];
                }
                VertexPositionColorTextureColor[] itemVertices = item.vertices;
                for (int ii = 0, v = 0, nn = verticesCount << 1; v < nn; ii++, v += 2)
                {
                    itemVertices[ii].Color               = color;
                    itemVertices[ii].Color2              = darkColor;
                    itemVertices[ii].Position.X          = vertices[v];
                    itemVertices[ii].Position.Y          = vertices[v + 1];
                    itemVertices[ii].Position.Z          = 0;
                    itemVertices[ii].TextureCoordinate.X = uvs[v];
                    itemVertices[ii].TextureCoordinate.Y = uvs[v + 1];
                }

                clipper.ClipEnd(slot);
            }
            clipper.ClipEnd();
        }