Пример #1
0
        /// <summary>Fires events for frames &gt; lastTime and &lt;= time.</summary>
        public void Apply(Skeleton skeleton, float lastTime, float time, ExposedList <Event> firedEvents, float alpha)
        {
            if (firedEvents == null)
            {
                return;
            }
            float[] frames     = this.frames;
            int     frameCount = frames.Length;

            if (lastTime > time)               // Fire events after last time for looped animations.
            {
                Apply(skeleton, lastTime, int.MaxValue, firedEvents, alpha);
                lastTime = -1f;
            }
            else if (lastTime >= frames[frameCount - 1])               // Last time is after last frame.
            {
                return;
            }
            if (time < frames[0])
            {
                return;                               // Time is before first frame.
            }
            int frame;

            if (lastTime < frames[0])
            {
                frame = 0;
            }
            else
            {
                frame = Animation.binarySearch(frames, lastTime);
                float frameTime = frames[frame];
                while (frame > 0)                   // Fire multiple events with the same frame.
                {
                    if (frames[frame - 1] != frameTime)
                    {
                        break;
                    }
                    frame--;
                }
            }
            for (; frame < frameCount && time >= frames[frame]; frame++)
            {
                firedEvents.Add(events[frame]);
            }
        }
Пример #2
0
        public IkConstraint(IkConstraintData data, Skeleton skeleton)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data", "data cannot be null.");
            }
            if (skeleton == null)
            {
                throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
            }
            this.data     = data;
            mix           = data.mix;
            bendDirection = data.bendDirection;

            bones = new ExposedList <Bone>(data.bones.Count);
            foreach (BoneData boneData in data.bones)
            {
                bones.Add(skeleton.FindBone(boneData.name));
            }
            target = skeleton.FindBone(data.target.name);
        }
Пример #3
0
        public void Apply(Skeleton skeleton, float lastTime, float time, ExposedList <Event> firedEvents, float alpha)
        {
            float[] frames = this.frames;
            if (time < frames[0])
            {
                return;                               // Time is before first frame.
            }
            int frame;

            if (time >= frames[frames.Length - 1])             // Time is after last frame.
            {
                frame = frames.Length - 1;
            }
            else
            {
                frame = Animation.binarySearch(frames, time) - 1;
            }

            ExposedList <Slot> drawOrder = skeleton.drawOrder;
            ExposedList <Slot> slots     = skeleton.slots;

            int[] drawOrderToSetupIndex = drawOrders[frame];
            if (drawOrderToSetupIndex == null)
            {
                drawOrder.Clear();
                for (int i = 0, n = slots.Count; i < n; i++)
                {
                    drawOrder.Add(slots.Items[i]);
                }
            }
            else
            {
                var drawOrderItems = drawOrder.Items;
                var slotsItems     = slots.Items;
                for (int i = 0, n = drawOrderToSetupIndex.Length; i < n; i++)
                {
                    drawOrderItems[i] = slotsItems[drawOrderToSetupIndex[i]];
                }
            }
        }
Пример #4
0
 public PathConstraint(PathConstraintData data, Skeleton skeleton)
 {
     if (data == null)
     {
         throw new ArgumentNullException("data", "data cannot be null.");
     }
     if (skeleton == null)
     {
         throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
     }
     this.data = data;
     bones     = new ExposedList <Bone>(data.Bones.Count);
     foreach (BoneData boneData in data.bones)
     {
         bones.Add(skeleton.FindBone(boneData.name));
     }
     target       = skeleton.FindSlot(data.target.name);
     position     = data.position;
     spacing      = data.spacing;
     rotateMix    = data.rotateMix;
     translateMix = data.translateMix;
 }
        public TransformConstraint(TransformConstraintData data, Skeleton skeleton)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data", "data cannot be null.");
            }
            if (skeleton == null)
            {
                throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
            }
            this.data    = data;
            rotateMix    = data.rotateMix;
            translateMix = data.translateMix;
            scaleMix     = data.scaleMix;
            shearMix     = data.shearMix;

            bones = new ExposedList <Bone>();
            foreach (BoneData boneData in data.bones)
            {
                bones.Add(skeleton.FindBone(boneData.name));
            }

            target = skeleton.FindBone(data.target.name);
        }
Пример #6
0
        private void ReadAnimation(String name, Stream input, SkeletonData skeletonData)
        {
            var   timelines = new ExposedList <Timeline>();
            float scale     = Scale;
            float duration  = 0;

            // Slot timelines.
            for (int i = 0, n = ReadVarint(input, true); i < n; i++)
            {
                int slotIndex = ReadVarint(input, true);
                for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
                {
                    int timelineType = input.ReadByte();
                    int frameCount   = ReadVarint(input, true);
                    switch (timelineType)
                    {
                    case SLOT_COLOR: {
                        ColorTimeline timeline = new ColorTimeline(frameCount);
                        timeline.slotIndex = slotIndex;
                        for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                        {
                            float time  = ReadFloat(input);
                            int   color = ReadInt(input);
                            float r     = ((color & 0xff000000) >> 24) / 255f;
                            float g     = ((color & 0x00ff0000) >> 16) / 255f;
                            float b     = ((color & 0x0000ff00) >> 8) / 255f;
                            float a     = ((color & 0x000000ff)) / 255f;
                            timeline.SetFrame(frameIndex, time, r, g, b, a);
                            if (frameIndex < frameCount - 1)
                            {
                                ReadCurve(input, frameIndex, timeline);
                            }
                        }
                        timelines.Add(timeline);
                        duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * ColorTimeline.ENTRIES]);
                        break;
                    }

                    case SLOT_ATTACHMENT: {
                        AttachmentTimeline timeline = new AttachmentTimeline(frameCount);
                        timeline.slotIndex = slotIndex;
                        for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                        {
                            timeline.SetFrame(frameIndex, ReadFloat(input), ReadString(input));
                        }
                        timelines.Add(timeline);
                        duration = Math.Max(duration, timeline.frames[frameCount - 1]);
                        break;
                    }
                    }
                }
            }

            // Bone timelines.
            for (int i = 0, n = ReadVarint(input, true); i < n; i++)
            {
                int boneIndex = ReadVarint(input, true);
                for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
                {
                    int timelineType = input.ReadByte();
                    int frameCount   = ReadVarint(input, true);
                    switch (timelineType)
                    {
                    case BONE_ROTATE: {
                        RotateTimeline timeline = new RotateTimeline(frameCount);
                        timeline.boneIndex = boneIndex;
                        for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                        {
                            timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input));
                            if (frameIndex < frameCount - 1)
                            {
                                ReadCurve(input, frameIndex, timeline);
                            }
                        }
                        timelines.Add(timeline);
                        duration = Math.Max(duration, timeline.frames[(frameCount - 1) * RotateTimeline.ENTRIES]);
                        break;
                    }

                    case BONE_TRANSLATE:
                    case BONE_SCALE:
                    case BONE_SHEAR: {
                        TranslateTimeline timeline;
                        float             timelineScale = 1;
                        if (timelineType == BONE_SCALE)
                        {
                            timeline = new ScaleTimeline(frameCount);
                        }
                        else if (timelineType == BONE_SHEAR)
                        {
                            timeline = new ShearTimeline(frameCount);
                        }
                        else
                        {
                            timeline      = new TranslateTimeline(frameCount);
                            timelineScale = scale;
                        }
                        timeline.boneIndex = boneIndex;
                        for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                        {
                            timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input) * timelineScale, ReadFloat(input)
                                              * timelineScale);
                            if (frameIndex < frameCount - 1)
                            {
                                ReadCurve(input, frameIndex, timeline);
                            }
                        }
                        timelines.Add(timeline);
                        duration = Math.Max(duration, timeline.frames[(frameCount - 1) * TranslateTimeline.ENTRIES]);
                        break;
                    }
                    }
                }
            }

            // IK timelines.
            for (int i = 0, n = ReadVarint(input, true); i < n; i++)
            {
                int index      = ReadVarint(input, true);
                int frameCount = ReadVarint(input, true);
                IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount);
                timeline.ikConstraintIndex = index;
                for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                {
                    timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadSByte(input));
                    if (frameIndex < frameCount - 1)
                    {
                        ReadCurve(input, frameIndex, timeline);
                    }
                }
                timelines.Add(timeline);
                duration = Math.Max(duration, timeline.frames[(frameCount - 1) * IkConstraintTimeline.ENTRIES]);
            }

            // Transform constraint timelines.
            for (int i = 0, n = ReadVarint(input, true); i < n; i++)
            {
                int index      = ReadVarint(input, true);
                int frameCount = ReadVarint(input, true);
                TransformConstraintTimeline timeline = new TransformConstraintTimeline(frameCount);
                timeline.transformConstraintIndex = index;
                for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                {
                    timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadFloat(input), ReadFloat(input), ReadFloat(input));
                    if (frameIndex < frameCount - 1)
                    {
                        ReadCurve(input, frameIndex, timeline);
                    }
                }
                timelines.Add(timeline);
                duration = Math.Max(duration, timeline.frames[(frameCount - 1) * TransformConstraintTimeline.ENTRIES]);
            }

            // Path constraint timelines.
            for (int i = 0, n = ReadVarint(input, true); i < n; i++)
            {
                int index = ReadVarint(input, true);
                PathConstraintData data = skeletonData.pathConstraints.Items[index];
                for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
                {
                    int timelineType = ReadSByte(input);
                    int frameCount   = ReadVarint(input, true);
                    switch (timelineType)
                    {
                    case PATH_POSITION:
                    case PATH_SPACING: {
                        PathConstraintPositionTimeline timeline;
                        float timelineScale = 1;
                        if (timelineType == PATH_SPACING)
                        {
                            timeline = new PathConstraintSpacingTimeline(frameCount);
                            if (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed)
                            {
                                timelineScale = scale;
                            }
                        }
                        else
                        {
                            timeline = new PathConstraintPositionTimeline(frameCount);
                            if (data.positionMode == PositionMode.Fixed)
                            {
                                timelineScale = scale;
                            }
                        }
                        timeline.pathConstraintIndex = index;
                        for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                        {
                            timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input) * timelineScale);
                            if (frameIndex < frameCount - 1)
                            {
                                ReadCurve(input, frameIndex, timeline);
                            }
                        }
                        timelines.Add(timeline);
                        duration = Math.Max(duration, timeline.frames[(frameCount - 1) * PathConstraintPositionTimeline.ENTRIES]);
                        break;
                    }

                    case PATH_MIX: {
                        PathConstraintMixTimeline timeline = new PathConstraintMixTimeline(frameCount);
                        timeline.pathConstraintIndex = index;
                        for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                        {
                            timeline.SetFrame(frameIndex, ReadFloat(input), ReadFloat(input), ReadFloat(input));
                            if (frameIndex < frameCount - 1)
                            {
                                ReadCurve(input, frameIndex, timeline);
                            }
                        }
                        timelines.Add(timeline);
                        duration = Math.Max(duration, timeline.frames[(frameCount - 1) * PathConstraintMixTimeline.ENTRIES]);
                        break;
                    }
                    }
                }
            }

            // Deform timelines.
            for (int i = 0, n = ReadVarint(input, true); i < n; i++)
            {
                Skin skin = skeletonData.skins.Items[ReadVarint(input, true)];
                for (int ii = 0, nn = ReadVarint(input, true); ii < nn; ii++)
                {
                    int slotIndex = ReadVarint(input, true);
                    for (int iii = 0, nnn = ReadVarint(input, true); iii < nnn; iii++)
                    {
                        VertexAttachment attachment = (VertexAttachment)skin.GetAttachment(slotIndex, ReadString(input));
                        bool             weighted   = attachment.bones != null;
                        float[]          vertices   = attachment.vertices;
                        int deformLength            = weighted ? vertices.Length / 3 * 2 : vertices.Length;

                        int            frameCount = ReadVarint(input, true);
                        DeformTimeline timeline   = new DeformTimeline(frameCount);
                        timeline.slotIndex  = slotIndex;
                        timeline.attachment = attachment;

                        for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                        {
                            float   time = ReadFloat(input);
                            float[] deform;
                            int     end = ReadVarint(input, true);
                            if (end == 0)
                            {
                                deform = weighted ? new float[deformLength] : vertices;
                            }
                            else
                            {
                                deform = new float[deformLength];
                                int start = ReadVarint(input, true);
                                end += start;
                                if (scale == 1)
                                {
                                    for (int v = start; v < end; v++)
                                    {
                                        deform[v] = ReadFloat(input);
                                    }
                                }
                                else
                                {
                                    for (int v = start; v < end; v++)
                                    {
                                        deform[v] = ReadFloat(input) * scale;
                                    }
                                }
                                if (!weighted)
                                {
                                    for (int v = 0, vn = deform.Length; v < vn; v++)
                                    {
                                        deform[v] += vertices[v];
                                    }
                                }
                            }

                            timeline.SetFrame(frameIndex, time, deform);
                            if (frameIndex < frameCount - 1)
                            {
                                ReadCurve(input, frameIndex, timeline);
                            }
                        }
                        timelines.Add(timeline);
                        duration = Math.Max(duration, timeline.frames[frameCount - 1]);
                    }
                }
            }

            // Draw order timeline.
            int drawOrderCount = ReadVarint(input, true);

            if (drawOrderCount > 0)
            {
                DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount);
                int slotCount = skeletonData.slots.Count;
                for (int i = 0; i < drawOrderCount; i++)
                {
                    float time        = ReadFloat(input);
                    int   offsetCount = ReadVarint(input, true);
                    int[] drawOrder   = new int[slotCount];
                    for (int ii = slotCount - 1; ii >= 0; ii--)
                    {
                        drawOrder[ii] = -1;
                    }
                    int[] unchanged = new int[slotCount - offsetCount];
                    int   originalIndex = 0, unchangedIndex = 0;
                    for (int ii = 0; ii < offsetCount; ii++)
                    {
                        int slotIndex = ReadVarint(input, true);
                        // Collect unchanged items.
                        while (originalIndex != slotIndex)
                        {
                            unchanged[unchangedIndex++] = originalIndex++;
                        }
                        // Set changed items.
                        drawOrder[originalIndex + ReadVarint(input, true)] = originalIndex++;
                    }
                    // Collect remaining unchanged items.
                    while (originalIndex < slotCount)
                    {
                        unchanged[unchangedIndex++] = originalIndex++;
                    }
                    // Fill in unchanged items.
                    for (int ii = slotCount - 1; ii >= 0; ii--)
                    {
                        if (drawOrder[ii] == -1)
                        {
                            drawOrder[ii] = unchanged[--unchangedIndex];
                        }
                    }
                    timeline.SetFrame(i, time, drawOrder);
                }
                timelines.Add(timeline);
                duration = Math.Max(duration, timeline.frames[drawOrderCount - 1]);
            }

            // Event timeline.
            int eventCount = ReadVarint(input, true);

            if (eventCount > 0)
            {
                EventTimeline timeline = new EventTimeline(eventCount);
                for (int i = 0; i < eventCount; i++)
                {
                    float     time      = ReadFloat(input);
                    EventData eventData = skeletonData.events.Items[ReadVarint(input, true)];
                    Event     e         = new Event(time, eventData);
                    e.Int    = ReadVarint(input, false);
                    e.Float  = ReadFloat(input);
                    e.String = ReadBoolean(input) ? ReadString(input) : eventData.String;
                    timeline.SetFrame(i, e);
                }
                timelines.Add(timeline);
                duration = Math.Max(duration, timeline.frames[eventCount - 1]);
            }

            timelines.TrimExcess();
            skeletonData.animations.Add(new Animation(name, timelines, duration));
        }
Пример #7
0
        private void ReadAnimation(Dictionary <String, Object> map, String name, SkeletonData skeletonData)
        {
            var   scale     = this.Scale;
            var   timelines = new ExposedList <Timeline>();
            float duration  = 0;

            // Slot timelines.
            if (map.ContainsKey("slots"))
            {
                foreach (KeyValuePair <String, Object> entry in (Dictionary <String, Object>)map["slots"])
                {
                    String slotName    = entry.Key;
                    int    slotIndex   = skeletonData.FindSlotIndex(slotName);
                    var    timelineMap = (Dictionary <String, Object>)entry.Value;
                    foreach (KeyValuePair <String, Object> timelineEntry in timelineMap)
                    {
                        var values       = (List <Object>)timelineEntry.Value;
                        var timelineName = (String)timelineEntry.Key;
                        if (timelineName == "color")
                        {
                            var timeline = new ColorTimeline(values.Count);
                            timeline.slotIndex = slotIndex;

                            int frameIndex = 0;
                            foreach (Dictionary <String, Object> valueMap in values)
                            {
                                float  time = (float)valueMap["time"];
                                String c    = (String)valueMap["color"];
                                timeline.SetFrame(frameIndex, time, ToColor(c, 0), ToColor(c, 1), ToColor(c, 2), ToColor(c, 3));
                                ReadCurve(valueMap, timeline, frameIndex);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * ColorTimeline.ENTRIES]);
                        }
                        else if (timelineName == "attachment")
                        {
                            var timeline = new AttachmentTimeline(values.Count);
                            timeline.slotIndex = slotIndex;

                            int frameIndex = 0;
                            foreach (Dictionary <String, Object> valueMap in values)
                            {
                                float time = (float)valueMap["time"];
                                timeline.SetFrame(frameIndex++, time, (String)valueMap["name"]);
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]);
                        }
                        else
                        {
                            throw new Exception("Invalid timeline type for a slot: " + timelineName + " (" + slotName + ")");
                        }
                    }
                }
            }

            // Bone timelines.
            if (map.ContainsKey("bones"))
            {
                foreach (KeyValuePair <String, Object> entry in (Dictionary <String, Object>)map["bones"])
                {
                    String boneName  = entry.Key;
                    int    boneIndex = skeletonData.FindBoneIndex(boneName);
                    if (boneIndex == -1)
                    {
                        throw new Exception("Bone not found: " + boneName);
                    }
                    var timelineMap = (Dictionary <String, Object>)entry.Value;
                    foreach (KeyValuePair <String, Object> timelineEntry in timelineMap)
                    {
                        var values       = (List <Object>)timelineEntry.Value;
                        var timelineName = (String)timelineEntry.Key;
                        if (timelineName == "rotate")
                        {
                            var timeline = new RotateTimeline(values.Count);
                            timeline.boneIndex = boneIndex;

                            int frameIndex = 0;
                            foreach (Dictionary <String, Object> valueMap in values)
                            {
                                timeline.SetFrame(frameIndex, (float)valueMap["time"], (float)valueMap["angle"]);
                                ReadCurve(valueMap, timeline, frameIndex);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * RotateTimeline.ENTRIES]);
                        }
                        else if (timelineName == "translate" || timelineName == "scale" || timelineName == "shear")
                        {
                            TranslateTimeline timeline;
                            float             timelineScale = 1;
                            if (timelineName == "scale")
                            {
                                timeline = new ScaleTimeline(values.Count);
                            }
                            else if (timelineName == "shear")
                            {
                                timeline = new ShearTimeline(values.Count);
                            }
                            else
                            {
                                timeline      = new TranslateTimeline(values.Count);
                                timelineScale = scale;
                            }
                            timeline.boneIndex = boneIndex;

                            int frameIndex = 0;
                            foreach (Dictionary <String, Object> valueMap in values)
                            {
                                float time = (float)valueMap["time"];
                                float x    = GetFloat(valueMap, "x", 0);
                                float y    = GetFloat(valueMap, "y", 0);
                                timeline.SetFrame(frameIndex, time, x * timelineScale, y * timelineScale);
                                ReadCurve(valueMap, timeline, frameIndex);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * TranslateTimeline.ENTRIES]);
                        }
                        else
                        {
                            throw new Exception("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
                        }
                    }
                }
            }

            // IK constraint timelines.
            if (map.ContainsKey("ik"))
            {
                foreach (KeyValuePair <String, Object> constraintMap in (Dictionary <String, Object>)map["ik"])
                {
                    IkConstraintData constraint = skeletonData.FindIkConstraint(constraintMap.Key);
                    var values   = (List <Object>)constraintMap.Value;
                    var timeline = new IkConstraintTimeline(values.Count);
                    timeline.ikConstraintIndex = skeletonData.ikConstraints.IndexOf(constraint);
                    int frameIndex = 0;
                    foreach (Dictionary <String, Object> valueMap in values)
                    {
                        float time         = (float)valueMap["time"];
                        float mix          = GetFloat(valueMap, "mix", 1);
                        bool  bendPositive = GetBoolean(valueMap, "bendPositive", true);
                        timeline.SetFrame(frameIndex, time, mix, bendPositive ? 1 : -1);
                        ReadCurve(valueMap, timeline, frameIndex);
                        frameIndex++;
                    }
                    timelines.Add(timeline);
                    duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * IkConstraintTimeline.ENTRIES]);
                }
            }

            // Transform constraint timelines.
            if (map.ContainsKey("transform"))
            {
                foreach (KeyValuePair <String, Object> constraintMap in (Dictionary <String, Object>)map["transform"])
                {
                    TransformConstraintData constraint = skeletonData.FindTransformConstraint(constraintMap.Key);
                    var values   = (List <Object>)constraintMap.Value;
                    var timeline = new TransformConstraintTimeline(values.Count);
                    timeline.transformConstraintIndex = skeletonData.transformConstraints.IndexOf(constraint);
                    int frameIndex = 0;
                    foreach (Dictionary <String, Object> valueMap in values)
                    {
                        float time         = (float)valueMap["time"];
                        float rotateMix    = GetFloat(valueMap, "rotateMix", 1);
                        float translateMix = GetFloat(valueMap, "translateMix", 1);
                        float scaleMix     = GetFloat(valueMap, "scaleMix", 1);
                        float shearMix     = GetFloat(valueMap, "shearMix", 1);
                        timeline.SetFrame(frameIndex, time, rotateMix, translateMix, scaleMix, shearMix);
                        ReadCurve(valueMap, timeline, frameIndex);
                        frameIndex++;
                    }
                    timelines.Add(timeline);
                    duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * TransformConstraintTimeline.ENTRIES]);
                }
            }

            // Path constraint timelines.
            if (map.ContainsKey("paths"))
            {
                foreach (KeyValuePair <String, Object> constraintMap in (Dictionary <String, Object>)map["paths"])
                {
                    int index = skeletonData.FindPathConstraintIndex(constraintMap.Key);
                    if (index == -1)
                    {
                        throw new Exception("Path constraint not found: " + constraintMap.Key);
                    }
                    PathConstraintData data = skeletonData.pathConstraints.Items[index];
                    var timelineMap         = (Dictionary <String, Object>)constraintMap.Value;
                    foreach (KeyValuePair <String, Object> timelineEntry in timelineMap)
                    {
                        var values       = (List <Object>)timelineEntry.Value;
                        var timelineName = (String)timelineEntry.Key;
                        if (timelineName == "position" || timelineName == "spacing")
                        {
                            PathConstraintPositionTimeline timeline;
                            float timelineScale = 1;
                            if (timelineName == "spacing")
                            {
                                timeline = new PathConstraintSpacingTimeline(values.Count);
                                if (data.spacingMode == SpacingMode.Length || data.spacingMode == SpacingMode.Fixed)
                                {
                                    timelineScale = scale;
                                }
                            }
                            else
                            {
                                timeline = new PathConstraintPositionTimeline(values.Count);
                                if (data.positionMode == PositionMode.Fixed)
                                {
                                    timelineScale = scale;
                                }
                            }
                            timeline.pathConstraintIndex = index;
                            int frameIndex = 0;
                            foreach (Dictionary <String, Object> valueMap in values)
                            {
                                timeline.SetFrame(frameIndex, (float)valueMap["time"], GetFloat(valueMap, timelineName, 0) * timelineScale);
                                ReadCurve(valueMap, timeline, frameIndex);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * PathConstraintPositionTimeline.ENTRIES]);
                        }
                        else if (timelineName == "mix")
                        {
                            PathConstraintMixTimeline timeline = new PathConstraintMixTimeline(values.Count);
                            timeline.pathConstraintIndex = index;
                            int frameIndex = 0;
                            foreach (Dictionary <String, Object> valueMap in values)
                            {
                                timeline.SetFrame(frameIndex, (float)valueMap["time"], GetFloat(valueMap, "rotateMix", 1), GetFloat(valueMap, "translateMix", 1));
                                ReadCurve(valueMap, timeline, frameIndex);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.frames[(timeline.FrameCount - 1) * PathConstraintMixTimeline.ENTRIES]);
                        }
                    }
                }
            }

            // Deform timelines.
            if (map.ContainsKey("deform"))
            {
                foreach (KeyValuePair <String, Object> deformMap in (Dictionary <String, Object>)map["deform"])
                {
                    Skin skin = skeletonData.FindSkin(deformMap.Key);
                    foreach (KeyValuePair <String, Object> slotMap in (Dictionary <String, Object>)deformMap.Value)
                    {
                        int slotIndex = skeletonData.FindSlotIndex(slotMap.Key);
                        if (slotIndex == -1)
                        {
                            throw new Exception("Slot not found: " + slotMap.Key);
                        }
                        foreach (KeyValuePair <String, Object> timelineMap in (Dictionary <String, Object>)slotMap.Value)
                        {
                            var values = (List <Object>)timelineMap.Value;
                            VertexAttachment attachment = (VertexAttachment)skin.GetAttachment(slotIndex, timelineMap.Key);
                            if (attachment == null)
                            {
                                throw new Exception("Deform attachment not found: " + timelineMap.Key);
                            }
                            bool    weighted     = attachment.bones != null;
                            float[] vertices     = attachment.vertices;
                            int     deformLength = weighted ? vertices.Length / 3 * 2 : vertices.Length;

                            var timeline = new DeformTimeline(values.Count);
                            timeline.slotIndex  = slotIndex;
                            timeline.attachment = attachment;

                            int frameIndex = 0;
                            foreach (Dictionary <String, Object> valueMap in values)
                            {
                                float[] deform;
                                if (!valueMap.ContainsKey("vertices"))
                                {
                                    deform = weighted ? new float[deformLength] : vertices;
                                }
                                else
                                {
                                    deform = new float[deformLength];
                                    int     start         = GetInt(valueMap, "offset", 0);
                                    float[] verticesValue = GetFloatArray(valueMap, "vertices", 1);
                                    Array.Copy(verticesValue, 0, deform, start, verticesValue.Length);
                                    if (scale != 1)
                                    {
                                        for (int i = start, n = i + verticesValue.Length; i < n; i++)
                                        {
                                            deform[i] *= scale;
                                        }
                                    }

                                    if (!weighted)
                                    {
                                        for (int i = 0; i < deformLength; i++)
                                        {
                                            deform[i] += vertices[i];
                                        }
                                    }
                                }

                                timeline.SetFrame(frameIndex, (float)valueMap["time"], deform);
                                ReadCurve(valueMap, timeline, frameIndex);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]);
                        }
                    }
                }
            }

            // Draw order timeline.
            if (map.ContainsKey("drawOrder") || map.ContainsKey("draworder"))
            {
                var values     = (List <Object>)map[map.ContainsKey("drawOrder") ? "drawOrder" : "draworder"];
                var timeline   = new DrawOrderTimeline(values.Count);
                int slotCount  = skeletonData.slots.Count;
                int frameIndex = 0;
                foreach (Dictionary <String, Object> drawOrderMap in values)
                {
                    int[] drawOrder = null;
                    if (drawOrderMap.ContainsKey("offsets"))
                    {
                        drawOrder = new int[slotCount];
                        for (int i = slotCount - 1; i >= 0; i--)
                        {
                            drawOrder[i] = -1;
                        }
                        var   offsets = (List <Object>)drawOrderMap["offsets"];
                        int[] unchanged = new int[slotCount - offsets.Count];
                        int   originalIndex = 0, unchangedIndex = 0;
                        foreach (Dictionary <String, Object> offsetMap in offsets)
                        {
                            int slotIndex = skeletonData.FindSlotIndex((String)offsetMap["slot"]);
                            if (slotIndex == -1)
                            {
                                throw new Exception("Slot not found: " + offsetMap["slot"]);
                            }
                            // Collect unchanged items.
                            while (originalIndex != slotIndex)
                            {
                                unchanged[unchangedIndex++] = originalIndex++;
                            }
                            // Set changed items.
                            int index = originalIndex + (int)(float)offsetMap["offset"];
                            drawOrder[index] = originalIndex++;
                        }
                        // Collect remaining unchanged items.
                        while (originalIndex < slotCount)
                        {
                            unchanged[unchangedIndex++] = originalIndex++;
                        }
                        // Fill in unchanged items.
                        for (int i = slotCount - 1; i >= 0; i--)
                        {
                            if (drawOrder[i] == -1)
                            {
                                drawOrder[i] = unchanged[--unchangedIndex];
                            }
                        }
                    }
                    timeline.SetFrame(frameIndex++, (float)drawOrderMap["time"], drawOrder);
                }
                timelines.Add(timeline);
                duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]);
            }

            // Event timeline.
            if (map.ContainsKey("events"))
            {
                var eventsMap  = (List <Object>)map["events"];
                var timeline   = new EventTimeline(eventsMap.Count);
                int frameIndex = 0;
                foreach (Dictionary <String, Object> eventMap in eventsMap)
                {
                    EventData eventData = skeletonData.FindEvent((String)eventMap["name"]);
                    if (eventData == null)
                    {
                        throw new Exception("Event not found: " + eventMap["name"]);
                    }
                    var e = new Event((float)eventMap["time"], eventData);
                    e.Int    = GetInt(eventMap, "int", eventData.Int);
                    e.Float  = GetFloat(eventMap, "float", eventData.Float);
                    e.String = GetString(eventMap, "string", eventData.String);
                    timeline.SetFrame(frameIndex++, e);
                }
                timelines.Add(timeline);
                duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]);
            }

            timelines.TrimExcess();
            skeletonData.animations.Add(new Animation(name, timelines, duration));
        }
Пример #8
0
        /// <summary>Caches information about bones and constraints. Must be called if bones, constraints or weighted path attachments are added
        /// or removed.</summary>
        public void UpdateCache()
        {
            ExposedList <IUpdatable> updateCache = this.updateCache;

            updateCache.Clear();

            ExposedList <Bone> bones = this.bones;

            for (int i = 0, n = bones.Count; i < n; i++)
            {
                bones.Items[i].sorted = false;
            }

            ExposedList <IkConstraint> ikConstraints = this.ikConstraintsSorted;

            ikConstraints.Clear();
            ikConstraints.AddRange(this.ikConstraints);
            int ikCount = ikConstraints.Count;

            for (int i = 0, level, n = ikCount; i < n; i++)
            {
                IkConstraint ik   = ikConstraints.Items[i];
                Bone         bone = ik.bones.Items[0].parent;
                for (level = 0; bone != null; level++)
                {
                    bone = bone.parent;
                }
                ik.level = level;
            }
            for (int i = 1, ii; i < ikCount; i++)
            {
                IkConstraint ik    = ikConstraints.Items[i];
                int          level = ik.level;
                for (ii = i - 1; ii >= 0; ii--)
                {
                    IkConstraint other = ikConstraints.Items[ii];
                    if (other.level < level)
                    {
                        break;
                    }
                    ikConstraints.Items[ii + 1] = other;
                }
                ikConstraints.Items[ii + 1] = ik;
            }
            for (int i = 0, n = ikConstraints.Count; i < n; i++)
            {
                IkConstraint constraint = ikConstraints.Items[i];
                Bone         target     = constraint.target;
                SortBone(target);

                ExposedList <Bone> constrained = constraint.bones;
                Bone parent = constrained.Items[0];
                SortBone(parent);

                updateCache.Add(constraint);

                SortReset(parent.children);
                constrained.Items[constrained.Count - 1].sorted = true;
            }

            ExposedList <PathConstraint> pathConstraints = this.pathConstraints;

            for (int i = 0, n = pathConstraints.Count; i < n; i++)
            {
                PathConstraint constraint = pathConstraints.Items[i];

                Slot slot      = constraint.target;
                int  slotIndex = slot.data.index;
                Bone slotBone  = slot.bone;
                if (skin != null)
                {
                    SortPathConstraintAttachment(skin, slotIndex, slotBone);
                }
                if (data.defaultSkin != null && data.defaultSkin != skin)
                {
                    SortPathConstraintAttachment(data.defaultSkin, slotIndex, slotBone);
                }
                for (int ii = 0, nn = data.skins.Count; ii < nn; ii++)
                {
                    SortPathConstraintAttachment(data.skins.Items[ii], slotIndex, slotBone);
                }

                PathAttachment attachment = slot.Attachment as PathAttachment;
                if (attachment != null)
                {
                    SortPathConstraintAttachment(attachment, slotBone);
                }

                ExposedList <Bone> constrained = constraint.bones;
                int boneCount = constrained.Count;
                for (int ii = 0; ii < boneCount; ii++)
                {
                    SortBone(constrained.Items[ii]);
                }

                updateCache.Add(constraint);

                for (int ii = 0; ii < boneCount; ii++)
                {
                    SortReset(constrained.Items[ii].children);
                }
                for (int ii = 0; ii < boneCount; ii++)
                {
                    constrained.Items[ii].sorted = true;
                }
            }

            ExposedList <TransformConstraint> transformConstraints = this.transformConstraints;

            for (int i = 0, n = transformConstraints.Count; i < n; i++)
            {
                TransformConstraint constraint = transformConstraints.Items[i];

                SortBone(constraint.target);

                ExposedList <Bone> constrained = constraint.bones;
                int boneCount = constrained.Count;
                for (int ii = 0; ii < boneCount; ii++)
                {
                    SortBone(constrained.Items[ii]);
                }

                updateCache.Add(constraint);

                for (int ii = 0; ii < boneCount; ii++)
                {
                    SortReset(constrained.Items[ii].children);
                }
                for (int ii = 0; ii < boneCount; ii++)
                {
                    constrained.Items[ii].sorted = true;
                }
            }

            for (int i = 0, n = bones.Count; i < n; i++)
            {
                SortBone(bones.Items[i]);
            }
        }