mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +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(1, "start", 0.1f, 1), //
|
||||||
|
|
||||||
expect(0, "interrupt", 1, 1), //
|
expect(0, "interrupt", 1, 1), //
|
||||||
expect(0, "event 30", 1, 1), //
|
|
||||||
expect(0, "complete 1", 1, 1), //
|
expect(0, "complete 1", 1, 1), //
|
||||||
expect(0, "event 0", 1, 1), //
|
|
||||||
|
|
||||||
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, "event 14", 1.5f, 1.5f), //
|
|
||||||
expect(0, "end", 1.6f, 1.6f), //
|
expect(0, "end", 1.6f, 1.6f), //
|
||||||
|
|
||||||
expect(1, "event 30", 1, 1.9f), //
|
expect(1, "event 30", 1, 1.9f), //
|
||||||
@ -259,12 +256,10 @@ public class AnimationStateTest {
|
|||||||
expect(1, "start", 0.1f, 0.5f), //
|
expect(1, "start", 0.1f, 0.5f), //
|
||||||
|
|
||||||
expect(0, "interrupt", 0.5f, 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 0", 0.1f, 0.5f), //
|
||||||
expect(1, "event 14", 0.5f, 0.9f), //
|
expect(1, "event 14", 0.5f, 0.9f), //
|
||||||
|
|
||||||
expect(0, "event 30", 1, 1), //
|
|
||||||
expect(0, "complete 1", 1, 1), //
|
expect(0, "complete 1", 1, 1), //
|
||||||
expect(0, "end", 1.1f, 1.1f), //
|
expect(0, "end", 1.1f, 1.1f), //
|
||||||
|
|
||||||
@ -307,10 +302,12 @@ public class AnimationStateTest {
|
|||||||
expect(1, "start", 0.1f, 0.5f), //
|
expect(1, "start", 0.1f, 0.5f), //
|
||||||
|
|
||||||
expect(0, "interrupt", 0.5f, 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 0", 0.1f, 0.5f), //
|
||||||
expect(1, "event 14", 0.5f, 0.9f), //
|
expect(1, "event 14", 0.5f, 0.9f), //
|
||||||
|
|
||||||
|
expect(0, "event 30", 1, 1), //
|
||||||
expect(0, "complete 1", 1, 1), //
|
expect(0, "complete 1", 1, 1), //
|
||||||
expect(0, "end", 1.1f, 1.1f), //
|
expect(0, "end", 1.1f, 1.1f), //
|
||||||
|
|
||||||
@ -318,7 +315,7 @@ public class AnimationStateTest {
|
|||||||
expect(1, "complete 1", 1, 1.4f), //
|
expect(1, "complete 1", 1, 1.4f), //
|
||||||
expect(1, "end", 1, 1.5f) //
|
expect(1, "end", 1, 1.5f) //
|
||||||
);
|
);
|
||||||
state.setDefaultEventThreshold(0f);
|
state.setDefaultEventThreshold(1);
|
||||||
state.setAnimation(0, "events1", false);
|
state.setAnimation(0, "events1", false);
|
||||||
state.addAnimation(0, "events2", false, 0.4f);
|
state.addAnimation(0, "events2", false, 0.4f);
|
||||||
run(0.1f, 1000);
|
run(0.1f, 1000);
|
||||||
@ -334,7 +331,7 @@ public class AnimationStateTest {
|
|||||||
time = 0;
|
time = 0;
|
||||||
fail = false;
|
fail = false;
|
||||||
buffer.setLength(0);
|
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) {
|
void run (float incr, float endTime) {
|
||||||
@ -349,8 +346,8 @@ public class AnimationStateTest {
|
|||||||
actual.clear();
|
actual.clear();
|
||||||
expected.clear();
|
expected.clear();
|
||||||
if (fail) {
|
if (fail) {
|
||||||
System.out.println("Test failed: " + test);
|
|
||||||
System.out.println(buffer);
|
System.out.println(buffer);
|
||||||
|
System.out.println("TEST FAILED!");
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
System.out.println(buffer);
|
System.out.println(buffer);
|
||||||
|
|||||||
@ -40,8 +40,8 @@ import com.esotericsoftware.spine.attachments.VertexAttachment;
|
|||||||
|
|
||||||
public class Animation {
|
public class Animation {
|
||||||
final String name;
|
final String name;
|
||||||
private final Array<Timeline> timelines;
|
final Array<Timeline> timelines;
|
||||||
private float duration;
|
float duration;
|
||||||
|
|
||||||
public Animation (String name, Array<Timeline> timelines, float duration) {
|
public Animation (String name, Array<Timeline> timelines, float duration) {
|
||||||
if (name == null) throw new IllegalArgumentException("name cannot be null.");
|
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.IntArray;
|
||||||
import com.badlogic.gdx.utils.Pool;
|
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.Timeline;
|
||||||
|
|
||||||
/** Stores state for an animation and automatically mixes between animations. */
|
/** Stores state for an animation and automatically mixes between animations. */
|
||||||
public class AnimationState {
|
public class AnimationState {
|
||||||
@ -44,7 +46,7 @@ public class AnimationState {
|
|||||||
private final EventQueue queue = new EventQueue();
|
private final EventQueue queue = new EventQueue();
|
||||||
final Array<AnimationStateListener> listeners = new Array();
|
final Array<AnimationStateListener> listeners = new Array();
|
||||||
private float timeScale = 1;
|
private float timeScale = 1;
|
||||||
private float defaultEventThreshold = 1;
|
private float defaultEventThreshold, defaultAttachmentThreshold;
|
||||||
|
|
||||||
final Pool<TrackEntry> trackEntryPool = new Pool() {
|
final Pool<TrackEntry> trackEntryPool = new Pool() {
|
||||||
protected Object newObject () {
|
protected Object newObject () {
|
||||||
@ -103,21 +105,13 @@ public class AnimationState {
|
|||||||
TrackEntry current = tracks.get(i);
|
TrackEntry current = tracks.get(i);
|
||||||
if (current == null) continue;
|
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;
|
boolean loop = current.loop;
|
||||||
if (!loop && time > endTime) time = endTime;
|
if (!loop && time > endTime) time = endTime;
|
||||||
|
|
||||||
TrackEntry previous = current.previous;
|
if (current.previous != null) {
|
||||||
if (previous != null) {
|
|
||||||
mix *= current.mixTime / current.mixDuration;
|
mix *= current.mixTime / current.mixDuration;
|
||||||
Array<Event> previousEvents = mix < previous.eventThreshold ? events : null;
|
applyPrevious(current.previous, skeleton, mix);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (mix >= 1) {
|
if (mix >= 1) {
|
||||||
mix = 1;
|
mix = 1;
|
||||||
queue.end(current.previous);
|
queue.end(current.previous);
|
||||||
@ -133,6 +127,35 @@ public class AnimationState {
|
|||||||
queue.drain();
|
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) {
|
private void queueEvents (TrackEntry entry, float lastTime, float time, float endTime) {
|
||||||
Array<Event> events = this.events;
|
Array<Event> events = this.events;
|
||||||
int n = events.size;
|
int n = events.size;
|
||||||
@ -240,6 +263,7 @@ public class AnimationState {
|
|||||||
entry.loop = loop;
|
entry.loop = loop;
|
||||||
entry.endTime = animation.getDuration();
|
entry.endTime = animation.getDuration();
|
||||||
entry.eventThreshold = defaultEventThreshold;
|
entry.eventThreshold = defaultEventThreshold;
|
||||||
|
entry.attachmentThreshold = defaultAttachmentThreshold;
|
||||||
|
|
||||||
setCurrent(trackIndex, entry);
|
setCurrent(trackIndex, entry);
|
||||||
queue.drain();
|
queue.drain();
|
||||||
@ -261,6 +285,7 @@ public class AnimationState {
|
|||||||
entry.loop = loop;
|
entry.loop = loop;
|
||||||
entry.endTime = animation.getDuration();
|
entry.endTime = animation.getDuration();
|
||||||
entry.eventThreshold = defaultEventThreshold;
|
entry.eventThreshold = defaultEventThreshold;
|
||||||
|
entry.attachmentThreshold = defaultAttachmentThreshold;
|
||||||
|
|
||||||
TrackEntry last = expandToIndex(trackIndex);
|
TrackEntry last = expandToIndex(trackIndex);
|
||||||
if (last != null) {
|
if (last != null) {
|
||||||
@ -322,6 +347,14 @@ public class AnimationState {
|
|||||||
this.defaultEventThreshold = defaultEventThreshold;
|
this.defaultEventThreshold = defaultEventThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getDefaultAttachmentThreshold () {
|
||||||
|
return defaultAttachmentThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultAttachmentThreshold (float defaultAttachmentThreshold) {
|
||||||
|
this.defaultAttachmentThreshold = defaultAttachmentThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
public AnimationStateData getData () {
|
public AnimationStateData getData () {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -352,10 +385,10 @@ public class AnimationState {
|
|||||||
TrackEntry next, previous;
|
TrackEntry next, previous;
|
||||||
Animation animation;
|
Animation animation;
|
||||||
boolean loop;
|
boolean loop;
|
||||||
float delay, time, lastTime = -1, endTime, timeScale = 1, eventThreshold;
|
float delay, time, lastTime = -1, endTime, timeScale = 1, eventThreshold, attachmentThreshold;
|
||||||
float mixTime, mixDuration;
|
float mixTime, mixDuration;
|
||||||
AnimationStateListener listener;
|
AnimationStateListener listener;
|
||||||
float mix = 1;
|
float alpha = 1;
|
||||||
|
|
||||||
public void reset () {
|
public void reset () {
|
||||||
next = null;
|
next = null;
|
||||||
@ -424,11 +457,11 @@ public class AnimationState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public float getMix () {
|
public float getMix () {
|
||||||
return mix;
|
return alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMix (float mix) {
|
public void setMix (float mix) {
|
||||||
this.mix = mix;
|
this.alpha = mix;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getTimeScale () {
|
public float getTimeScale () {
|
||||||
@ -447,6 +480,14 @@ public class AnimationState {
|
|||||||
this.eventThreshold = eventThreshold;
|
this.eventThreshold = eventThreshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getAttachmentThreshold () {
|
||||||
|
return attachmentThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttachmentThreshold (float attachmentThreshold) {
|
||||||
|
this.attachmentThreshold = attachmentThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
public TrackEntry getNext () {
|
public TrackEntry getNext () {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user