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