Example #1
0
        /// <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;
                    vertices       = temp;
                    if (vertices.Length < 8)
                    {
                        vertices = 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;
                        vertices       = temp;
                        if (vertices.Length < verticesLength)
                        {
                            vertices = 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 MeshAttachment NewMeshAttachment(Skin skin, string name, string path)
        {
            AtlasRegion region = FindRegion(path);

            if (region == null)
            {
                throw new ArgumentException(string.Format("Region not found in atlas: {0} (region attachment: {1})", path, name));
            }
            MeshAttachment attachment = new MeshAttachment(name);

            attachment.RendererObject       = region;
            attachment.RegionU              = region.u;
            attachment.RegionV              = region.v;
            attachment.RegionU2             = region.u2;
            attachment.RegionV2             = region.v2;
            attachment.RegionRotate         = region.rotate;
            attachment.regionOffsetX        = region.offsetX;
            attachment.regionOffsetY        = region.offsetY;
            attachment.regionWidth          = region.width;
            attachment.regionHeight         = region.height;
            attachment.regionOriginalWidth  = region.originalWidth;
            attachment.regionOriginalHeight = region.originalHeight;
            return(attachment);
        }
Example #3
0
        private Attachment ReadAttachment(Stream input, SkeletonData skeletonData, Skin skin, int slotIndex, String attachmentName, bool nonessential)
        {
            float scale = Scale;

            String name = ReadString(input);

            if (name == null)
            {
                name = attachmentName;
            }

            AttachmentType type = (AttachmentType)input.ReadByte();

            switch (type)
            {
            case AttachmentType.Region: {
                String path     = ReadString(input);
                float  rotation = ReadFloat(input);
                float  x        = ReadFloat(input);
                float  y        = ReadFloat(input);
                float  scaleX   = ReadFloat(input);
                float  scaleY   = ReadFloat(input);
                float  width    = ReadFloat(input);
                float  height   = ReadFloat(input);
                int    color    = ReadInt(input);

                if (path == null)
                {
                    path = name;
                }
                RegionAttachment region = attachmentLoader.NewRegionAttachment(skin, name, path);
                if (region == null)
                {
                    return(null);
                }
                region.Path     = path;
                region.x        = x * scale;
                region.y        = y * scale;
                region.scaleX   = scaleX;
                region.scaleY   = scaleY;
                region.rotation = rotation;
                region.width    = width * scale;
                region.height   = height * scale;
                region.r        = ((color & 0xff000000) >> 24) / 255f;
                region.g        = ((color & 0x00ff0000) >> 16) / 255f;
                region.b        = ((color & 0x0000ff00) >> 8) / 255f;
                region.a        = ((color & 0x000000ff)) / 255f;
                region.UpdateOffset();
                return(region);
            }

            case AttachmentType.Boundingbox: {
                int      vertexCount = ReadVarint(input, true);
                Vertices vertices    = ReadVertices(input, vertexCount);
                if (nonessential)
                {
                    ReadInt(input);                                       //int color = nonessential ? ReadInt(input) : 0; // Avoid unused local warning.
                }
                BoundingBoxAttachment box = attachmentLoader.NewBoundingBoxAttachment(skin, name);
                if (box == null)
                {
                    return(null);
                }
                box.worldVerticesLength = vertexCount << 1;
                box.vertices            = vertices.vertices;
                box.bones = vertices.bones;
                return(box);
            }

            case AttachmentType.Mesh: {
                String   path = ReadString(input);
                int      color = ReadInt(input);
                int      vertexCount = ReadVarint(input, true);
                float[]  uvs = ReadFloatArray(input, vertexCount << 1, 1);
                int[]    triangles = ReadShortArray(input);
                Vertices vertices = ReadVertices(input, vertexCount);
                int      hullLength = ReadVarint(input, true);
                int[]    edges = null;
                float    width = 0, height = 0;
                if (nonessential)
                {
                    edges  = ReadShortArray(input);
                    width  = ReadFloat(input);
                    height = ReadFloat(input);
                }

                if (path == null)
                {
                    path = name;
                }
                MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
                if (mesh == null)
                {
                    return(null);
                }
                mesh.Path                = path;
                mesh.r                   = ((color & 0xff000000) >> 24) / 255f;
                mesh.g                   = ((color & 0x00ff0000) >> 16) / 255f;
                mesh.b                   = ((color & 0x0000ff00) >> 8) / 255f;
                mesh.a                   = ((color & 0x000000ff)) / 255f;
                mesh.bones               = vertices.bones;
                mesh.vertices            = vertices.vertices;
                mesh.WorldVerticesLength = vertexCount << 1;
                mesh.triangles           = triangles;
                mesh.regionUVs           = uvs;
                mesh.UpdateUVs();
                mesh.HullLength = hullLength << 1;
                if (nonessential)
                {
                    mesh.Edges  = edges;
                    mesh.Width  = width * scale;
                    mesh.Height = height * scale;
                }
                return(mesh);
            }

            case AttachmentType.Linkedmesh: {
                String path = ReadString(input);
                int    color = ReadInt(input);
                String skinName = ReadString(input);
                String parent = ReadString(input);
                bool   inheritDeform = ReadBoolean(input);
                float  width = 0, height = 0;
                if (nonessential)
                {
                    width  = ReadFloat(input);
                    height = ReadFloat(input);
                }

                if (path == null)
                {
                    path = name;
                }
                MeshAttachment mesh = attachmentLoader.NewMeshAttachment(skin, name, path);
                if (mesh == null)
                {
                    return(null);
                }
                mesh.Path          = path;
                mesh.r             = ((color & 0xff000000) >> 24) / 255f;
                mesh.g             = ((color & 0x00ff0000) >> 16) / 255f;
                mesh.b             = ((color & 0x0000ff00) >> 8) / 255f;
                mesh.a             = ((color & 0x000000ff)) / 255f;
                mesh.inheritDeform = inheritDeform;
                if (nonessential)
                {
                    mesh.Width  = width * scale;
                    mesh.Height = height * scale;
                }
                linkedMeshes.Add(new SkeletonJson.LinkedMesh(mesh, skinName, slotIndex, parent));
                return(mesh);
            }

            case AttachmentType.Path: {
                bool     closed        = ReadBoolean(input);
                bool     constantSpeed = ReadBoolean(input);
                int      vertexCount   = ReadVarint(input, true);
                Vertices vertices      = ReadVertices(input, vertexCount);
                float[]  lengths       = new float[vertexCount / 3];
                for (int i = 0, n = lengths.Length; i < n; i++)
                {
                    lengths[i] = ReadFloat(input) * scale;
                }
                if (nonessential)
                {
                    ReadInt(input);                                       //int color = nonessential ? ReadInt(input) : 0;
                }
                PathAttachment path = attachmentLoader.NewPathAttachment(skin, name);
                if (path == null)
                {
                    return(null);
                }
                path.closed              = closed;
                path.constantSpeed       = constantSpeed;
                path.worldVerticesLength = vertexCount << 1;
                path.vertices            = vertices.vertices;
                path.bones   = vertices.bones;
                path.lengths = lengths;
                return(path);
            }

            case AttachmentType.Point: {
                float rotation = ReadFloat(input);
                float x        = ReadFloat(input);
                float y        = ReadFloat(input);
                if (nonessential)
                {
                    ReadInt(input);                                       //int color = nonessential ? ReadInt(input) : 0;
                }
                PointAttachment point = attachmentLoader.NewPointAttachment(skin, name);
                if (point == null)
                {
                    return(null);
                }
                point.x        = x * scale;
                point.y        = y * scale;
                point.rotation = rotation;
                //if (nonessential) point.color = color;
                return(point);
            }

            case AttachmentType.Clipping: {
                int      endSlotIndex = ReadVarint(input, true);
                int      vertexCount  = ReadVarint(input, true);
                Vertices vertices     = ReadVertices(input, vertexCount);
                if (nonessential)
                {
                    ReadInt(input);
                }

                ClippingAttachment clip = attachmentLoader.NewClippingAttachment(skin, name);
                if (clip == null)
                {
                    return(null);
                }
                clip.EndSlot             = skeletonData.slots.Items[endSlotIndex];
                clip.worldVerticesLength = vertexCount << 1;
                clip.vertices            = vertices.vertices;
                clip.bones = vertices.bones;
                return(clip);
            }
            }
            return(null);
        }
        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();

            if (VertexEffect != null)
            {
                VertexEffect.Begin(skeleton);
            }

            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 blendState = new BlendState();
                Blend      blendSrc;
                Blend      blendDst;
                if (premultipliedAlpha)
                {
                    blendState.AlphaBlendFunction  = BlendState.AlphaBlend.AlphaBlendFunction;
                    blendState.BlendFactor         = BlendState.AlphaBlend.BlendFactor;
                    blendState.ColorBlendFunction  = BlendState.AlphaBlend.ColorBlendFunction;
                    blendState.ColorWriteChannels  = BlendState.AlphaBlend.ColorWriteChannels;
                    blendState.ColorWriteChannels1 = BlendState.AlphaBlend.ColorWriteChannels1;
                    blendState.ColorWriteChannels2 = BlendState.AlphaBlend.ColorWriteChannels2;
                    blendState.ColorWriteChannels3 = BlendState.AlphaBlend.ColorWriteChannels3;
                    blendState.MultiSampleMask     = BlendState.AlphaBlend.MultiSampleMask;
                }
                else
                {
                    blendState.AlphaBlendFunction  = BlendState.NonPremultiplied.AlphaBlendFunction;
                    blendState.BlendFactor         = BlendState.NonPremultiplied.BlendFactor;
                    blendState.ColorBlendFunction  = BlendState.NonPremultiplied.ColorBlendFunction;
                    blendState.ColorWriteChannels  = BlendState.NonPremultiplied.ColorWriteChannels;
                    blendState.ColorWriteChannels1 = BlendState.NonPremultiplied.ColorWriteChannels1;
                    blendState.ColorWriteChannels2 = BlendState.NonPremultiplied.ColorWriteChannels2;
                    blendState.ColorWriteChannels3 = BlendState.NonPremultiplied.ColorWriteChannels3;
                    blendState.MultiSampleMask     = BlendState.NonPremultiplied.MultiSampleMask;
                }
                switch (slot.Data.BlendMode)
                {
                case BlendMode.Additive:
                    blendState = BlendState.Additive;
                    break;

                case BlendMode.Multiply:
                    blendSrc = BlendXna.GetXNABlend(BlendXna.GL_DST_COLOR);
                    blendDst = BlendXna.GetXNABlend(BlendXna.GL_ONE_MINUS_SRC_ALPHA);
                    blendState.ColorSourceBlend      = blendSrc;
                    blendState.AlphaSourceBlend      = blendSrc;
                    blendState.ColorDestinationBlend = blendDst;
                    blendState.AlphaDestinationBlend = blendDst;
                    break;

                case BlendMode.Screen:
                    blendSrc = BlendXna.GetXNABlend(premultipliedAlpha ? BlendXna.GL_ONE : BlendXna.GL_SRC_ALPHA);
                    blendDst = BlendXna.GetXNABlend(BlendXna.GL_ONE_MINUS_SRC_COLOR);
                    blendState.ColorSourceBlend      = blendSrc;
                    blendState.AlphaSourceBlend      = blendSrc;
                    blendState.ColorDestinationBlend = blendDst;
                    blendState.AlphaDestinationBlend = blendDst;
                    break;

                default:
                    blendState = defaultBlendState;
                    break;
                }

                if (device.BlendState != blendState)
                {
                    End();
                    device.BlendState = blendState;
                }



                // 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)
                {
                    if (premultipliedAlpha)
                    {
                        darkColor = new Color(slot.R2 * a, slot.G2 * a, slot.B2 * a);
                    }
                    else
                    {
                        darkColor = new Color(slot.R2 * a, slot.G2 * a, slot.B2 * a);
                    }
                }
                darkColor.A = premultipliedAlpha ? (byte)255 : (byte)0;

                // 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];
                    if (VertexEffect != null)
                    {
                        VertexEffect.Transform(ref itemVertices[ii]);
                    }
                }

                clipper.ClipEnd(slot);
            }
            clipper.ClipEnd();
            if (VertexEffect != null)
            {
                VertexEffect.End();
            }
        }