mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
Moved track changes to update, so AnimationState can be applied to multiple skeletons without side effects.
Also: - Moved queue drains outside of update loop. - Better naming. - Dirty flag after animations have been changed to avoid computing timelinesFirst more times than needed. - Don't use timelinesFirst when mix == 1.
This commit is contained in:
parent
ef2a440655
commit
4c2d2b0c0a
@ -167,9 +167,11 @@ public class AnimationStateTest {
|
|||||||
expect(1, "start", 0.1f, 1.1f), //
|
expect(1, "start", 0.1f, 1.1f), //
|
||||||
|
|
||||||
expect(0, "interrupt", 1.1f, 1.1f), //
|
expect(0, "interrupt", 1.1f, 1.1f), //
|
||||||
expect(0, "end", 1.1f, 1.1f), //
|
|
||||||
|
|
||||||
expect(1, "event 0", 0.1f, 1.1f), //
|
expect(1, "event 0", 0.1f, 1.1f), //
|
||||||
|
|
||||||
|
expect(0, "end", 1.1f, 1.2f), //
|
||||||
|
|
||||||
expect(1, "event 14", 0.5f, 1.5f), //
|
expect(1, "event 14", 0.5f, 1.5f), //
|
||||||
expect(1, "event 30", 1, 2), //
|
expect(1, "event 30", 1, 2), //
|
||||||
expect(1, "complete", 1, 2), //
|
expect(1, "complete", 1, 2), //
|
||||||
@ -177,9 +179,11 @@ public class AnimationStateTest {
|
|||||||
expect(0, "start", 0.1f, 2.1f), //
|
expect(0, "start", 0.1f, 2.1f), //
|
||||||
|
|
||||||
expect(1, "interrupt", 1.1f, 2.1f), //
|
expect(1, "interrupt", 1.1f, 2.1f), //
|
||||||
expect(1, "end", 1.1f, 2.1f), //
|
|
||||||
|
|
||||||
expect(0, "event 0", 0.1f, 2.1f), //
|
expect(0, "event 0", 0.1f, 2.1f), //
|
||||||
|
|
||||||
|
expect(1, "end", 1.1f, 2.2f), //
|
||||||
|
|
||||||
expect(0, "event 14", 0.5f, 2.5f), //
|
expect(0, "event 14", 0.5f, 2.5f), //
|
||||||
expect(0, "event 30", 1, 3), //
|
expect(0, "event 30", 1, 3), //
|
||||||
expect(0, "complete", 1, 3), //
|
expect(0, "complete", 1, 3), //
|
||||||
@ -198,9 +202,11 @@ public class AnimationStateTest {
|
|||||||
expect(1, "start", 0.1f, 0.6f), //
|
expect(1, "start", 0.1f, 0.6f), //
|
||||||
|
|
||||||
expect(0, "interrupt", 0.6f, 0.6f), //
|
expect(0, "interrupt", 0.6f, 0.6f), //
|
||||||
expect(0, "end", 0.6f, 0.6f), //
|
|
||||||
|
|
||||||
expect(1, "event 0", 0.1f, 0.6f), //
|
expect(1, "event 0", 0.1f, 0.6f), //
|
||||||
|
|
||||||
|
expect(0, "end", 0.6f, 0.7f), //
|
||||||
|
|
||||||
expect(1, "event 14", 0.5f, 1.0f), //
|
expect(1, "event 14", 0.5f, 1.0f), //
|
||||||
expect(1, "event 30", 1, 1.5f), //
|
expect(1, "event 30", 1, 1.5f), //
|
||||||
expect(1, "complete", 1, 1.5f), //
|
expect(1, "complete", 1, 1.5f), //
|
||||||
@ -223,7 +229,7 @@ public class AnimationStateTest {
|
|||||||
expect(1, "event 0", 0.1f, 1), //
|
expect(1, "event 0", 0.1f, 1), //
|
||||||
expect(1, "event 14", 0.5f, 1.4f), //
|
expect(1, "event 14", 0.5f, 1.4f), //
|
||||||
|
|
||||||
expect(0, "end", 1.6f, 1.6f), //
|
expect(0, "end", 1.6f, 1.7f), //
|
||||||
|
|
||||||
expect(1, "event 30", 1, 1.9f), //
|
expect(1, "event 30", 1, 1.9f), //
|
||||||
expect(1, "complete", 1, 1.9f), //
|
expect(1, "complete", 1, 1.9f), //
|
||||||
@ -246,7 +252,7 @@ public class AnimationStateTest {
|
|||||||
expect(1, "event 14", 0.5f, 0.9f), //
|
expect(1, "event 14", 0.5f, 0.9f), //
|
||||||
|
|
||||||
expect(0, "complete", 1, 1), //
|
expect(0, "complete", 1, 1), //
|
||||||
expect(0, "end", 1.1f, 1.1f), //
|
expect(0, "end", 1.1f, 1.2f), //
|
||||||
|
|
||||||
expect(1, "event 30", 1, 1.4f), //
|
expect(1, "event 30", 1, 1.4f), //
|
||||||
expect(1, "complete", 1, 1.4f), //
|
expect(1, "complete", 1, 1.4f), //
|
||||||
@ -270,7 +276,7 @@ public class AnimationStateTest {
|
|||||||
expect(1, "event 14", 0.5f, 0.9f), //
|
expect(1, "event 14", 0.5f, 0.9f), //
|
||||||
|
|
||||||
expect(0, "complete", 1, 1), //
|
expect(0, "complete", 1, 1), //
|
||||||
expect(0, "end", 1.1f, 1.1f), //
|
expect(0, "end", 1.1f, 1.2f), //
|
||||||
|
|
||||||
expect(1, "event 30", 1, 1.4f), //
|
expect(1, "event 30", 1, 1.4f), //
|
||||||
expect(1, "complete", 1, 1.4f), //
|
expect(1, "complete", 1, 1.4f), //
|
||||||
@ -298,7 +304,7 @@ public class AnimationStateTest {
|
|||||||
|
|
||||||
expect(1, "event 14", 0.5f, 1.3f), //
|
expect(1, "event 14", 0.5f, 1.3f), //
|
||||||
|
|
||||||
expect(0, "end", 1.5f, 1.5f), //
|
expect(0, "end", 1.5f, 1.6f), //
|
||||||
|
|
||||||
expect(1, "event 30", 1, 1.8f), //
|
expect(1, "event 30", 1, 1.8f), //
|
||||||
expect(1, "complete", 1, 1.8f), //
|
expect(1, "complete", 1, 1.8f), //
|
||||||
@ -341,9 +347,11 @@ public class AnimationStateTest {
|
|||||||
expect(1, "start", 0.1f, 2.1f), //
|
expect(1, "start", 0.1f, 2.1f), //
|
||||||
|
|
||||||
expect(0, "interrupt", 2.1f, 2.1f), //
|
expect(0, "interrupt", 2.1f, 2.1f), //
|
||||||
expect(0, "end", 2.1f, 2.1f), //
|
|
||||||
|
|
||||||
expect(1, "event 0", 0.1f, 2.1f), //
|
expect(1, "event 0", 0.1f, 2.1f), //
|
||||||
|
|
||||||
|
expect(0, "end", 2.1f, 2.2f), //
|
||||||
|
|
||||||
expect(1, "event 14", 0.5f, 2.5f), //
|
expect(1, "event 14", 0.5f, 2.5f), //
|
||||||
expect(1, "event 30", 1, 3), //
|
expect(1, "event 30", 1, 3), //
|
||||||
expect(1, "complete", 1, 3), //
|
expect(1, "complete", 1, 3), //
|
||||||
@ -368,9 +376,11 @@ public class AnimationStateTest {
|
|||||||
expect(1, "start", 0.1f, 2.1f), //
|
expect(1, "start", 0.1f, 2.1f), //
|
||||||
|
|
||||||
expect(0, "interrupt", 2.1f, 2.1f), //
|
expect(0, "interrupt", 2.1f, 2.1f), //
|
||||||
expect(0, "end", 2.1f, 2.1f), //
|
|
||||||
|
|
||||||
expect(1, "event 0", 0.1f, 2.1f), //
|
expect(1, "event 0", 0.1f, 2.1f), //
|
||||||
|
|
||||||
|
expect(0, "end", 2.1f, 2.2f), //
|
||||||
|
|
||||||
expect(1, "event 14", 0.5f, 2.5f), //
|
expect(1, "event 14", 0.5f, 2.5f), //
|
||||||
expect(1, "event 30", 1, 3), //
|
expect(1, "event 30", 1, 3), //
|
||||||
expect(1, "complete", 1, 3), //
|
expect(1, "complete", 1, 3), //
|
||||||
@ -461,7 +471,7 @@ public class AnimationStateTest {
|
|||||||
|
|
||||||
expect(1, "event 14", 0.5f, 1.2f), //
|
expect(1, "event 14", 0.5f, 1.2f), //
|
||||||
|
|
||||||
expect(0, "end", 1.4f, 1.4f), //
|
expect(0, "end", 1.4f, 1.5f), //
|
||||||
|
|
||||||
expect(1, "event 30", 1, 1.7f), //
|
expect(1, "event 30", 1, 1.7f), //
|
||||||
expect(1, "complete", 1, 1.7f), //
|
expect(1, "complete", 1, 1.7f), //
|
||||||
@ -488,7 +498,7 @@ public class AnimationStateTest {
|
|||||||
expect(1, "event 0", 0.1f, 1), //
|
expect(1, "event 0", 0.1f, 1), //
|
||||||
expect(1, "event 14", 0.5f, 1.4f), //
|
expect(1, "event 14", 0.5f, 1.4f), //
|
||||||
|
|
||||||
expect(0, "end", 1.6f, 1.6f), //
|
expect(0, "end", 1.6f, 1.7f), //
|
||||||
|
|
||||||
expect(1, "event 30", 1, 1.9f), //
|
expect(1, "event 30", 1, 1.9f), //
|
||||||
expect(1, "complete", 1, 1.9f), //
|
expect(1, "complete", 1, 1.9f), //
|
||||||
@ -507,17 +517,21 @@ public class AnimationStateTest {
|
|||||||
expect(1, "start", 0, 0), //
|
expect(1, "start", 0, 0), //
|
||||||
|
|
||||||
expect(0, "interrupt", 0, 0), //
|
expect(0, "interrupt", 0, 0), //
|
||||||
expect(0, "end", 0, 0), //
|
|
||||||
|
|
||||||
expect(1, "event 0", 0, 0), //
|
expect(1, "event 0", 0, 0), //
|
||||||
|
|
||||||
|
expect(0, "end", 0.1f, 0.2f), //
|
||||||
|
|
||||||
expect(1, "event 14", 0.5f, 0.5f), //
|
expect(1, "event 14", 0.5f, 0.5f), //
|
||||||
|
|
||||||
expect(0, "start", 0.1f, 0.8f), //
|
expect(0, "start", 0.1f, 0.8f), //
|
||||||
|
|
||||||
expect(1, "interrupt", 0.8f, 0.8f), //
|
expect(1, "interrupt", 0.8f, 0.8f), //
|
||||||
expect(1, "end", 0.8f, 0.8f), //
|
|
||||||
|
|
||||||
expect(0, "event 0", 0.1f, 0.8f), //
|
expect(0, "event 0", 0.1f, 0.8f), //
|
||||||
|
|
||||||
|
expect(1, "end", 0.8f, 0.9f), //
|
||||||
|
|
||||||
expect(0, "event 14", 0.5f, 1.2f), //
|
expect(0, "event 14", 0.5f, 1.2f), //
|
||||||
expect(0, "event 30", 1, 1.7f), //
|
expect(0, "event 30", 1, 1.7f), //
|
||||||
expect(0, "complete", 1, 1.7f), //
|
expect(0, "complete", 1, 1.7f), //
|
||||||
|
|||||||
@ -144,7 +144,7 @@ public class Animation {
|
|||||||
public void apply (Skeleton skeleton, float lastTime, float time, Array<Event> events, float alpha, boolean setupPose,
|
public void apply (Skeleton skeleton, float lastTime, float time, Array<Event> events, float alpha, boolean setupPose,
|
||||||
boolean mixingOut);
|
boolean mixingOut);
|
||||||
|
|
||||||
public int getId ();
|
public int getPropertyId ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static private enum TimelineType {
|
static private enum TimelineType {
|
||||||
@ -255,7 +255,7 @@ public class Animation {
|
|||||||
frames = new float[frameCount << 1];
|
frames = new float[frameCount << 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return (TimelineType.rotate.ordinal() << 24) + boneIndex;
|
return (TimelineType.rotate.ordinal() << 24) + boneIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,7 +330,7 @@ public class Animation {
|
|||||||
frames = new float[frameCount * ENTRIES];
|
frames = new float[frameCount * ENTRIES];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return (TimelineType.translate.ordinal() << 24) + boneIndex;
|
return (TimelineType.translate.ordinal() << 24) + boneIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -397,7 +397,7 @@ public class Animation {
|
|||||||
super(frameCount);
|
super(frameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return (TimelineType.scale.ordinal() << 24) + boneIndex;
|
return (TimelineType.scale.ordinal() << 24) + boneIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,7 +455,7 @@ public class Animation {
|
|||||||
super(frameCount);
|
super(frameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return (TimelineType.shear.ordinal() << 24) + boneIndex;
|
return (TimelineType.shear.ordinal() << 24) + boneIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,7 +508,7 @@ public class Animation {
|
|||||||
frames = new float[frameCount * ENTRIES];
|
frames = new float[frameCount * ENTRIES];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return (TimelineType.color.ordinal() << 24) + slotIndex;
|
return (TimelineType.color.ordinal() << 24) + slotIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -584,7 +584,7 @@ public class Animation {
|
|||||||
attachmentNames = new String[frameCount];
|
attachmentNames = new String[frameCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return (TimelineType.attachment.ordinal() << 24) + slotIndex;
|
return (TimelineType.attachment.ordinal() << 24) + slotIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,7 +651,7 @@ public class Animation {
|
|||||||
frameVertices = new float[frameCount][];
|
frameVertices = new float[frameCount][];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return (TimelineType.deform.ordinal() << 24) + slotIndex;
|
return (TimelineType.deform.ordinal() << 24) + slotIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -742,7 +742,7 @@ public class Animation {
|
|||||||
events = new Event[frameCount];
|
events = new Event[frameCount];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return TimelineType.event.ordinal() << 24;
|
return TimelineType.event.ordinal() << 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -803,7 +803,7 @@ public class Animation {
|
|||||||
drawOrders = new int[frameCount][];
|
drawOrders = new int[frameCount][];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return TimelineType.drawOrder.ordinal() << 24;
|
return TimelineType.drawOrder.ordinal() << 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -862,7 +862,7 @@ public class Animation {
|
|||||||
frames = new float[frameCount * ENTRIES];
|
frames = new float[frameCount * ENTRIES];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return (TimelineType.ikConstraint.ordinal() << 24) + ikConstraintIndex;
|
return (TimelineType.ikConstraint.ordinal() << 24) + ikConstraintIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -924,7 +924,7 @@ public class Animation {
|
|||||||
frames = new float[frameCount * ENTRIES];
|
frames = new float[frameCount * ENTRIES];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return (TimelineType.transformConstraint.ordinal() << 24) + transformConstraintIndex;
|
return (TimelineType.transformConstraint.ordinal() << 24) + transformConstraintIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -998,7 +998,7 @@ public class Animation {
|
|||||||
frames = new float[frameCount * ENTRIES];
|
frames = new float[frameCount * ENTRIES];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return (TimelineType.pathConstraintPosition.ordinal() << 24) + pathConstraintIndex;
|
return (TimelineType.pathConstraintPosition.ordinal() << 24) + pathConstraintIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1050,7 +1050,7 @@ public class Animation {
|
|||||||
super(frameCount);
|
super(frameCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return (TimelineType.pathConstraintSpacing.ordinal() << 24) + pathConstraintIndex;
|
return (TimelineType.pathConstraintSpacing.ordinal() << 24) + pathConstraintIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1091,7 +1091,7 @@ public class Animation {
|
|||||||
frames = new float[frameCount * ENTRIES];
|
frames = new float[frameCount * ENTRIES];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getId () {
|
public int getPropertyId () {
|
||||||
return (TimelineType.pathConstraintMix.ordinal() << 24) + pathConstraintIndex;
|
return (TimelineType.pathConstraintMix.ordinal() << 24) + pathConstraintIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -53,7 +53,8 @@ public class AnimationState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
private final EventQueue queue = new EventQueue(listeners, trackEntryPool);
|
private final EventQueue queue = new EventQueue(listeners, trackEntryPool);
|
||||||
private final IntSet usage = new IntSet();
|
private final IntSet propertyIDs = new IntSet();
|
||||||
|
private boolean animationsChanged;
|
||||||
private float timeScale = 1;
|
private float timeScale = 1;
|
||||||
|
|
||||||
/** Creates an uninitialized AnimationState. The animation state data must be set before use. */
|
/** Creates an uninitialized AnimationState. The animation state data must be set before use. */
|
||||||
@ -68,7 +69,7 @@ public class AnimationState {
|
|||||||
/** Increments the track entry times, setting queued animations as current if needed. */
|
/** Increments the track entry times, setting queued animations as current if needed. */
|
||||||
public void update (float delta) {
|
public void update (float delta) {
|
||||||
delta *= timeScale;
|
delta *= timeScale;
|
||||||
for (int i = 0; i < tracks.size; i++) {
|
for (int i = 0, n = tracks.size; i < n; i++) {
|
||||||
TrackEntry current = tracks.get(i);
|
TrackEntry current = tracks.get(i);
|
||||||
if (current == null) continue;
|
if (current == null) continue;
|
||||||
|
|
||||||
@ -81,7 +82,7 @@ public class AnimationState {
|
|||||||
current.delay = 0;
|
current.delay = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TrackEntry next = current.next;
|
TrackEntry next = current.next, mixingFrom = current.mixingFrom;
|
||||||
if (next != null) {
|
if (next != null) {
|
||||||
// When the next entry's delay is passed, change to the next entry.
|
// When the next entry's delay is passed, change to the next entry.
|
||||||
float nextTime = current.trackLast - next.delay;
|
float nextTime = current.trackLast - next.delay;
|
||||||
@ -95,23 +96,40 @@ public class AnimationState {
|
|||||||
}
|
}
|
||||||
} else if (current.trackLast >= current.trackEnd) {
|
} else if (current.trackLast >= current.trackEnd) {
|
||||||
// Clear the track when the end time is reached and there is no next entry.
|
// Clear the track when the end time is reached and there is no next entry.
|
||||||
clearTrack(i);
|
// BOZO - This leaves the skeleton in the last pose, with no easy way of resetting.
|
||||||
|
// Should we get rid of the track end time?
|
||||||
|
// Or default it to MAX_VALUE even for non-looping animations?
|
||||||
|
// Or reset the skeleton before clearing? Note only apply() has a skeleton.
|
||||||
|
freeAll(current.next);
|
||||||
|
queue.end(current);
|
||||||
|
if (mixingFrom != null) queue.end(mixingFrom);
|
||||||
|
tracks.set(i, null);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
current.trackTime += currentDelta;
|
current.trackTime += currentDelta;
|
||||||
if (current.mixingFrom != null) {
|
if (mixingFrom != null) {
|
||||||
float mixingFromDelta = delta * current.mixingFrom.timeScale;
|
if (current.mixTime >= current.mixDuration && current.mixTime > 0) {
|
||||||
current.mixingFrom.trackTime += mixingFromDelta;
|
queue.end(mixingFrom);
|
||||||
current.mixTime += mixingFromDelta;
|
current.mixingFrom = null;
|
||||||
|
animationsChanged = true;
|
||||||
|
} else {
|
||||||
|
float mixingFromDelta = delta * mixingFrom.timeScale;
|
||||||
|
mixingFrom.trackTime += mixingFromDelta;
|
||||||
|
current.mixTime += mixingFromDelta;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
queue.drain();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Poses the skeleton using the track entry animations. */
|
/** Poses the skeleton using the track entry animations. */
|
||||||
public void apply (Skeleton skeleton) {
|
public void apply (Skeleton skeleton) {
|
||||||
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
|
if (skeleton == null) throw new IllegalArgumentException("skeleton cannot be null.");
|
||||||
|
|
||||||
|
if (animationsChanged) animationsChanged();
|
||||||
|
|
||||||
Array<Event> events = this.events;
|
Array<Event> events = this.events;
|
||||||
|
|
||||||
for (int i = 0; i < tracks.size; i++) {
|
for (int i = 0; i < tracks.size; i++) {
|
||||||
@ -128,18 +146,18 @@ public class AnimationState {
|
|||||||
if (mix > 1) mix = 1;
|
if (mix > 1) mix = 1;
|
||||||
}
|
}
|
||||||
applyMixingFrom(current.mixingFrom, skeleton, mix);
|
applyMixingFrom(current.mixingFrom, skeleton, mix);
|
||||||
if (mix == 1) {
|
|
||||||
queue.end(current.mixingFrom);
|
|
||||||
current.mixingFrom = null;
|
|
||||||
updateSetupPose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float animationLast = current.animationLast, animationTime = current.getAnimationTime();
|
float animationLast = current.animationLast, animationTime = current.getAnimationTime();
|
||||||
Array<Timeline> timelines = current.animation.timelines;
|
Array<Timeline> timelines = current.animation.timelines;
|
||||||
BooleanArray setupPose = current.setupPose;
|
if (mix == 1) {
|
||||||
for (int ii = 0, n = timelines.size; ii < n; ii++)
|
for (int ii = 0, n = timelines.size; ii < n; ii++)
|
||||||
timelines.get(ii).apply(skeleton, animationLast, animationTime, events, mix, setupPose.get(ii), false);
|
timelines.get(ii).apply(skeleton, animationLast, animationTime, events, 1, false, false);
|
||||||
|
} else {
|
||||||
|
boolean[] timelinesFirst = current.timelinesFirst.items;
|
||||||
|
for (int ii = 0, n = timelines.size; ii < n; ii++)
|
||||||
|
timelines.get(ii).apply(skeleton, animationLast, animationTime, events, mix, timelinesFirst[ii], false);
|
||||||
|
}
|
||||||
queueEvents(current, animationTime);
|
queueEvents(current, animationTime);
|
||||||
current.animationLast = animationTime;
|
current.animationLast = animationTime;
|
||||||
current.trackLast = current.trackTime;
|
current.trackLast = current.trackTime;
|
||||||
@ -154,12 +172,12 @@ public class AnimationState {
|
|||||||
|
|
||||||
float animationLast = entry.animationLast, animationTime = entry.getAnimationTime();
|
float animationLast = entry.animationLast, animationTime = entry.getAnimationTime();
|
||||||
Array<Timeline> timelines = entry.animation.timelines;
|
Array<Timeline> timelines = entry.animation.timelines;
|
||||||
BooleanArray setupPose = entry.setupPose;
|
boolean[] timelinesFirst = entry.timelinesFirst.items;
|
||||||
float alphaFull = entry.alpha, alphaMix = entry.alpha * (1 - mix);
|
float alphaFull = entry.alpha, alphaMix = entry.alpha * (1 - mix);
|
||||||
if (attachments && drawOrder) {
|
if (attachments && drawOrder) {
|
||||||
for (int i = 0, n = timelines.size; i < n; i++) {
|
for (int i = 0, n = timelines.size; i < n; i++) {
|
||||||
Timeline timeline = timelines.get(i);
|
Timeline timeline = timelines.get(i);
|
||||||
if (setupPose.get(i))
|
if (timelinesFirst[i])
|
||||||
timeline.apply(skeleton, animationLast, animationTime, events, alphaMix, true, true);
|
timeline.apply(skeleton, animationLast, animationTime, events, alphaMix, true, true);
|
||||||
else
|
else
|
||||||
timeline.apply(skeleton, animationLast, animationTime, events, alphaFull, false, false);
|
timeline.apply(skeleton, animationLast, animationTime, events, alphaFull, false, false);
|
||||||
@ -167,12 +185,13 @@ public class AnimationState {
|
|||||||
} else {
|
} else {
|
||||||
for (int i = 0, n = timelines.size; i < n; i++) {
|
for (int i = 0, n = timelines.size; i < n; i++) {
|
||||||
Timeline timeline = timelines.get(i);
|
Timeline timeline = timelines.get(i);
|
||||||
if (!attachments && timeline instanceof AttachmentTimeline) continue;
|
if (timelinesFirst[i])
|
||||||
if (!drawOrder && timeline instanceof DrawOrderTimeline) continue;
|
|
||||||
if (setupPose.get(i))
|
|
||||||
timeline.apply(skeleton, animationLast, animationTime, events, alphaMix, true, true);
|
timeline.apply(skeleton, animationLast, animationTime, events, alphaMix, true, true);
|
||||||
else
|
else {
|
||||||
|
if (!attachments && timeline instanceof AttachmentTimeline) continue;
|
||||||
|
if (!drawOrder && timeline instanceof DrawOrderTimeline) continue;
|
||||||
timeline.apply(skeleton, animationLast, animationTime, events, alphaFull, false, false);
|
timeline.apply(skeleton, animationLast, animationTime, events, alphaFull, false, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,6 +236,7 @@ public class AnimationState {
|
|||||||
tracks.clear();
|
tracks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BOZO - This leaves the skeleton in the last pose, with no easy way of resetting.
|
||||||
public void clearTrack (int trackIndex) {
|
public void clearTrack (int trackIndex) {
|
||||||
if (trackIndex >= tracks.size) return;
|
if (trackIndex >= tracks.size) return;
|
||||||
TrackEntry current = tracks.get(trackIndex);
|
TrackEntry current = tracks.get(trackIndex);
|
||||||
@ -268,60 +288,50 @@ public class AnimationState {
|
|||||||
if (mixingFrom != null) queue.end(mixingFrom);
|
if (mixingFrom != null) queue.end(mixingFrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
queue.drain();
|
animationsChanged = true;
|
||||||
|
|
||||||
updateSetupPose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSetupPose () {
|
private void animationsChanged () {
|
||||||
usage.clear();
|
animationsChanged = false;
|
||||||
|
propertyIDs.clear();
|
||||||
int i = 0, n = tracks.size;
|
int i = 0, n = tracks.size;
|
||||||
for (; i < n; i++) {
|
for (; i < n; i++) {
|
||||||
TrackEntry entry = tracks.get(i);
|
TrackEntry entry = tracks.get(i);
|
||||||
if (entry == null) continue;
|
if (entry == null) continue;
|
||||||
if (entry.mixingFrom != null) {
|
if (entry.mixingFrom != null) {
|
||||||
updateFirstSetupPose(entry.mixingFrom);
|
setTimelinesFirst(entry.mixingFrom);
|
||||||
updateSetupPose(entry);
|
checkTimelinesFirst(entry);
|
||||||
} else
|
} else
|
||||||
updateFirstSetupPose(entry);
|
setTimelinesFirst(entry);
|
||||||
i++;
|
i++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (; i < n; i++) {
|
for (; i < n; i++) {
|
||||||
TrackEntry entry = tracks.get(i);
|
TrackEntry entry = tracks.get(i);
|
||||||
if (entry == null) continue;
|
if (entry == null) continue;
|
||||||
if (entry.mixingFrom != null) updateSetupPose(entry.mixingFrom);
|
if (entry.mixingFrom != null) checkTimelinesFirst(entry.mixingFrom);
|
||||||
updateSetupPose(entry);
|
checkTimelinesFirst(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateFirstSetupPose (TrackEntry entry) {
|
private void setTimelinesFirst (TrackEntry entry) {
|
||||||
IntSet usage = this.usage;
|
IntSet propertyIDs = this.propertyIDs;
|
||||||
BooleanArray setupPose = entry.setupPose;
|
|
||||||
setupPose.clear();
|
|
||||||
Array<Timeline> timelines = entry.animation.timelines;
|
Array<Timeline> timelines = entry.animation.timelines;
|
||||||
for (int ii = 0, nn = timelines.size; ii < nn; ii++) {
|
int n = timelines.size;
|
||||||
Timeline timeline = timelines.get(ii);
|
boolean[] timelinesFirst = entry.timelinesFirst.setSize(n);
|
||||||
usage.add(timeline.getId());
|
for (int i = 0; i < n; i++) {
|
||||||
setupPose.add(true);
|
propertyIDs.add(timelines.get(i).getPropertyId());
|
||||||
|
timelinesFirst[i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSetupPose (TrackEntry entry) {
|
private void checkTimelinesFirst (TrackEntry entry) {
|
||||||
IntSet usage = this.usage;
|
IntSet propertyIDs = this.propertyIDs;
|
||||||
BooleanArray setupPose = entry.setupPose;
|
|
||||||
setupPose.clear();
|
|
||||||
Array<Timeline> timelines = entry.animation.timelines;
|
Array<Timeline> timelines = entry.animation.timelines;
|
||||||
for (int ii = 0, nn = timelines.size; ii < nn; ii++) {
|
int n = timelines.size;
|
||||||
Timeline timeline = timelines.get(ii);
|
boolean[] timelinesFirst = entry.timelinesFirst.setSize(n);
|
||||||
int id = timeline.getId();
|
for (int i = 0; i < n; i++)
|
||||||
if (usage.contains(id))
|
timelinesFirst[i] = propertyIDs.add(timelines.get(i).getPropertyId());
|
||||||
setupPose.add(false);
|
|
||||||
else {
|
|
||||||
usage.add(id);
|
|
||||||
setupPose.add(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @see #setAnimation(int, Animation, boolean) */
|
/** @see #setAnimation(int, Animation, boolean) */
|
||||||
@ -340,13 +350,15 @@ public class AnimationState {
|
|||||||
if (animation == null) throw new IllegalArgumentException("animation cannot be null.");
|
if (animation == null) throw new IllegalArgumentException("animation cannot be null.");
|
||||||
TrackEntry current = expandToIndex(trackIndex);
|
TrackEntry current = expandToIndex(trackIndex);
|
||||||
TrackEntry entry = trackEntry(trackIndex, animation, loop, current);
|
TrackEntry entry = trackEntry(trackIndex, animation, loop, current);
|
||||||
if (current == null)
|
if (current == null) {
|
||||||
setCurrent(trackIndex, entry);
|
setCurrent(trackIndex, entry);
|
||||||
else {
|
queue.drain();
|
||||||
|
} else {
|
||||||
freeAll(current.next);
|
freeAll(current.next);
|
||||||
if (current.trackLast == -1) // If current was never applied, replace it.
|
if (current.trackLast == -1) { // If current was never applied, replace it.
|
||||||
setCurrent(trackIndex, entry);
|
setCurrent(trackIndex, entry);
|
||||||
else {
|
queue.drain();
|
||||||
|
} else {
|
||||||
current.next = entry;
|
current.next = entry;
|
||||||
entry.delay = current.trackLast;
|
entry.delay = current.trackLast;
|
||||||
}
|
}
|
||||||
@ -377,9 +389,10 @@ public class AnimationState {
|
|||||||
|
|
||||||
TrackEntry entry = trackEntry(trackIndex, animation, loop, last);
|
TrackEntry entry = trackEntry(trackIndex, animation, loop, last);
|
||||||
|
|
||||||
if (last == null)
|
if (last == null) {
|
||||||
setCurrent(trackIndex, entry);
|
setCurrent(trackIndex, entry);
|
||||||
else {
|
queue.drain();
|
||||||
|
} else {
|
||||||
last.next = entry;
|
last.next = entry;
|
||||||
if (delay <= 0) {
|
if (delay <= 0) {
|
||||||
float duration = last.animationEnd - last.animationStart;
|
float duration = last.animationEnd - last.animationStart;
|
||||||
@ -402,7 +415,7 @@ public class AnimationState {
|
|||||||
entry.loop = loop;
|
entry.loop = loop;
|
||||||
|
|
||||||
entry.eventThreshold = 0;
|
entry.eventThreshold = 0;
|
||||||
entry.attachmentThreshold = 1;
|
entry.attachmentThreshold = 0;
|
||||||
entry.drawOrderThreshold = 0;
|
entry.drawOrderThreshold = 0;
|
||||||
|
|
||||||
entry.delay = 0;
|
entry.delay = 0;
|
||||||
@ -496,14 +509,14 @@ public class AnimationState {
|
|||||||
float delay, trackTime, trackLast, trackEnd, animationStart, animationEnd, animationLast, timeScale;
|
float delay, trackTime, trackLast, trackEnd, animationStart, animationEnd, animationLast, timeScale;
|
||||||
float alpha;
|
float alpha;
|
||||||
float mixTime, mixDuration;
|
float mixTime, mixDuration;
|
||||||
final BooleanArray setupPose = new BooleanArray();
|
final BooleanArray timelinesFirst = new BooleanArray();
|
||||||
|
|
||||||
public void reset () {
|
public void reset () {
|
||||||
next = null;
|
next = null;
|
||||||
mixingFrom = null;
|
mixingFrom = null;
|
||||||
animation = null;
|
animation = null;
|
||||||
listener = null;
|
listener = null;
|
||||||
setupPose.clear();
|
timelinesFirst.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTrackIndex () {
|
public int getTrackIndex () {
|
||||||
@ -538,7 +551,8 @@ public class AnimationState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Current time in seconds this track entry has been the current track entry. The track time determines
|
/** Current time in seconds this track entry has been the current track entry. The track time determines
|
||||||
* {@link #getAnimationTime()} and can be set to start the animation at a time other than 0. */
|
* {@link #getAnimationTime()}. The track time can be set to start the animation at a time other than 0, without affecting
|
||||||
|
* looping. */
|
||||||
public float getTrackTime () {
|
public float getTrackTime () {
|
||||||
return trackTime;
|
return trackTime;
|
||||||
}
|
}
|
||||||
@ -548,8 +562,8 @@ public class AnimationState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** The track time in seconds when this animation will be removed from the track. If the track end time is reached and no
|
/** The track time in seconds when this animation will be removed from the track. If the track end time is reached and no
|
||||||
* other animations are queued for playback, the track is cleared. Defaults to the animation duration for non-looping
|
* other animations are queued for playback, the track is cleared, leaving the skeleton in the last applied pose. Defaults
|
||||||
* animations and to {@link Integer#MAX_VALUE} for looping animations. */
|
* to the animation duration for non-looping animations and to {@link Integer#MAX_VALUE} for looping animations. */
|
||||||
public float getTrackEnd () {
|
public float getTrackEnd () {
|
||||||
return trackEnd;
|
return trackEnd;
|
||||||
}
|
}
|
||||||
@ -560,8 +574,8 @@ public class AnimationState {
|
|||||||
|
|
||||||
/** Seconds when this animation starts, both initially and after looping. Defaults to 0.
|
/** Seconds when this animation starts, both initially and after looping. Defaults to 0.
|
||||||
* <p>
|
* <p>
|
||||||
* When changing the animation start time, it often makes sense to also change {@link #getAnimationLast()} to control when
|
* When changing the animation start time, it often makes sense to also change {@link #getAnimationLast()} to control which
|
||||||
* timelines will trigger. */
|
* timeline keys will trigger. */
|
||||||
public float getAnimationStart () {
|
public float getAnimationStart () {
|
||||||
return animationStart;
|
return animationStart;
|
||||||
}
|
}
|
||||||
@ -581,8 +595,8 @@ public class AnimationState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this
|
/** The time in seconds this animation was last applied. Some timelines use this for one-time triggers. Eg, when this
|
||||||
* animation is applied, event timelines will fire all events between lastTime (exclusive) and time (inclusive). Defaults to
|
* animation is applied, event timelines will fire all events between the animation last time (exclusive) and animation time
|
||||||
* -1 to ensure triggers on frame 0 happen the first time this animation is applied. */
|
* (inclusive). Defaults to -1 to ensure triggers on frame 0 happen the first time this animation is applied. */
|
||||||
public float getAnimationLast () {
|
public float getAnimationLast () {
|
||||||
return animationLast;
|
return animationLast;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user