[libgdx] Added slider (time) timeline.

This commit is contained in:
Nathan Sweet 2025-04-22 18:54:07 -04:00
parent 82ad1691c3
commit ac656fc8a9
3 changed files with 88 additions and 106 deletions

View File

@ -183,7 +183,7 @@ public class Animation {
physicsConstraintInertia, physicsConstraintStrength, physicsConstraintDamping, physicsConstraintMass, // physicsConstraintInertia, physicsConstraintStrength, physicsConstraintDamping, physicsConstraintMass, //
physicsConstraintWind, physicsConstraintGravity, physicsConstraintMix, physicsConstraintReset, // physicsConstraintWind, physicsConstraintGravity, physicsConstraintMix, physicsConstraintReset, //
sequence, // sequence, //
sliderMix sliderTime, sliderMix
} }
/** The base class for all timelines. */ /** The base class for all timelines. */
@ -512,16 +512,17 @@ public class Animation {
} }
} }
/** The base class for a {@link CurveTimeline} which sets two properties. */ /** The base class for a {@link CurveTimeline} that is a {@link BoneTimeline} and sets two properties. */
static abstract public class CurveTimeline2 extends CurveTimeline { static abstract public class BoneTimeline2 extends CurveTimeline implements BoneTimeline {
static public final int ENTRIES = 3; static public final int ENTRIES = 3;
static final int VALUE1 = 1, VALUE2 = 2; static final int VALUE1 = 1, VALUE2 = 2;
/** @param bezierCount The maximum number of Bezier curves. See {@link #shrink(int)}. final int boneIndex;
* @param propertyId1 Unique identifier for the first property the timeline modifies.
* @param propertyId2 Unique identifier for the second property the timeline modifies. */ /** @param bezierCount The maximum number of Bezier curves. See {@link #shrink(int)}. */
public CurveTimeline2 (int frameCount, int bezierCount, String propertyId1, String propertyId2) { public BoneTimeline2 (int frameCount, int bezierCount, int boneIndex, Property property1, Property property2) {
super(frameCount, bezierCount, propertyId1, propertyId2); super(frameCount, bezierCount, property1.ordinal() + "|" + boneIndex, property2.ordinal() + "|" + boneIndex);
this.boneIndex = boneIndex;
} }
public int getFrameEntries () { public int getFrameEntries () {
@ -537,21 +538,6 @@ public class Animation {
frames[frame + VALUE1] = value1; frames[frame + VALUE1] = value1;
frames[frame + VALUE2] = value2; frames[frame + VALUE2] = value2;
} }
}
/** An interface for timelines which change the property of a bone. */
static public interface BoneTimeline {
/** The index of the bone in {@link Skeleton#getBones()} that will be changed when this timeline is applied. */
public int getBoneIndex ();
}
static abstract public class BoneTimeline1 extends CurveTimeline1 implements BoneTimeline {
final int boneIndex;
public BoneTimeline1 (int frameCount, int bezierCount, int boneIndex, Property property) {
super(frameCount, bezierCount, property.ordinal() + "|" + boneIndex);
this.boneIndex = boneIndex;
}
public int getBoneIndex () { public int getBoneIndex () {
return boneIndex; return boneIndex;
@ -568,11 +554,17 @@ public class Animation {
MixDirection direction); MixDirection direction);
} }
static abstract public class BoneTimeline2 extends CurveTimeline2 implements BoneTimeline { /** An interface for timelines which change the property of a bone. */
static public interface BoneTimeline {
/** The index of the bone in {@link Skeleton#getBones()} that will be changed when this timeline is applied. */
public int getBoneIndex ();
}
static abstract public class BoneTimeline1 extends CurveTimeline1 implements BoneTimeline {
final int boneIndex; final int boneIndex;
public BoneTimeline2 (int frameCount, int bezierCount, int boneIndex, Property property1, Property property2) { public BoneTimeline1 (int frameCount, int bezierCount, int boneIndex, Property property) {
super(frameCount, bezierCount, property1.ordinal() + "|" + boneIndex, property2.ordinal() + "|" + boneIndex); super(frameCount, bezierCount, property.ordinal() + "|" + boneIndex);
this.boneIndex = boneIndex; this.boneIndex = boneIndex;
} }
@ -2165,18 +2157,24 @@ public class Animation {
} }
} }
/** Changes a path constraint's {@link PathConstraintPose#getPosition()}. */ static abstract public class ConstraintTimeline1 extends CurveTimeline1 implements ConstraintTimeline {
static public class PathConstraintPositionTimeline extends CurveTimeline1 implements ConstraintTimeline {
final int constraintIndex; final int constraintIndex;
public PathConstraintPositionTimeline (int frameCount, int bezierCount, int constraintIndex) { public ConstraintTimeline1 (int frameCount, int bezierCount, int constraintIndex, Property property) {
super(frameCount, bezierCount, Property.pathConstraintPosition.ordinal() + "|" + constraintIndex); super(frameCount, bezierCount, property.ordinal() + "|" + constraintIndex);
this.constraintIndex = constraintIndex; this.constraintIndex = constraintIndex;
} }
public int getConstraintIndex () { public int getConstraintIndex () {
return constraintIndex; return constraintIndex;
} }
}
/** Changes a path constraint's {@link PathConstraintPose#getPosition()}. */
static public class PathConstraintPositionTimeline extends ConstraintTimeline1 {
public PathConstraintPositionTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.pathConstraintPosition);
}
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend, public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
MixDirection direction, boolean appliedPose) { MixDirection direction, boolean appliedPose) {
@ -2190,16 +2188,9 @@ public class Animation {
} }
/** Changes a path constraint's {@link PathConstraintPose#getSpacing()}. */ /** Changes a path constraint's {@link PathConstraintPose#getSpacing()}. */
static public class PathConstraintSpacingTimeline extends CurveTimeline1 implements ConstraintTimeline { static public class PathConstraintSpacingTimeline extends ConstraintTimeline1 {
final int constraintIndex;
public PathConstraintSpacingTimeline (int frameCount, int bezierCount, int constraintIndex) { public PathConstraintSpacingTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, Property.pathConstraintSpacing.ordinal() + "|" + constraintIndex); super(frameCount, bezierCount, constraintIndex, Property.pathConstraintSpacing);
this.constraintIndex = constraintIndex;
}
public int getConstraintIndex () {
return constraintIndex;
} }
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend, public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
@ -2307,19 +2298,10 @@ public class Animation {
} }
/** The base class for most {@link PhysicsConstraint} timelines. */ /** The base class for most {@link PhysicsConstraint} timelines. */
static abstract public class PhysicsConstraintTimeline extends CurveTimeline1 implements ConstraintTimeline { static abstract public class PhysicsConstraintTimeline extends ConstraintTimeline1 {
final int constraintIndex;
/** @param constraintIndex -1 for all physics constraints in the skeleton. */ /** @param constraintIndex -1 for all physics constraints in the skeleton. */
public PhysicsConstraintTimeline (int frameCount, int bezierCount, int constraintIndex, Property property) { public PhysicsConstraintTimeline (int frameCount, int bezierCount, int constraintIndex, Property property) {
super(frameCount, bezierCount, property.ordinal() + "|" + constraintIndex); super(frameCount, bezierCount, constraintIndex, property);
this.constraintIndex = constraintIndex;
}
/** The index of the physics constraint in {@link Skeleton#getConstraints()} that will be changed when this timeline is
* applied, or -1 if all physics constraints in the skeleton will be changed. */
public int getConstraintIndex () {
return constraintIndex;
} }
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend, public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
@ -2546,17 +2528,27 @@ public class Animation {
} }
} }
/** Changes a slider's {@link SliderPose#getMix()}. */ /** Changes a slider's {@link SliderPose#getTime()}. */
static public class SliderMixTimeline extends CurveTimeline1 implements ConstraintTimeline { static public class SliderTimeline extends ConstraintTimeline1 {
final int constraintIndex; public SliderTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.sliderTime);
public SliderMixTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, Property.sliderMix.ordinal() + "|" + constraintIndex);
this.constraintIndex = constraintIndex;
} }
public int getConstraintIndex () { public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,
return constraintIndex; MixDirection direction, boolean appliedPose) {
var constraint = (Slider)skeleton.constraints.items[constraintIndex];
if (constraint.active) {
SliderPose pose = appliedPose ? constraint.applied : constraint.pose;
pose.time = getAbsoluteValue(time, alpha, blend, pose.time, constraint.data.setup.time);
}
}
}
/** Changes a slider's {@link SliderPose#getMix()}. */
static public class SliderMixTimeline extends ConstraintTimeline1 {
public SliderMixTimeline (int frameCount, int bezierCount, int constraintIndex) {
super(frameCount, bezierCount, constraintIndex, Property.sliderMix);
} }
public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend, public void apply (Skeleton skeleton, float lastTime, float time, @Null Array<Event> events, float alpha, MixBlend blend,

View File

@ -45,9 +45,9 @@ import com.badlogic.gdx.utils.SerializationException;
import com.esotericsoftware.spine.Animation.AlphaTimeline; import com.esotericsoftware.spine.Animation.AlphaTimeline;
import com.esotericsoftware.spine.Animation.AttachmentTimeline; import com.esotericsoftware.spine.Animation.AttachmentTimeline;
import com.esotericsoftware.spine.Animation.BoneTimeline2;
import com.esotericsoftware.spine.Animation.CurveTimeline; import com.esotericsoftware.spine.Animation.CurveTimeline;
import com.esotericsoftware.spine.Animation.CurveTimeline1; import com.esotericsoftware.spine.Animation.CurveTimeline1;
import com.esotericsoftware.spine.Animation.CurveTimeline2;
import com.esotericsoftware.spine.Animation.DeformTimeline; import com.esotericsoftware.spine.Animation.DeformTimeline;
import com.esotericsoftware.spine.Animation.DrawOrderTimeline; import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
import com.esotericsoftware.spine.Animation.EventTimeline; import com.esotericsoftware.spine.Animation.EventTimeline;
@ -77,6 +77,7 @@ import com.esotericsoftware.spine.Animation.ShearTimeline;
import com.esotericsoftware.spine.Animation.ShearXTimeline; import com.esotericsoftware.spine.Animation.ShearXTimeline;
import com.esotericsoftware.spine.Animation.ShearYTimeline; import com.esotericsoftware.spine.Animation.ShearYTimeline;
import com.esotericsoftware.spine.Animation.SliderMixTimeline; import com.esotericsoftware.spine.Animation.SliderMixTimeline;
import com.esotericsoftware.spine.Animation.SliderTimeline;
import com.esotericsoftware.spine.Animation.Timeline; import com.esotericsoftware.spine.Animation.Timeline;
import com.esotericsoftware.spine.Animation.TransformConstraintTimeline; import com.esotericsoftware.spine.Animation.TransformConstraintTimeline;
import com.esotericsoftware.spine.Animation.TranslateTimeline; import com.esotericsoftware.spine.Animation.TranslateTimeline;
@ -160,7 +161,8 @@ public class SkeletonBinary extends SkeletonLoader {
static public final int PHYSICS_MIX = 7; static public final int PHYSICS_MIX = 7;
static public final int PHYSICS_RESET = 8; static public final int PHYSICS_RESET = 8;
static public final int SLIDER_MIX = 0; static public final int SLIDER_TIME = 0;
static public final int SLIDER_MIX = 1;
static public final int CURVE_LINEAR = 0; static public final int CURVE_LINEAR = 0;
static public final int CURVE_STEPPED = 1; static public final int CURVE_STEPPED = 1;
@ -1055,24 +1057,11 @@ public class SkeletonBinary extends SkeletonLoader {
int index = input.readInt(true); int index = input.readInt(true);
for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) { for (int ii = 0, nn = input.readInt(true); ii < nn; ii++) {
int type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true); int type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true);
switch (type) { readTimeline(input, timelines, switch (type) {
case SLIDER_MIX -> { case SLIDER_TIME -> new SliderTimeline(frameCount, bezierCount, index);
var timeline = new SliderMixTimeline(frameCount, bezierCount, index); case SLIDER_MIX -> new SliderMixTimeline(frameCount, bezierCount, index);
float time = input.readFloat(), mix = input.readFloat(); default -> throw new SerializationException();
for (int frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1;; frame++) { }, 1);
timeline.setFrame(frame, time, mix);
if (frame == frameLast) break;
float time2 = input.readFloat(), mix2 = input.readFloat();
switch (input.readByte()) {
case CURVE_STEPPED -> timeline.setStepped(frame);
case CURVE_BEZIER -> setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1);
}
time = time2;
mix = mix2;
}
timelines.add(timeline);
}
}
} }
} }
@ -1221,7 +1210,7 @@ public class SkeletonBinary extends SkeletonLoader {
timelines.add(timeline); timelines.add(timeline);
} }
private void readTimeline (SkeletonInput input, Array<Timeline> timelines, CurveTimeline2 timeline, float scale) private void readTimeline (SkeletonInput input, Array<Timeline> timelines, BoneTimeline2 timeline, float scale)
throws IOException { throws IOException {
float time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale; float time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale;
for (int frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1;; frame++) { for (int frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1;; frame++) {

View File

@ -46,9 +46,9 @@ import com.badlogic.gdx.utils.SerializationException;
import com.esotericsoftware.spine.Animation.AlphaTimeline; import com.esotericsoftware.spine.Animation.AlphaTimeline;
import com.esotericsoftware.spine.Animation.AttachmentTimeline; import com.esotericsoftware.spine.Animation.AttachmentTimeline;
import com.esotericsoftware.spine.Animation.BoneTimeline2;
import com.esotericsoftware.spine.Animation.CurveTimeline; import com.esotericsoftware.spine.Animation.CurveTimeline;
import com.esotericsoftware.spine.Animation.CurveTimeline1; import com.esotericsoftware.spine.Animation.CurveTimeline1;
import com.esotericsoftware.spine.Animation.CurveTimeline2;
import com.esotericsoftware.spine.Animation.DeformTimeline; import com.esotericsoftware.spine.Animation.DeformTimeline;
import com.esotericsoftware.spine.Animation.DrawOrderTimeline; import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
import com.esotericsoftware.spine.Animation.EventTimeline; import com.esotericsoftware.spine.Animation.EventTimeline;
@ -78,6 +78,7 @@ import com.esotericsoftware.spine.Animation.ShearTimeline;
import com.esotericsoftware.spine.Animation.ShearXTimeline; import com.esotericsoftware.spine.Animation.ShearXTimeline;
import com.esotericsoftware.spine.Animation.ShearYTimeline; import com.esotericsoftware.spine.Animation.ShearYTimeline;
import com.esotericsoftware.spine.Animation.SliderMixTimeline; import com.esotericsoftware.spine.Animation.SliderMixTimeline;
import com.esotericsoftware.spine.Animation.SliderTimeline;
import com.esotericsoftware.spine.Animation.Timeline; import com.esotericsoftware.spine.Animation.Timeline;
import com.esotericsoftware.spine.Animation.TransformConstraintTimeline; import com.esotericsoftware.spine.Animation.TransformConstraintTimeline;
import com.esotericsoftware.spine.Animation.TranslateTimeline; import com.esotericsoftware.spine.Animation.TranslateTimeline;
@ -763,7 +764,7 @@ public class SkeletonJson extends SkeletonLoader {
} }
timelines.add(timeline); timelines.add(timeline);
} }
case "alpha" -> timelines.add(readTimeline(keyMap, new AlphaTimeline(frames, frames, slot.index), 0, 1)); case "alpha" -> readTimeline(timelines, keyMap, new AlphaTimeline(frames, frames, slot.index), 0, 1);
case "rgba2" -> { case "rgba2" -> {
var timeline = new RGBA2Timeline(frames, frames * 7, slot.index); var timeline = new RGBA2Timeline(frames, frames * 7, slot.index);
float time = keyMap.getFloat("time", 0); float time = keyMap.getFloat("time", 0);
@ -878,21 +879,17 @@ public class SkeletonJson extends SkeletonLoader {
int frames = timelineMap.size; int frames = timelineMap.size;
switch (timelineMap.name) { switch (timelineMap.name) {
case "rotate" -> timelines.add(readTimeline(keyMap, new RotateTimeline(frames, frames, bone.index), 0, 1)); case "rotate" -> readTimeline(timelines, keyMap, new RotateTimeline(frames, frames, bone.index), 0, 1);
case "translate" -> // case "translate" -> //
timelines.add(readTimeline(keyMap, new TranslateTimeline(frames, frames << 1, bone.index), "x", "y", 0, scale)); readTimeline(timelines, keyMap, new TranslateTimeline(frames, frames << 1, bone.index), "x", "y", 0, scale);
case "translatex" -> // case "translatex" -> readTimeline(timelines, keyMap, new TranslateXTimeline(frames, frames, bone.index), 0, scale);
timelines.add(readTimeline(keyMap, new TranslateXTimeline(frames, frames, bone.index), 0, scale)); case "translatey" -> readTimeline(timelines, keyMap, new TranslateYTimeline(frames, frames, bone.index), 0, scale);
case "translatey" -> // case "scale" -> readTimeline(timelines, keyMap, new ScaleTimeline(frames, frames << 1, bone.index), "x", "y", 1, 1);
timelines.add(readTimeline(keyMap, new TranslateYTimeline(frames, frames, bone.index), 0, scale)); case "scalex" -> readTimeline(timelines, keyMap, new ScaleXTimeline(frames, frames, bone.index), 1, 1);
case "scale" -> timelines case "scaley" -> readTimeline(timelines, keyMap, new ScaleYTimeline(frames, frames, bone.index), 1, 1);
.add(readTimeline(keyMap, new ScaleTimeline(frames, frames << 1, bone.index), "x", "y", 1, 1)); case "shear" -> readTimeline(timelines, keyMap, new ShearTimeline(frames, frames << 1, bone.index), "x", "y", 0, 1);
case "scalex" -> timelines.add(readTimeline(keyMap, new ScaleXTimeline(frames, frames, bone.index), 1, 1)); case "shearx" -> readTimeline(timelines, keyMap, new ShearXTimeline(frames, frames, bone.index), 0, 1);
case "scaley" -> timelines.add(readTimeline(keyMap, new ScaleYTimeline(frames, frames, bone.index), 1, 1)); case "sheary" -> readTimeline(timelines, keyMap, new ShearYTimeline(frames, frames, bone.index), 0, 1);
case "shear" -> //
timelines.add(readTimeline(keyMap, new ShearTimeline(frames, frames << 1, bone.index), "x", "y", 0, 1));
case "shearx" -> timelines.add(readTimeline(keyMap, new ShearXTimeline(frames, frames, bone.index), 0, 1));
case "sheary" -> timelines.add(readTimeline(keyMap, new ShearYTimeline(frames, frames, bone.index), 0, 1));
case "inherit" -> { case "inherit" -> {
var timeline = new InheritTimeline(frames, bone.index); var timeline = new InheritTimeline(frames, bone.index);
for (int frame = 0; keyMap != null; keyMap = keyMap.next, frame++) { for (int frame = 0; keyMap != null; keyMap = keyMap.next, frame++) {
@ -997,12 +994,12 @@ public class SkeletonJson extends SkeletonLoader {
switch (timelineMap.name) { switch (timelineMap.name) {
case "position" -> { case "position" -> {
var timeline = new PathConstraintPositionTimeline(frames, frames, index); var timeline = new PathConstraintPositionTimeline(frames, frames, index);
timelines.add(readTimeline(keyMap, timeline, 0, constraint.positionMode == PositionMode.fixed ? scale : 1)); readTimeline(timelines, keyMap, timeline, 0, constraint.positionMode == PositionMode.fixed ? scale : 1);
} }
case "spacing" -> { case "spacing" -> {
var timeline = new PathConstraintSpacingTimeline(frames, frames, index); var timeline = new PathConstraintSpacingTimeline(frames, frames, index);
timelines.add(readTimeline(keyMap, timeline, 0, readTimeline(timelines, keyMap, timeline, 0,
constraint.spacingMode == SpacingMode.length || constraint.spacingMode == SpacingMode.fixed ? scale : 1)); constraint.spacingMode == SpacingMode.length || constraint.spacingMode == SpacingMode.fixed ? scale : 1);
} }
case "mix" -> { case "mix" -> {
var timeline = new PathConstraintMixTimeline(frames, frames * 3, index); var timeline = new PathConstraintMixTimeline(frames, frames * 3, index);
@ -1074,7 +1071,7 @@ public class SkeletonJson extends SkeletonLoader {
continue; continue;
} }
} }
timelines.add(readTimeline(keyMap, timeline, defaultValue, 1)); readTimeline(timelines, keyMap, timeline, defaultValue, 1);
} }
} }
@ -1089,7 +1086,8 @@ public class SkeletonJson extends SkeletonLoader {
int frames = timelineMap.size; int frames = timelineMap.size;
switch (timelineMap.name) { switch (timelineMap.name) {
case "mix" -> timelines.add(readTimeline(keyMap, new SliderMixTimeline(frames, frames, index), 1, 1)); case "time" -> readTimeline(timelines, keyMap, new SliderTimeline(frames, frames, index), 1, 1);
case "mix" -> readTimeline(timelines, keyMap, new SliderMixTimeline(frames, frames, index), 1, 1);
} }
} }
} }
@ -1231,14 +1229,16 @@ public class SkeletonJson extends SkeletonLoader {
skeletonData.animations.add(new Animation(name, timelines, duration)); skeletonData.animations.add(new Animation(name, timelines, duration));
} }
private Timeline readTimeline (JsonValue keyMap, CurveTimeline1 timeline, float defaultValue, float scale) { private void readTimeline (Array<Timeline> timelines, JsonValue keyMap, CurveTimeline1 timeline, float defaultValue,
float scale) {
float time = keyMap.getFloat("time", 0), value = keyMap.getFloat("value", defaultValue) * scale; float time = keyMap.getFloat("time", 0), value = keyMap.getFloat("value", defaultValue) * scale;
for (int frame = 0, bezier = 0;; frame++) { for (int frame = 0, bezier = 0;; frame++) {
timeline.setFrame(frame, time, value); timeline.setFrame(frame, time, value);
JsonValue nextMap = keyMap.next; JsonValue nextMap = keyMap.next;
if (nextMap == null) { if (nextMap == null) {
timeline.shrink(bezier); timeline.shrink(bezier);
return timeline; timelines.add(timeline);
return;
} }
float time2 = nextMap.getFloat("time", 0); float time2 = nextMap.getFloat("time", 0);
float value2 = nextMap.getFloat("value", defaultValue) * scale; float value2 = nextMap.getFloat("value", defaultValue) * scale;
@ -1250,8 +1250,8 @@ public class SkeletonJson extends SkeletonLoader {
} }
} }
private Timeline readTimeline (JsonValue keyMap, CurveTimeline2 timeline, String name1, String name2, float defaultValue, private void readTimeline (Array<Timeline> timelines, JsonValue keyMap, BoneTimeline2 timeline, String name1, String name2,
float scale) { float defaultValue, float scale) {
float time = keyMap.getFloat("time", 0); float time = keyMap.getFloat("time", 0);
float value1 = keyMap.getFloat(name1, defaultValue) * scale, value2 = keyMap.getFloat(name2, defaultValue) * scale; float value1 = keyMap.getFloat(name1, defaultValue) * scale, value2 = keyMap.getFloat(name2, defaultValue) * scale;
for (int frame = 0, bezier = 0;; frame++) { for (int frame = 0, bezier = 0;; frame++) {
@ -1259,7 +1259,8 @@ public class SkeletonJson extends SkeletonLoader {
JsonValue nextMap = keyMap.next; JsonValue nextMap = keyMap.next;
if (nextMap == null) { if (nextMap == null) {
timeline.shrink(bezier); timeline.shrink(bezier);
return timeline; timelines.add(timeline);
return;
} }
float time2 = nextMap.getFloat("time", 0); float time2 = nextMap.getFloat("time", 0);
float nvalue1 = nextMap.getFloat(name1, defaultValue) * scale, nvalue2 = nextMap.getFloat(name2, defaultValue) * scale; float nvalue1 = nextMap.getFloat(name1, defaultValue) * scale, nvalue2 = nextMap.getFloat(name2, defaultValue) * scale;