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 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 = 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 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: case TIMELINE_SHEAR: { TranslateTimeline timeline; float timelineScale = 1; if (timelineType == TIMELINE_SCALE) { timeline = new ScaleTimeline(frameCount); } else if (timelineType == TIMELINE_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 * 3 - 3]); break; } } } } // IK timelines. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { IkConstraintData constraint = skeletonData.ikConstraints.Items[ReadVarint(input, true)]; int frameCount = ReadVarint(input, true); IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount); timeline.ikConstraintIndex = skeletonData.ikConstraints.IndexOf(constraint); 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]); } // Transform constraint timelines. for (int i = 0, n = ReadVarint(input, true); i < n; i++) { TransformConstraintData constraint = skeletonData.transformConstraints.Items[ReadVarint(input, true)]; int frameCount = ReadVarint(input, true); TransformConstraintTimeline timeline = new TransformConstraintTimeline(frameCount); timeline.transformConstraintIndex = skeletonData.transformConstraints.IndexOf(constraint); 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 * 5 - 5]); } // FFD 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++) { Attachment attachment = skin.GetAttachment(slotIndex, ReadString(input)); int frameCount = ReadVarint(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 = ((WeightedMeshAttachment)attachment).weights.Length / 3 * 2; } int end = ReadVarint(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 = ReadVarint(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 = 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)); }