diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java index 69d218e70..4259e7800 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java @@ -274,7 +274,7 @@ public class Animation { * @param propertyIds Unique identifiers for each property the timeline modifies. */ public CurveTimeline (int frameCount, int frameEntries, int bezierCount, String... propertyIds) { super(frameCount, frameEntries, propertyIds); - curves = new float[frameCount - 1 + (bezierCount == 0 ? frameCount - 1 : bezierCount) * BEZIER_SIZE]; + curves = new float[frameCount - 1 + bezierCount * BEZIER_SIZE]; } /** Sets the specified key frame to linear interpolation. @@ -377,6 +377,31 @@ public class Animation { } } + /** The base class for a {@link PercentCurveTimeline} which changes two float properties. */ + static public abstract class PercentCurveTimeline2 extends PercentCurveTimeline { + static public final int ENTRIES = 3; + static final int PREV_TIME = -3, PREV_VALUE1 = -2, PREV_VALUE2 = -1; + static final int VALUE1 = 1, VALUE2 = 2; + + /** @param bezierCount The maximum number of frames that will use Bezier curves. See {@link #shrink(int)}. + * @param propertyIds Unique identifiers for each property the timeline modifies. */ + public PercentCurveTimeline2 (int frameCount, int bezierCount, String... propertyIds) { + super(frameCount, ENTRIES, bezierCount, propertyIds); + } + + public int getFrameCount () { + return frames.length / ENTRIES; + } + + /** Sets the time in seconds and the values for the specified key frame. */ + public void setFrame (int frameIndex, float time, float value1, float value2) { + frameIndex *= ENTRIES; + frames[frameIndex] = time; + frames[frameIndex + VALUE1] = value1; + frames[frameIndex + VALUE2] = value2; + } + } + /** The base class for timelines that use interpolation between key frames for a single property using the key frames' value * space. */ static public abstract class ValueCurveTimeline extends CurveTimeline { @@ -394,7 +419,6 @@ public class Animation { return frames.length >> 1; } - /** Sets the time in seconds and the value for the specified key frame. */ public void setFrame (int frameIndex, float time, float value) { frameIndex <<= 1; frames[frameIndex] = time; @@ -453,12 +477,11 @@ public class Animation { static public class RotateTimeline extends ValueCurveTimeline implements BoneTimeline { final int boneIndex; - public RotateTimeline (int frameCount, int bezierIndex, int boneIndex) { - super(frameCount, bezierIndex, TimelineType.rotate.ordinal() + "|" + boneIndex); + public RotateTimeline (int frameCount, int bezierCount, int boneIndex) { + super(frameCount, bezierCount, TimelineType.rotate.ordinal() + "|" + boneIndex); this.boneIndex = boneIndex; } - /** The index of the bone in {@link Skeleton#getBones()} that will be changed. */ public int getBoneIndex () { return boneIndex; } @@ -516,36 +539,20 @@ public class Animation { } /** Changes a bone's local {@link Bone#getX()} and {@link Bone#getY()}. */ - static public class TranslateTimeline extends PercentCurveTimeline implements BoneTimeline { - static public final int ENTRIES = 3; - static final int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1; - static final int X = 1, Y = 2; - + static public class TranslateTimeline extends PercentCurveTimeline2 implements BoneTimeline { final int boneIndex; - public TranslateTimeline (int frameCount, int bezierIndex, int boneIndex) { - super(frameCount, ENTRIES, bezierIndex, // - TimelineType.translateX.ordinal() + "|" + boneIndex, TimelineType.translateY.ordinal() + "|" + boneIndex); + public TranslateTimeline (int frameCount, int bezierCount, int boneIndex) { + super(frameCount, bezierCount, // + TimelineType.translateX.ordinal() + "|" + boneIndex, // + TimelineType.translateY.ordinal() + "|" + boneIndex); this.boneIndex = boneIndex; } - public int getFrameCount () { - return frames.length / ENTRIES; - } - - /** The index of the bone in {@link Skeleton#getBones()} that will be changed. */ public int getBoneIndex () { return boneIndex; } - /** Sets the time in seconds, x, and y values for the specified key frame. */ - public void setFrame (int frameIndex, float time, float x, float y) { - frameIndex *= ENTRIES; - frames[frameIndex] = time; - frames[frameIndex + X] = x; - frames[frameIndex + Y] = y; - } - public void apply (Skeleton skeleton, float lastTime, float time, Array events, float alpha, MixBlend blend, MixDirection direction) { @@ -567,16 +574,16 @@ public class Animation { float x, y; if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame. - x = frames[frames.length + PREV_X]; - y = frames[frames.length + PREV_Y]; + x = frames[frames.length + PREV_VALUE1]; + y = frames[frames.length + PREV_VALUE2]; } else { // Interpolate between the previous frame and the current frame. int frame = binarySearch(frames, time, ENTRIES); - x = frames[frame + PREV_X]; - y = frames[frame + PREV_Y]; + x = frames[frame + PREV_VALUE1]; + y = frames[frame + PREV_VALUE2]; float percent = getCurvePercent(frame / ENTRIES - 1, time, frames[frame + PREV_TIME], frames[frame]); - x += (frames[frame + X] - x) * percent; - y += (frames[frame + Y] - y) * percent; + x += (frames[frame + VALUE1] - x) * percent; + y += (frames[frame + VALUE2] - y) * percent; } switch (blend) { case setup: @@ -596,36 +603,20 @@ public class Animation { } /** Changes a bone's local {@link Bone#getScaleX()} and {@link Bone#getScaleY()}. */ - static public class ScaleTimeline extends PercentCurveTimeline implements BoneTimeline { - static public final int ENTRIES = 3; - static final int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1; - static final int X = 1, Y = 2; - + static public class ScaleTimeline extends PercentCurveTimeline2 implements BoneTimeline { final int boneIndex; - public ScaleTimeline (int frameCount, int bezierIndex, int boneIndex) { - super(frameCount, ENTRIES, bezierIndex, // - TimelineType.scaleX.ordinal() + "|" + boneIndex, TimelineType.scaleY.ordinal() + "|" + boneIndex); + public ScaleTimeline (int frameCount, int bezierCount, int boneIndex) { + super(frameCount, bezierCount, // + TimelineType.scaleX.ordinal() + "|" + boneIndex, // + TimelineType.scaleY.ordinal() + "|" + boneIndex); this.boneIndex = boneIndex; } - public int getFrameCount () { - return frames.length / ENTRIES; - } - - /** The index of the bone in {@link Skeleton#getBones()} that will be changed. */ public int getBoneIndex () { return boneIndex; } - /** Sets the time in seconds, x, and y values for the specified key frame. */ - public void setFrame (int frameIndex, float time, float x, float y) { - frameIndex *= ENTRIES; - frames[frameIndex] = time; - frames[frameIndex + X] = x; - frames[frameIndex + Y] = y; - } - public void apply (Skeleton skeleton, float lastTime, float time, Array events, float alpha, MixBlend blend, MixDirection direction) { @@ -647,16 +638,16 @@ public class Animation { float x, y; if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame. - x = frames[frames.length + PREV_X] * bone.data.scaleX; - y = frames[frames.length + PREV_Y] * bone.data.scaleY; + x = frames[frames.length + PREV_VALUE1] * bone.data.scaleX; + y = frames[frames.length + PREV_VALUE2] * bone.data.scaleY; } else { // Interpolate between the previous frame and the current frame. int frame = binarySearch(frames, time, ENTRIES); - x = frames[frame + PREV_X]; - y = frames[frame + PREV_Y]; + x = frames[frame + PREV_VALUE1]; + y = frames[frame + PREV_VALUE2]; float percent = getCurvePercent(frame / ENTRIES - 1, time, frames[frame + PREV_TIME], frames[frame]); - x = (x + (frames[frame + X] - x) * percent) * bone.data.scaleX; - y = (y + (frames[frame + Y] - y) * percent) * bone.data.scaleY; + x = (x + (frames[frame + VALUE1] - x) * percent) * bone.data.scaleX; + y = (y + (frames[frame + VALUE2] - y) * percent) * bone.data.scaleY; } if (alpha == 1) { if (blend == add) { @@ -717,36 +708,20 @@ public class Animation { } /** Changes a bone's local {@link Bone#getShearX()} and {@link Bone#getShearY()}. */ - static public class ShearTimeline extends PercentCurveTimeline implements BoneTimeline { - static public final int ENTRIES = 3; - static final int PREV_TIME = -3, PREV_X = -2, PREV_Y = -1; - static final int X = 1, Y = 2; - + static public class ShearTimeline extends PercentCurveTimeline2 implements BoneTimeline { final int boneIndex; - public ShearTimeline (int frameCount, int bezierIndex, int boneIndex) { - super(frameCount, ENTRIES, bezierIndex, // - TimelineType.shearX.ordinal() + "|" + boneIndex, TimelineType.shearY.ordinal() + "|" + boneIndex); + public ShearTimeline (int frameCount, int bezierCount, int boneIndex) { + super(frameCount, bezierCount, // + TimelineType.shearX.ordinal() + "|" + boneIndex, // + TimelineType.shearY.ordinal() + "|" + boneIndex); this.boneIndex = boneIndex; } - public int getFrameCount () { - return frames.length / ENTRIES; - } - - /** The index of the bone in {@link Skeleton#getBones()} that will be changed. */ public int getBoneIndex () { return boneIndex; } - /** Sets the time in seconds, x, and y values for the specified key frame. */ - public void setFrame (int frameIndex, float time, float x, float y) { - frameIndex *= ENTRIES; - frames[frameIndex] = time; - frames[frameIndex + X] = x; - frames[frameIndex + Y] = y; - } - public void apply (Skeleton skeleton, float lastTime, float time, Array events, float alpha, MixBlend blend, MixDirection direction) { @@ -768,16 +743,16 @@ public class Animation { float x, y; if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame. - x = frames[frames.length + PREV_X]; - y = frames[frames.length + PREV_Y]; + x = frames[frames.length + PREV_VALUE1]; + y = frames[frames.length + PREV_VALUE2]; } else { // Interpolate between the previous frame and the current frame. int frame = binarySearch(frames, time, ENTRIES); - x = frames[frame + PREV_X]; - y = frames[frame + PREV_Y]; + x = frames[frame + PREV_VALUE1]; + y = frames[frame + PREV_VALUE2]; float percent = getCurvePercent(frame / ENTRIES - 1, time, frames[frame + PREV_TIME], frames[frame]); - x = x + (frames[frame + X] - x) * percent; - y = y + (frames[frame + Y] - y) * percent; + x = x + (frames[frame + VALUE1] - x) * percent; + y = y + (frames[frame + VALUE2] - y) * percent; } switch (blend) { case setup: @@ -804,8 +779,8 @@ public class Animation { final int slotIndex; - public ColorTimeline (int frameCount, int bezierIndex, int slotIndex) { - super(frameCount, ENTRIES, bezierIndex, // + public ColorTimeline (int frameCount, int bezierCount, int slotIndex) { + super(frameCount, ENTRIES, bezierCount, // TimelineType.rgb.ordinal() + "|" + slotIndex, // TimelineType.a.ordinal() + "|" + slotIndex); this.slotIndex = slotIndex; @@ -815,7 +790,6 @@ public class Animation { return frames.length / ENTRIES; } - /** The index of the slot in {@link Skeleton#getSlots()} that will be changed. */ public int getSlotIndex () { return slotIndex; } @@ -888,8 +862,8 @@ public class Animation { final int slotIndex; - public TwoColorTimeline (int frameCount, int bezierIndex, int slotIndex) { - super(frameCount, ENTRIES, bezierIndex, // + public TwoColorTimeline (int frameCount, int bezierCount, int slotIndex) { + super(frameCount, ENTRIES, bezierCount, // TimelineType.rgb.ordinal() + "|" + slotIndex, // TimelineType.a.ordinal() + "|" + slotIndex, // TimelineType.rgb2.ordinal() + "|" + slotIndex); @@ -999,7 +973,6 @@ public class Animation { return frames.length; } - /** The index of the slot in {@link Skeleton#getSlots()} that will be changed. */ public int getSlotIndex () { return slotIndex; } @@ -1052,8 +1025,8 @@ public class Animation { final VertexAttachment attachment; private final float[][] frameVertices; - public DeformTimeline (int frameCount, int bezierIndex, int slotIndex, VertexAttachment attachment) { - super(frameCount, 1, bezierIndex, TimelineType.deform.ordinal() + "|" + slotIndex + "|" + attachment.getId()); + public DeformTimeline (int frameCount, int bezierCount, int slotIndex, VertexAttachment attachment) { + super(frameCount, 1, bezierCount, TimelineType.deform.ordinal() + "|" + slotIndex + "|" + attachment.getId()); this.slotIndex = slotIndex; this.attachment = attachment; frameVertices = new float[frameCount][]; @@ -1063,7 +1036,6 @@ public class Animation { return frames.length; } - /** The index of the slot in {@link Skeleton#getSlots()} that will be changed. */ public int getSlotIndex () { return slotIndex; } @@ -1392,8 +1364,8 @@ public class Animation { final int ikConstraintIndex; - public IkConstraintTimeline (int frameCount, int bezierIndex, int ikConstraintIndex) { - super(frameCount, ENTRIES, bezierIndex, TimelineType.ikConstraint.ordinal() + "|" + ikConstraintIndex); + public IkConstraintTimeline (int frameCount, int bezierCount, int ikConstraintIndex) { + super(frameCount, ENTRIES, bezierCount, TimelineType.ikConstraint.ordinal() + "|" + ikConstraintIndex); this.ikConstraintIndex = ikConstraintIndex; } @@ -1509,8 +1481,8 @@ public class Animation { final int transformConstraintIndex; - public TransformConstraintTimeline (int frameCount, int bezierIndex, int transformConstraintIndex) { - super(frameCount, ENTRIES, bezierIndex, TimelineType.transformConstraint.ordinal() + "|" + transformConstraintIndex); + public TransformConstraintTimeline (int frameCount, int bezierCount, int transformConstraintIndex) { + super(frameCount, ENTRIES, bezierCount, TimelineType.transformConstraint.ordinal() + "|" + transformConstraintIndex); this.transformConstraintIndex = transformConstraintIndex; } @@ -1593,34 +1565,19 @@ public class Animation { } /** Changes a path constraint's {@link PathConstraint#getPosition()}. */ - static public class PathConstraintPositionTimeline extends PercentCurveTimeline { - static public final int ENTRIES = 2; - static final int PREV_TIME = -2, PREV_VALUE = -1; - static final int VALUE = 1; - + static public class PathConstraintPositionTimeline extends ValueCurveTimeline { final int pathConstraintIndex; - public PathConstraintPositionTimeline (int frameCount, int bezierIndex, int pathConstraintIndex) { - super(frameCount, ENTRIES, bezierIndex, TimelineType.pathConstraintPosition.ordinal() + "|" + pathConstraintIndex); + public PathConstraintPositionTimeline (int frameCount, int bezierCount, int pathConstraintIndex) { + super(frameCount, bezierCount, TimelineType.pathConstraintPosition.ordinal() + "|" + pathConstraintIndex); this.pathConstraintIndex = pathConstraintIndex; } - public int getFrameCount () { - return frames.length >> 1; - } - /** The index of the path constraint slot in {@link Skeleton#getPathConstraints()} that will be changed. */ public int getPathConstraintIndex () { return pathConstraintIndex; } - /** Sets the time in seconds and path constraint position for the specified key frame. */ - public void setFrame (int frameIndex, float time, float position) { - frameIndex <<= 1; - frames[frameIndex] = time; - frames[frameIndex + VALUE] = position; - } - public void apply (Skeleton skeleton, float lastTime, float time, Array events, float alpha, MixBlend blend, MixDirection direction) { @@ -1644,10 +1601,11 @@ public class Animation { else { // Interpolate between the previous frame and the current frame. int frame = binarySearch(frames, time, ENTRIES); - position = frames[frame + PREV_VALUE]; - float percent = getCurvePercent((frame >> 1) - 1, time, frames[frame + PREV_TIME], frames[frame]); - position += (frames[frame + VALUE] - position) * percent; + position = getCurveValue((frame >> 1) - 1, time, // + frames[frame + PREV_TIME], frames[frame + PREV_VALUE], // + frames[frame], frames[frame + VALUE]); } + if (blend == setup) constraint.position = constraint.data.position + (position - constraint.data.position) * alpha; else @@ -1656,34 +1614,19 @@ public class Animation { } /** Changes a path constraint's {@link PathConstraint#getSpacing()}. */ - static public class PathConstraintSpacingTimeline extends PercentCurveTimeline { - static public final int ENTRIES = 2; - static final int PREV_TIME = -2, PREV_VALUE = -1; - static final int VALUE = 1; - + static public class PathConstraintSpacingTimeline extends ValueCurveTimeline { final int pathConstraintIndex; - public PathConstraintSpacingTimeline (int frameCount, int bezierIndex, int pathConstraintIndex) { - super(frameCount, ENTRIES, bezierIndex, TimelineType.pathConstraintSpacing.ordinal() + "|" + pathConstraintIndex); + public PathConstraintSpacingTimeline (int frameCount, int bezierCount, int pathConstraintIndex) { + super(frameCount, bezierCount, TimelineType.pathConstraintSpacing.ordinal() + "|" + pathConstraintIndex); this.pathConstraintIndex = pathConstraintIndex; } - public int getFrameCount () { - return frames.length >> 1; - } - /** The index of the path constraint slot in {@link Skeleton#getPathConstraints()} that will be changed. */ public int getPathConstraintIndex () { return pathConstraintIndex; } - /** Sets the time in seconds and path constraint position for the specified key frame. */ - public void setFrame (int frameIndex, float time, float position) { - frameIndex <<= 1; - frames[frameIndex] = time; - frames[frameIndex + VALUE] = position; - } - public void apply (Skeleton skeleton, float lastTime, float time, Array events, float alpha, MixBlend blend, MixDirection direction) { @@ -1707,9 +1650,9 @@ public class Animation { else { // Interpolate between the previous frame and the current frame. int frame = binarySearch(frames, time, ENTRIES); - spacing = frames[frame + PREV_VALUE]; - float percent = getCurvePercent((frame >> 1) - 1, time, frames[frame + PREV_TIME], frames[frame]); - spacing += (frames[frame + VALUE] - spacing) * percent; + spacing = getCurveValue((frame >> 1) - 1, time, // + frames[frame + PREV_TIME], frames[frame + PREV_VALUE], // + frames[frame], frames[frame + VALUE]); } if (blend == setup) @@ -1721,35 +1664,19 @@ public class Animation { /** Changes a transform constraint's {@link PathConstraint#getRotateMix()} and * {@link TransformConstraint#getTranslateMix()}. */ - static public class PathConstraintMixTimeline extends PercentCurveTimeline { - static public final int ENTRIES = 3; - static private final int PREV_TIME = -3, PREV_ROTATE = -2, PREV_TRANSLATE = -1; - static private final int ROTATE = 1, TRANSLATE = 2; - + static public class PathConstraintMixTimeline extends PercentCurveTimeline2 { final int pathConstraintIndex; - public PathConstraintMixTimeline (int frameCount, int bezierIndex, int pathConstraintIndex) { - super(frameCount, ENTRIES, bezierIndex, TimelineType.pathConstraintMix.ordinal() + "|" + pathConstraintIndex); + public PathConstraintMixTimeline (int frameCount, int bezierCount, int pathConstraintIndex) { + super(frameCount, bezierCount, TimelineType.pathConstraintMix.ordinal() + "|" + pathConstraintIndex); this.pathConstraintIndex = pathConstraintIndex; } - public int getFrameCount () { - return frames.length / ENTRIES; - } - /** The index of the path constraint slot in {@link Skeleton#getPathConstraints()} that will be changed. */ public int getPathConstraintIndex () { return pathConstraintIndex; } - /** The time in seconds, rotate mix, and translate mix for the specified key frame. */ - public void setFrame (int frameIndex, float time, float rotateMix, float translateMix) { - frameIndex *= ENTRIES; - frames[frameIndex] = time; - frames[frameIndex + ROTATE] = rotateMix; - frames[frameIndex + TRANSLATE] = translateMix; - } - public void apply (Skeleton skeleton, float lastTime, float time, Array events, float alpha, MixBlend blend, MixDirection direction) { @@ -1771,16 +1698,16 @@ public class Animation { float rotate, translate; if (time >= frames[frames.length - ENTRIES]) { // Time is after last frame. - rotate = frames[frames.length + PREV_ROTATE]; - translate = frames[frames.length + PREV_TRANSLATE]; + rotate = frames[frames.length + PREV_VALUE1]; + translate = frames[frames.length + PREV_VALUE2]; } else { // Interpolate between the previous frame and the current frame. int frame = binarySearch(frames, time, ENTRIES); - rotate = frames[frame + PREV_ROTATE]; - translate = frames[frame + PREV_TRANSLATE]; + rotate = frames[frame + PREV_VALUE1]; + translate = frames[frame + PREV_VALUE2]; float percent = getCurvePercent(frame / ENTRIES - 1, time, frames[frame + PREV_TIME], frames[frame]); - rotate += (frames[frame + ROTATE] - rotate) * percent; - translate += (frames[frame + TRANSLATE] - translate) * percent; + rotate += (frames[frame + VALUE1] - rotate) * percent; + translate += (frames[frame + VALUE2] - translate) * percent; } if (blend == setup) { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java index 06129a9e7..1957700a5 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonBinary.java @@ -51,6 +51,7 @@ import com.esotericsoftware.spine.Animation.PathConstraintMixTimeline; import com.esotericsoftware.spine.Animation.PathConstraintPositionTimeline; import com.esotericsoftware.spine.Animation.PathConstraintSpacingTimeline; import com.esotericsoftware.spine.Animation.PercentCurveTimeline; +import com.esotericsoftware.spine.Animation.PercentCurveTimeline2; import com.esotericsoftware.spine.Animation.RotateTimeline; import com.esotericsoftware.spine.Animation.ScaleTimeline; import com.esotericsoftware.spine.Animation.ShearTimeline; @@ -374,8 +375,7 @@ public class SkeletonBinary { String name = input.readStringRef(); if (name == null) name = attachmentName; - AttachmentType type = AttachmentType.values[input.readByte()]; - switch (type) { + switch (AttachmentType.values[input.readByte()]) { case region: { String path = input.readStringRef(); float rotation = input.readFloat(); @@ -529,6 +529,7 @@ public class SkeletonBinary { } private Vertices readVertices (SkeletonInput input, int vertexCount) throws IOException { + float scale = this.scale; int verticesLength = vertexCount << 1; Vertices vertices = new Vertices(); if (!input.readBoolean()) { @@ -572,297 +573,257 @@ public class SkeletonBinary { return array; } - private Animation readAnimation (SkeletonInput input, String name, SkeletonData skeletonData) { - Array timelines = new Array(32); + private Animation readAnimation (SkeletonInput input, String name, SkeletonData skeletonData) throws IOException { + Array timelines = new Array(input.readInt(true)); float scale = this.scale; - try { - // Slot timelines. - for (int i = 0, n = input.readInt(true); i < n; i++) { - int slotIndex = input.readInt(true); - for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { - int timelineType = input.readByte(); - int frameCount = input.readInt(true), frameLast = frameCount - 1; - switch (timelineType) { - case SLOT_ATTACHMENT: { - AttachmentTimeline timeline = new AttachmentTimeline(frameCount, slotIndex); - for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) - timeline.setFrame(frameIndex, input.readFloat(), input.readStringRef()); - timelines.add(timeline); - break; - } - case SLOT_COLOR: { - ColorTimeline timeline = new ColorTimeline(frameCount, input.readInt(true), slotIndex); - float time = input.readFloat(); - for (int frameIndex = 0, bezierIndex = 0; frameIndex < frameCount; frameIndex++) { - Color.rgba8888ToColor(tempColor1, input.readInt()); - timeline.setFrame(frameIndex, time, tempColor1.r, tempColor1.g, tempColor1.b, tempColor1.a); - if (frameIndex < frameLast) - bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); - } - timelines.add(timeline); - break; - } - case SLOT_TWO_COLOR: { - TwoColorTimeline timeline = new TwoColorTimeline(frameCount, input.readInt(true), slotIndex); - float time = input.readFloat(); - for (int frameIndex = 0, bezierIndex = 0; frameIndex < frameCount; frameIndex++) { - Color.rgba8888ToColor(tempColor1, input.readInt()); - Color.rgb888ToColor(tempColor2, input.readInt()); - timeline.setFrame(frameIndex, time, tempColor1.r, tempColor1.g, tempColor1.b, tempColor1.a, tempColor2.r, - tempColor2.g, tempColor2.b); - if (frameIndex < frameLast) - bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); - } - timelines.add(timeline); - break; - } - } + // Slot timelines. + for (int i = 0, n = input.readInt(true); i < n; i++) { + int slotIndex = input.readInt(true); + for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { + int timelineType = input.readByte(), frameCount = input.readInt(true), frameLast = frameCount - 1; + switch (timelineType) { + case SLOT_ATTACHMENT: { + AttachmentTimeline timeline = new AttachmentTimeline(frameCount, slotIndex); + for (int frameIndex = 0; frameIndex < frameCount; frameIndex++) + timeline.setFrame(frameIndex, input.readFloat(), input.readStringRef()); + timelines.add(timeline); + break; } - } - - // Bone timelines. - for (int i = 0, n = input.readInt(true); i < n; i++) { - int boneIndex = input.readInt(true); - for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { - int timelineType = input.readByte(); - int frameCount = input.readInt(true), frameLast = frameCount - 1; - switch (timelineType) { - case BONE_ROTATE: { - RotateTimeline timeline = new RotateTimeline(frameCount, input.readInt(true), boneIndex); - float time = input.readFloat(), value = input.readFloat(); - for (int frameIndex = 0, bezierIndex = 0; frameIndex < frameCount; frameIndex++) { - timeline.setFrame(frameIndex, time, value); - if (frameIndex < frameLast) readCurve(input, timeline, frameIndex, bezierIndex, time, value, - time = input.readFloat(), value = input.readFloat()); - } - timelines.add(timeline); - break; - } - case BONE_TRANSLATE: { - TranslateTimeline timeline = new TranslateTimeline(frameCount, input.readInt(true), boneIndex); - float time = input.readFloat(); - for (int frameIndex = 0, bezierIndex = 0; frameIndex < frameCount; frameIndex++) { - timeline.setFrame(frameIndex, time, input.readFloat() * scale, input.readFloat() * scale); - if (frameIndex < frameLast) - bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); - } - timelines.add(timeline); - break; - } - case BONE_SCALE: { - ScaleTimeline timeline = new ScaleTimeline(frameCount, input.readInt(true), boneIndex); - float time = input.readFloat(); - for (int frameIndex = 0, bezierIndex = 0; frameIndex < frameCount; frameIndex++) { - timeline.setFrame(frameIndex, time, input.readFloat(), input.readFloat()); - if (frameIndex < frameLast) - bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); - } - timelines.add(timeline); - break; - } - case BONE_SHEAR: { - ShearTimeline timeline = new ShearTimeline(frameCount, input.readInt(true), boneIndex); - float time = input.readFloat(); - for (int frameIndex = 0, bezierIndex = 0; frameIndex < frameCount; frameIndex++) { - timeline.setFrame(frameIndex, time, input.readFloat(), input.readFloat()); - if (frameIndex < frameLast) - bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); - } - timelines.add(timeline); - break; - } - } - } - } - - // IK constraint timelines. - for (int i = 0, n = input.readInt(true); i < n; i++) { - int index = input.readInt(true); - int frameCount = input.readInt(true), frameLast = frameCount - 1; - IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index); - float time = input.readFloat(); - for (int frameIndex = 0, bezierIndex = 0; frameIndex < frameCount; frameIndex++) { - timeline.setFrame(frameIndex, time, input.readFloat(), input.readFloat() * scale, input.readByte(), - input.readBoolean(), input.readBoolean()); - if (frameIndex < frameLast) - bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); - } - timelines.add(timeline); - } - - // Transform constraint timelines. - for (int i = 0, n = input.readInt(true); i < n; i++) { - int index = input.readInt(true); - int frameCount = input.readInt(true), frameLast = frameCount - 1; - TransformConstraintTimeline timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index); - float time = input.readFloat(); - for (int frameIndex = 0, bezierIndex = 0; frameIndex < frameCount; frameIndex++) { - timeline.setFrame(frameIndex, time, input.readFloat(), input.readFloat(), input.readFloat(), input.readFloat()); - if (frameIndex < frameLast) - bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); - } - timelines.add(timeline); - } - - // Path constraint timelines. - for (int i = 0, n = input.readInt(true); i < n; i++) { - int index = input.readInt(true); - PathConstraintData data = skeletonData.pathConstraints.get(index); - for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { - int timelineType = input.readByte(); - int frameCount = input.readInt(true), frameLast = frameCount - 1; - switch (timelineType) { - case PATH_POSITION: { - PathConstraintSpacingTimeline timeline = new PathConstraintSpacingTimeline(frameCount, input.readInt(true), - index); - float timelineScale = data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed ? scale - : 1; - float time = input.readFloat(); - for (int frameIndex = 0, bezierIndex = 0; frameIndex < frameCount; frameIndex++) { - timeline.setFrame(frameIndex, time, input.readFloat() * timelineScale); - if (frameIndex < frameLast) - bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); - } - timelines.add(timeline); - break; - } - case PATH_SPACING: { - PathConstraintPositionTimeline timeline = new PathConstraintPositionTimeline(frameCount, input.readInt(true), - index); - float timelineScale = data.positionMode == PositionMode.fixed ? scale : 1; - float time = input.readFloat(); - for (int frameIndex = 0, bezierIndex = 0; frameIndex < frameCount; frameIndex++) { - timeline.setFrame(frameIndex, time, input.readFloat() * timelineScale); - if (frameIndex < frameLast) - bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); - } - timelines.add(timeline); - break; - } - case PATH_MIX: { - PathConstraintMixTimeline timeline = new PathConstraintMixTimeline(frameCount, input.readInt(true), index); - float time = input.readFloat(); - for (int frameIndex = 0, bezierIndex = 0; frameIndex < frameCount; frameIndex++) { - timeline.setFrame(frameIndex, time, input.readFloat(), input.readFloat()); - if (frameIndex < frameLast) - bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); - } - timelines.add(timeline); - break; - } - } - } - } - - // Deform timelines. - for (int i = 0, n = input.readInt(true); i < n; i++) { - Skin skin = skeletonData.skins.get(input.readInt(true)); - for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { - int slotIndex = input.readInt(true); - for (int iii = 0, nnn = input.readInt(true); iii < nnn; iii++) { - VertexAttachment attachment = (VertexAttachment)skin.getAttachment(slotIndex, input.readStringRef()); - boolean weighted = attachment.getBones() != null; - float[] vertices = attachment.getVertices(); - int deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; - - int frameCount = input.readInt(true), frameLast = frameCount - 1; - DeformTimeline timeline = new DeformTimeline(frameCount, input.readInt(true), slotIndex, attachment); - - float time = input.readFloat(); - for (int frameIndex = 0, bezierIndex = 0; frameIndex < frameCount; frameIndex++) { - float[] deform; - int end = input.readInt(true); - if (end == 0) - deform = weighted ? new float[deformLength] : vertices; - else { - deform = new float[deformLength]; - int start = input.readInt(true); - end += start; - if (scale == 1) { - for (int v = start; v < end; v++) - deform[v] = input.readFloat(); - } else { - for (int v = start; v < end; v++) - deform[v] = input.readFloat() * scale; - } - if (!weighted) { - for (int v = 0, vn = deform.length; v < vn; v++) - deform[v] += vertices[v]; - } - } - - timeline.setFrame(frameIndex, time, deform); - if (frameIndex < frameLast) - bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); - } - timelines.add(timeline); - } - } - } - - // Draw order timeline. - int drawOrderCount = input.readInt(true); - if (drawOrderCount > 0) { - DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount); - int slotCount = skeletonData.slots.size; - for (int i = 0; i < drawOrderCount; i++) { + case SLOT_COLOR: { + ColorTimeline timeline = new ColorTimeline(frameCount, input.readInt(true), slotIndex); float time = input.readFloat(); - int offsetCount = input.readInt(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 = input.readInt(true); - // Collect unchanged items. - while (originalIndex != slotIndex) - unchanged[unchangedIndex++] = originalIndex++; - // Set changed items. - drawOrder[originalIndex + input.readInt(true)] = originalIndex++; + for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { + Color.rgba8888ToColor(tempColor1, input.readInt()); + timeline.setFrame(frameIndex, time, tempColor1.r, tempColor1.g, tempColor1.b, tempColor1.a); + if (frameIndex == frameLast) break; + bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); } - // 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); + break; } - timelines.add(timeline); - } - - // Event timeline. - int eventCount = input.readInt(true); - if (eventCount > 0) { - EventTimeline timeline = new EventTimeline(eventCount); - for (int i = 0; i < eventCount; i++) { + case SLOT_TWO_COLOR: { + TwoColorTimeline timeline = new TwoColorTimeline(frameCount, input.readInt(true), slotIndex); float time = input.readFloat(); - EventData eventData = skeletonData.events.get(input.readInt(true)); - Event event = new Event(time, eventData); - event.intValue = input.readInt(false); - event.floatValue = input.readFloat(); - event.stringValue = input.readBoolean() ? input.readString() : eventData.stringValue; - if (event.getData().audioPath != null) { - event.volume = input.readFloat(); - event.balance = input.readFloat(); + for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { + Color.rgba8888ToColor(tempColor1, input.readInt()); + Color.rgb888ToColor(tempColor2, input.readInt()); + timeline.setFrame(frameIndex, time, tempColor1.r, tempColor1.g, tempColor1.b, tempColor1.a, tempColor2.r, + tempColor2.g, tempColor2.b); + if (frameIndex == frameLast) break; + bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); } - timeline.setFrame(i, event); + timelines.add(timeline); + break; + } } - timelines.add(timeline); } - } catch (IOException ex) { - throw new SerializationException("Error reading skeleton file.", ex); } - timelines.shrink(); + // Bone timelines. + for (int i = 0, n = input.readInt(true); i < n; i++) { + int boneIndex = input.readInt(true); + for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { + switch (input.readByte()) { + case BONE_ROTATE: { + timelines.add(readTimeline(input, new RotateTimeline(input.readInt(true), input.readInt(true), boneIndex), 1)); + break; + } + case BONE_TRANSLATE: { + timelines + .add(readTimeline(input, new TranslateTimeline(input.readInt(true), input.readInt(true), boneIndex), scale)); + break; + } + case BONE_SCALE: { + timelines.add(readTimeline(input, new ScaleTimeline(input.readInt(true), input.readInt(true), boneIndex), 1)); + break; + } + case BONE_SHEAR: { + timelines.add(readTimeline(input, new ShearTimeline(input.readInt(true), input.readInt(true), boneIndex), 1)); + break; + } + } + } + } + + // IK constraint timelines. + for (int i = 0, n = input.readInt(true); i < n; i++) { + int index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + IkConstraintTimeline timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index); + float time = input.readFloat(); + for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { + timeline.setFrame(frameIndex, time, input.readFloat(), input.readFloat() * scale, input.readByte(), + input.readBoolean(), input.readBoolean()); + if (frameIndex == frameLast) break; + bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); + } + timelines.add(timeline); + } + + // Transform constraint timelines. + for (int i = 0, n = input.readInt(true); i < n; i++) { + int index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1; + TransformConstraintTimeline timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index); + float time = input.readFloat(); + for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { + timeline.setFrame(frameIndex, time, input.readFloat(), input.readFloat(), input.readFloat(), input.readFloat()); + if (frameIndex == frameLast) break; + bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); + } + timelines.add(timeline); + } + + // Path constraint timelines. + for (int i = 0, n = input.readInt(true); i < n; i++) { + int index = input.readInt(true); + PathConstraintData data = skeletonData.pathConstraints.get(index); + for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { + switch (input.readByte()) { + case PATH_POSITION: { + timelines + .add(readTimeline(input, new PathConstraintSpacingTimeline(input.readInt(true), input.readInt(true), index), + data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed ? scale : 1)); + break; + } + case PATH_SPACING: { + timelines + .add(readTimeline(input, new PathConstraintPositionTimeline(input.readInt(true), input.readInt(true), index), + data.positionMode == PositionMode.fixed ? scale : 1)); + break; + } + case PATH_MIX: { + timelines + .add(readTimeline(input, new PathConstraintMixTimeline(input.readInt(true), input.readInt(true), index), 1)); + break; + } + } + } + } + + // Deform timelines. + for (int i = 0, n = input.readInt(true); i < n; i++) { + Skin skin = skeletonData.skins.get(input.readInt(true)); + for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { + int slotIndex = input.readInt(true); + for (int iii = 0, nnn = input.readInt(true); iii < nnn; iii++) { + VertexAttachment attachment = (VertexAttachment)skin.getAttachment(slotIndex, input.readStringRef()); + boolean weighted = attachment.getBones() != null; + float[] vertices = attachment.getVertices(); + int deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; + + int frameCount = input.readInt(true), frameLast = frameCount - 1; + DeformTimeline timeline = new DeformTimeline(frameCount, input.readInt(true), slotIndex, attachment); + + float time = input.readFloat(); + for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { + float[] deform; + int end = input.readInt(true); + if (end == 0) + deform = weighted ? new float[deformLength] : vertices; + else { + deform = new float[deformLength]; + int start = input.readInt(true); + end += start; + if (scale == 1) { + for (int v = start; v < end; v++) + deform[v] = input.readFloat(); + } else { + for (int v = start; v < end; v++) + deform[v] = input.readFloat() * scale; + } + if (!weighted) { + for (int v = 0, vn = deform.length; v < vn; v++) + deform[v] += vertices[v]; + } + } + timeline.setFrame(frameIndex, time, deform); + if (frameIndex == frameLast) break; + bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); + } + timelines.add(timeline); + } + } + } + + // Draw order timeline. + int drawOrderCount = input.readInt(true); + if (drawOrderCount > 0) { + DrawOrderTimeline timeline = new DrawOrderTimeline(drawOrderCount); + int slotCount = skeletonData.slots.size; + for (int i = 0; i < drawOrderCount; i++) { + float time = input.readFloat(); + int offsetCount = input.readInt(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 = input.readInt(true); + // Collect unchanged items. + while (originalIndex != slotIndex) + unchanged[unchangedIndex++] = originalIndex++; + // Set changed items. + drawOrder[originalIndex + input.readInt(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); + } + + // Event timeline. + int eventCount = input.readInt(true); + if (eventCount > 0) { + EventTimeline timeline = new EventTimeline(eventCount); + for (int i = 0; i < eventCount; i++) { + float time = input.readFloat(); + EventData eventData = skeletonData.events.get(input.readInt(true)); + Event event = new Event(time, eventData); + event.intValue = input.readInt(false); + event.floatValue = input.readFloat(); + event.stringValue = input.readBoolean() ? input.readString() : eventData.stringValue; + if (event.getData().audioPath != null) { + event.volume = input.readFloat(); + event.balance = input.readFloat(); + } + timeline.setFrame(i, event); + } + timelines.add(timeline); + } + float duration = 0; for (int i = 0, n = timelines.size; i < n; i++) duration = Math.max(duration, timelines.get(i).getDuration()); return new Animation(name, timelines, duration); } + private Timeline readTimeline (SkeletonInput input, ValueCurveTimeline timeline, float scale) throws IOException { + float time = input.readFloat(), value = input.readFloat() * scale; + for (int frameIndex = 0, bezierIndex = 0, frameLast = timeline.getFrameCount() - 1;; frameIndex++) { + timeline.setFrame(frameIndex, time, value); + if (frameIndex == frameLast) break; + bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, value, time = input.readFloat(), + value = input.readFloat() * scale); + } + return timeline; + } + + private Timeline readTimeline (SkeletonInput input, PercentCurveTimeline2 timeline, float scale) throws IOException { + float time = input.readFloat(); + for (int frameIndex = 0, bezierIndex = 0, frameLast = timeline.getFrameCount() - 1;; frameIndex++) { + timeline.setFrame(frameIndex, time, input.readFloat() * scale, input.readFloat() * scale); + if (frameIndex == frameLast) break; + bezierIndex = readCurve(input, timeline, frameIndex, bezierIndex, time, time = input.readFloat()); + } + return timeline; + } + int readCurve (SkeletonInput input, PercentCurveTimeline timeline, int frameIndex, int bezierIndex, float time1, float time2) throws IOException { switch (input.readByte()) { diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java index fa176e55d..39ccc29a1 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/SkeletonJson.java @@ -51,6 +51,7 @@ import com.esotericsoftware.spine.Animation.PathConstraintMixTimeline; import com.esotericsoftware.spine.Animation.PathConstraintPositionTimeline; import com.esotericsoftware.spine.Animation.PathConstraintSpacingTimeline; import com.esotericsoftware.spine.Animation.PercentCurveTimeline; +import com.esotericsoftware.spine.Animation.PercentCurveTimeline2; import com.esotericsoftware.spine.Animation.RotateTimeline; import com.esotericsoftware.spine.Animation.ScaleTimeline; import com.esotericsoftware.spine.Animation.ShearTimeline; @@ -359,9 +360,7 @@ public class SkeletonJson { float scale = this.scale; name = map.getString("name", name); - String type = map.getString("type", AttachmentType.region.name()); - - switch (AttachmentType.valueOf(type)) { + switch (AttachmentType.valueOf(map.getString("type", AttachmentType.region.name()))) { case region: { String path = map.getString("path", name); RegionAttachment region = attachmentLoader.newRegionAttachment(skin, name, path); @@ -507,44 +506,46 @@ public class SkeletonJson { SlotData slot = skeletonData.findSlot(slotMap.name); if (slot == null) throw new SerializationException("Slot not found: " + slotMap.name); for (JsonValue timelineMap = slotMap.child; timelineMap != null; timelineMap = timelineMap.next) { - JsonValue valueMap = timelineMap.child; - if (valueMap == null) continue; + JsonValue keyMap = timelineMap.child; + if (keyMap == null) continue; String timelineName = timelineMap.name; if (timelineName.equals("attachment")) { AttachmentTimeline timeline = new AttachmentTimeline(timelineMap.size, slot.index); - for (int frameIndex = 0; valueMap != null; valueMap = valueMap.next, frameIndex++) - timeline.setFrame(frameIndex, valueMap.getFloat("time", 0), valueMap.getString("name")); + for (int frameIndex = 0; keyMap != null; keyMap = keyMap.next, frameIndex++) + timeline.setFrame(frameIndex, keyMap.getFloat("time", 0), keyMap.getString("name")); timelines.add(timeline); } else if (timelineName.equals("color")) { - ColorTimeline timeline = new ColorTimeline(timelineMap.size, 0, slot.index); + ColorTimeline timeline = new ColorTimeline(timelineMap.size, timelineMap.size, slot.index); float time = timelineMap.child.getFloat("time", 0); for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { - Color color = Color.valueOf(valueMap.getString("color")); + Color color = Color.valueOf(keyMap.getString("color")); timeline.setFrame(frameIndex, time, color.r, color.g, color.b, color.a); - valueMap = valueMap.next; - if (valueMap == null) { + JsonValue nextMap = keyMap.next; + if (nextMap == null) { timeline.shrink(bezierIndex); break; } - bezierIndex = readCurve(valueMap, timeline, frameIndex, bezierIndex, time, time = valueMap.getFloat("time", 0)); + bezierIndex = readCurve(keyMap, timeline, frameIndex, bezierIndex, time, time = nextMap.getFloat("time", 0)); + keyMap = nextMap; } timelines.add(timeline); } else if (timelineName.equals("twoColor")) { - TwoColorTimeline timeline = new TwoColorTimeline(timelineMap.size, 0, slot.index); + TwoColorTimeline timeline = new TwoColorTimeline(timelineMap.size, timelineMap.size, slot.index); float time = timelineMap.child.getFloat("time", 0); for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { - Color light = Color.valueOf(valueMap.getString("light")), dark = Color.valueOf(valueMap.getString("dark")); + Color light = Color.valueOf(keyMap.getString("light")), dark = Color.valueOf(keyMap.getString("dark")); timeline.setFrame(frameIndex, time, light.r, light.g, light.b, light.a, // dark.r, dark.g, dark.b); - valueMap = valueMap.next; - if (valueMap == null) { + JsonValue nextMap = keyMap.next; + if (nextMap == null) { timeline.shrink(bezierIndex); break; } - bezierIndex = readCurve(valueMap, timeline, frameIndex, bezierIndex, time, time = valueMap.getFloat("time", 0)); + bezierIndex = readCurve(keyMap, timeline, frameIndex, bezierIndex, time, time = nextMap.getFloat("time", 0)); + keyMap = nextMap; } timelines.add(timeline); @@ -558,102 +559,65 @@ public class SkeletonJson { BoneData bone = skeletonData.findBone(boneMap.name); if (bone == null) throw new SerializationException("Bone not found: " + boneMap.name); for (JsonValue timelineMap = boneMap.child; timelineMap != null; timelineMap = timelineMap.next) { - JsonValue valueMap = timelineMap.child; - if (valueMap == null) continue; + JsonValue keyMap = timelineMap.child; + if (keyMap == null) continue; + String timelineName = timelineMap.name; - - if (timelineName.equals("rotate")) { - timelines.add(readTimeline(valueMap, new RotateTimeline(timelineMap.size, 0, bone.index))); - - } else if (timelineName.equals("translate")) { - TranslateTimeline timeline = new TranslateTimeline(timelineMap.size, 0, bone.index); - float time = valueMap.getFloat("time", 0); - for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { - float x = valueMap.getFloat("x", 0), y = valueMap.getFloat("y", 0); - timeline.setFrame(frameIndex, time, x * scale, y * scale); - valueMap = valueMap.next; - if (valueMap == null) { - timeline.shrink(bezierIndex); - break; - } - bezierIndex = readCurve(valueMap, timeline, frameIndex, bezierIndex, time, time = valueMap.getFloat("time", 0)); - } - timelines.add(timeline); - - } else if (timelineName.equals("scale")) { - ScaleTimeline timeline = new ScaleTimeline(timelineMap.size, 0, bone.index); - float time = valueMap.getFloat("time", 0); - for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { - float x = valueMap.getFloat("x", 1), y = valueMap.getFloat("y", 1); - timeline.setFrame(frameIndex, time, x, y); - valueMap = valueMap.next; - if (valueMap == null) { - timeline.shrink(bezierIndex); - break; - } - bezierIndex = readCurve(valueMap, timeline, frameIndex, bezierIndex, time, time = valueMap.getFloat("time", 0)); - } - timelines.add(timeline); - - } else if (timelineName.equals("shear")) { - ShearTimeline timeline = new ShearTimeline(timelineMap.size, 0, bone.index); - float time = valueMap.getFloat("time", 0); - for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { - float x = valueMap.getFloat("x", 0), y = valueMap.getFloat("y", 0); - timeline.setFrame(frameIndex, time, x, y); - valueMap = valueMap.next; - if (valueMap == null) { - timeline.shrink(bezierIndex); - break; - } - bezierIndex = readCurve(valueMap, timeline, frameIndex, bezierIndex, time, time = valueMap.getFloat("time", 0)); - } - timelines.add(timeline); - - } else + if (timelineName.equals("rotate")) + timelines.add(readTimeline(keyMap, new RotateTimeline(timelineMap.size, timelineMap.size, bone.index), 0, 1)); + else if (timelineName.equals("translate")) { + timelines + .add(readTimeline(keyMap, new TranslateTimeline(timelineMap.size, timelineMap.size, bone.index), 0, scale)); + } else if (timelineName.equals("scale")) + timelines.add(readTimeline(keyMap, new ScaleTimeline(timelineMap.size, timelineMap.size, bone.index), 1, 1)); + else if (timelineName.equals("shear")) + timelines.add(readTimeline(keyMap, new ShearTimeline(timelineMap.size, timelineMap.size, bone.index), 0, 1)); + else throw new RuntimeException("Invalid timeline type for a bone: " + timelineName + " (" + boneMap.name + ")"); } } // IK constraint timelines. for (JsonValue timelineMap = map.getChild("ik"); timelineMap != null; timelineMap = timelineMap.next) { - JsonValue valueMap = timelineMap.child; - if (valueMap == null) continue; + JsonValue keyMap = timelineMap.child; + if (keyMap == null) continue; IkConstraintData constraint = skeletonData.findIkConstraint(timelineMap.name); - IkConstraintTimeline timeline = new IkConstraintTimeline(timelineMap.size, 0, + IkConstraintTimeline timeline = new IkConstraintTimeline(timelineMap.size, timelineMap.size, skeletonData.getIkConstraints().indexOf(constraint, true)); - float time = valueMap.getFloat("time", 0); + float time = keyMap.getFloat("time", 0); for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { - timeline.setFrame(frameIndex, time, valueMap.getFloat("mix", 1), valueMap.getFloat("softness", 0) * scale, - valueMap.getBoolean("bendPositive", true) ? 1 : -1, valueMap.getBoolean("compress", false), - valueMap.getBoolean("stretch", false)); - valueMap = valueMap.next; - if (valueMap == null) { + timeline.setFrame(frameIndex, time, keyMap.getFloat("mix", 1), keyMap.getFloat("softness", 0) * scale, + keyMap.getBoolean("bendPositive", true) ? 1 : -1, keyMap.getBoolean("compress", false), + keyMap.getBoolean("stretch", false)); + JsonValue nextMap = keyMap.next; + if (nextMap == null) { timeline.shrink(bezierIndex); break; } - bezierIndex = readCurve(valueMap, timeline, frameIndex, bezierIndex, time, time = valueMap.getFloat("time", 0)); + bezierIndex = readCurve(keyMap, timeline, frameIndex, bezierIndex, time, time = nextMap.getFloat("time", 0)); + keyMap = nextMap; } timelines.add(timeline); } // Transform constraint timelines. for (JsonValue timelineMap = map.getChild("transform"); timelineMap != null; timelineMap = timelineMap.next) { - JsonValue valueMap = timelineMap.child; - if (valueMap == null) continue; + JsonValue keyMap = timelineMap.child; + if (keyMap == null) continue; TransformConstraintData constraint = skeletonData.findTransformConstraint(timelineMap.name); - TransformConstraintTimeline timeline = new TransformConstraintTimeline(timelineMap.size, 0, + TransformConstraintTimeline timeline = new TransformConstraintTimeline(timelineMap.size, timelineMap.size, skeletonData.getTransformConstraints().indexOf(constraint, true)); - float time = valueMap.getFloat("time", 0); + float time = keyMap.getFloat("time", 0); for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { - timeline.setFrame(frameIndex, time, valueMap.getFloat("rotateMix", 1), valueMap.getFloat("translateMix", 1), - valueMap.getFloat("scaleMix", 1), valueMap.getFloat("shearMix", 1)); - valueMap = valueMap.next; - if (valueMap == null) { + timeline.setFrame(frameIndex, time, keyMap.getFloat("rotateMix", 1), keyMap.getFloat("translateMix", 1), + keyMap.getFloat("scaleMix", 1), keyMap.getFloat("shearMix", 1)); + JsonValue nextMap = keyMap.next; + if (nextMap == null) { timeline.shrink(bezierIndex); break; } - bezierIndex = readCurve(valueMap, timeline, frameIndex, bezierIndex, time, time = valueMap.getFloat("time", 0)); + bezierIndex = readCurve(keyMap, timeline, frameIndex, bezierIndex, time, time = nextMap.getFloat("time", 0)); + keyMap = nextMap; } timelines.add(timeline); } @@ -664,53 +628,19 @@ public class SkeletonJson { if (data == null) throw new SerializationException("Path constraint not found: " + constraintMap.name); int index = skeletonData.pathConstraints.indexOf(data, true); for (JsonValue timelineMap = constraintMap.child; timelineMap != null; timelineMap = timelineMap.next) { - JsonValue valueMap = timelineMap.child; - if (valueMap == null) continue; + JsonValue keyMap = timelineMap.child; + if (keyMap == null) continue; String timelineName = timelineMap.name; if (timelineName.equals("position")) { - PathConstraintPositionTimeline timeline = new PathConstraintPositionTimeline(timelineMap.size, 0, index); - float timelineScale = data.positionMode == PositionMode.fixed ? scale : 1; - float time = valueMap.getFloat("time", 0); - for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { - timeline.setFrame(frameIndex, time, valueMap.getFloat(timelineName, 0) * timelineScale); - valueMap = valueMap.next; - if (valueMap == null) { - timeline.shrink(bezierIndex); - break; - } - bezierIndex = readCurve(valueMap, timeline, frameIndex, bezierIndex, time, time = valueMap.getFloat("time", 0)); - } - timelines.add(timeline); - + timelines.add(readTimeline(keyMap, new PathConstraintPositionTimeline(timelineMap.size, timelineMap.size, index), + 0, data.positionMode == PositionMode.fixed ? scale : 1)); } else if (timelineName.equals("spacing")) { - PathConstraintSpacingTimeline timeline = new PathConstraintSpacingTimeline(timelineMap.size, 0, index); - float timelineScale = data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed ? scale : 1; - float time = valueMap.getFloat("time", 0); - for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { - timeline.setFrame(frameIndex, time, valueMap.getFloat(timelineName, 0) * timelineScale); - valueMap = valueMap.next; - if (valueMap == null) { - timeline.shrink(bezierIndex); - break; - } - bezierIndex = readCurve(valueMap, timeline, frameIndex, bezierIndex, time, time = valueMap.getFloat("time", 0)); - } - timelines.add(timeline); - + timelines.add(readTimeline(keyMap, new PathConstraintSpacingTimeline(timelineMap.size, timelineMap.size, index), 0, + data.spacingMode == SpacingMode.length || data.spacingMode == SpacingMode.fixed ? scale : 1)); } else if (timelineName.equals("mix")) { - PathConstraintMixTimeline timeline = new PathConstraintMixTimeline(timelineMap.size, 0, index); - float time = valueMap.getFloat("time", 0); - for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { - timeline.setFrame(frameIndex, time, valueMap.getFloat("rotateMix", 1), valueMap.getFloat("translateMix", 1)); - valueMap = valueMap.next; - if (valueMap == null) { - timeline.shrink(bezierIndex); - break; - } - bezierIndex = readCurve(valueMap, timeline, frameIndex, bezierIndex, time, time = valueMap.getFloat("time", 0)); - } - timelines.add(timeline); + timelines + .add(readTimeline(keyMap, new PathConstraintMixTimeline(timelineMap.size, timelineMap.size, index), 1, 1)); } } } @@ -723,8 +653,8 @@ public class SkeletonJson { SlotData slot = skeletonData.findSlot(slotMap.name); if (slot == null) throw new SerializationException("Slot not found: " + slotMap.name); for (JsonValue timelineMap = slotMap.child; timelineMap != null; timelineMap = timelineMap.next) { - JsonValue valueMap = timelineMap.child; - if (valueMap == null) continue; + JsonValue keyMap = timelineMap.child; + if (keyMap == null) continue; VertexAttachment attachment = (VertexAttachment)skin.getAttachment(slot.index, timelineMap.name); if (attachment == null) throw new SerializationException("Deform attachment not found: " + timelineMap.name); @@ -732,17 +662,16 @@ public class SkeletonJson { float[] vertices = attachment.getVertices(); int deformLength = weighted ? vertices.length / 3 * 2 : vertices.length; - DeformTimeline timeline = new DeformTimeline(timelineMap.size, 0, slot.index, attachment); - int bezierIndex = 0; - float time = valueMap.getFloat("time", 0); - for (int frameIndex = 0;; frameIndex++) { + DeformTimeline timeline = new DeformTimeline(timelineMap.size, timelineMap.size, slot.index, attachment); + float time = keyMap.getFloat("time", 0); + for (int frameIndex = 0, bezierIndex = 0;; frameIndex++) { float[] deform; - JsonValue verticesValue = valueMap.get("vertices"); + JsonValue verticesValue = keyMap.get("vertices"); if (verticesValue == null) deform = weighted ? new float[deformLength] : vertices; else { deform = new float[deformLength]; - int start = valueMap.getInt("offset", 0); + int start = keyMap.getInt("offset", 0); arraycopy(verticesValue.asFloatArray(), 0, deform, start, verticesValue.size); if (scale != 1) { for (int i = start, n = i + verticesValue.size; i < n; i++) @@ -755,12 +684,15 @@ public class SkeletonJson { } timeline.setFrame(frameIndex, time, deform); - valueMap = valueMap.next; - if (valueMap == null) break; - bezierIndex = readCurve(valueMap, timeline, frameIndex, bezierIndex, time, time = valueMap.getFloat("time", 0)); + JsonValue nextMap = keyMap.next; + if (nextMap == null) { + timeline.shrink(bezierIndex); + break; + } + bezierIndex = readCurve(keyMap, timeline, frameIndex, bezierIndex, time, time = nextMap.getFloat("time", 0)); + keyMap = nextMap; } - timeline.shrink(bezierIndex); - timelines.add(timeline); + //timelines.add(timeline); } } } @@ -830,15 +762,32 @@ public class SkeletonJson { skeletonData.animations.add(new Animation(name, timelines, duration)); } - private ValueCurveTimeline readTimeline (JsonValue valueMap, ValueCurveTimeline timeline) { - float time = valueMap.getFloat("time", 0), value = valueMap.getFloat("value", 0); + private ValueCurveTimeline readTimeline (JsonValue keyMap, ValueCurveTimeline timeline, float defaultValue, float scale) { + float time = keyMap.getFloat("time", 0), value = keyMap.getFloat("value", defaultValue); int bezierIndex = 0; for (int frameIndex = 0;; frameIndex++) { timeline.setFrame(frameIndex, time, value); - valueMap = valueMap.next; - if (valueMap == null) break; - bezierIndex = readCurve(valueMap, timeline, frameIndex, bezierIndex, // - time, value, time = valueMap.getFloat("time", 0), value = valueMap.getFloat("value", 0)); + JsonValue nextMap = keyMap.next; + if (nextMap == null) break; + bezierIndex = readCurve(keyMap, timeline, frameIndex, bezierIndex, // + time, value, time = nextMap.getFloat("time", 0), value = nextMap.getFloat("value", defaultValue)); + keyMap = nextMap; + } + timeline.shrink(bezierIndex); + return timeline; + } + + private PercentCurveTimeline2 readTimeline (JsonValue keyMap, PercentCurveTimeline2 timeline, float defaultValue, + float scale) { + float time = keyMap.getFloat("time", 0); + int bezierIndex = 0; + for (int frameIndex = 0;; frameIndex++) { + float x = keyMap.getFloat("x", defaultValue), y = keyMap.getFloat("y", defaultValue); + timeline.setFrame(frameIndex, time, x * scale, y * scale); + JsonValue nextMap = keyMap.next; + if (nextMap == null) break; + bezierIndex = readCurve(keyMap, timeline, frameIndex, bezierIndex, time, time = nextMap.getFloat("time", 0)); + keyMap = nextMap; } timeline.shrink(bezierIndex); return timeline;