Beispiel #1
0
        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 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];
                }

                clipper.ClipEnd(slot);
            }
            clipper.ClipEnd();
        }
        float[] ComputeWorldPositions(PathAttachment path, int spacesCount, bool tangents, bool percentPosition,
                                      bool percentSpacing)
        {
            Slot  target   = this.target;
            float position = this.position;

            float[] spacesItems = this.spaces.Items, output = this.positions.Resize(spacesCount * 3 + 2).Items, world;
            bool    closed = path.Closed;
            int     verticesLength = path.WorldVerticesLength, curveCount = verticesLength / 6, prevCurve = NONE;

            float pathLength;

            if (!path.ConstantSpeed)
            {
                float[] lengths = path.Lengths;
                curveCount -= closed ? 1 : 2;
                pathLength  = lengths[curveCount];
                if (percentPosition)
                {
                    position *= pathLength;
                }
                if (percentSpacing)
                {
                    for (int i = 0; i < spacesCount; i++)
                    {
                        spacesItems[i] *= pathLength;
                    }
                }
                world = this.world.Resize(8).Items;
                for (int i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3)
                {
                    float space = spacesItems[i];
                    position += space;
                    float p = position;

                    if (closed)
                    {
                        p %= pathLength;
                        if (p < 0)
                        {
                            p += pathLength;
                        }
                        curve = 0;
                    }
                    else if (p < 0)
                    {
                        if (prevCurve != BEFORE)
                        {
                            prevCurve = BEFORE;
                            path.ComputeWorldVertices(target, 2, 4, world, 0);
                        }
                        AddBeforePosition(p, world, 0, output, o);
                        continue;
                    }
                    else if (p > pathLength)
                    {
                        if (prevCurve != AFTER)
                        {
                            prevCurve = AFTER;
                            path.ComputeWorldVertices(target, verticesLength - 6, 4, world, 0);
                        }
                        AddAfterPosition(p - pathLength, world, 0, output, o);
                        continue;
                    }

                    // Determine curve containing position.
                    for (;; curve++)
                    {
                        float length = lengths[curve];
                        if (p > length)
                        {
                            continue;
                        }
                        if (curve == 0)
                        {
                            p /= length;
                        }
                        else
                        {
                            float prev = lengths[curve - 1];
                            p = (p - prev) / (length - prev);
                        }
                        break;
                    }
                    if (curve != prevCurve)
                    {
                        prevCurve = curve;
                        if (closed && curve == curveCount)
                        {
                            path.ComputeWorldVertices(target, verticesLength - 4, 4, world, 0);
                            path.ComputeWorldVertices(target, 0, 4, world, 4);
                        }
                        else
                        {
                            path.ComputeWorldVertices(target, curve * 6 + 2, 8, world, 0);
                        }
                    }
                    AddCurvePosition(p, world[0], world[1], world[2], world[3], world[4], world[5], world[6], world[7], output, o,
                                     tangents || (i > 0 && space < PathConstraint.Epsilon));
                }
                return(output);
            }

            // World vertices.
            if (closed)
            {
                verticesLength += 2;
                world           = this.world.Resize(verticesLength).Items;
                path.ComputeWorldVertices(target, 2, verticesLength - 4, world, 0);
                path.ComputeWorldVertices(target, 0, 2, world, verticesLength - 4);
                world[verticesLength - 2] = world[0];
                world[verticesLength - 1] = world[1];
            }
            else
            {
                curveCount--;
                verticesLength -= 4;
                world           = this.world.Resize(verticesLength).Items;
                path.ComputeWorldVertices(target, 2, verticesLength, world, 0);
            }

            // Curve lengths.
            float[] curves = this.curves.Resize(curveCount).Items;
            pathLength = 0;
            float x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0;
            float tmpx, tmpy, dddfx, dddfy, ddfx, ddfy, dfx, dfy;

            for (int i = 0, w = 2; i < curveCount; i++, w += 6)
            {
                cx1         = world[w];
                cy1         = world[w + 1];
                cx2         = world[w + 2];
                cy2         = world[w + 3];
                x2          = world[w + 4];
                y2          = world[w + 5];
                tmpx        = (x1 - cx1 * 2 + cx2) * 0.1875f;
                tmpy        = (y1 - cy1 * 2 + cy2) * 0.1875f;
                dddfx       = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375f;
                dddfy       = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375f;
                ddfx        = tmpx * 2 + dddfx;
                ddfy        = tmpy * 2 + dddfy;
                dfx         = (cx1 - x1) * 0.75f + tmpx + dddfx * 0.16666667f;
                dfy         = (cy1 - y1) * 0.75f + tmpy + dddfy * 0.16666667f;
                pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                dfx        += ddfx;
                dfy        += ddfy;
                ddfx       += dddfx;
                ddfy       += dddfy;
                pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                dfx        += ddfx;
                dfy        += ddfy;
                pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                dfx        += ddfx + dddfx;
                dfy        += ddfy + dddfy;
                pathLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                curves[i]   = pathLength;
                x1          = x2;
                y1          = y2;
            }
            if (percentPosition)
            {
                position *= pathLength;
            }
            if (percentSpacing)
            {
                for (int i = 0; i < spacesCount; i++)
                {
                    spacesItems[i] *= pathLength;
                }
            }

            float[] segments    = this.segments;
            float   curveLength = 0;

            for (int i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3)
            {
                float space = spacesItems[i];
                position += space;
                float p = position;

                if (closed)
                {
                    p %= pathLength;
                    if (p < 0)
                    {
                        p += pathLength;
                    }
                    curve = 0;
                }
                else if (p < 0)
                {
                    AddBeforePosition(p, world, 0, output, o);
                    continue;
                }
                else if (p > pathLength)
                {
                    AddAfterPosition(p - pathLength, world, verticesLength - 4, output, o);
                    continue;
                }

                // Determine curve containing position.
                for (;; curve++)
                {
                    float length = curves[curve];
                    if (p > length)
                    {
                        continue;
                    }
                    if (curve == 0)
                    {
                        p /= length;
                    }
                    else
                    {
                        float prev = curves[curve - 1];
                        p = (p - prev) / (length - prev);
                    }
                    break;
                }

                // Curve segment lengths.
                if (curve != prevCurve)
                {
                    prevCurve = curve;
                    int ii = curve * 6;
                    x1          = world[ii];
                    y1          = world[ii + 1];
                    cx1         = world[ii + 2];
                    cy1         = world[ii + 3];
                    cx2         = world[ii + 4];
                    cy2         = world[ii + 5];
                    x2          = world[ii + 6];
                    y2          = world[ii + 7];
                    tmpx        = (x1 - cx1 * 2 + cx2) * 0.03f;
                    tmpy        = (y1 - cy1 * 2 + cy2) * 0.03f;
                    dddfx       = ((cx1 - cx2) * 3 - x1 + x2) * 0.006f;
                    dddfy       = ((cy1 - cy2) * 3 - y1 + y2) * 0.006f;
                    ddfx        = tmpx * 2 + dddfx;
                    ddfy        = tmpy * 2 + dddfy;
                    dfx         = (cx1 - x1) * 0.3f + tmpx + dddfx * 0.16666667f;
                    dfy         = (cy1 - y1) * 0.3f + tmpy + dddfy * 0.16666667f;
                    curveLength = (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                    segments[0] = curveLength;
                    for (ii = 1; ii < 8; ii++)
                    {
                        dfx         += ddfx;
                        dfy         += ddfy;
                        ddfx        += dddfx;
                        ddfy        += dddfy;
                        curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                        segments[ii] = curveLength;
                    }
                    dfx         += ddfx;
                    dfy         += ddfy;
                    curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                    segments[8]  = curveLength;
                    dfx         += ddfx + dddfx;
                    dfy         += ddfy + dddfy;
                    curveLength += (float)Math.Sqrt(dfx * dfx + dfy * dfy);
                    segments[9]  = curveLength;
                    segment      = 0;
                }

                // Weight by segment length.
                p *= curveLength;
                for (;; segment++)
                {
                    float length = segments[segment];
                    if (p > length)
                    {
                        continue;
                    }
                    if (segment == 0)
                    {
                        p /= length;
                    }
                    else
                    {
                        float prev = segments[segment - 1];
                        p = segment + (p - prev) / (length - prev);
                    }
                    break;
                }
                AddCurvePosition(p * 0.1f, x1, y1, cx1, cy1, cx2, cy2, x2, y2, output, o, tangents || (i > 0 && space < PathConstraint.Epsilon));
            }
            return(output);
        }