AnimationState, added attachment threshold. Defaults changed to NOT apply attachment timelines or fire events for an animation being mixed out.

#621
This commit is contained in:
NathanSweet 2016-08-18 14:46:15 +02:00
parent b020bc0d44
commit cc4f19da98
3 changed files with 64 additions and 26 deletions

View File

@ -233,14 +233,11 @@ public class AnimationStateTest {
expect(1, "start", 0.1f, 1), //
expect(0, "interrupt", 1, 1), //
expect(0, "event 30", 1, 1), //
expect(0, "complete 1", 1, 1), //
expect(0, "event 0", 1, 1), //
expect(1, "event 0", 0.1f, 1), //
expect(1, "event 14", 0.5f, 1.4f), //
expect(0, "event 14", 1.5f, 1.5f), //
expect(0, "end", 1.6f, 1.6f), //
expect(1, "event 30", 1, 1.9f), //
@ -259,12 +256,10 @@ public class AnimationStateTest {
expect(1, "start", 0.1f, 0.5f), //
expect(0, "interrupt", 0.5f, 0.5f), //
expect(0, "event 14", 0.5f, 0.5f), //
expect(1, "event 0", 0.1f, 0.5f), //
expect(1, "event 14", 0.5f, 0.9f), //
expect(0, "event 30", 1, 1), //
expect(0, "complete 1", 1, 1), //
expect(0, "end", 1.1f, 1.1f), //
@ -307,10 +302,12 @@ public class AnimationStateTest {
expect(1, "start", 0.1f, 0.5f), //
expect(0, "interrupt", 0.5f, 0.5f), //
expect(0, "event 14", 0.5f, 0.5f), //
expect(1, "event 0", 0.1f, 0.5f), //
expect(1, "event 14", 0.5f, 0.9f), //
expect(0, "event 30", 1, 1), //
expect(0, "complete 1", 1, 1), //
expect(0, "end", 1.1f, 1.1f), //
@ -318,7 +315,7 @@ public class AnimationStateTest {
expect(1, "complete 1", 1, 1.4f), //
expect(1, "end", 1, 1.5f) //
);
state.setDefaultEventThreshold(0f);
state.setDefaultEventThreshold(1);
state.setAnimation(0, "events1", false);
state.addAnimation(0, "events2", false, 0.4f);
run(0.1f, 1000);
@ -334,7 +331,7 @@ public class AnimationStateTest {
time = 0;
fail = false;
buffer.setLength(0);
buffer.append(String.format("%-12s%-8s%-8s%-8s%s\n", "", "anim", "track", "total", "result"));
buffer.append(String.format("%-12s%-8s%-8s%-8s%s\n", "#" + test, "anim", "track", "total", "result"));
}
void run (float incr, float endTime) {
@ -349,8 +346,8 @@ public class AnimationStateTest {
actual.clear();
expected.clear();
if (fail) {
System.out.println("Test failed: " + test);
System.out.println(buffer);
System.out.println("TEST FAILED!");
System.exit(0);
}
System.out.println(buffer);

View File

@ -40,8 +40,8 @@ import com.esotericsoftware.spine.attachments.VertexAttachment;
public class Animation {
final String name;
private final Array<Timeline> timelines;
private float duration;
final Array<Timeline> timelines;
float duration;
public Animation (String name, Array<Timeline> timelines, float duration) {
if (name == null) throw new IllegalArgumentException("name cannot be null.");

View File

@ -35,6 +35,8 @@ import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.IntArray;
import com.badlogic.gdx.utils.Pool;
import com.badlogic.gdx.utils.Pool.Poolable;
import com.esotericsoftware.spine.Animation.AttachmentTimeline;
import com.esotericsoftware.spine.Animation.Timeline;
/** Stores state for an animation and automatically mixes between animations. */
public class AnimationState {
@ -44,7 +46,7 @@ public class AnimationState {
private final EventQueue queue = new EventQueue();
final Array<AnimationStateListener> listeners = new Array();
private float timeScale = 1;
private float defaultEventThreshold = 1;
private float defaultEventThreshold, defaultAttachmentThreshold;
final Pool<TrackEntry> trackEntryPool = new Pool() {
protected Object newObject () {
@ -103,21 +105,13 @@ public class AnimationState {
TrackEntry current = tracks.get(i);
if (current == null) continue;
float time = current.time, lastTime = current.lastTime, endTime = current.endTime, mix = current.mix;
float time = current.time, lastTime = current.lastTime, endTime = current.endTime, mix = current.alpha;
boolean loop = current.loop;
if (!loop && time > endTime) time = endTime;
TrackEntry previous = current.previous;
if (previous != null) {
if (current.previous != null) {
mix *= current.mixTime / current.mixDuration;
Array<Event> previousEvents = mix < previous.eventThreshold ? events : null;
float previousTime = previous.time;
if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime;
previous.animation.mix(skeleton, previous.lastTime, previousTime, previous.loop, previousEvents, previous.mix);
queueEvents(previous, previous.lastTime, previousTime, previous.endTime);
previous.lastTime = previousTime;
applyPrevious(current.previous, skeleton, mix);
if (mix >= 1) {
mix = 1;
queue.end(current.previous);
@ -133,6 +127,35 @@ public class AnimationState {
queue.drain();
}
private void applyPrevious (TrackEntry previous, Skeleton skeleton, float mix) {
float previousTime = previous.time;
if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime;
float lastTime = previous.lastTime, time = previousTime, alpha = previous.alpha;
Animation animation = previous.animation;
if (previous.loop && animation.duration != 0) {
time %= animation.duration;
if (lastTime > 0) lastTime %= animation.duration;
}
Array<Event> events = mix < previous.eventThreshold ? this.events : null;
Array<Timeline> timelines = animation.timelines;
if (mix < previous.attachmentThreshold) {
for (int i = 0, n = timelines.size; i < n; i++)
timelines.get(i).apply(skeleton, lastTime, time, events, alpha);
} else {
for (int i = 0, n = timelines.size; i < n; i++) {
Timeline timeline = timelines.get(i);
if (timeline instanceof AttachmentTimeline) continue;
timeline.apply(skeleton, lastTime, time, events, alpha);
}
}
queueEvents(previous, previous.lastTime, previousTime, previous.endTime);
previous.lastTime = previousTime;
}
private void queueEvents (TrackEntry entry, float lastTime, float time, float endTime) {
Array<Event> events = this.events;
int n = events.size;
@ -240,6 +263,7 @@ public class AnimationState {
entry.loop = loop;
entry.endTime = animation.getDuration();
entry.eventThreshold = defaultEventThreshold;
entry.attachmentThreshold = defaultAttachmentThreshold;
setCurrent(trackIndex, entry);
queue.drain();
@ -261,6 +285,7 @@ public class AnimationState {
entry.loop = loop;
entry.endTime = animation.getDuration();
entry.eventThreshold = defaultEventThreshold;
entry.attachmentThreshold = defaultAttachmentThreshold;
TrackEntry last = expandToIndex(trackIndex);
if (last != null) {
@ -322,6 +347,14 @@ public class AnimationState {
this.defaultEventThreshold = defaultEventThreshold;
}
public float getDefaultAttachmentThreshold () {
return defaultAttachmentThreshold;
}
public void setDefaultAttachmentThreshold (float defaultAttachmentThreshold) {
this.defaultAttachmentThreshold = defaultAttachmentThreshold;
}
public AnimationStateData getData () {
return data;
}
@ -352,10 +385,10 @@ public class AnimationState {
TrackEntry next, previous;
Animation animation;
boolean loop;
float delay, time, lastTime = -1, endTime, timeScale = 1, eventThreshold;
float delay, time, lastTime = -1, endTime, timeScale = 1, eventThreshold, attachmentThreshold;
float mixTime, mixDuration;
AnimationStateListener listener;
float mix = 1;
float alpha = 1;
public void reset () {
next = null;
@ -424,11 +457,11 @@ public class AnimationState {
}
public float getMix () {
return mix;
return alpha;
}
public void setMix (float mix) {
this.mix = mix;
this.alpha = mix;
}
public float getTimeScale () {
@ -447,6 +480,14 @@ public class AnimationState {
this.eventThreshold = eventThreshold;
}
public float getAttachmentThreshold () {
return attachmentThreshold;
}
public void setAttachmentThreshold (float attachmentThreshold) {
this.attachmentThreshold = attachmentThreshold;
}
public TrackEntry getNext () {
return next;
}