|
@@ -43,6 +43,7 @@ import com.badlogic.gdx.utils.Pool;
|
|
import com.badlogic.gdx.utils.Pool.Poolable;
|
|
import com.badlogic.gdx.utils.Pool.Poolable;
|
|
import com.esotericsoftware.spine.Animation.AttachmentTimeline;
|
|
import com.esotericsoftware.spine.Animation.AttachmentTimeline;
|
|
import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
|
|
import com.esotericsoftware.spine.Animation.DrawOrderTimeline;
|
|
|
|
+import com.esotericsoftware.spine.Animation.EventTimeline;
|
|
import com.esotericsoftware.spine.Animation.MixBlend;
|
|
import com.esotericsoftware.spine.Animation.MixBlend;
|
|
import com.esotericsoftware.spine.Animation.MixDirection;
|
|
import com.esotericsoftware.spine.Animation.MixDirection;
|
|
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
|
import com.esotericsoftware.spine.Animation.RotateTimeline;
|
|
@@ -79,6 +80,12 @@ public class AnimationState {
|
|
* (which affects B and C). Without using D to mix out, A would be applied fully until mixing completes, then snap into
|
|
* (which affects B and C). Without using D to mix out, A would be applied fully until mixing completes, then snap into
|
|
* place. */
|
|
* place. */
|
|
static private final int HOLD_MIX = 3;
|
|
static private final int HOLD_MIX = 3;
|
|
|
|
+ /** 1) An attachment timeline in a subsequent track entry sets the attachment for the same slot as this attachment
|
|
|
|
+ * timeline.<br>
|
|
|
|
+ * Result: This attachment timeline will not use MixDirection.out, which would otherwise show the setup mode attachment (or
|
|
|
|
+ * none if not visible in setup mode). This allows deform timelines to be applied for the subsequent entry to mix from, rather
|
|
|
|
+ * than mixing from the setup pose. */
|
|
|
|
+ static private final int NOT_LAST = 4;
|
|
|
|
|
|
private AnimationStateData data;
|
|
private AnimationStateData data;
|
|
final Array<TrackEntry> tracks = new Array();
|
|
final Array<TrackEntry> tracks = new Array();
|
|
@@ -229,7 +236,7 @@ public class AnimationState {
|
|
|
|
|
|
for (int ii = 0; ii < timelineCount; ii++) {
|
|
for (int ii = 0; ii < timelineCount; ii++) {
|
|
Timeline timeline = (Timeline)timelines[ii];
|
|
Timeline timeline = (Timeline)timelines[ii];
|
|
- MixBlend timelineBlend = timelineMode[ii] == SUBSEQUENT ? blend : MixBlend.setup;
|
|
|
|
|
|
+ MixBlend timelineBlend = (timelineMode[ii] & NOT_LAST - 1) == SUBSEQUENT ? blend : MixBlend.setup;
|
|
if (timeline instanceof RotateTimeline) {
|
|
if (timeline instanceof RotateTimeline) {
|
|
applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1,
|
|
applyRotateTimeline(timeline, skeleton, animationTime, mix, timelineBlend, timelinesRotation, ii << 1,
|
|
firstFrame);
|
|
firstFrame);
|
|
@@ -285,7 +292,7 @@ public class AnimationState {
|
|
MixDirection direction = MixDirection.out;
|
|
MixDirection direction = MixDirection.out;
|
|
MixBlend timelineBlend;
|
|
MixBlend timelineBlend;
|
|
float alpha;
|
|
float alpha;
|
|
- switch (timelineMode[i]) {
|
|
|
|
|
|
+ switch (timelineMode[i] & NOT_LAST - 1) {
|
|
case SUBSEQUENT:
|
|
case SUBSEQUENT:
|
|
if (!attachments && timeline instanceof AttachmentTimeline) continue;
|
|
if (!attachments && timeline instanceof AttachmentTimeline) continue;
|
|
if (!drawOrder && timeline instanceof DrawOrderTimeline) continue;
|
|
if (!drawOrder && timeline instanceof DrawOrderTimeline) continue;
|
|
@@ -313,7 +320,7 @@ public class AnimationState {
|
|
} else {
|
|
} else {
|
|
if (timelineBlend == MixBlend.setup) {
|
|
if (timelineBlend == MixBlend.setup) {
|
|
if (timeline instanceof AttachmentTimeline) {
|
|
if (timeline instanceof AttachmentTimeline) {
|
|
- if (attachments) direction = MixDirection.in;
|
|
|
|
|
|
+ if (attachments || (timelineMode[i] & NOT_LAST) == NOT_LAST) direction = MixDirection.in;
|
|
} else if (timeline instanceof DrawOrderTimeline) {
|
|
} else if (timeline instanceof DrawOrderTimeline) {
|
|
if (drawOrder) direction = MixDirection.in;
|
|
if (drawOrder) direction = MixDirection.in;
|
|
}
|
|
}
|
|
@@ -688,22 +695,31 @@ public class AnimationState {
|
|
private void animationsChanged () {
|
|
private void animationsChanged () {
|
|
animationsChanged = false;
|
|
animationsChanged = false;
|
|
|
|
|
|
|
|
+ // Process in the order that animations are applied.
|
|
propertyIDs.clear(2048);
|
|
propertyIDs.clear(2048);
|
|
-
|
|
|
|
for (int i = 0, n = tracks.size; i < n; i++) {
|
|
for (int i = 0, n = tracks.size; i < n; i++) {
|
|
TrackEntry entry = tracks.get(i);
|
|
TrackEntry entry = tracks.get(i);
|
|
if (entry == null) continue;
|
|
if (entry == null) continue;
|
|
- // Move to last entry, then iterate in reverse (the order animations are applied).
|
|
|
|
- while (entry.mixingFrom != null)
|
|
|
|
|
|
+ while (entry.mixingFrom != null) // Move to last entry, then iterate in reverse.
|
|
entry = entry.mixingFrom;
|
|
entry = entry.mixingFrom;
|
|
do {
|
|
do {
|
|
- if (entry.mixingTo == null || entry.mixBlend != MixBlend.add) setTimelineModes(entry);
|
|
|
|
|
|
+ if (entry.mixingTo == null || entry.mixBlend != MixBlend.add) computeHold(entry);
|
|
entry = entry.mixingTo;
|
|
entry = entry.mixingTo;
|
|
} while (entry != null);
|
|
} while (entry != null);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // Process in the reverse order that animations are applied.
|
|
|
|
+ propertyIDs.clear(2048);
|
|
|
|
+ for (int i = tracks.size - 1; i >= 0; i--) {
|
|
|
|
+ TrackEntry entry = tracks.get(i);
|
|
|
|
+ do {
|
|
|
|
+ computeNotLast(entry);
|
|
|
|
+ entry = entry.mixingFrom;
|
|
|
|
+ } while (entry != null);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
- private void setTimelineModes (TrackEntry entry) {
|
|
|
|
|
|
+ private void computeHold (TrackEntry entry) {
|
|
TrackEntry to = entry.mixingTo;
|
|
TrackEntry to = entry.mixingTo;
|
|
Object[] timelines = entry.animation.timelines.items;
|
|
Object[] timelines = entry.animation.timelines.items;
|
|
int timelinesCount = entry.animation.timelines.size;
|
|
int timelinesCount = entry.animation.timelines.size;
|
|
@@ -722,12 +738,14 @@ public class AnimationState {
|
|
|
|
|
|
outer:
|
|
outer:
|
|
for (int i = 0; i < timelinesCount; i++) {
|
|
for (int i = 0; i < timelinesCount; i++) {
|
|
- int id = ((Timeline)timelines[i]).getPropertyId();
|
|
|
|
|
|
+ Timeline timeline = (Timeline)timelines[i];
|
|
|
|
+ int id = timeline.getPropertyId();
|
|
if (!propertyIDs.add(id))
|
|
if (!propertyIDs.add(id))
|
|
timelineMode[i] = SUBSEQUENT;
|
|
timelineMode[i] = SUBSEQUENT;
|
|
- else if (to == null || !hasTimeline(to, id))
|
|
|
|
|
|
+ else if (to == null || timeline instanceof AttachmentTimeline || timeline instanceof DrawOrderTimeline
|
|
|
|
+ || timeline instanceof EventTimeline || !hasTimeline(to, id)) {
|
|
timelineMode[i] = FIRST;
|
|
timelineMode[i] = FIRST;
|
|
- else {
|
|
|
|
|
|
+ } else {
|
|
for (TrackEntry next = to.mixingTo; next != null; next = next.mixingTo) {
|
|
for (TrackEntry next = to.mixingTo; next != null; next = next.mixingTo) {
|
|
if (hasTimeline(next, id)) continue;
|
|
if (hasTimeline(next, id)) continue;
|
|
if (next.mixDuration > 0) {
|
|
if (next.mixDuration > 0) {
|
|
@@ -742,6 +760,20 @@ public class AnimationState {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private void computeNotLast (TrackEntry entry) {
|
|
|
|
+ Object[] timelines = entry.animation.timelines.items;
|
|
|
|
+ int timelinesCount = entry.animation.timelines.size;
|
|
|
|
+ int[] timelineMode = entry.timelineMode.items;
|
|
|
|
+ IntSet propertyIDs = this.propertyIDs;
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < timelinesCount; i++) {
|
|
|
|
+ if (timelines[i] instanceof AttachmentTimeline) {
|
|
|
|
+ AttachmentTimeline timeline = (AttachmentTimeline)timelines[i];
|
|
|
|
+ if (!propertyIDs.add(timeline.slotIndex)) timelineMode[i] |= NOT_LAST;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
private boolean hasTimeline (TrackEntry entry, int id) {
|
|
private boolean hasTimeline (TrackEntry entry, int id) {
|
|
Object[] timelines = entry.animation.timelines.items;
|
|
Object[] timelines = entry.animation.timelines.items;
|
|
for (int i = 0, n = entry.animation.timelines.size; i < n; i++)
|
|
for (int i = 0, n = entry.animation.timelines.size; i < n; i++)
|