mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-10 00:58:43 +08:00
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:
parent
b020bc0d44
commit
cc4f19da98
@ -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);
|
||||
|
||||
@ -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.");
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user