diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AnimationStateTest.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AnimationStateTest.java index 691ca2c13..28bce52aa 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AnimationStateTest.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/AnimationStateTest.java @@ -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); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java index 39b368960..35c86e0b1 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Animation.java @@ -40,8 +40,8 @@ import com.esotericsoftware.spine.attachments.VertexAttachment; public class Animation { final String name; - private final Array timelines; - private float duration; + final Array timelines; + float duration; public Animation (String name, Array timelines, float duration) { if (name == null) throw new IllegalArgumentException("name cannot be null."); diff --git a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java index a8f54ed1b..0e393346a 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java @@ -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 listeners = new Array(); private float timeScale = 1; - private float defaultEventThreshold = 1; + private float defaultEventThreshold, defaultAttachmentThreshold; final Pool 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 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 events = mix < previous.eventThreshold ? this.events : null; + + Array 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 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; }