Inheritance: CurveTimeline
Exemple #1
0
	static void ParseRotateTimeline (Skeleton skeleton, RotateTimeline timeline, AnimationClip clip) {
		var boneData = skeleton.Data.Bones[timeline.BoneIndex];
		var bone = skeleton.Bones[timeline.BoneIndex];

		AnimationCurve curve = new AnimationCurve();

		float endTime = timeline.Frames[(timeline.FrameCount * 2) - 2];

		float currentTime = timeline.Frames[0];

		List<Keyframe> keys = new List<Keyframe>();

		float rotation = timeline.Frames[1] + boneData.Rotation;

		keys.Add(new Keyframe(timeline.Frames[0], rotation, 0, 0));

		int listIndex = 1;
		int frameIndex = 1;
		int f = 2;
		float[] frames = timeline.Frames;
		skeleton.SetToSetupPose();
		float lastTime = 0;
		float angle = rotation;
		while (currentTime < endTime) {
			int pIndex = listIndex - 1;
			float curveType = timeline.GetCurveType(frameIndex - 1);

			if (curveType == 0) {
				//linear
				Keyframe pk = keys[pIndex];

				float time = frames[f];

				rotation = frames[f + 1] + boneData.Rotation;
				angle += Mathf.DeltaAngle(angle, rotation);
				float r = angle;

				float rOut = (r - pk.value) / (time - pk.time);

				pk.outTangent = rOut;

				keys.Add(new Keyframe(time, r, rOut, 0));

				keys[pIndex] = pk;

				currentTime = time;

				timeline.Apply(skeleton, lastTime, currentTime, null, 1);

				lastTime = time;
				listIndex++;
			} else if (curveType == 1) {
				//stepped

				Keyframe pk = keys[pIndex];

				float time = frames[f];

				rotation = frames[f + 1] + boneData.Rotation;
				angle += Mathf.DeltaAngle(angle, rotation);
				float r = angle;

				float rOut = float.PositiveInfinity;

				pk.outTangent = rOut;

				keys.Add(new Keyframe(time, r, rOut, 0));

				keys[pIndex] = pk;

				currentTime = time;

				timeline.Apply(skeleton, lastTime, currentTime, null, 1);

				lastTime = time;
				listIndex++;
			} else if (curveType == 2) {
				//bezier
				Keyframe pk = keys[pIndex];

				float time = frames[f];

				timeline.Apply(skeleton, lastTime, currentTime, null, 1);
				skeleton.UpdateWorldTransform();

				rotation = frames[f + 1] + boneData.Rotation;
				angle += Mathf.DeltaAngle(angle, rotation);
				float r = angle;

				int steps = Mathf.FloorToInt((time - pk.time) / bakeIncrement);

				for (int i = 1; i <= steps; i++) {
					currentTime += bakeIncrement;
					if (i == steps)
						currentTime = time;

					timeline.Apply(skeleton, lastTime, currentTime, null, 1);
					skeleton.UpdateWorldTransform();
					pk = keys[listIndex - 1];

					rotation = bone.Rotation;
					angle += Mathf.DeltaAngle(angle, rotation);
					r = angle;

					float rOut = (r - pk.value) / (currentTime - pk.time);

					pk.outTangent = rOut;

					keys.Add(new Keyframe(currentTime, r, rOut, 0));

					keys[listIndex - 1] = pk;

					listIndex++;
					lastTime = currentTime;
				}
			}

			frameIndex++;
			f += 2;
		}

		curve = EnsureCurveKeyCount(new AnimationCurve(keys.ToArray()));

		string path = GetPath(boneData);
		string propertyName = "localEulerAnglesBaked";

		EditorCurveBinding xBind = EditorCurveBinding.FloatCurve(path, typeof(Transform), propertyName + ".x");
		AnimationUtility.SetEditorCurve(clip, xBind, new AnimationCurve());
		EditorCurveBinding yBind = EditorCurveBinding.FloatCurve(path, typeof(Transform), propertyName + ".y");
		AnimationUtility.SetEditorCurve(clip, yBind, new AnimationCurve());
		EditorCurveBinding zBind = EditorCurveBinding.FloatCurve(path, typeof(Transform), propertyName + ".z");
		AnimationUtility.SetEditorCurve(clip, zBind, curve);

	}
Exemple #2
0
        public bool Apply(Skeleton skeleton)
        {
            if (skeleton == null)
            {
                throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
            }
            if (this.animationsChanged)
            {
                this.AnimationsChanged();
            }
            ExposedList <Spine.Event> events = this.events;
            bool flag = false;

            TrackEntry[] items = this.tracks.Items;
            int          index = 0;
            int          count = this.tracks.Count;

            while (index < count)
            {
                TrackEntry to = items[index];
                if ((to != null) && (to.delay <= 0f))
                {
                    flag = true;
                    MixPose currentPose = (index != 0) ? MixPose.CurrentLayered : MixPose.Current;
                    float   alpha       = to.alpha;
                    if (to.mixingFrom != null)
                    {
                        alpha *= this.ApplyMixingFrom(to, skeleton, currentPose);
                    }
                    else if ((to.trackTime >= to.trackEnd) && (to.next == null))
                    {
                        alpha = 0f;
                    }
                    float animationLast = to.animationLast;
                    float animationTime = to.AnimationTime;
                    int   num6          = to.animation.timelines.Count;
                    ExposedList <Timeline> timelines     = to.animation.timelines;
                    Timeline[]             timelineArray = timelines.Items;
                    if (alpha == 1f)
                    {
                        for (int i = 0; i < num6; i++)
                        {
                            timelineArray[i].Apply(skeleton, animationLast, animationTime, events, 1f, MixPose.Setup, MixDirection.In);
                        }
                    }
                    else
                    {
                        int[] numArray   = to.timelineData.Items;
                        bool  firstFrame = to.timelinesRotation.Count == 0;
                        if (firstFrame)
                        {
                            to.timelinesRotation.EnsureCapacity(timelines.Count << 1);
                        }
                        float[] timelinesRotation = to.timelinesRotation.Items;
                        for (int i = 0; i < num6; i++)
                        {
                            Timeline       timeline       = timelineArray[i];
                            MixPose        pose           = (numArray[i] < 1) ? currentPose : MixPose.Setup;
                            RotateTimeline rotateTimeline = timeline as RotateTimeline;
                            if (rotateTimeline != null)
                            {
                                ApplyRotateTimeline(rotateTimeline, skeleton, animationTime, alpha, pose, timelinesRotation, i << 1, firstFrame);
                            }
                            else
                            {
                                timeline.Apply(skeleton, animationLast, animationTime, events, alpha, pose, MixDirection.In);
                            }
                        }
                    }
                    this.QueueEvents(to, animationTime);
                    events.Clear(false);
                    to.nextAnimationLast = animationTime;
                    to.nextTrackLast     = to.trackTime;
                }
                index++;
            }
            this.queue.Drain();
            return(flag);
        }
Exemple #3
0
        void ReadBoneAnimation(ref ExposedList <Timeline> timelines, SkeletonDataStream input, ref float duration, float scale)
        {
            // Bone timelines.
            for (int i = 0, n = SkeletonDataStream.sp_readVarint(input.ptr, 1); i < n; i++)
            {
                int boneIndex = SkeletonDataStream.sp_readVarint(input.ptr, 1);
                for (int ii = 0, nn = SkeletonDataStream.sp_readVarint(input.ptr, 1); ii < nn; ii++)
                {
                    int timelineType = input.ReadByte();
                    int frameCount   = SkeletonDataStream.sp_readVarint(input.ptr, 1);
                    switch (timelineType)
                    {
                    case BONE_ROTATE: {
                        RotateTimeline timeline = new RotateTimeline(frameCount);
                        timeline.boneIndex = boneIndex;
                        for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                        {
                            timeline.SetFrame(frameIndex, SkeletonDataStream.sp_readFloat(input.ptr), SkeletonDataStream.sp_readFloat(input.ptr));
                            if (frameIndex < frameCount - 1)
                            {
                                SkeletonDataStream.sp_readCurve(input.ptr, frameIndex, timeline.curves);
                            }
                        }
                        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, SkeletonDataStream.sp_readFloat(input.ptr), SkeletonDataStream.sp_readFloat(input.ptr) * timelineScale, SkeletonDataStream.sp_readFloat(input.ptr)
                                              * timelineScale);
                            if (frameIndex < frameCount - 1)
                            {
                                SkeletonDataStream.sp_readCurve(input.ptr, frameIndex, timeline.curves);
                            }
                        }
                        timelines.Add(timeline);
                        duration = Math.Max(duration, timeline.frames[(frameCount - 1) * TranslateTimeline.ENTRIES]);
                        break;
                    }
                    }
                }
            }
        }
        private void readAnimation(String name, Dictionary<String, Object> map, SkeletonData skeletonData)
        {
            var timelines = new List<Timeline>();
            float duration = 0;

            var bonesMap = (Dictionary<String, Object>)map["bones"];
            foreach (KeyValuePair<String, Object> entry in bonesMap) {
                String boneName = entry.Key;
                int boneIndex = skeletonData.FindBoneIndex(boneName);
                if (boneIndex == -1)
                    throw new Exception("Bone not found: " + boneName);

                Dictionary<String, Object> timelineMap = (Dictionary<String, Object>)entry.Value;
                foreach (KeyValuePair<String, Object> timelineEntry in timelineMap) {
                    List<Object> values = (List<Object>)timelineEntry.Value;
                    String timelineName = (String)timelineEntry.Key;
                    if (timelineName.Equals(TIMELINE_ROTATE)) {
                        RotateTimeline timeline = new RotateTimeline(values.Count);
                        timeline.BoneIndex = boneIndex;

                        int frameIndex = 0;
                        foreach (Dictionary<String, Object> valueMap in values) {
                            float time = (float)valueMap["time"];
                            timeline.SetFrame(frameIndex, time, (float)valueMap["angle"]);
                            readCurve(timeline, frameIndex, valueMap);
                            frameIndex++;
                        }
                        timelines.Add(timeline);
                        duration = Math.Max(duration, timeline.Frames[timeline.FrameCount * 2 - 2]);

                    } else if (timelineName.Equals(TIMELINE_TRANSLATE) || timelineName.Equals(TIMELINE_SCALE)) {
                        TranslateTimeline timeline;
                        float timelineScale = 1;
                        if (timelineName.Equals(TIMELINE_SCALE))
                            timeline = new ScaleTimeline(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 = valueMap.ContainsKey("x") ? (float)valueMap["x"] : 0;
                            float y = valueMap.ContainsKey("y") ? (float)valueMap["y"] : 0;
                            timeline.SetFrame(frameIndex, time, (float)x * timelineScale, (float)y * timelineScale);
                            readCurve(timeline, frameIndex, valueMap);
                            frameIndex++;
                        }
                        timelines.Add(timeline);
                        duration = Math.Max(duration, timeline.Frames[timeline.FrameCount * 3 - 3]);

                    } else
                        throw new Exception("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
                }
            }

            if (map.ContainsKey("slots")) {
                Dictionary<String, Object> slotsMap = (Dictionary<String, Object>)map["slots"];
                foreach (KeyValuePair<String, Object> entry in slotsMap) {
                    String slotName = entry.Key;
                    int slotIndex = skeletonData.FindSlotIndex(slotName);
                    Dictionary<String, Object> timelineMap = (Dictionary<String, Object>)entry.Value;

                    foreach (KeyValuePair<String, Object> timelineEntry in timelineMap) {
                        List<Object> values = (List<Object>)timelineEntry.Value;
                        String timelineName = (String)timelineEntry.Key;
                        if (timelineName.Equals(TIMELINE_COLOR)) {
                            ColorTimeline 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(timeline, frameIndex, valueMap);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.Frames[timeline.FrameCount * 5 - 5]);

                        } else if (timelineName.Equals(TIMELINE_ATTACHMENT)) {
                            AttachmentTimeline 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 + ")");
                    }
                }
            }

            timelines.TrimExcess();
            skeletonData.AddAnimation(new Animation(name, timelines, duration));
        }
Exemple #5
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    = (valueMap.ContainsKey("color"))?
                                              (String)valueMap["color"] : "FFFFFFFF";
                                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));
        }
		private void ReadAnimation (String name, Dictionary<String, Object> map, SkeletonData skeletonData) {
			var timelines = new List<Timeline>();
			float duration = 0;

			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;
						String timelineName = (String)timelineEntry.Key;
						if (timelineName.Equals(TIMELINE_ROTATE)) {
							RotateTimeline timeline = new RotateTimeline(values.Count);
							timeline.boneIndex = boneIndex;

							int frameIndex = 0;
							foreach (Dictionary<String, Object> valueMap in values) {
								float time = (float)valueMap["time"];
								timeline.SetFrame(frameIndex, time, (float)valueMap["angle"]);
								ReadCurve(timeline, frameIndex, valueMap);
								frameIndex++;
							}
							timelines.Add(timeline);
							duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 2 - 2]);

						} else if (timelineName.Equals(TIMELINE_TRANSLATE) || timelineName.Equals(TIMELINE_SCALE)) {
							TranslateTimeline timeline;
							float timelineScale = 1;
							if (timelineName.Equals(TIMELINE_SCALE))
								timeline = new ScaleTimeline(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 = valueMap.ContainsKey("x") ? (float)valueMap["x"] : 0;
								float y = valueMap.ContainsKey("y") ? (float)valueMap["y"] : 0;
								timeline.SetFrame(frameIndex, time, (float)x * timelineScale, (float)y * timelineScale);
								ReadCurve(timeline, frameIndex, valueMap);
								frameIndex++;
							}
							timelines.Add(timeline);
							duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 3 - 3]);

						} else
							throw new Exception("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
					}
				}
			}

			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;
						String timelineName = (String)timelineEntry.Key;
						if (timelineName.Equals(TIMELINE_COLOR)) {
							ColorTimeline 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(timeline, frameIndex, valueMap);
								frameIndex++;
							}
							timelines.Add(timeline);
							duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 5 - 5]);

						} else if (timelineName.Equals(TIMELINE_ATTACHMENT)) {
							AttachmentTimeline 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 + ")");
					}
				}
			}

			if (map.ContainsKey("events")) {
				var eventsMap = (List<Object>)map["events"];
				EventTimeline 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"]);
					Event e = new Event(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++, (float)eventMap["time"], e);
				}
				timelines.Add(timeline);
				duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]);
			}

			if (map.ContainsKey("draworder")) {
				var values = (List<Object>)map["draworder"];
				DrawOrderTimeline 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;
						List<Object> 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.
							drawOrder[originalIndex + (int)(float)offsetMap["offset"]] = 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]);
			}

			timelines.TrimExcess();
			skeletonData.AddAnimation(new Animation(name, timelines, duration));
		}
Exemple #7
0
        private void ReadAnimation(String name, Dictionary <String, Object> map, SkeletonData skeletonData)
        {
            var   timelines = new ExposedList <Timeline>();
            float duration  = 0;
            var   scale     = this.Scale;

            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(timeline, frameIndex, valueMap);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 5 - 5]);
                        }
                        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 + ")");
                        }
                    }
                }
            }

            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)
                            {
                                float time = (float)valueMap["time"];
                                timeline.SetFrame(frameIndex, time, (float)valueMap["angle"]);
                                ReadCurve(timeline, frameIndex, valueMap);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 2 - 2]);
                        }
                        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, (float)x * timelineScale, (float)y * timelineScale);
                                ReadCurve(timeline, frameIndex, valueMap);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 3 - 3]);
                        }
                        else
                        {
                            throw new Exception("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
                        }
                    }
                }
            }

            // IK 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(timeline, frameIndex, valueMap);
                        frameIndex++;
                    }
                    timelines.Add(timeline);
                    duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 3 - 3]);
                }
            }

            // 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(timeline, frameIndex, valueMap);
                        frameIndex++;
                    }
                    timelines.Add(timeline);
                    duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 5 - 5]);
                }
            }

            // FFD timelines.
            if (map.ContainsKey("ffd"))
            {
                foreach (KeyValuePair <String, Object> ffdMap in (Dictionary <String, Object>)map["ffd"])
                {
                    Skin skin = skeletonData.FindSkin(ffdMap.Key);
                    foreach (KeyValuePair <String, Object> slotMap in (Dictionary <String, Object>)ffdMap.Value)
                    {
                        int slotIndex = skeletonData.FindSlotIndex(slotMap.Key);
                        foreach (KeyValuePair <String, Object> meshMap in (Dictionary <String, Object>)slotMap.Value)
                        {
                            var        values     = (List <Object>)meshMap.Value;
                            var        timeline   = new FfdTimeline(values.Count);
                            Attachment attachment = skin.GetAttachment(slotIndex, meshMap.Key);
                            if (attachment == null)
                            {
                                throw new Exception("FFD attachment not found: " + meshMap.Key);
                            }
                            timeline.slotIndex  = slotIndex;
                            timeline.attachment = attachment;

                            int vertexCount;
                            if (attachment is MeshAttachment)
                            {
                                vertexCount = ((MeshAttachment)attachment).vertices.Length;
                            }
                            else
                            {
                                vertexCount = ((WeightedMeshAttachment)attachment).Weights.Length / 3 * 2;
                            }

                            int frameIndex = 0;
                            foreach (Dictionary <String, Object> valueMap in values)
                            {
                                float[] vertices;
                                if (!valueMap.ContainsKey("vertices"))
                                {
                                    if (attachment is MeshAttachment)
                                    {
                                        vertices = ((MeshAttachment)attachment).vertices;
                                    }
                                    else
                                    {
                                        vertices = new float[vertexCount];
                                    }
                                }
                                else
                                {
                                    var verticesValue = (List <Object>)valueMap["vertices"];
                                    vertices = new float[vertexCount];
                                    int start = GetInt(valueMap, "offset", 0);
                                    if (scale == 1)
                                    {
                                        for (int i = 0, n = verticesValue.Count; i < n; i++)
                                        {
                                            vertices[i + start] = (float)verticesValue[i];
                                        }
                                    }
                                    else
                                    {
                                        for (int i = 0, n = verticesValue.Count; i < n; i++)
                                        {
                                            vertices[i + start] = (float)verticesValue[i] * scale;
                                        }
                                    }
                                    if (attachment is MeshAttachment)
                                    {
                                        float[] meshVertices = ((MeshAttachment)attachment).vertices;
                                        for (int i = 0; i < vertexCount; i++)
                                        {
                                            vertices[i] += meshVertices[i];
                                        }
                                    }
                                }

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

            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]);
            }

            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));
        }
Exemple #8
0
        private void ReadAnimation(string name, Stream input, SkeletonData skeletonData)
        {
            ExposedList <Timeline> exposedList = new ExposedList <Timeline>();
            float scale = Scale;
            float num   = 0f;
            int   i     = 0;

            for (int num2 = ReadVarint(input, optimizePositive: true); i < num2; i++)
            {
                int slotIndex = ReadVarint(input, optimizePositive: true);
                int j         = 0;
                for (int num3 = ReadVarint(input, optimizePositive: true); j < num3; j++)
                {
                    int num4 = input.ReadByte();
                    int num5 = ReadVarint(input, optimizePositive: true);
                    switch (num4)
                    {
                    case 0:
                    {
                        AttachmentTimeline attachmentTimeline = new AttachmentTimeline(num5);
                        attachmentTimeline.slotIndex = slotIndex;
                        for (int m = 0; m < num5; m++)
                        {
                            attachmentTimeline.SetFrame(m, ReadFloat(input), ReadString(input));
                        }
                        exposedList.Add(attachmentTimeline);
                        num = Math.Max(num, attachmentTimeline.frames[num5 - 1]);
                        break;
                    }

                    case 1:
                    {
                        ColorTimeline colorTimeline = new ColorTimeline(num5);
                        colorTimeline.slotIndex = slotIndex;
                        for (int l = 0; l < num5; l++)
                        {
                            float time2 = ReadFloat(input);
                            int   num8  = ReadInt(input);
                            float r3    = (float)((num8 & 4278190080u) >> 24) / 255f;
                            float g3    = (float)((num8 & 0xFF0000) >> 16) / 255f;
                            float b3    = (float)((num8 & 0xFF00) >> 8) / 255f;
                            float a2    = (float)(num8 & 0xFF) / 255f;
                            colorTimeline.SetFrame(l, time2, r3, g3, b3, a2);
                            if (l < num5 - 1)
                            {
                                ReadCurve(input, l, colorTimeline);
                            }
                        }
                        exposedList.Add(colorTimeline);
                        num = Math.Max(num, colorTimeline.frames[(colorTimeline.FrameCount - 1) * 5]);
                        break;
                    }

                    case 2:
                    {
                        TwoColorTimeline twoColorTimeline = new TwoColorTimeline(num5);
                        twoColorTimeline.slotIndex = slotIndex;
                        for (int k = 0; k < num5; k++)
                        {
                            float time = ReadFloat(input);
                            int   num6 = ReadInt(input);
                            float r    = (float)((num6 & 4278190080u) >> 24) / 255f;
                            float g    = (float)((num6 & 0xFF0000) >> 16) / 255f;
                            float b    = (float)((num6 & 0xFF00) >> 8) / 255f;
                            float a    = (float)(num6 & 0xFF) / 255f;
                            int   num7 = ReadInt(input);
                            float r2   = (float)((num7 & 0xFF0000) >> 16) / 255f;
                            float g2   = (float)((num7 & 0xFF00) >> 8) / 255f;
                            float b2   = (float)(num7 & 0xFF) / 255f;
                            twoColorTimeline.SetFrame(k, time, r, g, b, a, r2, g2, b2);
                            if (k < num5 - 1)
                            {
                                ReadCurve(input, k, twoColorTimeline);
                            }
                        }
                        exposedList.Add(twoColorTimeline);
                        num = Math.Max(num, twoColorTimeline.frames[(twoColorTimeline.FrameCount - 1) * 8]);
                        break;
                    }
                    }
                }
            }
            int n = 0;

            for (int num9 = ReadVarint(input, optimizePositive: true); n < num9; n++)
            {
                int boneIndex = ReadVarint(input, optimizePositive: true);
                int num10     = 0;
                for (int num11 = ReadVarint(input, optimizePositive: true); num10 < num11; num10++)
                {
                    int num12 = input.ReadByte();
                    int num13 = ReadVarint(input, optimizePositive: true);
                    switch (num12)
                    {
                    case 0:
                    {
                        RotateTimeline rotateTimeline = new RotateTimeline(num13);
                        rotateTimeline.boneIndex = boneIndex;
                        for (int num16 = 0; num16 < num13; num16++)
                        {
                            rotateTimeline.SetFrame(num16, ReadFloat(input), ReadFloat(input));
                            if (num16 < num13 - 1)
                            {
                                ReadCurve(input, num16, rotateTimeline);
                            }
                        }
                        exposedList.Add(rotateTimeline);
                        num = Math.Max(num, rotateTimeline.frames[(num13 - 1) * 2]);
                        break;
                    }

                    case 1:
                    case 2:
                    case 3:
                    {
                        float             num14 = 1f;
                        TranslateTimeline translateTimeline;
                        switch (num12)
                        {
                        case 2:
                            translateTimeline = new ScaleTimeline(num13);
                            break;

                        case 3:
                            translateTimeline = new ShearTimeline(num13);
                            break;

                        default:
                            translateTimeline = new TranslateTimeline(num13);
                            num14             = scale;
                            break;
                        }
                        translateTimeline.boneIndex = boneIndex;
                        for (int num15 = 0; num15 < num13; num15++)
                        {
                            translateTimeline.SetFrame(num15, ReadFloat(input), ReadFloat(input) * num14, ReadFloat(input) * num14);
                            if (num15 < num13 - 1)
                            {
                                ReadCurve(input, num15, translateTimeline);
                            }
                        }
                        exposedList.Add(translateTimeline);
                        num = Math.Max(num, translateTimeline.frames[(num13 - 1) * 3]);
                        break;
                    }
                    }
                }
            }
            int num17 = 0;

            for (int num18 = ReadVarint(input, optimizePositive: true); num17 < num18; num17++)
            {
                int ikConstraintIndex = ReadVarint(input, optimizePositive: true);
                int num19             = ReadVarint(input, optimizePositive: true);
                IkConstraintTimeline ikConstraintTimeline = new IkConstraintTimeline(num19);
                ikConstraintTimeline.ikConstraintIndex = ikConstraintIndex;
                for (int num20 = 0; num20 < num19; num20++)
                {
                    ikConstraintTimeline.SetFrame(num20, ReadFloat(input), ReadFloat(input), ReadSByte(input));
                    if (num20 < num19 - 1)
                    {
                        ReadCurve(input, num20, ikConstraintTimeline);
                    }
                }
                exposedList.Add(ikConstraintTimeline);
                num = Math.Max(num, ikConstraintTimeline.frames[(num19 - 1) * 3]);
            }
            int num21 = 0;

            for (int num22 = ReadVarint(input, optimizePositive: true); num21 < num22; num21++)
            {
                int transformConstraintIndex = ReadVarint(input, optimizePositive: true);
                int num23 = ReadVarint(input, optimizePositive: true);
                TransformConstraintTimeline transformConstraintTimeline = new TransformConstraintTimeline(num23);
                transformConstraintTimeline.transformConstraintIndex = transformConstraintIndex;
                for (int num24 = 0; num24 < num23; num24++)
                {
                    transformConstraintTimeline.SetFrame(num24, ReadFloat(input), ReadFloat(input), ReadFloat(input), ReadFloat(input), ReadFloat(input));
                    if (num24 < num23 - 1)
                    {
                        ReadCurve(input, num24, transformConstraintTimeline);
                    }
                }
                exposedList.Add(transformConstraintTimeline);
                num = Math.Max(num, transformConstraintTimeline.frames[(num23 - 1) * 5]);
            }
            int num25 = 0;

            for (int num26 = ReadVarint(input, optimizePositive: true); num25 < num26; num25++)
            {
                int num27 = ReadVarint(input, optimizePositive: true);
                PathConstraintData pathConstraintData = skeletonData.pathConstraints.Items[num27];
                int num28 = 0;
                for (int num29 = ReadVarint(input, optimizePositive: true); num28 < num29; num28++)
                {
                    int num30 = ReadSByte(input);
                    int num31 = ReadVarint(input, optimizePositive: true);
                    switch (num30)
                    {
                    case 0:
                    case 1:
                    {
                        float num33 = 1f;
                        PathConstraintPositionTimeline pathConstraintPositionTimeline;
                        if (num30 == 1)
                        {
                            pathConstraintPositionTimeline = new PathConstraintSpacingTimeline(num31);
                            if (pathConstraintData.spacingMode == SpacingMode.Length || pathConstraintData.spacingMode == SpacingMode.Fixed)
                            {
                                num33 = scale;
                            }
                        }
                        else
                        {
                            pathConstraintPositionTimeline = new PathConstraintPositionTimeline(num31);
                            if (pathConstraintData.positionMode == PositionMode.Fixed)
                            {
                                num33 = scale;
                            }
                        }
                        pathConstraintPositionTimeline.pathConstraintIndex = num27;
                        for (int num34 = 0; num34 < num31; num34++)
                        {
                            pathConstraintPositionTimeline.SetFrame(num34, ReadFloat(input), ReadFloat(input) * num33);
                            if (num34 < num31 - 1)
                            {
                                ReadCurve(input, num34, pathConstraintPositionTimeline);
                            }
                        }
                        exposedList.Add(pathConstraintPositionTimeline);
                        num = Math.Max(num, pathConstraintPositionTimeline.frames[(num31 - 1) * 2]);
                        break;
                    }

                    case 2:
                    {
                        PathConstraintMixTimeline pathConstraintMixTimeline = new PathConstraintMixTimeline(num31);
                        pathConstraintMixTimeline.pathConstraintIndex = num27;
                        for (int num32 = 0; num32 < num31; num32++)
                        {
                            pathConstraintMixTimeline.SetFrame(num32, ReadFloat(input), ReadFloat(input), ReadFloat(input));
                            if (num32 < num31 - 1)
                            {
                                ReadCurve(input, num32, pathConstraintMixTimeline);
                            }
                        }
                        exposedList.Add(pathConstraintMixTimeline);
                        num = Math.Max(num, pathConstraintMixTimeline.frames[(num31 - 1) * 3]);
                        break;
                    }
                    }
                }
            }
            int num35 = 0;

            for (int num36 = ReadVarint(input, optimizePositive: true); num35 < num36; num35++)
            {
                Skin skin  = skeletonData.skins.Items[ReadVarint(input, optimizePositive: true)];
                int  num37 = 0;
                for (int num38 = ReadVarint(input, optimizePositive: true); num37 < num38; num37++)
                {
                    int slotIndex2 = ReadVarint(input, optimizePositive: true);
                    int num39      = 0;
                    for (int num40 = ReadVarint(input, optimizePositive: true); num39 < num40; num39++)
                    {
                        VertexAttachment vertexAttachment = (VertexAttachment)skin.GetAttachment(slotIndex2, ReadString(input));
                        bool             flag             = vertexAttachment.bones != null;
                        float[]          vertices         = vertexAttachment.vertices;
                        int            num41          = (!flag) ? vertices.Length : (vertices.Length / 3 * 2);
                        int            num42          = ReadVarint(input, optimizePositive: true);
                        DeformTimeline deformTimeline = new DeformTimeline(num42);
                        deformTimeline.slotIndex  = slotIndex2;
                        deformTimeline.attachment = vertexAttachment;
                        for (int num43 = 0; num43 < num42; num43++)
                        {
                            float   time3 = ReadFloat(input);
                            int     num44 = ReadVarint(input, optimizePositive: true);
                            float[] array;
                            if (num44 == 0)
                            {
                                array = ((!flag) ? vertices : new float[num41]);
                            }
                            else
                            {
                                array = new float[num41];
                                int num45 = ReadVarint(input, optimizePositive: true);
                                num44 += num45;
                                if (scale == 1f)
                                {
                                    for (int num46 = num45; num46 < num44; num46++)
                                    {
                                        array[num46] = ReadFloat(input);
                                    }
                                }
                                else
                                {
                                    for (int num47 = num45; num47 < num44; num47++)
                                    {
                                        array[num47] = ReadFloat(input) * scale;
                                    }
                                }
                                if (!flag)
                                {
                                    int num48 = 0;
                                    for (int num49 = array.Length; num48 < num49; num48++)
                                    {
                                        array[num48] += vertices[num48];
                                    }
                                }
                            }
                            deformTimeline.SetFrame(num43, time3, array);
                            if (num43 < num42 - 1)
                            {
                                ReadCurve(input, num43, deformTimeline);
                            }
                        }
                        exposedList.Add(deformTimeline);
                        num = Math.Max(num, deformTimeline.frames[num42 - 1]);
                    }
                }
            }
            int num50 = ReadVarint(input, optimizePositive: true);

            if (num50 > 0)
            {
                DrawOrderTimeline drawOrderTimeline = new DrawOrderTimeline(num50);
                int count = skeletonData.slots.Count;
                for (int num51 = 0; num51 < num50; num51++)
                {
                    float time4  = ReadFloat(input);
                    int   num52  = ReadVarint(input, optimizePositive: true);
                    int[] array2 = new int[count];
                    for (int num53 = count - 1; num53 >= 0; num53--)
                    {
                        array2[num53] = -1;
                    }
                    int[] array3 = new int[count - num52];
                    int   num54  = 0;
                    int   num55  = 0;
                    for (int num56 = 0; num56 < num52; num56++)
                    {
                        int num57 = ReadVarint(input, optimizePositive: true);
                        while (num54 != num57)
                        {
                            array3[num55++] = num54++;
                        }
                        array2[num54 + ReadVarint(input, optimizePositive: true)] = num54++;
                    }
                    while (num54 < count)
                    {
                        array3[num55++] = num54++;
                    }
                    for (int num63 = count - 1; num63 >= 0; num63--)
                    {
                        if (array2[num63] == -1)
                        {
                            array2[num63] = array3[--num55];
                        }
                    }
                    drawOrderTimeline.SetFrame(num51, time4, array2);
                }
                exposedList.Add(drawOrderTimeline);
                num = Math.Max(num, drawOrderTimeline.frames[num50 - 1]);
            }
            int num64 = ReadVarint(input, optimizePositive: true);

            if (num64 > 0)
            {
                EventTimeline eventTimeline = new EventTimeline(num64);
                for (int num65 = 0; num65 < num64; num65++)
                {
                    float     time5     = ReadFloat(input);
                    EventData eventData = skeletonData.events.Items[ReadVarint(input, optimizePositive: true)];
                    Event     @event    = new Event(time5, eventData);
                    @event.Int    = ReadVarint(input, optimizePositive: false);
                    @event.Float  = ReadFloat(input);
                    @event.String = ((!ReadBoolean(input)) ? eventData.String : ReadString(input));
                    eventTimeline.SetFrame(num65, @event);
                }
                exposedList.Add(eventTimeline);
                num = Math.Max(num, eventTimeline.frames[num64 - 1]);
            }
            exposedList.TrimExcess();
            skeletonData.animations.Add(new Animation(name, exposedList, num));
        }
        static private void ApplyRotateTimeline(RotateTimeline rotateTimeline, Skeleton skeleton, float time, float alpha, bool setupPose,
                                                float[] timelinesRotation, int i, bool firstFrame)
        {
            if (firstFrame)
            {
                timelinesRotation[i] = 0;
            }

            if (alpha == 1)
            {
                rotateTimeline.Apply(skeleton, 0, time, null, 1, setupPose, false);
                return;
            }

            Bone bone = skeleton.bones.Items[rotateTimeline.boneIndex];

            float[] frames = rotateTimeline.frames;
            if (time < frames[0])
            {
                if (setupPose)
                {
                    bone.rotation = bone.data.rotation;
                }
                return;
            }

            float r2;

            if (time >= frames[frames.Length - RotateTimeline.ENTRIES])             // Time is after last frame.
            {
                r2 = bone.data.rotation + frames[frames.Length + RotateTimeline.PREV_ROTATION];
            }
            else
            {
                // Interpolate between the previous frame and the current frame.
                int   frame        = Animation.BinarySearch(frames, time, RotateTimeline.ENTRIES);
                float prevRotation = frames[frame + RotateTimeline.PREV_ROTATION];
                float frameTime    = frames[frame];
                float percent      = rotateTimeline.GetCurvePercent((frame >> 1) - 1,
                                                                    1 - (time - frameTime) / (frames[frame + RotateTimeline.PREV_TIME] - frameTime));

                r2  = frames[frame + RotateTimeline.ROTATION] - prevRotation;
                r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360;
                r2  = prevRotation + r2 * percent + bone.data.rotation;
                r2 -= (16384 - (int)(16384.499999999996 - r2 / 360)) * 360;
            }

            // Mix between rotations using the direction of the shortest route on the first frame while detecting crosses.
            float r1 = setupPose ? bone.data.rotation : bone.rotation;
            float total, diff = r2 - r1;

            if (diff == 0)
            {
                total = timelinesRotation[i];
            }
            else
            {
                diff -= (16384 - (int)(16384.499999999996 - diff / 360)) * 360;
                float lastTotal, lastDiff;
                if (firstFrame)
                {
                    lastTotal = 0;
                    lastDiff  = diff;
                }
                else
                {
                    lastTotal = timelinesRotation[i];                     // Angle and direction of mix, including loops.
                    lastDiff  = timelinesRotation[i + 1];                 // Difference between bones.
                }
                bool current = diff > 0, dir = lastTotal >= 0;
                // Detect cross at 0 (not 180).
                if (Math.Sign(lastDiff) != Math.Sign(diff) && Math.Abs(lastDiff) <= 90)
                {
                    // A cross after a 360 rotation is a loop.
                    if (Math.Abs(lastTotal) > 180)
                    {
                        lastTotal += 360 * Math.Sign(lastTotal);
                    }
                    dir = current;
                }
                total = diff + lastTotal - lastTotal % 360;                 // Store loops as part of lastTotal.
                if (dir != current)
                {
                    total += 360 * Math.Sign(lastTotal);
                }
                timelinesRotation[i] = total;
            }
            timelinesRotation[i + 1] = diff;
            r1           += total * alpha;
            bone.rotation = r1 - (16384 - (int)(16384.499999999996 - r1 / 360)) * 360;
        }
Exemple #10
0
        private float ApplyMixingFrom(TrackEntry to, Skeleton skeleton, MixPose currentPose)
        {
            TrackEntry mixingFrom = to.mixingFrom;

            if (mixingFrom.mixingFrom != null)
            {
                ApplyMixingFrom(mixingFrom, skeleton, currentPose);
            }
            float num;

            if (to.mixDuration == 0f)
            {
                num = 1f;
            }
            else
            {
                num = to.mixTime / to.mixDuration;
                if (num > 1f)
                {
                    num = 1f;
                }
            }
            ExposedList <Event> exposedList = (!(num < mixingFrom.eventThreshold)) ? null : events;
            bool  flag          = num < mixingFrom.attachmentThreshold;
            bool  flag2         = num < mixingFrom.drawOrderThreshold;
            float animationLast = mixingFrom.animationLast;
            float animationTime = mixingFrom.AnimationTime;
            ExposedList <Timeline> timelines = mixingFrom.animation.timelines;
            int count = timelines.Count;

            Timeline[]   items  = timelines.Items;
            int[]        items2 = mixingFrom.timelineData.Items;
            TrackEntry[] items3 = mixingFrom.timelineDipMix.Items;
            bool         flag3  = mixingFrom.timelinesRotation.Count == 0;

            if (flag3)
            {
                mixingFrom.timelinesRotation.Resize(timelines.Count << 1);
            }
            float[] items4 = mixingFrom.timelinesRotation.Items;
            float   num2   = mixingFrom.alpha * to.interruptAlpha;
            float   num3   = num2 * (1f - num);

            mixingFrom.totalAlpha = 0f;
            for (int i = 0; i < count; i++)
            {
                Timeline timeline = items[i];
                MixPose  pose;
                float    num4;
                switch (items2[i])
                {
                case 0:
                    if ((!flag && timeline is AttachmentTimeline) || (!flag2 && timeline is DrawOrderTimeline))
                    {
                        continue;
                    }
                    pose = currentPose;
                    num4 = num3;
                    break;

                case 1:
                    pose = MixPose.Setup;
                    num4 = num3;
                    break;

                case 2:
                    pose = MixPose.Setup;
                    num4 = num2;
                    break;

                default:
                {
                    pose = MixPose.Setup;
                    num4 = num2;
                    TrackEntry trackEntry = items3[i];
                    num4 *= Math.Max(0f, 1f - trackEntry.mixTime / trackEntry.mixDuration);
                    break;
                }
                }
                mixingFrom.totalAlpha += num4;
                RotateTimeline rotateTimeline = timeline as RotateTimeline;
                if (rotateTimeline != null)
                {
                    ApplyRotateTimeline(rotateTimeline, skeleton, animationTime, num4, pose, items4, i << 1, flag3);
                }
                else
                {
                    timeline.Apply(skeleton, animationLast, animationTime, exposedList, num4, pose, MixDirection.Out);
                }
            }
            if (to.mixDuration > 0f)
            {
                QueueEvents(mixingFrom, animationTime);
            }
            events.Clear(clearArray: false);
            mixingFrom.nextAnimationLast = animationTime;
            mixingFrom.nextTrackLast     = mixingFrom.trackTime;
            return(num);
        }
Exemple #11
0
        private static void ApplyRotateTimeline(RotateTimeline rotateTimeline, Skeleton skeleton, float time, float alpha, MixPose pose, float[] timelinesRotation, int i, bool firstFrame)
        {
            if (firstFrame)
            {
                timelinesRotation[i] = 0f;
            }
            if (alpha == 1f)
            {
                rotateTimeline.Apply(skeleton, 0f, time, null, 1f, pose, MixDirection.In);
                return;
            }
            Bone bone = skeleton.bones.Items[rotateTimeline.boneIndex];

            float[] frames = rotateTimeline.frames;
            if (time < frames[0])
            {
                if (pose == MixPose.Setup)
                {
                    bone.rotation = bone.data.rotation;
                }
                return;
            }
            float num;

            if (time >= frames[frames.Length - 2])
            {
                num = bone.data.rotation + frames[frames.Length + -1];
            }
            else
            {
                int   num2         = Animation.BinarySearch(frames, time, 2);
                float num3         = frames[num2 + -1];
                float num4         = frames[num2];
                float curvePercent = rotateTimeline.GetCurvePercent((num2 >> 1) - 1, 1f - (time - num4) / (frames[num2 + -2] - num4));
                num  = frames[num2 + 1] - num3;
                num -= (float)((16384 - (int)(16384.499999999996 - (double)(num / 360f))) * 360);
                num  = num3 + num * curvePercent + bone.data.rotation;
                num -= (float)((16384 - (int)(16384.499999999996 - (double)(num / 360f))) * 360);
            }
            float num5 = (pose != 0) ? bone.rotation : bone.data.rotation;
            float num6 = num - num5;
            float num7;

            if (num6 == 0f)
            {
                num7 = timelinesRotation[i];
            }
            else
            {
                num6 -= (float)((16384 - (int)(16384.499999999996 - (double)(num6 / 360f))) * 360);
                float num8;
                float value;
                if (firstFrame)
                {
                    num8  = 0f;
                    value = num6;
                }
                else
                {
                    num8  = timelinesRotation[i];
                    value = timelinesRotation[i + 1];
                }
                bool flag  = num6 > 0f;
                bool flag2 = num8 >= 0f;
                if (Math.Sign(value) != Math.Sign(num6) && Math.Abs(value) <= 90f)
                {
                    if (Math.Abs(num8) > 180f)
                    {
                        num8 += (float)(360 * Math.Sign(num8));
                    }
                    flag2 = flag;
                }
                num7 = num6 + num8 - num8 % 360f;
                if (flag2 != flag)
                {
                    num7 += (float)(360 * Math.Sign(num8));
                }
                timelinesRotation[i] = num7;
            }
            timelinesRotation[i + 1] = num6;
            num5         += num7 * alpha;
            bone.rotation = num5 - (float)((16384 - (int)(16384.499999999996 - (double)(num5 / 360f))) * 360);
        }
Exemple #12
0
        public bool Apply(Skeleton skeleton)
        {
            if (skeleton == null)
            {
                throw new ArgumentNullException("skeleton", "skeleton cannot be null.");
            }
            if (animationsChanged)
            {
                AnimationsChanged();
            }
            ExposedList <Event> exposedList = events;
            bool result = false;

            TrackEntry[] items = tracks.Items;
            int          i     = 0;

            for (int count = tracks.Count; i < count; i++)
            {
                TrackEntry trackEntry = items[i];
                if (trackEntry == null || trackEntry.delay > 0f)
                {
                    continue;
                }
                result = true;
                MixPose mixPose = (i == 0) ? MixPose.Current : MixPose.CurrentLayered;
                float   num     = trackEntry.alpha;
                if (trackEntry.mixingFrom != null)
                {
                    num *= ApplyMixingFrom(trackEntry, skeleton, mixPose);
                }
                else if (trackEntry.trackTime >= trackEntry.trackEnd && trackEntry.next == null)
                {
                    num = 0f;
                }
                float animationLast = trackEntry.animationLast;
                float animationTime = trackEntry.AnimationTime;
                int   count2        = trackEntry.animation.timelines.Count;
                ExposedList <Timeline> timelines = trackEntry.animation.timelines;
                Timeline[]             items2    = timelines.Items;
                if (num == 1f)
                {
                    for (int j = 0; j < count2; j++)
                    {
                        items2[j].Apply(skeleton, animationLast, animationTime, exposedList, 1f, MixPose.Setup, MixDirection.In);
                    }
                }
                else
                {
                    int[] items3 = trackEntry.timelineData.Items;
                    bool  flag   = trackEntry.timelinesRotation.Count == 0;
                    if (flag)
                    {
                        trackEntry.timelinesRotation.EnsureCapacity(timelines.Count << 1);
                    }
                    float[] items4 = trackEntry.timelinesRotation.Items;
                    for (int k = 0; k < count2; k++)
                    {
                        Timeline       timeline       = items2[k];
                        MixPose        pose           = (items3[k] < 1) ? mixPose : MixPose.Setup;
                        RotateTimeline rotateTimeline = timeline as RotateTimeline;
                        if (rotateTimeline != null)
                        {
                            ApplyRotateTimeline(rotateTimeline, skeleton, animationTime, num, pose, items4, k << 1, flag);
                        }
                        else
                        {
                            timeline.Apply(skeleton, animationLast, animationTime, exposedList, num, pose, MixDirection.In);
                        }
                    }
                }
                QueueEvents(trackEntry, animationTime);
                exposedList.Clear(clearArray: false);
                trackEntry.nextAnimationLast = animationTime;
                trackEntry.nextTrackLast     = trackEntry.trackTime;
            }
            queue.Drain();
            return(result);
        }
Exemple #13
0
 private static void ApplyRotateTimeline(RotateTimeline rotateTimeline, Skeleton skeleton, float time, float alpha, MixPose pose, float[] timelinesRotation, int i, bool firstFrame)
 {
     if (firstFrame)
     {
         timelinesRotation[i] = 0f;
     }
     if (alpha == 1f)
     {
         rotateTimeline.Apply(skeleton, 0f, time, null, 1f, pose, MixDirection.In);
     }
     else
     {
         Bone    bone   = skeleton.bones.Items[rotateTimeline.boneIndex];
         float[] frames = rotateTimeline.frames;
         if (time < frames[0])
         {
             if (pose == MixPose.Setup)
             {
                 bone.rotation = bone.data.rotation;
             }
         }
         else
         {
             float num;
             float num7;
             if (time >= frames[frames.Length - 2])
             {
                 num = bone.data.rotation + frames[frames.Length + -1];
             }
             else
             {
                 int   index        = Animation.BinarySearch(frames, time, 2);
                 float num3         = frames[index + -1];
                 float num4         = frames[index];
                 float curvePercent = rotateTimeline.GetCurvePercent((index >> 1) - 1, 1f - ((time - num4) / (frames[index + -2] - num4)));
                 num  = frames[index + 1] - num3;
                 num -= (0x4000 - ((int)(16384.499999999996 - (num / 360f)))) * 360;
                 num  = (num3 + (num * curvePercent)) + bone.data.rotation;
                 num -= (0x4000 - ((int)(16384.499999999996 - (num / 360f)))) * 360;
             }
             float num6 = (pose != MixPose.Setup) ? bone.rotation : bone.data.rotation;
             float num8 = num - num6;
             if (num8 == 0f)
             {
                 num7 = timelinesRotation[i];
             }
             else
             {
                 float num9;
                 float num10;
                 num8 -= (0x4000 - ((int)(16384.499999999996 - (num8 / 360f)))) * 360;
                 if (firstFrame)
                 {
                     num9  = 0f;
                     num10 = num8;
                 }
                 else
                 {
                     num9  = timelinesRotation[i];
                     num10 = timelinesRotation[i + 1];
                 }
                 bool flag  = num8 > 0f;
                 bool flag2 = num9 >= 0f;
                 if ((Math.Sign(num10) != Math.Sign(num8)) && (Math.Abs(num10) <= 90f))
                 {
                     if (Math.Abs(num9) > 180f)
                     {
                         num9 += 360 * Math.Sign(num9);
                     }
                     flag2 = flag;
                 }
                 num7 = (num8 + num9) - (num9 % 360f);
                 if (flag2 != flag)
                 {
                     num7 += 360 * Math.Sign(num9);
                 }
                 timelinesRotation[i] = num7;
             }
             timelinesRotation[i + 1] = num8;
             num6         += num7 * alpha;
             bone.rotation = num6 - ((0x4000 - ((int)(16384.499999999996 - (num6 / 360f)))) * 360);
         }
     }
 }
Exemple #14
0
        private float ApplyMixingFrom(TrackEntry to, Skeleton skeleton, MixPose currentPose)
        {
            float      num;
            TrackEntry mixingFrom = to.mixingFrom;

            if (mixingFrom.mixingFrom != null)
            {
                this.ApplyMixingFrom(mixingFrom, skeleton, currentPose);
            }
            if (to.mixDuration == 0f)
            {
                num         = 1f;
                currentPose = MixPose.Setup;
            }
            else
            {
                num = to.mixTime / to.mixDuration;
                if (num > 1f)
                {
                    num = 1f;
                }
            }
            ExposedList <Spine.Event> events = (num >= mixingFrom.eventThreshold) ? null : this.events;
            bool  flag          = num < mixingFrom.attachmentThreshold;
            bool  flag2         = num < mixingFrom.drawOrderThreshold;
            float animationLast = mixingFrom.animationLast;
            float animationTime = mixingFrom.AnimationTime;
            ExposedList <Timeline> timelines = mixingFrom.animation.timelines;
            int count = timelines.Count;

            Timeline[]   items      = timelines.Items;
            int[]        numArray   = mixingFrom.timelineData.Items;
            TrackEntry[] entryArray = mixingFrom.timelineDipMix.Items;
            bool         firstFrame = mixingFrom.timelinesRotation.Count == 0;

            if (firstFrame)
            {
                mixingFrom.timelinesRotation.Resize(timelines.Count << 1);
            }
            float[] timelinesRotation = mixingFrom.timelinesRotation.Items;
            float   num5 = mixingFrom.alpha * to.interruptAlpha;
            float   num6 = num5 * (1f - num);

            mixingFrom.totalAlpha = 0f;
            for (int i = 0; i < count; i++)
            {
                MixPose  setup;
                float    num7;
                Timeline timeline = items[i];
                switch (numArray[i])
                {
                case 0:
                {
                    if (flag || !(timeline is AttachmentTimeline))
                    {
                        break;
                    }
                    continue;
                }

                case 1:
                    setup = MixPose.Setup;
                    num7  = num6;
                    goto Label_01E3;

                case 2:
                    setup = MixPose.Setup;
                    num7  = num5;
                    goto Label_01E3;

                default:
                {
                    setup = MixPose.Setup;
                    TrackEntry entry2 = entryArray[i];
                    num7 = num5 * Math.Max((float)0f, (float)(1f - (entry2.mixTime / entry2.mixDuration)));
                    goto Label_01E3;
                }
                }
                if (!flag2 && (timeline is DrawOrderTimeline))
                {
                    continue;
                }
                setup = currentPose;
                num7  = num6;
Label_01E3:
                mixingFrom.totalAlpha += num7;
                RotateTimeline rotateTimeline = timeline as RotateTimeline;
                if (rotateTimeline != null)
                {
                    ApplyRotateTimeline(rotateTimeline, skeleton, animationTime, num7, setup, timelinesRotation, i << 1, firstFrame);
                }
                else
                {
                    timeline.Apply(skeleton, animationLast, animationTime, events, num7, setup, MixDirection.Out);
                }
            }
            if (to.mixDuration > 0f)
            {
                this.QueueEvents(mixingFrom, animationTime);
            }
            this.events.Clear(false);
            mixingFrom.nextAnimationLast = animationTime;
            mixingFrom.nextTrackLast     = mixingFrom.trackTime;
            return(num);
        }
        private void ReadAnimation(String name, Dictionary <String, Object> map, SkeletonData skeletonData)
        {
            var   timelines = new List <Timeline>();
            float duration  = 0;

            if (map.ContainsKey("bones"))
            {
                var bonesMap = (Dictionary <String, Object>)map["bones"];
                foreach (KeyValuePair <String, Object> entry in bonesMap)
                {
                    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;
                        String timelineName = (String)timelineEntry.Key;
                        if (timelineName.Equals(TIMELINE_ROTATE))
                        {
                            RotateTimeline timeline = new RotateTimeline(values.Count);
                            timeline.BoneIndex = boneIndex;

                            int frameIndex = 0;
                            foreach (Dictionary <String, Object> valueMap in values)
                            {
                                float time = (float)valueMap["time"];
                                timeline.SetFrame(frameIndex, time, (float)valueMap["angle"]);
                                ReadCurve(timeline, frameIndex, valueMap);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.Frames[timeline.FrameCount * 2 - 2]);
                        }
                        else if (timelineName.Equals(TIMELINE_TRANSLATE) || timelineName.Equals(TIMELINE_SCALE))
                        {
                            TranslateTimeline timeline;
                            float             timelineScale = 1;
                            if (timelineName.Equals(TIMELINE_SCALE))
                            {
                                timeline = new ScaleTimeline(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    = valueMap.ContainsKey("x") ? (float)valueMap["x"] : 0;
                                float y    = valueMap.ContainsKey("y") ? (float)valueMap["y"] : 0;
                                timeline.SetFrame(frameIndex, time, (float)x * timelineScale, (float)y * timelineScale);
                                ReadCurve(timeline, frameIndex, valueMap);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.Frames[timeline.FrameCount * 3 - 3]);
                        }
                        else
                        {
                            throw new Exception("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
                        }
                    }
                }
            }

            if (map.ContainsKey("slots"))
            {
                var slotsMap = (Dictionary <String, Object>)map["slots"];
                foreach (KeyValuePair <String, Object> entry in slotsMap)
                {
                    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;
                        String timelineName = (String)timelineEntry.Key;
                        if (timelineName.Equals(TIMELINE_COLOR))
                        {
                            ColorTimeline 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(timeline, frameIndex, valueMap);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.Frames[timeline.FrameCount * 5 - 5]);
                        }
                        else if (timelineName.Equals(TIMELINE_ATTACHMENT))
                        {
                            AttachmentTimeline 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 + ")");
                        }
                    }
                }
            }

            timelines.TrimExcess();
            skeletonData.AddAnimation(new Animation(name, timelines, duration));
        }
        private void ReadAnimation(string name, Dictionary <string, object> map, SkeletonData skeletonData)
        {
            ExposedList <Timeline> exposedList = new ExposedList <Timeline>();
            float num   = 0f;
            float scale = this.Scale;

            if (map.ContainsKey("slots"))
            {
                using (Dictionary <string, object> .Enumerator enumerator = ((Dictionary <string, object>)map.get_Item("slots")).GetEnumerator())
                {
                    while (enumerator.MoveNext())
                    {
                        KeyValuePair <string, object> current = enumerator.get_Current();
                        string key       = current.get_Key();
                        int    slotIndex = skeletonData.FindSlotIndex(key);
                        Dictionary <string, object> dictionary = (Dictionary <string, object>)current.get_Value();
                        using (Dictionary <string, object> .Enumerator enumerator2 = dictionary.GetEnumerator())
                        {
                            while (enumerator2.MoveNext())
                            {
                                KeyValuePair <string, object> current2 = enumerator2.get_Current();
                                List <object> list = (List <object>)current2.get_Value();
                                string        key2 = current2.get_Key();
                                if (key2 == "color")
                                {
                                    ColorTimeline colorTimeline = new ColorTimeline(list.get_Count());
                                    colorTimeline.slotIndex = slotIndex;
                                    int num2 = 0;
                                    for (int i = 0; i < list.get_Count(); i++)
                                    {
                                        Dictionary <string, object> dictionary2 = (Dictionary <string, object>)list.get_Item(i);
                                        float  time      = (float)dictionary2.get_Item("time");
                                        string hexString = (string)dictionary2.get_Item("color");
                                        colorTimeline.SetFrame(num2, time, this.ToColor(hexString, 0), this.ToColor(hexString, 1), this.ToColor(hexString, 2), this.ToColor(hexString, 3));
                                        this.ReadCurve(colorTimeline, num2, dictionary2);
                                        num2++;
                                    }
                                    exposedList.Add(colorTimeline);
                                    num = Math.Max(num, colorTimeline.frames[colorTimeline.FrameCount * 5 - 5]);
                                }
                                else if (key2 == "attachment")
                                {
                                    AttachmentTimeline attachmentTimeline = new AttachmentTimeline(list.get_Count());
                                    attachmentTimeline.slotIndex = slotIndex;
                                    int num3 = 0;
                                    for (int j = 0; j < list.get_Count(); j++)
                                    {
                                        Dictionary <string, object> dictionary3 = (Dictionary <string, object>)list.get_Item(j);
                                        float time2 = (float)dictionary3.get_Item("time");
                                        attachmentTimeline.SetFrame(num3++, time2, (string)dictionary3.get_Item("name"));
                                    }
                                    exposedList.Add(attachmentTimeline);
                                    num = Math.Max(num, attachmentTimeline.frames[attachmentTimeline.FrameCount - 1]);
                                }
                            }
                        }
                    }
                }
            }
            if (map.ContainsKey("bones"))
            {
                using (Dictionary <string, object> .Enumerator enumerator3 = ((Dictionary <string, object>)map.get_Item("bones")).GetEnumerator())
                {
                    while (enumerator3.MoveNext())
                    {
                        KeyValuePair <string, object> current3 = enumerator3.get_Current();
                        string key3 = current3.get_Key();
                        int    num4 = skeletonData.FindBoneIndex(key3);
                        if (num4 == -1)
                        {
                            throw new Exception("Bone not found: " + key3);
                        }
                        Dictionary <string, object> dictionary4 = (Dictionary <string, object>)current3.get_Value();
                        using (Dictionary <string, object> .Enumerator enumerator4 = dictionary4.GetEnumerator())
                        {
                            while (enumerator4.MoveNext())
                            {
                                KeyValuePair <string, object> current4 = enumerator4.get_Current();
                                List <object> list2 = (List <object>)current4.get_Value();
                                string        key4  = current4.get_Key();
                                if (key4 == "rotate")
                                {
                                    RotateTimeline rotateTimeline = new RotateTimeline(list2.get_Count());
                                    rotateTimeline.boneIndex = num4;
                                    int num5 = 0;
                                    for (int k = 0; k < list2.get_Count(); k++)
                                    {
                                        Dictionary <string, object> dictionary5 = (Dictionary <string, object>)list2.get_Item(k);
                                        float time3 = (float)dictionary5.get_Item("time");
                                        rotateTimeline.SetFrame(num5, time3, (float)dictionary5.get_Item("angle"));
                                        this.ReadCurve(rotateTimeline, num5, dictionary5);
                                        num5++;
                                    }
                                    exposedList.Add(rotateTimeline);
                                    num = Math.Max(num, rotateTimeline.frames[rotateTimeline.FrameCount * 2 - 2]);
                                }
                                else if (key4 == "translate" || key4 == "scale")
                                {
                                    float             num6 = 1f;
                                    TranslateTimeline translateTimeline;
                                    if (key4 == "scale")
                                    {
                                        translateTimeline = new ScaleTimeline(list2.get_Count());
                                    }
                                    else
                                    {
                                        translateTimeline = new TranslateTimeline(list2.get_Count());
                                        num6 = scale;
                                    }
                                    translateTimeline.boneIndex = num4;
                                    int num7 = 0;
                                    for (int l = 0; l < list2.get_Count(); l++)
                                    {
                                        Dictionary <string, object> dictionary6 = (Dictionary <string, object>)list2.get_Item(l);
                                        float time4 = (float)dictionary6.get_Item("time");
                                        float num8  = (!dictionary6.ContainsKey("x")) ? 0f : ((float)dictionary6.get_Item("x"));
                                        float num9  = (!dictionary6.ContainsKey("y")) ? 0f : ((float)dictionary6.get_Item("y"));
                                        translateTimeline.SetFrame(num7, time4, num8 * num6, num9 * num6);
                                        this.ReadCurve(translateTimeline, num7, dictionary6);
                                        num7++;
                                    }
                                    exposedList.Add(translateTimeline);
                                    num = Math.Max(num, translateTimeline.frames[translateTimeline.FrameCount * 3 - 3]);
                                }
                                else if (key4 == "flipX" || key4 == "flipY")
                                {
                                    bool          flag          = key4 == "flipX";
                                    FlipXTimeline flipXTimeline = (!flag) ? new FlipYTimeline(list2.get_Count()) : new FlipXTimeline(list2.get_Count());
                                    flipXTimeline.boneIndex = num4;
                                    string text  = (!flag) ? "y" : "x";
                                    int    num10 = 0;
                                    for (int m = 0; m < list2.get_Count(); m++)
                                    {
                                        Dictionary <string, object> dictionary7 = (Dictionary <string, object>)list2.get_Item(m);
                                        float time5 = (float)dictionary7.get_Item("time");
                                        flipXTimeline.SetFrame(num10, time5, dictionary7.ContainsKey(text) && (bool)dictionary7.get_Item(text));
                                        num10++;
                                    }
                                    exposedList.Add(flipXTimeline);
                                    num = Math.Max(num, flipXTimeline.frames[flipXTimeline.FrameCount * 2 - 2]);
                                }
                            }
                        }
                    }
                }
            }
            if (map.ContainsKey("ik"))
            {
                using (Dictionary <string, object> .Enumerator enumerator5 = ((Dictionary <string, object>)map.get_Item("ik")).GetEnumerator())
                {
                    while (enumerator5.MoveNext())
                    {
                        KeyValuePair <string, object> current5 = enumerator5.get_Current();
                        IkConstraintData     item  = skeletonData.FindIkConstraint(current5.get_Key());
                        List <object>        list3 = (List <object>)current5.get_Value();
                        IkConstraintTimeline ikConstraintTimeline = new IkConstraintTimeline(list3.get_Count());
                        ikConstraintTimeline.ikConstraintIndex = skeletonData.ikConstraints.IndexOf(item);
                        int num11 = 0;
                        for (int n = 0; n < list3.get_Count(); n++)
                        {
                            Dictionary <string, object> dictionary8 = (Dictionary <string, object>)list3.get_Item(n);
                            float time6 = (float)dictionary8.get_Item("time");
                            float mix   = (!dictionary8.ContainsKey("mix")) ? 1f : ((float)dictionary8.get_Item("mix"));
                            bool  flag2 = !dictionary8.ContainsKey("bendPositive") || (bool)dictionary8.get_Item("bendPositive");
                            ikConstraintTimeline.SetFrame(num11, time6, mix, (!flag2) ? -1 : 1);
                            this.ReadCurve(ikConstraintTimeline, num11, dictionary8);
                            num11++;
                        }
                        exposedList.Add(ikConstraintTimeline);
                        num = Math.Max(num, ikConstraintTimeline.frames[ikConstraintTimeline.FrameCount * 3 - 3]);
                    }
                }
            }
            if (map.ContainsKey("ffd"))
            {
                using (Dictionary <string, object> .Enumerator enumerator6 = ((Dictionary <string, object>)map.get_Item("ffd")).GetEnumerator())
                {
                    while (enumerator6.MoveNext())
                    {
                        KeyValuePair <string, object> current6 = enumerator6.get_Current();
                        Skin skin = skeletonData.FindSkin(current6.get_Key());
                        using (Dictionary <string, object> .Enumerator enumerator7 = ((Dictionary <string, object>)current6.get_Value()).GetEnumerator())
                        {
                            while (enumerator7.MoveNext())
                            {
                                KeyValuePair <string, object> current7 = enumerator7.get_Current();
                                int slotIndex2 = skeletonData.FindSlotIndex(current7.get_Key());
                                using (Dictionary <string, object> .Enumerator enumerator8 = ((Dictionary <string, object>)current7.get_Value()).GetEnumerator())
                                {
                                    while (enumerator8.MoveNext())
                                    {
                                        KeyValuePair <string, object> current8 = enumerator8.get_Current();
                                        List <object> list4       = (List <object>)current8.get_Value();
                                        FFDTimeline   fFDTimeline = new FFDTimeline(list4.get_Count());
                                        Attachment    attachment  = skin.GetAttachment(slotIndex2, current8.get_Key());
                                        if (attachment == null)
                                        {
                                            throw new Exception("FFD attachment not found: " + current8.get_Key());
                                        }
                                        fFDTimeline.slotIndex  = slotIndex2;
                                        fFDTimeline.attachment = attachment;
                                        int num12;
                                        if (attachment is MeshAttachment)
                                        {
                                            num12 = ((MeshAttachment)attachment).vertices.Length;
                                        }
                                        else
                                        {
                                            num12 = ((SkinnedMeshAttachment)attachment).Weights.Length / 3 * 2;
                                        }
                                        int num13 = 0;
                                        for (int num14 = 0; num14 < list4.get_Count(); num14++)
                                        {
                                            Dictionary <string, object> dictionary9 = (Dictionary <string, object>)list4.get_Item(num14);
                                            float[] array;
                                            if (!dictionary9.ContainsKey("vertices"))
                                            {
                                                if (attachment is MeshAttachment)
                                                {
                                                    array = ((MeshAttachment)attachment).vertices;
                                                }
                                                else
                                                {
                                                    array = new float[num12];
                                                }
                                            }
                                            else
                                            {
                                                List <object> list5 = (List <object>)dictionary9.get_Item("vertices");
                                                array = new float[num12];
                                                int @int = this.GetInt(dictionary9, "offset", 0);
                                                if (scale == 1f)
                                                {
                                                    int num15 = 0;
                                                    int count = list5.get_Count();
                                                    while (num15 < count)
                                                    {
                                                        array[num15 + @int] = (float)list5.get_Item(num15);
                                                        num15++;
                                                    }
                                                }
                                                else
                                                {
                                                    int num16  = 0;
                                                    int count2 = list5.get_Count();
                                                    while (num16 < count2)
                                                    {
                                                        array[num16 + @int] = (float)list5.get_Item(num16) * scale;
                                                        num16++;
                                                    }
                                                }
                                                if (attachment is MeshAttachment)
                                                {
                                                    float[] vertices = ((MeshAttachment)attachment).vertices;
                                                    for (int num17 = 0; num17 < num12; num17++)
                                                    {
                                                        array[num17] += vertices[num17];
                                                    }
                                                }
                                            }
                                            fFDTimeline.SetFrame(num13, (float)dictionary9.get_Item("time"), array);
                                            this.ReadCurve(fFDTimeline, num13, dictionary9);
                                            num13++;
                                        }
                                        exposedList.Add(fFDTimeline);
                                        num = Math.Max(num, fFDTimeline.frames[fFDTimeline.FrameCount - 1]);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (map.ContainsKey("drawOrder") || map.ContainsKey("draworder"))
            {
                List <object>     list6             = (List <object>)map.get_Item((!map.ContainsKey("drawOrder")) ? "draworder" : "drawOrder");
                DrawOrderTimeline drawOrderTimeline = new DrawOrderTimeline(list6.get_Count());
                int count3 = skeletonData.slots.Count;
                int num18  = 0;
                for (int num19 = 0; num19 < list6.get_Count(); num19++)
                {
                    Dictionary <string, object> dictionary10 = (Dictionary <string, object>)list6.get_Item(num19);
                    int[] array2 = null;
                    if (dictionary10.ContainsKey("offsets"))
                    {
                        array2 = new int[count3];
                        for (int num20 = count3 - 1; num20 >= 0; num20--)
                        {
                            array2[num20] = -1;
                        }
                        List <object> list7  = (List <object>)dictionary10.get_Item("offsets");
                        int[]         array3 = new int[count3 - list7.get_Count()];
                        int           num21  = 0;
                        int           num22  = 0;
                        for (int num23 = 0; num23 < list7.get_Count(); num23++)
                        {
                            Dictionary <string, object> dictionary11 = (Dictionary <string, object>)list7.get_Item(num23);
                            int num24 = skeletonData.FindSlotIndex((string)dictionary11.get_Item("slot"));
                            if (num24 == -1)
                            {
                                throw new Exception("Slot not found: " + dictionary11.get_Item("slot"));
                            }
                            while (num21 != num24)
                            {
                                array3[num22++] = num21++;
                            }
                            int num25 = num21 + (int)((float)dictionary11.get_Item("offset"));
                            array2[num25] = num21++;
                        }
                        while (num21 < count3)
                        {
                            array3[num22++] = num21++;
                        }
                        for (int num26 = count3 - 1; num26 >= 0; num26--)
                        {
                            if (array2[num26] == -1)
                            {
                                array2[num26] = array3[--num22];
                            }
                        }
                    }
                    drawOrderTimeline.SetFrame(num18++, (float)dictionary10.get_Item("time"), array2);
                }
                exposedList.Add(drawOrderTimeline);
                num = Math.Max(num, drawOrderTimeline.frames[drawOrderTimeline.FrameCount - 1]);
            }
            if (map.ContainsKey("events"))
            {
                List <object> list8         = (List <object>)map.get_Item("events");
                EventTimeline eventTimeline = new EventTimeline(list8.get_Count());
                int           num27         = 0;
                for (int num28 = 0; num28 < list8.get_Count(); num28++)
                {
                    Dictionary <string, object> dictionary12 = (Dictionary <string, object>)list8.get_Item(num28);
                    EventData eventData = skeletonData.FindEvent((string)dictionary12.get_Item("name"));
                    if (eventData == null)
                    {
                        throw new Exception("Event not found: " + dictionary12.get_Item("name"));
                    }
                    Event @event = new Event(eventData);
                    @event.Int    = this.GetInt(dictionary12, "int", eventData.Int);
                    @event.Float  = this.GetFloat(dictionary12, "float", eventData.Float);
                    @event.String = this.GetString(dictionary12, "string", eventData.String);
                    eventTimeline.SetFrame(num27++, (float)dictionary12.get_Item("time"), @event);
                }
                exposedList.Add(eventTimeline);
                num = Math.Max(num, eventTimeline.frames[eventTimeline.FrameCount - 1]);
            }
            exposedList.TrimExcess();
            skeletonData.animations.Add(new Animation(name, exposedList, num));
        }
		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 = ReadInt(input, true); i < n; i++) {
				int slotIndex = ReadInt(input, true);
				for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++) {
					int timelineType = input.ReadByte();
					int frameCount = ReadInt(input, true);
					switch (timelineType) {
					case TIMELINE_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[frameCount * 5 - 5]);
						break;
					}
					case TIMELINE_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 = ReadInt(input, true); i < n; i++) {
				int boneIndex = ReadInt(input, true);
				for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++) {
					int timelineType = input.ReadByte();
					int frameCount = ReadInt(input, true);
					switch (timelineType) {
					case TIMELINE_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 * 2 - 2]);
						break;
					}
					case TIMELINE_TRANSLATE:
					case TIMELINE_SCALE: {
						TranslateTimeline timeline;
						float timelineScale = 1;
						if (timelineType == TIMELINE_SCALE)
							timeline = new ScaleTimeline(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 * 3 - 3]);
						break;
					}
					case TIMELINE_FLIPX:
					case TIMELINE_FLIPY: {
						FlipXTimeline timeline = timelineType == TIMELINE_FLIPX ? new FlipXTimeline(frameCount) : new FlipYTimeline(
							frameCount);
						timeline.boneIndex = boneIndex;
						for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
							timeline.SetFrame(frameIndex, ReadFloat(input), ReadBoolean(input));
						timelines.Add(timeline);
						duration = Math.Max(duration, timeline.frames[frameCount * 2 - 2]);
						break;
					}
					}
				}
			}

			// IK timelines.
			for (int i = 0, n = ReadInt(input, true); i < n; i++) {
				IkConstraintData ikConstraint = skeletonData.ikConstraints.Items[ReadInt(input, true)];
				int frameCount = ReadInt(input, true);
				IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount);
				timeline.ikConstraintIndex = skeletonData.ikConstraints.IndexOf(ikConstraint);
				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 * 3 - 3]);
			}

			// FFD timelines.
			for (int i = 0, n = ReadInt(input, true); i < n; i++) {
				Skin skin = skeletonData.skins.Items[ReadInt(input, true)];
				for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++) {
					int slotIndex = ReadInt(input, true);
					for (int iii = 0, nnn = ReadInt(input, true); iii < nnn; iii++) {
						Attachment attachment = skin.GetAttachment(slotIndex, ReadString(input));
						int frameCount = ReadInt(input, true);
						FFDTimeline timeline = new FFDTimeline(frameCount);
						timeline.slotIndex = slotIndex;
						timeline.attachment = attachment;
						for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) {
							float time = ReadFloat(input);

							float[] vertices;
							int vertexCount;
							if (attachment is MeshAttachment)
								vertexCount = ((MeshAttachment)attachment).vertices.Length;
							else
								vertexCount = ((SkinnedMeshAttachment)attachment).weights.Length / 3 * 2;

							int end = ReadInt(input, true);
							if (end == 0) {
								if (attachment is MeshAttachment)
									vertices = ((MeshAttachment)attachment).vertices;
								else
									vertices = new float[vertexCount];
							} else {
								vertices = new float[vertexCount];
								int start = ReadInt(input, true);
								end += start;
								if (scale == 1) {
									for (int v = start; v < end; v++)
										vertices[v] = ReadFloat(input);
								} else {
									for (int v = start; v < end; v++)
										vertices[v] = ReadFloat(input) * scale;
								}
								if (attachment is MeshAttachment) {
									float[] meshVertices = ((MeshAttachment)attachment).vertices;
									for (int v = 0, vn = vertices.Length; v < vn; v++)
										vertices[v] += meshVertices[v];
								}
							}

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

			// Draw order timeline.
			int drawOrderCount = ReadInt(input, true);
			if (drawOrderCount > 0) {
				DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount);
				int slotCount = skeletonData.slots.Count;
				for (int i = 0; i < drawOrderCount; i++) {
					int offsetCount = ReadInt(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 = ReadInt(input, true);
						// Collect unchanged items.
						while (originalIndex != slotIndex)
							unchanged[unchangedIndex++] = originalIndex++;
						// Set changed items.
						drawOrder[originalIndex + ReadInt(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, ReadFloat(input), drawOrder);
				}
				timelines.Add(timeline);
				duration = Math.Max(duration, timeline.frames[drawOrderCount - 1]);
			}

			// Event timeline.
			int eventCount = ReadInt(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[ReadInt(input, true)];
					Event e = new Event(eventData);
					e.Int = ReadInt(input, false);
					e.Float = ReadFloat(input);
					e.String = ReadBoolean(input) ? ReadString(input) : eventData.String;
					timeline.SetFrame(i, time, e);
				}
				timelines.Add(timeline);
				duration = Math.Max(duration, timeline.frames[eventCount - 1]);
			}

			timelines.TrimExcess();
			skeletonData.animations.Add(new Animation(name, timelines, duration));
		}
		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));
		}
        private void ReadAnimation(String name, NewStream 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));
        }
        private void ReadAnimation(String name, Dictionary <String, Object> map, SkeletonData skeletonData)
        {
            var   timelines = new List <Timeline>();
            float duration  = 0;

            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;
                        String timelineName = (String)timelineEntry.Key;
                        if (timelineName.Equals(TIMELINE_ROTATE))
                        {
                            RotateTimeline timeline = new RotateTimeline(values.Count);
                            timeline.boneIndex = boneIndex;

                            int frameIndex = 0;
                            foreach (Dictionary <String, Object> valueMap in values)
                            {
                                float time = (float)valueMap["time"];
                                timeline.SetFrame(frameIndex, time, (float)valueMap["angle"]);
                                ReadCurve(timeline, frameIndex, valueMap);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 2 - 2]);
                        }
                        else if (timelineName.Equals(TIMELINE_TRANSLATE) || timelineName.Equals(TIMELINE_SCALE))
                        {
                            TranslateTimeline timeline;
                            float             timelineScale = 1;
                            if (timelineName.Equals(TIMELINE_SCALE))
                            {
                                timeline = new ScaleTimeline(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    = valueMap.ContainsKey("x") ? (float)valueMap["x"] : 0;
                                float y    = valueMap.ContainsKey("y") ? (float)valueMap["y"] : 0;
                                timeline.SetFrame(frameIndex, time, (float)x * timelineScale, (float)y * timelineScale);
                                ReadCurve(timeline, frameIndex, valueMap);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 3 - 3]);
                        }
                        else
                        {
                            throw new Exception("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
                        }
                    }
                }
            }

            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;
                        String timelineName = (String)timelineEntry.Key;
                        if (timelineName.Equals(TIMELINE_COLOR))
                        {
                            ColorTimeline 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(timeline, frameIndex, valueMap);
                                frameIndex++;
                            }
                            timelines.Add(timeline);
                            duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 5 - 5]);
                        }
                        else if (timelineName.Equals(TIMELINE_ATTACHMENT))
                        {
                            AttachmentTimeline 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 + ")");
                        }
                    }
                }
            }

            if (map.ContainsKey("events"))
            {
                var           eventsMap  = (List <Object>)map["events"];
                EventTimeline 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"]);
                    }
                    Event e = new Event(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++, (float)eventMap["time"], e);
                }
                timelines.Add(timeline);
                duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]);
            }

            if (map.ContainsKey("draworder"))
            {
                var values = (List <Object>)map["draworder"];
                DrawOrderTimeline 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;
                        }
                        List <Object> 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.
                            drawOrder[originalIndex + (int)(float)offsetMap["offset"]] = 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]);
            }

            timelines.TrimExcess();
            skeletonData.AddAnimation(new Animation(name, timelines, duration));
        }
		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));
		}
        private void ReadAnimation(String name, Dictionary <String, Object> map, SkeletonData skeletonData)
        {
            var   timelines = new List <Timeline>();
            float duration  = 0;
            float scale     = Scale;

            if (map.ContainsKey("slots"))
            {
                foreach (var entry in (Dictionary <String, Object>)map["slots"])
                {
                    String slotName    = entry.Key;
                    int    slotIndex   = skeletonData.FindSlotIndex(slotName);
                    var    timelineMap = (Dictionary <String, Object>)entry.Value;

                    foreach (var timelineEntry in timelineMap)
                    {
                        var    values       = (List <Object>)timelineEntry.Value;
                        string timelineName = timelineEntry.Key;
                        if (timelineName.Equals("color"))
                        {
                            var timeline = new ColorTimeline(values.Count);
                            timeline.slotIndex = slotIndex;

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

                            int frameIndex = 0;
                            foreach (Dictionary <String, Object> valueMap in values)
                            {
                                var 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 +
                                                ")");
                        }
                    }
                }
            }

            if (map.ContainsKey("bones"))
            {
                foreach (var 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 (var timelineEntry in timelineMap)
                    {
                        var    values       = (List <Object>)timelineEntry.Value;
                        string timelineName = timelineEntry.Key;
                        if (timelineName.Equals("rotate"))
                        {
                            var timeline = new RotateTimeline(values.Count);
                            timeline.boneIndex = boneIndex;

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

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

            if (map.ContainsKey("ffd"))
            {
                foreach (var ffdMap in (Dictionary <String, Object>)map["ffd"])
                {
                    Skin skin = skeletonData.FindSkin(ffdMap.Key);
                    foreach (var slotMap in (Dictionary <String, Object>)ffdMap.Value)
                    {
                        int slotIndex = skeletonData.FindSlotIndex(slotMap.Key);
                        foreach (var meshMap in (Dictionary <String, Object>)slotMap.Value)
                        {
                            var        values     = (List <Object>)meshMap.Value;
                            var        timeline   = new FFDTimeline(values.Count);
                            Attachment attachment = skin.GetAttachment(slotIndex, meshMap.Key);
                            if (attachment == null)
                            {
                                throw new Exception("FFD attachment not found: " + meshMap.Key);
                            }
                            timeline.slotIndex  = slotIndex;
                            timeline.attachment = attachment;

                            int vertexCount;
                            if (attachment is MeshAttachment)
                            {
                                vertexCount = ((MeshAttachment)attachment).vertices.Length;
                            }
                            else
                            {
                                vertexCount = ((SkinnedMeshAttachment)attachment).Weights.Length / 3 * 2;
                            }

                            int frameIndex = 0;
                            foreach (Dictionary <String, Object> valueMap in values)
                            {
                                float[] vertices;
                                if (!valueMap.ContainsKey("vertices"))
                                {
                                    if (attachment is MeshAttachment)
                                    {
                                        vertices = ((MeshAttachment)attachment).vertices;
                                    }
                                    else
                                    {
                                        vertices = new float[vertexCount];
                                    }
                                }
                                else
                                {
                                    var verticesValue = (List <Object>)valueMap["vertices"];
                                    vertices = new float[vertexCount];
                                    int start = GetInt(valueMap, "offset", 0);
                                    if (scale == 1)
                                    {
                                        for (int i = 0, n = verticesValue.Count; i < n; i++)
                                        {
                                            vertices[i + start] = (float)verticesValue[i];
                                        }
                                    }
                                    else
                                    {
                                        for (int i = 0, n = verticesValue.Count; i < n; i++)
                                        {
                                            vertices[i + start] = (float)verticesValue[i] * scale;
                                        }
                                    }
                                    if (attachment is MeshAttachment)
                                    {
                                        float[] meshVertices = ((MeshAttachment)attachment).vertices;
                                        for (int i = 0; i < vertexCount; i++)
                                        {
                                            vertices[i] += meshVertices[i];
                                        }
                                    }
                                }

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

            if (map.ContainsKey("draworder"))
            {
                var values     = (List <Object>)map["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"];
                        var 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.
                            drawOrder[originalIndex + (int)(float)offsetMap["offset"]] = 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]);
            }

            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(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++, (float)eventMap["time"], e);
                }
                timelines.Add(timeline);
                duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]);
            }

            timelines.TrimExcess();
            skeletonData.AddAnimation(new Animation(name, timelines, duration));
        }
		private void ReadAnimation (String name, Dictionary<String, Object> map, SkeletonData skeletonData) {
			var timelines = new ExposedList<Timeline>();
			float duration = 0;
			float scale = Scale;

			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(timeline, frameIndex, valueMap);
								frameIndex++;
							}
							timelines.Add(timeline);
							duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 5 - 5]);

						} 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 + ")");
					}
				}
			}

			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) {
								float time = (float)valueMap["time"];
								timeline.SetFrame(frameIndex, time, (float)valueMap["angle"]);
								ReadCurve(timeline, frameIndex, valueMap);
								frameIndex++;
							}
							timelines.Add(timeline);
							duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 2 - 2]);

						} else if (timelineName == "translate" || timelineName == "scale") {
							TranslateTimeline timeline;
							float timelineScale = 1;
							if (timelineName == "scale")
								timeline = new ScaleTimeline(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 = valueMap.ContainsKey("x") ? (float)valueMap["x"] : 0;
								float y = valueMap.ContainsKey("y") ? (float)valueMap["y"] : 0;
								timeline.SetFrame(frameIndex, time, (float)x * timelineScale, (float)y * timelineScale);
								ReadCurve(timeline, frameIndex, valueMap);
								frameIndex++;
							}
							timelines.Add(timeline);
							duration = Math.Max(duration, timeline.frames[timeline.FrameCount * 3 - 3]);

						} else
							throw new Exception("Invalid timeline type for a bone: " + timelineName + " (" + boneName + ")");
					}
				}
			}

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

			if (map.ContainsKey("ffd")) {
				foreach (KeyValuePair<String, Object> ffdMap in (Dictionary<String, Object>)map["ffd"]) {
					Skin skin = skeletonData.FindSkin(ffdMap.Key);
					foreach (KeyValuePair<String, Object> slotMap in (Dictionary<String, Object>)ffdMap.Value) {
						int slotIndex = skeletonData.FindSlotIndex(slotMap.Key);
						foreach (KeyValuePair<String, Object> meshMap in (Dictionary<String, Object>)slotMap.Value) {
							var values = (List<Object>)meshMap.Value;
							var timeline = new FFDTimeline(values.Count);
							Attachment attachment = skin.GetAttachment(slotIndex, meshMap.Key);
							if (attachment == null) throw new Exception("FFD attachment not found: " + meshMap.Key);
							timeline.slotIndex = slotIndex;
							timeline.attachment = attachment;

							int vertexCount;
							if (attachment is MeshAttachment)
								vertexCount = ((MeshAttachment)attachment).vertices.Length;
							else
								vertexCount = ((WeightedMeshAttachment)attachment).Weights.Length / 3 * 2;

							int frameIndex = 0;
							foreach (Dictionary<String, Object> valueMap in values) {
								float[] vertices;
								if (!valueMap.ContainsKey("vertices")) {
									if (attachment is MeshAttachment)
										vertices = ((MeshAttachment)attachment).vertices;
									else
										vertices = new float[vertexCount];
								} else {
									var verticesValue = (List<Object>)valueMap["vertices"];
									vertices = new float[vertexCount];
									int start = GetInt(valueMap, "offset", 0);
									if (scale == 1) {
										for (int i = 0, n = verticesValue.Count; i < n; i++)
											vertices[i + start] = (float)verticesValue[i];
									} else {
										for (int i = 0, n = verticesValue.Count; i < n; i++)
											vertices[i + start] = (float)verticesValue[i] * scale;
									}
									if (attachment is MeshAttachment) {
										float[] meshVertices = ((MeshAttachment)attachment).vertices;
										for (int i = 0; i < vertexCount; i++)
											vertices[i] += meshVertices[i];
									}
								}

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

			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]);
			}

			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"]);
					float time = (float)eventMap["time"];
					var e = new Event(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++, time, e);
				}
				timelines.Add(timeline);
				duration = Math.Max(duration, timeline.frames[timeline.FrameCount - 1]);
			}

			timelines.TrimExcess();
			skeletonData.animations.Add(new Animation(name, timelines, duration));
		}
Exemple #24
0
        private void ReadAnimation(string name, Stream input, SkeletonData skeletonData)
        {
            ExposedList <Timeline> exposedList = new ExposedList <Timeline>();
            float scale = this.Scale;
            float num   = 0f;
            int   i     = 0;
            int   num2  = SkeletonBinary.ReadVarint(input, true);

            while (i < num2)
            {
                int slotIndex = SkeletonBinary.ReadVarint(input, true);
                int j         = 0;
                int num3      = SkeletonBinary.ReadVarint(input, true);
                while (j < num3)
                {
                    int num4 = input.ReadByte();
                    int num5 = SkeletonBinary.ReadVarint(input, true);
                    if (num4 != 1)
                    {
                        if (num4 == 0)
                        {
                            AttachmentTimeline attachmentTimeline = new AttachmentTimeline(num5);
                            attachmentTimeline.slotIndex = slotIndex;
                            for (int k = 0; k < num5; k++)
                            {
                                attachmentTimeline.SetFrame(k, this.ReadFloat(input), this.ReadString(input));
                            }
                            exposedList.Add(attachmentTimeline);
                            num = Math.Max(num, attachmentTimeline.frames[num5 - 1]);
                        }
                    }
                    else
                    {
                        ColorTimeline colorTimeline = new ColorTimeline(num5);
                        colorTimeline.slotIndex = slotIndex;
                        for (int l = 0; l < num5; l++)
                        {
                            float time = this.ReadFloat(input);
                            int   num6 = SkeletonBinary.ReadInt(input);
                            float r    = (float)((num6 & 4278190080u) >> 24) / 255f;
                            float g    = (float)((num6 & 16711680) >> 16) / 255f;
                            float b    = (float)((num6 & 65280) >> 8) / 255f;
                            float a    = (float)(num6 & 255) / 255f;
                            colorTimeline.SetFrame(l, time, r, g, b, a);
                            if (l < num5 - 1)
                            {
                                this.ReadCurve(input, l, colorTimeline);
                            }
                        }
                        exposedList.Add(colorTimeline);
                        num = Math.Max(num, colorTimeline.frames[(colorTimeline.FrameCount - 1) * 5]);
                    }
                    j++;
                }
                i++;
            }
            int m    = 0;
            int num7 = SkeletonBinary.ReadVarint(input, true);

            while (m < num7)
            {
                int boneIndex = SkeletonBinary.ReadVarint(input, true);
                int n         = 0;
                int num8      = SkeletonBinary.ReadVarint(input, true);
                while (n < num8)
                {
                    int num9  = input.ReadByte();
                    int num10 = SkeletonBinary.ReadVarint(input, true);
                    switch (num9)
                    {
                    case 0:
                    {
                        RotateTimeline rotateTimeline = new RotateTimeline(num10);
                        rotateTimeline.boneIndex = boneIndex;
                        for (int num11 = 0; num11 < num10; num11++)
                        {
                            rotateTimeline.SetFrame(num11, this.ReadFloat(input), this.ReadFloat(input));
                            if (num11 < num10 - 1)
                            {
                                this.ReadCurve(input, num11, rotateTimeline);
                            }
                        }
                        exposedList.Add(rotateTimeline);
                        num = Math.Max(num, rotateTimeline.frames[(num10 - 1) * 2]);
                        break;
                    }

                    case 1:
                    case 2:
                    case 3:
                    {
                        float             num12 = 1f;
                        TranslateTimeline translateTimeline;
                        if (num9 == 2)
                        {
                            translateTimeline = new ScaleTimeline(num10);
                        }
                        else if (num9 == 3)
                        {
                            translateTimeline = new ShearTimeline(num10);
                        }
                        else
                        {
                            translateTimeline = new TranslateTimeline(num10);
                            num12             = scale;
                        }
                        translateTimeline.boneIndex = boneIndex;
                        for (int num13 = 0; num13 < num10; num13++)
                        {
                            translateTimeline.SetFrame(num13, this.ReadFloat(input), this.ReadFloat(input) * num12, this.ReadFloat(input) * num12);
                            if (num13 < num10 - 1)
                            {
                                this.ReadCurve(input, num13, translateTimeline);
                            }
                        }
                        exposedList.Add(translateTimeline);
                        num = Math.Max(num, translateTimeline.frames[(num10 - 1) * 3]);
                        break;
                    }
                    }
                    n++;
                }
                m++;
            }
            int num14 = 0;
            int num15 = SkeletonBinary.ReadVarint(input, true);

            while (num14 < num15)
            {
                int ikConstraintIndex = SkeletonBinary.ReadVarint(input, true);
                int num16             = SkeletonBinary.ReadVarint(input, true);
                IkConstraintTimeline ikConstraintTimeline = new IkConstraintTimeline(num16);
                ikConstraintTimeline.ikConstraintIndex = ikConstraintIndex;
                for (int num17 = 0; num17 < num16; num17++)
                {
                    ikConstraintTimeline.SetFrame(num17, this.ReadFloat(input), this.ReadFloat(input), (int)SkeletonBinary.ReadSByte(input));
                    if (num17 < num16 - 1)
                    {
                        this.ReadCurve(input, num17, ikConstraintTimeline);
                    }
                }
                exposedList.Add(ikConstraintTimeline);
                num = Math.Max(num, ikConstraintTimeline.frames[(num16 - 1) * 3]);
                num14++;
            }
            int num18 = 0;
            int num19 = SkeletonBinary.ReadVarint(input, true);

            while (num18 < num19)
            {
                int transformConstraintIndex = SkeletonBinary.ReadVarint(input, true);
                int num20 = SkeletonBinary.ReadVarint(input, true);
                TransformConstraintTimeline transformConstraintTimeline = new TransformConstraintTimeline(num20);
                transformConstraintTimeline.transformConstraintIndex = transformConstraintIndex;
                for (int num21 = 0; num21 < num20; num21++)
                {
                    transformConstraintTimeline.SetFrame(num21, this.ReadFloat(input), this.ReadFloat(input), this.ReadFloat(input), this.ReadFloat(input), this.ReadFloat(input));
                    if (num21 < num20 - 1)
                    {
                        this.ReadCurve(input, num21, transformConstraintTimeline);
                    }
                }
                exposedList.Add(transformConstraintTimeline);
                num = Math.Max(num, transformConstraintTimeline.frames[(num20 - 1) * 5]);
                num18++;
            }
            int num22 = 0;
            int num23 = SkeletonBinary.ReadVarint(input, true);

            while (num22 < num23)
            {
                int num24 = SkeletonBinary.ReadVarint(input, true);
                PathConstraintData pathConstraintData = skeletonData.pathConstraints.Items[num24];
                int num25 = 0;
                int num26 = SkeletonBinary.ReadVarint(input, true);
                while (num25 < num26)
                {
                    int num27 = (int)SkeletonBinary.ReadSByte(input);
                    int num28 = SkeletonBinary.ReadVarint(input, true);
                    if (num27 != 0 && num27 != 1)
                    {
                        if (num27 == 2)
                        {
                            PathConstraintMixTimeline pathConstraintMixTimeline = new PathConstraintMixTimeline(num28);
                            pathConstraintMixTimeline.pathConstraintIndex = num24;
                            for (int num29 = 0; num29 < num28; num29++)
                            {
                                pathConstraintMixTimeline.SetFrame(num29, this.ReadFloat(input), this.ReadFloat(input), this.ReadFloat(input));
                                if (num29 < num28 - 1)
                                {
                                    this.ReadCurve(input, num29, pathConstraintMixTimeline);
                                }
                            }
                            exposedList.Add(pathConstraintMixTimeline);
                            num = Math.Max(num, pathConstraintMixTimeline.frames[(num28 - 1) * 3]);
                        }
                    }
                    else
                    {
                        float num30 = 1f;
                        PathConstraintPositionTimeline pathConstraintPositionTimeline;
                        if (num27 == 1)
                        {
                            pathConstraintPositionTimeline = new PathConstraintSpacingTimeline(num28);
                            if (pathConstraintData.spacingMode == SpacingMode.Length || pathConstraintData.spacingMode == SpacingMode.Fixed)
                            {
                                num30 = scale;
                            }
                        }
                        else
                        {
                            pathConstraintPositionTimeline = new PathConstraintPositionTimeline(num28);
                            if (pathConstraintData.positionMode == PositionMode.Fixed)
                            {
                                num30 = scale;
                            }
                        }
                        pathConstraintPositionTimeline.pathConstraintIndex = num24;
                        for (int num31 = 0; num31 < num28; num31++)
                        {
                            pathConstraintPositionTimeline.SetFrame(num31, this.ReadFloat(input), this.ReadFloat(input) * num30);
                            if (num31 < num28 - 1)
                            {
                                this.ReadCurve(input, num31, pathConstraintPositionTimeline);
                            }
                        }
                        exposedList.Add(pathConstraintPositionTimeline);
                        num = Math.Max(num, pathConstraintPositionTimeline.frames[(num28 - 1) * 2]);
                    }
                    num25++;
                }
                num22++;
            }
            int num32 = 0;
            int num33 = SkeletonBinary.ReadVarint(input, true);

            while (num32 < num33)
            {
                Skin skin  = skeletonData.skins.Items[SkeletonBinary.ReadVarint(input, true)];
                int  num34 = 0;
                int  num35 = SkeletonBinary.ReadVarint(input, true);
                while (num34 < num35)
                {
                    int slotIndex2 = SkeletonBinary.ReadVarint(input, true);
                    int num36      = 0;
                    int num37      = SkeletonBinary.ReadVarint(input, true);
                    while (num36 < num37)
                    {
                        VertexAttachment vertexAttachment = (VertexAttachment)skin.GetAttachment(slotIndex2, this.ReadString(input));
                        bool             flag             = vertexAttachment.bones != null;
                        float[]          vertices         = vertexAttachment.vertices;
                        int            num38          = (!flag) ? vertices.Length : (vertices.Length / 3 * 2);
                        int            num39          = SkeletonBinary.ReadVarint(input, true);
                        DeformTimeline deformTimeline = new DeformTimeline(num39);
                        deformTimeline.slotIndex  = slotIndex2;
                        deformTimeline.attachment = vertexAttachment;
                        for (int num40 = 0; num40 < num39; num40++)
                        {
                            float   time2 = this.ReadFloat(input);
                            int     num41 = SkeletonBinary.ReadVarint(input, true);
                            float[] array;
                            if (num41 == 0)
                            {
                                array = ((!flag) ? vertices : new float[num38]);
                            }
                            else
                            {
                                array = new float[num38];
                                int num42 = SkeletonBinary.ReadVarint(input, true);
                                num41 += num42;
                                if (scale == 1f)
                                {
                                    for (int num43 = num42; num43 < num41; num43++)
                                    {
                                        array[num43] = this.ReadFloat(input);
                                    }
                                }
                                else
                                {
                                    for (int num44 = num42; num44 < num41; num44++)
                                    {
                                        array[num44] = this.ReadFloat(input) * scale;
                                    }
                                }
                                if (!flag)
                                {
                                    int num45 = 0;
                                    int num46 = array.Length;
                                    while (num45 < num46)
                                    {
                                        array[num45] += vertices[num45];
                                        num45++;
                                    }
                                }
                            }
                            deformTimeline.SetFrame(num40, time2, array);
                            if (num40 < num39 - 1)
                            {
                                this.ReadCurve(input, num40, deformTimeline);
                            }
                        }
                        exposedList.Add(deformTimeline);
                        num = Math.Max(num, deformTimeline.frames[num39 - 1]);
                        num36++;
                    }
                    num34++;
                }
                num32++;
            }
            int num47 = SkeletonBinary.ReadVarint(input, true);

            if (num47 > 0)
            {
                DrawOrderTimeline drawOrderTimeline = new DrawOrderTimeline(num47);
                int count = skeletonData.slots.Count;
                for (int num48 = 0; num48 < num47; num48++)
                {
                    float time3  = this.ReadFloat(input);
                    int   num49  = SkeletonBinary.ReadVarint(input, true);
                    int[] array2 = new int[count];
                    for (int num50 = count - 1; num50 >= 0; num50--)
                    {
                        array2[num50] = -1;
                    }
                    int[] array3 = new int[count - num49];
                    int   num51  = 0;
                    int   num52  = 0;
                    for (int num53 = 0; num53 < num49; num53++)
                    {
                        int num54 = SkeletonBinary.ReadVarint(input, true);
                        while (num51 != num54)
                        {
                            array3[num52++] = num51++;
                        }
                        array2[num51 + SkeletonBinary.ReadVarint(input, true)] = num51++;
                    }
                    while (num51 < count)
                    {
                        array3[num52++] = num51++;
                    }
                    for (int num55 = count - 1; num55 >= 0; num55--)
                    {
                        if (array2[num55] == -1)
                        {
                            array2[num55] = array3[--num52];
                        }
                    }
                    drawOrderTimeline.SetFrame(num48, time3, array2);
                }
                exposedList.Add(drawOrderTimeline);
                num = Math.Max(num, drawOrderTimeline.frames[num47 - 1]);
            }
            int num56 = SkeletonBinary.ReadVarint(input, true);

            if (num56 > 0)
            {
                EventTimeline eventTimeline = new EventTimeline(num56);
                for (int num57 = 0; num57 < num56; num57++)
                {
                    float     time4     = this.ReadFloat(input);
                    EventData eventData = skeletonData.events.Items[SkeletonBinary.ReadVarint(input, true)];
                    eventTimeline.SetFrame(num57, new Event(time4, eventData)
                    {
                        Int    = SkeletonBinary.ReadVarint(input, false),
                        Float  = this.ReadFloat(input),
                        String = ((!SkeletonBinary.ReadBoolean(input)) ? eventData.String : this.ReadString(input))
                    });
                }
                exposedList.Add(eventTimeline);
                num = Math.Max(num, eventTimeline.frames[num56 - 1]);
            }
            exposedList.TrimExcess();
            skeletonData.animations.Add(new Animation(name, exposedList, num));
        }
        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 = ReadInt(input, true); i < n; i++)
            {
                int slotIndex = ReadInt(input, true);
                for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++)
                {
                    int timelineType = input.ReadByte();
                    int frameCount   = ReadInt(input, true);
                    switch (timelineType)
                    {
                    case TIMELINE_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[frameCount * 5 - 5]);
                        break;
                    }

                    case TIMELINE_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 = ReadInt(input, true); i < n; i++)
            {
                int boneIndex = ReadInt(input, true);
                for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++)
                {
                    int timelineType = input.ReadByte();
                    int frameCount   = ReadInt(input, true);
                    switch (timelineType)
                    {
                    case TIMELINE_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 * 2 - 2]);
                        break;
                    }

                    case TIMELINE_TRANSLATE:
                    case TIMELINE_SCALE: {
                        TranslateTimeline timeline;
                        float             timelineScale = 1;
                        if (timelineType == TIMELINE_SCALE)
                        {
                            timeline = new ScaleTimeline(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 * 3 - 3]);
                        break;
                    }

                    case TIMELINE_FLIPX:
                    case TIMELINE_FLIPY: {
                        FlipXTimeline timeline = timelineType == TIMELINE_FLIPX ? new FlipXTimeline(frameCount) : new FlipYTimeline(
                            frameCount);
                        timeline.boneIndex = boneIndex;
                        for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                        {
                            timeline.SetFrame(frameIndex, ReadFloat(input), ReadBoolean(input));
                        }
                        timelines.Add(timeline);
                        duration = Math.Max(duration, timeline.frames[frameCount * 2 - 2]);
                        break;
                    }
                    }
                }
            }

            // IK timelines.
            for (int i = 0, n = ReadInt(input, true); i < n; i++)
            {
                IkConstraintData ikConstraint = skeletonData.ikConstraints.Items[ReadInt(input, true)];
                int frameCount = ReadInt(input, true);
                IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount);
                timeline.ikConstraintIndex = skeletonData.ikConstraints.IndexOf(ikConstraint);
                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 * 3 - 3]);
            }

            // FFD timelines.
            for (int i = 0, n = ReadInt(input, true); i < n; i++)
            {
                Skin skin = skeletonData.skins.Items[ReadInt(input, true)];
                for (int ii = 0, nn = ReadInt(input, true); ii < nn; ii++)
                {
                    int slotIndex = ReadInt(input, true);
                    for (int iii = 0, nnn = ReadInt(input, true); iii < nnn; iii++)
                    {
                        Attachment  attachment = skin.GetAttachment(slotIndex, ReadString(input));
                        int         frameCount = ReadInt(input, true);
                        FFDTimeline timeline   = new FFDTimeline(frameCount);
                        timeline.slotIndex  = slotIndex;
                        timeline.attachment = attachment;
                        for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
                        {
                            float time = ReadFloat(input);

                            float[] vertices;
                            int     vertexCount;
                            if (attachment is MeshAttachment)
                            {
                                vertexCount = ((MeshAttachment)attachment).vertices.Length;
                            }
                            else
                            {
                                vertexCount = ((SkinnedMeshAttachment)attachment).weights.Length / 3 * 2;
                            }

                            int end = ReadInt(input, true);
                            if (end == 0)
                            {
                                if (attachment is MeshAttachment)
                                {
                                    vertices = ((MeshAttachment)attachment).vertices;
                                }
                                else
                                {
                                    vertices = new float[vertexCount];
                                }
                            }
                            else
                            {
                                vertices = new float[vertexCount];
                                int start = ReadInt(input, true);
                                end += start;
                                if (scale == 1)
                                {
                                    for (int v = start; v < end; v++)
                                    {
                                        vertices[v] = ReadFloat(input);
                                    }
                                }
                                else
                                {
                                    for (int v = start; v < end; v++)
                                    {
                                        vertices[v] = ReadFloat(input) * scale;
                                    }
                                }
                                if (attachment is MeshAttachment)
                                {
                                    float[] meshVertices = ((MeshAttachment)attachment).vertices;
                                    for (int v = 0, vn = vertices.Length; v < vn; v++)
                                    {
                                        vertices[v] += meshVertices[v];
                                    }
                                }
                            }

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

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

            if (drawOrderCount > 0)
            {
                DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount);
                int slotCount = skeletonData.slots.Count;
                for (int i = 0; i < drawOrderCount; i++)
                {
                    int   offsetCount = ReadInt(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 = ReadInt(input, true);
                        // Collect unchanged items.
                        while (originalIndex != slotIndex)
                        {
                            unchanged[unchangedIndex++] = originalIndex++;
                        }
                        // Set changed items.
                        drawOrder[originalIndex + ReadInt(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, ReadFloat(input), drawOrder);
                }
                timelines.Add(timeline);
                duration = Math.Max(duration, timeline.frames[drawOrderCount - 1]);
            }

            // Event timeline.
            int eventCount = ReadInt(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[ReadInt(input, true)];
                    Event     e         = new Event(eventData);
                    e.Int    = ReadInt(input, false);
                    e.Float  = ReadFloat(input);
                    e.String = ReadBoolean(input) ? ReadString(input) : eventData.String;
                    timeline.SetFrame(i, time, e);
                }
                timelines.Add(timeline);
                duration = Math.Max(duration, timeline.frames[eventCount - 1]);
            }

            timelines.TrimExcess();
            skeletonData.animations.Add(new Animation(name, timelines, duration));
        }
Exemple #26
0
        private void ReadAnimation(Dictionary <string, object> map, string name, SkeletonData skeletonData)
        {
            float scale = Scale;
            ExposedList <Timeline> exposedList = new ExposedList <Timeline>();
            float num = 0f;

            if (map.ContainsKey("slots"))
            {
                foreach (KeyValuePair <string, object> item3 in (Dictionary <string, object>)map["slots"])
                {
                    string key       = item3.Key;
                    int    slotIndex = skeletonData.FindSlotIndex(key);
                    Dictionary <string, object> dictionary = (Dictionary <string, object>)item3.Value;
                    foreach (KeyValuePair <string, object> item4 in dictionary)
                    {
                        List <object> list = (List <object>)item4.Value;
                        string        key2 = item4.Key;
                        if (key2 == "attachment")
                        {
                            AttachmentTimeline attachmentTimeline = new AttachmentTimeline(list.Count);
                            attachmentTimeline.slotIndex = slotIndex;
                            int num2 = 0;
                            foreach (Dictionary <string, object> item5 in list)
                            {
                                float time = (float)item5["time"];
                                attachmentTimeline.SetFrame(num2++, time, (string)item5["name"]);
                            }
                            exposedList.Add(attachmentTimeline);
                            num = Math.Max(num, attachmentTimeline.frames[attachmentTimeline.FrameCount - 1]);
                        }
                        else if (key2 == "color")
                        {
                            ColorTimeline colorTimeline = new ColorTimeline(list.Count);
                            colorTimeline.slotIndex = slotIndex;
                            int num4 = 0;
                            foreach (Dictionary <string, object> item6 in list)
                            {
                                float  time2     = (float)item6["time"];
                                string hexString = (string)item6["color"];
                                colorTimeline.SetFrame(num4, time2, ToColor(hexString, 0), ToColor(hexString, 1), ToColor(hexString, 2), ToColor(hexString, 3));
                                ReadCurve(item6, colorTimeline, num4);
                                num4++;
                            }
                            exposedList.Add(colorTimeline);
                            num = Math.Max(num, colorTimeline.frames[(colorTimeline.FrameCount - 1) * 5]);
                        }
                        else
                        {
                            if (!(key2 == "twoColor"))
                            {
                                throw new Exception("Invalid timeline type for a slot: " + key2 + " (" + key + ")");
                            }
                            TwoColorTimeline twoColorTimeline = new TwoColorTimeline(list.Count);
                            twoColorTimeline.slotIndex = slotIndex;
                            int num5 = 0;
                            foreach (Dictionary <string, object> item7 in list)
                            {
                                float  time3      = (float)item7["time"];
                                string hexString2 = (string)item7["light"];
                                string hexString3 = (string)item7["dark"];
                                twoColorTimeline.SetFrame(num5, time3, ToColor(hexString2, 0), ToColor(hexString2, 1), ToColor(hexString2, 2), ToColor(hexString2, 3), ToColor(hexString3, 0, 6), ToColor(hexString3, 1, 6), ToColor(hexString3, 2, 6));
                                ReadCurve(item7, twoColorTimeline, num5);
                                num5++;
                            }
                            exposedList.Add(twoColorTimeline);
                            num = Math.Max(num, twoColorTimeline.frames[(twoColorTimeline.FrameCount - 1) * 8]);
                        }
                    }
                }
            }
            if (map.ContainsKey("bones"))
            {
                foreach (KeyValuePair <string, object> item8 in (Dictionary <string, object>)map["bones"])
                {
                    string key3 = item8.Key;
                    int    num6 = skeletonData.FindBoneIndex(key3);
                    if (num6 == -1)
                    {
                        throw new Exception("Bone not found: " + key3);
                    }
                    Dictionary <string, object> dictionary5 = (Dictionary <string, object>)item8.Value;
                    foreach (KeyValuePair <string, object> item9 in dictionary5)
                    {
                        List <object> list2 = (List <object>)item9.Value;
                        string        key4  = item9.Key;
                        if (key4 == "rotate")
                        {
                            RotateTimeline rotateTimeline = new RotateTimeline(list2.Count);
                            rotateTimeline.boneIndex = num6;
                            int num7 = 0;
                            foreach (Dictionary <string, object> item10 in list2)
                            {
                                rotateTimeline.SetFrame(num7, (float)item10["time"], (float)item10["angle"]);
                                ReadCurve(item10, rotateTimeline, num7);
                                num7++;
                            }
                            exposedList.Add(rotateTimeline);
                            num = Math.Max(num, rotateTimeline.frames[(rotateTimeline.FrameCount - 1) * 2]);
                        }
                        else
                        {
                            if (!(key4 == "translate") && !(key4 == "scale") && !(key4 == "shear"))
                            {
                                throw new Exception("Invalid timeline type for a bone: " + key4 + " (" + key3 + ")");
                            }
                            float             num8 = 1f;
                            TranslateTimeline translateTimeline;
                            if (key4 == "scale")
                            {
                                translateTimeline = new ScaleTimeline(list2.Count);
                            }
                            else if (key4 == "shear")
                            {
                                translateTimeline = new ShearTimeline(list2.Count);
                            }
                            else
                            {
                                translateTimeline = new TranslateTimeline(list2.Count);
                                num8 = scale;
                            }
                            translateTimeline.boneIndex = num6;
                            int num9 = 0;
                            foreach (Dictionary <string, object> item11 in list2)
                            {
                                float time4  = (float)item11["time"];
                                float @float = GetFloat(item11, "x", 0f);
                                float float2 = GetFloat(item11, "y", 0f);
                                translateTimeline.SetFrame(num9, time4, @float * num8, float2 * num8);
                                ReadCurve(item11, translateTimeline, num9);
                                num9++;
                            }
                            exposedList.Add(translateTimeline);
                            num = Math.Max(num, translateTimeline.frames[(translateTimeline.FrameCount - 1) * 3]);
                        }
                    }
                }
            }
            if (map.ContainsKey("ik"))
            {
                foreach (KeyValuePair <string, object> item12 in (Dictionary <string, object>)map["ik"])
                {
                    IkConstraintData     item  = skeletonData.FindIkConstraint(item12.Key);
                    List <object>        list3 = (List <object>)item12.Value;
                    IkConstraintTimeline ikConstraintTimeline = new IkConstraintTimeline(list3.Count);
                    ikConstraintTimeline.ikConstraintIndex = skeletonData.ikConstraints.IndexOf(item);
                    int num10 = 0;
                    foreach (Dictionary <string, object> item13 in list3)
                    {
                        float time5   = (float)item13["time"];
                        float float3  = GetFloat(item13, "mix", 1f);
                        bool  boolean = GetBoolean(item13, "bendPositive", defaultValue: true);
                        ikConstraintTimeline.SetFrame(num10, time5, float3, boolean ? 1 : (-1));
                        ReadCurve(item13, ikConstraintTimeline, num10);
                        num10++;
                    }
                    exposedList.Add(ikConstraintTimeline);
                    num = Math.Max(num, ikConstraintTimeline.frames[(ikConstraintTimeline.FrameCount - 1) * 3]);
                }
            }
            if (map.ContainsKey("transform"))
            {
                foreach (KeyValuePair <string, object> item14 in (Dictionary <string, object>)map["transform"])
                {
                    TransformConstraintData     item2 = skeletonData.FindTransformConstraint(item14.Key);
                    List <object>               list4 = (List <object>)item14.Value;
                    TransformConstraintTimeline transformConstraintTimeline = new TransformConstraintTimeline(list4.Count);
                    transformConstraintTimeline.transformConstraintIndex = skeletonData.transformConstraints.IndexOf(item2);
                    int num11 = 0;
                    foreach (Dictionary <string, object> item15 in list4)
                    {
                        float time6  = (float)item15["time"];
                        float float4 = GetFloat(item15, "rotateMix", 1f);
                        float float5 = GetFloat(item15, "translateMix", 1f);
                        float float6 = GetFloat(item15, "scaleMix", 1f);
                        float float7 = GetFloat(item15, "shearMix", 1f);
                        transformConstraintTimeline.SetFrame(num11, time6, float4, float5, float6, float7);
                        ReadCurve(item15, transformConstraintTimeline, num11);
                        num11++;
                    }
                    exposedList.Add(transformConstraintTimeline);
                    num = Math.Max(num, transformConstraintTimeline.frames[(transformConstraintTimeline.FrameCount - 1) * 5]);
                }
            }
            if (map.ContainsKey("paths"))
            {
                foreach (KeyValuePair <string, object> item16 in (Dictionary <string, object>)map["paths"])
                {
                    int num12 = skeletonData.FindPathConstraintIndex(item16.Key);
                    if (num12 == -1)
                    {
                        throw new Exception("Path constraint not found: " + item16.Key);
                    }
                    PathConstraintData          pathConstraintData = skeletonData.pathConstraints.Items[num12];
                    Dictionary <string, object> dictionary10       = (Dictionary <string, object>)item16.Value;
                    foreach (KeyValuePair <string, object> item17 in dictionary10)
                    {
                        List <object> list5 = (List <object>)item17.Value;
                        string        key5  = item17.Key;
                        switch (key5)
                        {
                        case "position":
                        case "spacing":
                        {
                            float num14 = 1f;
                            PathConstraintPositionTimeline pathConstraintPositionTimeline;
                            if (key5 == "spacing")
                            {
                                pathConstraintPositionTimeline = new PathConstraintSpacingTimeline(list5.Count);
                                if (pathConstraintData.spacingMode == SpacingMode.Length || pathConstraintData.spacingMode == SpacingMode.Fixed)
                                {
                                    num14 = scale;
                                }
                            }
                            else
                            {
                                pathConstraintPositionTimeline = new PathConstraintPositionTimeline(list5.Count);
                                if (pathConstraintData.positionMode == PositionMode.Fixed)
                                {
                                    num14 = scale;
                                }
                            }
                            pathConstraintPositionTimeline.pathConstraintIndex = num12;
                            int num15 = 0;
                            foreach (Dictionary <string, object> item18 in list5)
                            {
                                pathConstraintPositionTimeline.SetFrame(num15, (float)item18["time"], GetFloat(item18, key5, 0f) * num14);
                                ReadCurve(item18, pathConstraintPositionTimeline, num15);
                                num15++;
                            }
                            exposedList.Add(pathConstraintPositionTimeline);
                            num = Math.Max(num, pathConstraintPositionTimeline.frames[(pathConstraintPositionTimeline.FrameCount - 1) * 2]);
                            break;
                        }

                        case "mix":
                        {
                            PathConstraintMixTimeline pathConstraintMixTimeline = new PathConstraintMixTimeline(list5.Count);
                            pathConstraintMixTimeline.pathConstraintIndex = num12;
                            int num13 = 0;
                            foreach (Dictionary <string, object> item19 in list5)
                            {
                                pathConstraintMixTimeline.SetFrame(num13, (float)item19["time"], GetFloat(item19, "rotateMix", 1f), GetFloat(item19, "translateMix", 1f));
                                ReadCurve(item19, pathConstraintMixTimeline, num13);
                                num13++;
                            }
                            exposedList.Add(pathConstraintMixTimeline);
                            num = Math.Max(num, pathConstraintMixTimeline.frames[(pathConstraintMixTimeline.FrameCount - 1) * 3]);
                            break;
                        }
                        }
                    }
                }
            }
            if (map.ContainsKey("deform"))
            {
                foreach (KeyValuePair <string, object> item20 in (Dictionary <string, object>)map["deform"])
                {
                    Skin skin = skeletonData.FindSkin(item20.Key);
                    foreach (KeyValuePair <string, object> item21 in (Dictionary <string, object>)item20.Value)
                    {
                        int num16 = skeletonData.FindSlotIndex(item21.Key);
                        if (num16 == -1)
                        {
                            throw new Exception("Slot not found: " + item21.Key);
                        }
                        foreach (KeyValuePair <string, object> item22 in (Dictionary <string, object>)item21.Value)
                        {
                            List <object>    list6            = (List <object>)item22.Value;
                            VertexAttachment vertexAttachment = (VertexAttachment)skin.GetAttachment(num16, item22.Key);
                            if (vertexAttachment == null)
                            {
                                throw new Exception("Deform attachment not found: " + item22.Key);
                            }
                            bool           flag           = vertexAttachment.bones != null;
                            float[]        vertices       = vertexAttachment.vertices;
                            int            num17          = (!flag) ? vertices.Length : (vertices.Length / 3 * 2);
                            DeformTimeline deformTimeline = new DeformTimeline(list6.Count);
                            deformTimeline.slotIndex  = num16;
                            deformTimeline.attachment = vertexAttachment;
                            int num18 = 0;
                            foreach (Dictionary <string, object> item23 in list6)
                            {
                                float[] array;
                                if (!item23.ContainsKey("vertices"))
                                {
                                    array = ((!flag) ? vertices : new float[num17]);
                                }
                                else
                                {
                                    array = new float[num17];
                                    int     @int       = GetInt(item23, "offset", 0);
                                    float[] floatArray = GetFloatArray(item23, "vertices", 1f);
                                    Array.Copy(floatArray, 0, array, @int, floatArray.Length);
                                    if (scale != 1f)
                                    {
                                        int i = @int;
                                        for (int num19 = i + floatArray.Length; i < num19; i++)
                                        {
                                            array[i] *= scale;
                                        }
                                    }
                                    if (!flag)
                                    {
                                        for (int j = 0; j < num17; j++)
                                        {
                                            array[j] += vertices[j];
                                        }
                                    }
                                }
                                deformTimeline.SetFrame(num18, (float)item23["time"], array);
                                ReadCurve(item23, deformTimeline, num18);
                                num18++;
                            }
                            exposedList.Add(deformTimeline);
                            num = Math.Max(num, deformTimeline.frames[deformTimeline.FrameCount - 1]);
                        }
                    }
                }
            }
            if (map.ContainsKey("drawOrder") || map.ContainsKey("draworder"))
            {
                List <object>     list7             = (List <object>)map[(!map.ContainsKey("drawOrder")) ? "draworder" : "drawOrder"];
                DrawOrderTimeline drawOrderTimeline = new DrawOrderTimeline(list7.Count);
                int count = skeletonData.slots.Count;
                int num20 = 0;
                foreach (Dictionary <string, object> item24 in list7)
                {
                    int[] array2 = null;
                    if (item24.ContainsKey("offsets"))
                    {
                        array2 = new int[count];
                        for (int num21 = count - 1; num21 >= 0; num21--)
                        {
                            array2[num21] = -1;
                        }
                        List <object> list8  = (List <object>)item24["offsets"];
                        int[]         array3 = new int[count - list8.Count];
                        int           num22  = 0;
                        int           num23  = 0;
                        foreach (Dictionary <string, object> item25 in list8)
                        {
                            int num24 = skeletonData.FindSlotIndex((string)item25["slot"]);
                            if (num24 == -1)
                            {
                                throw new Exception("Slot not found: " + item25["slot"]);
                            }
                            while (num22 != num24)
                            {
                                array3[num23++] = num22++;
                            }
                            int num27 = num22 + (int)(float)item25["offset"];
                            array2[num27] = num22++;
                        }
                        while (num22 < count)
                        {
                            array3[num23++] = num22++;
                        }
                        for (int num31 = count - 1; num31 >= 0; num31--)
                        {
                            if (array2[num31] == -1)
                            {
                                array2[num31] = array3[--num23];
                            }
                        }
                    }
                    drawOrderTimeline.SetFrame(num20++, (float)item24["time"], array2);
                }
                exposedList.Add(drawOrderTimeline);
                num = Math.Max(num, drawOrderTimeline.frames[drawOrderTimeline.FrameCount - 1]);
            }
            if (map.ContainsKey("events"))
            {
                List <object> list9         = (List <object>)map["events"];
                EventTimeline eventTimeline = new EventTimeline(list9.Count);
                int           num33         = 0;
                foreach (Dictionary <string, object> item26 in list9)
                {
                    EventData eventData = skeletonData.FindEvent((string)item26["name"]);
                    if (eventData == null)
                    {
                        throw new Exception("Event not found: " + item26["name"]);
                    }
                    Event @event = new Event((float)item26["time"], eventData);
                    @event.Int    = GetInt(item26, "int", eventData.Int);
                    @event.Float  = GetFloat(item26, "float", eventData.Float);
                    @event.String = GetString(item26, "string", eventData.String);
                    eventTimeline.SetFrame(num33++, @event);
                }
                exposedList.Add(eventTimeline);
                num = Math.Max(num, eventTimeline.frames[eventTimeline.FrameCount - 1]);
            }
            exposedList.TrimExcess();
            skeletonData.animations.Add(new Animation(name, exposedList, num));
        }