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 1b50f8c7e..0dea4cf96 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 @@ -67,20 +67,24 @@ public class AnimationStateTest { add(actual("start", entry)); } - public void event (TrackEntry entry, Event event) { - add(actual("event " + event.getString(), entry)); - } - public void interrupt (TrackEntry entry) { add(actual("interrupt", entry)); } + public void end (TrackEntry entry) { + add(actual("end", entry)); + } + + public void dispose (TrackEntry entry) { + add(actual("dispose", entry)); + } + public void complete (TrackEntry entry) { add(actual("complete", entry)); } - public void end (TrackEntry entry) { - add(actual("end", entry)); + public void event (TrackEntry entry, Event event) { + add(actual("event " + event.getString(), entry)); } private void add (Result result) { @@ -119,20 +123,36 @@ public class AnimationStateTest { expect(0, "event 14", 0.5f, 0.5f), // expect(0, "event 30", 1, 1), // expect(0, "complete", 1, 1), // - expect(0, "end", 1, 1.1f) // + expect(0, "end", 1, 1.1f), // + expect(0, "dispose", 1, 1.1f) // ); state.setAnimation(0, "events1", false); run(0.1f, 1000, null); - setup("1/60 time step", // 2 + setup("1/60 time step, dispose queued", // 2 + expect(0, "start", 0, 0), // + expect(0, "interrupt", 0, 0), // + expect(0, "end", 0, 0), // + expect(0, "dispose", 0, 0), // + expect(1, "dispose", 0, 0), // + expect(0, "dispose", 0, 0), // + expect(1, "dispose", 0, 0), // + + // First 2 set/addAnimation calls are done. + expect(0, "start", 0, 0), // expect(0, "event 0", 0, 0), // expect(0, "event 14", 0.467f, 0.467f), // expect(0, "event 30", 1, 1), // expect(0, "complete", 1, 1), // - expect(0, "end", 1, 1.017f) // + expect(0, "end", 1, 1.017f), // + expect(0, "dispose", 1, 1.017f) // ); state.setAnimation(0, "events1", false); + state.addAnimation(0, "events2", false, 0); + state.addAnimation(0, "events1", false, 0); + state.addAnimation(0, "events2", false, 0); + state.setAnimation(0, "events1", false); run(1 / 60f, 1000, null); setup("30 time step", // 3 @@ -141,7 +161,8 @@ public class AnimationStateTest { expect(0, "event 14", 30, 30), // expect(0, "event 30", 30, 30), // expect(0, "complete", 30, 30), // - expect(0, "end", 30, 60) // + expect(0, "end", 30, 60), // + expect(0, "dispose", 30, 60) // ); state.setAnimation(0, "events1", false); run(30, 1000, null); @@ -152,7 +173,8 @@ public class AnimationStateTest { expect(0, "event 14", 1, 1), // expect(0, "event 30", 1, 1), // expect(0, "complete", 1, 1), // - expect(0, "end", 1, 2) // + expect(0, "end", 1, 2), // + expect(0, "dispose", 1, 2) // ); state.setAnimation(0, "events1", false); run(1, 1.01f, null); @@ -171,6 +193,7 @@ public class AnimationStateTest { expect(1, "event 0", 0.1f, 1.1f), // expect(0, "end", 1.1f, 1.2f), // + expect(0, "dispose", 1.1f, 1.2f), // expect(1, "event 14", 0.5f, 1.5f), // expect(1, "event 30", 1, 2), // @@ -183,11 +206,13 @@ public class AnimationStateTest { expect(0, "event 0", 0.1f, 2.1f), // expect(1, "end", 1.1f, 2.2f), // + expect(1, "dispose", 1.1f, 2.2f), // expect(0, "event 14", 0.5f, 2.5f), // expect(0, "event 30", 1, 3), // expect(0, "complete", 1, 3), // - expect(0, "end", 1, 3.1f) // + expect(0, "end", 1, 3.1f), // + expect(0, "dispose", 1, 3.1f) // ); state.setAnimation(0, "events1", false); state.addAnimation(0, "events2", false, 0); @@ -206,11 +231,13 @@ public class AnimationStateTest { expect(1, "event 0", 0.1f, 0.6f), // expect(0, "end", 0.6f, 0.7f), // + expect(0, "dispose", 0.6f, 0.7f), // expect(1, "event 14", 0.5f, 1.0f), // expect(1, "event 30", 1, 1.5f), // expect(1, "complete", 1, 1.5f), // - expect(1, "end", 1, 1.6f) // + expect(1, "end", 1, 1.6f), // + expect(1, "dispose", 1, 1.6f) // ); state.setAnimation(0, "events1", false); state.addAnimation(0, "events2", false, 0.5f); @@ -230,10 +257,12 @@ public class AnimationStateTest { expect(1, "event 14", 0.5f, 1.4f), // expect(0, "end", 1.6f, 1.7f), // + expect(0, "dispose", 1.6f, 1.7f), // expect(1, "event 30", 1, 1.9f), // expect(1, "complete", 1, 1.9f), // - expect(1, "end", 1, 2) // + expect(1, "end", 1, 2), // + expect(1, "dispose", 1, 2) // ); stateData.setMix("events1", "events2", 0.7f); state.setAnimation(0, "events1", true); @@ -253,10 +282,12 @@ public class AnimationStateTest { expect(0, "complete", 1, 1), // expect(0, "end", 1.1f, 1.2f), // + expect(0, "dispose", 1.1f, 1.2f), // expect(1, "event 30", 1, 1.4f), // expect(1, "complete", 1, 1.4f), // - expect(1, "end", 1, 1.5f) // + expect(1, "end", 1, 1.5f), // + expect(1, "dispose", 1, 1.5f) // ); stateData.setDefaultMix(0.7f); state.setAnimation(0, "events1", false); @@ -277,10 +308,12 @@ public class AnimationStateTest { expect(0, "complete", 1, 1), // expect(0, "end", 1.1f, 1.2f), // + expect(0, "dispose", 1.1f, 1.2f), // expect(1, "event 30", 1, 1.4f), // expect(1, "complete", 1, 1.4f), // - expect(1, "end", 1, 1.5f) // + expect(1, "end", 1, 1.5f), // + expect(1, "dispose", 1, 1.5f) // ); stateData.setMix("events1", "events2", 0.7f); state.setAnimation(0, "events1", false).setEventThreshold(0.5f); @@ -305,10 +338,12 @@ public class AnimationStateTest { expect(1, "event 14", 0.5f, 1.3f), // expect(0, "end", 1.5f, 1.6f), // + expect(0, "dispose", 1.5f, 1.6f), // expect(1, "event 30", 1, 1.8f), // expect(1, "complete", 1, 1.8f), // - expect(1, "end", 1, 1.9f) // + expect(1, "end", 1, 1.9f), // + expect(1, "dispose", 1, 1.9f) // ); state.setAnimation(0, "events1", true).setEventThreshold(1); state.addAnimation(0, "events2", false, 0.8f).setMixDuration(0.7f); @@ -351,11 +386,13 @@ public class AnimationStateTest { expect(1, "event 0", 0.1f, 2.1f), // expect(0, "end", 2.1f, 2.2f), // + expect(0, "dispose", 2.1f, 2.2f), // expect(1, "event 14", 0.5f, 2.5f), // expect(1, "event 30", 1, 3), // expect(1, "complete", 1, 3), // - expect(1, "end", 1, 3.1f) // + expect(1, "end", 1, 3.1f), // + expect(1, "dispose", 1, 3.1f) // ); state.setAnimation(0, "events1", false); state.addAnimation(0, "events2", false, 2); @@ -380,11 +417,13 @@ public class AnimationStateTest { expect(1, "event 0", 0.1f, 2.1f), // expect(0, "end", 2.1f, 2.2f), // + expect(0, "dispose", 2.1f, 2.2f), // expect(1, "event 14", 0.5f, 2.5f), // expect(1, "event 30", 1, 3), // expect(1, "complete", 1, 3), // - expect(1, "end", 1, 3.1f) // + expect(1, "end", 1, 3.1f), // + expect(1, "dispose", 1, 3.1f) // ); state.setAnimation(0, "events1", true); run(0.1f, 6, new TestListener() { @@ -399,7 +438,8 @@ public class AnimationStateTest { expect(0, "event 14", 0.5f, 0.5f), // expect(0, "event 30", 1, 1), // expect(0, "complete", 1, 1), // - expect(0, "end", 1, 1.1f) // + expect(0, "end", 1, 1.1f), // + expect(0, "dispose", 1, 1.1f) // ); state.addAnimation(0, "events1", false, 0); run(0.1f, 1.9f, null); @@ -410,7 +450,8 @@ public class AnimationStateTest { expect(0, "event 14", 0.5f, 0.5f), // expect(0, "event 30", 1, 1), // expect(0, "complete", 1, 1), // - expect(0, "end", 9f, 9.1f) // + expect(0, "end", 9f, 9.1f), // + expect(0, "dispose", 9f, 9.1f) // ); state.setAnimation(0, "events1", false).setTrackEnd(9); run(0.1f, 10, null); @@ -447,7 +488,8 @@ public class AnimationStateTest { expect(0, "start", 0, 0), // expect(0, "event 14", 0.3f, 0.3f), // expect(0, "complete", 0.6f, 0.6f), // - expect(0, "end", 1, 1.1f) // + expect(0, "end", 1, 1.1f), // + expect(0, "dispose", 1, 1.1f) // ); entry = state.setAnimation(0, "events1", false); entry.setAnimationStart(0.2f); @@ -472,10 +514,12 @@ public class AnimationStateTest { expect(1, "event 14", 0.5f, 1.2f), // expect(0, "end", 1.4f, 1.5f), // + expect(0, "dispose", 1.4f, 1.5f), // expect(1, "event 30", 1, 1.7f), // expect(1, "complete", 1, 1.7f), // - expect(1, "end", 1, 1.8f) // + expect(1, "end", 1, 1.8f), // + expect(1, "dispose", 1, 1.8f) // ); entry = state.setAnimation(0, "events1", true); entry.setAnimationStart(0.2f); @@ -489,20 +533,24 @@ public class AnimationStateTest { expect(0, "start", 0, 0), // expect(0, "event 0", 0, 0), // expect(0, "event 14", 0.5f, 0.5f), // + expect(0, "event 30", 1, 1), // + expect(0, "complete", 1, 1), // + expect(0, "event 0", 1, 1), // - expect(1, "start", 0.1f, 1), // + expect(1, "start", 0, 1), // expect(0, "interrupt", 1, 1), // - expect(0, "complete", 1, 1), // - expect(1, "event 0", 0.1f, 1), // - expect(1, "event 14", 0.5f, 1.4f), // + expect(1, "event 0", 0.1f, 1.1f), // + expect(1, "event 14", 0.5f, 1.5f), // - expect(0, "end", 1.6f, 1.7f), // + expect(0, "end", 1.7f, 1.8f), // + expect(0, "dispose", 1.7f, 1.8f), // - expect(1, "event 30", 1, 1.9f), // - expect(1, "complete", 1, 1.9f), // - expect(1, "end", 1, 2) // + expect(1, "event 30", 1, 2), // + expect(1, "complete", 1, 2), // + expect(1, "end", 1, 2.1f), // + expect(1, "dispose", 1, 2.1f) // ); state.setAnimation(0, "events1", true); run(0.1f, 1000, new TestListener() { @@ -513,37 +561,39 @@ public class AnimationStateTest { setup("setAnimation twice", // 21 expect(0, "start", 0, 0), // + expect(0, "interrupt", 0, 0), // + expect(0, "end", 0, 0), // + expect(0, "dispose", 0, 0), // expect(1, "start", 0, 0), // - - expect(0, "interrupt", 0, 0), // - expect(1, "event 0", 0, 0), // - - expect(0, "end", 0.1f, 0.2f), // - expect(1, "event 14", 0.5f, 0.5f), // - expect(0, "start", 0.1f, 0.8f), // + // First 2 setAnimation calls are done. + + expect(0, "start", 0, 0.8f), // expect(1, "interrupt", 0.8f, 0.8f), // - expect(0, "event 0", 0.1f, 0.8f), // + expect(0, "interrupt", 0, 0.8f), // + expect(0, "end", 0, 0.8f), // + expect(0, "dispose", 0, 0.8f), // - expect(1, "end", 0.8f, 0.9f), // - - expect(0, "event 14", 0.5f, 1.2f), // - expect(0, "event 30", 1, 1.7f), // - expect(0, "complete", 1, 1.7f), // - expect(0, "end", 1, 1.8f) // + expect(1, "start", 0, 0.8f), // + expect(1, "event 0", 0.1f, 0.9f), // + expect(1, "event 14", 0.5f, 1.3f), // + expect(1, "event 30", 1, 1.8f), // + expect(1, "complete", 1, 1.8f), // + expect(1, "end", 1, 1.9f), // + expect(1, "dispose", 1, 1.9f) // ); state.setAnimation(0, "events1", false); // First should be ignored. state.setAnimation(0, "events2", false); run(0.1f, 1000, new TestListener() { public void frame (float time) { if (MathUtils.isEqual(time, 0.8f)) { - state.setAnimation(0, "events2", false); // First should be ignored. - state.setAnimation(0, "events1", false); + state.setAnimation(0, "events1", false); // First should be ignored. + state.setAnimation(0, "events2", false); } } }); @@ -554,7 +604,8 @@ public class AnimationStateTest { expect(0, "event 14", 0.5f, 5.5f), // expect(0, "event 30", 1, 6), // expect(0, "complete", 1, 6), // - expect(0, "end", 1, 6.1f) // + expect(0, "end", 1, 6.1f), // + expect(0, "dispose", 1, 6.1f) // ); state.addAnimation(0, "events1", false, 5); run(0.1f, 10, null); @@ -569,23 +620,41 @@ public class AnimationStateTest { state.addAnimation(3, "events2", false, 0); } - public void event (TrackEntry entry, Event event) { - if (entry.getTrackIndex() != 2) state.setAnimation(2, "events2", false); - } - public void end (TrackEntry entry) { if (entry.getAnimation().getName().equals("events1")) state.setAnimation(0, "events2", false); } + public void dispose (TrackEntry entry) { + if (entry.getAnimation().getName().equals("events1")) state.setAnimation(1, "events2", false); + } + public void complete (TrackEntry entry) { if (entry.getAnimation().getName().equals("events1")) state.setAnimation(1, "events2", false); } + + public void event (TrackEntry entry, Event event) { + if (entry.getTrackIndex() != 2) state.setAnimation(2, "events2", false); + } }); state.addAnimation(0, "events1", false, 0); state.addAnimation(0, "events2", false, 0); state.setAnimation(1, "events2", false); run(0.1f, 10, null); + setup("clearTrack", // 24 + expect(0, "start", 0, 0), // + expect(0, "event 0", 0, 0), // + expect(0, "event 14", 0.5f, 0.5f), // + expect(0, "end", 0.7f, 0.7f), // + expect(0, "dispose", 0.7f, 0.7f) // + ); + state.addAnimation(0, "events1", false, 0); + run(0.1f, 10, new TestListener() { + public void frame (float time) { + if (MathUtils.isEqual(time, 0.7f)) state.clearTrack(0); + } + }); + System.out.println("AnimationState tests passed."); } @@ -608,7 +677,6 @@ public class AnimationStateTest { state.apply(skeleton); while (time < endTime) { time += incr; - if (listener != null) listener.frame(time); skeleton.update(incr); state.update(incr); @@ -627,6 +695,8 @@ public class AnimationStateTest { state.apply(skeleton); state.apply(skeleton); if (expected.size > 0) state.addListener(stateListener); + + if (listener != null) listener.frame(time); } // Expecting more than actual is a failure. for (int i = actual.size, n = expected.size; i < n; i++) { diff --git a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest2.java b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest2.java index a7f1c8b24..1ab2f9d28 100644 --- a/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest2.java +++ b/spine-libgdx/spine-libgdx-tests/src/com/esotericsoftware/spine/SimpleTest2.java @@ -83,26 +83,31 @@ public class SimpleTest2 extends ApplicationAdapter { state = new AnimationState(stateData); // Holds the animation state for a skeleton (current animation, time, etc). state.setTimeScale(0.3f); // Slow all animations down to 30% speed. state.addListener(new AnimationStateListener() { - public void event (TrackEntry entry, Event event) { - System.out - .println(entry.getTrackIndex() + " event: " + entry + ", " + event.getData().getName() + ", " + event.getInt()); - } - public void complete (TrackEntry entry) { - System.out.println(entry.getTrackIndex() + " complete: " + entry); + public void start (TrackEntry entry) { + System.out.println(entry.getTrackIndex() + " start: " + entry); } public void interrupt (TrackEntry entry) { System.out.println(entry.getTrackIndex() + " interrupt: " + entry); } - public void start (TrackEntry entry) { - System.out.println(entry.getTrackIndex() + " start: " + entry); - } - public void end (TrackEntry entry) { System.out.println(entry.getTrackIndex() + " end: " + entry); } + + public void dispose (TrackEntry entry) { + System.out.println(entry.getTrackIndex() + " dispose: " + entry); + } + + public void complete (TrackEntry entry) { + System.out.println(entry.getTrackIndex() + " complete: " + entry); + } + + public void event (TrackEntry entry, Event event) { + System.out + .println(entry.getTrackIndex() + " event: " + entry + ", " + event.getData().getName() + ", " + event.getInt()); + } }); // Set animation on track 0. 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 edf27862b..0965a2144 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java @@ -103,18 +103,18 @@ public class AnimationState { // Should we get rid of the track end time? // Or default it to MAX_VALUE even for non-looping animations? // Or reset the skeleton before clearing? Note only apply() has a skeleton. - freeAll(current.next); - queue.end(current); - if (mixingFrom != null) queue.end(mixingFrom); tracks.set(i, null); + queue.end(current); + disposeNext(current); + if (mixingFrom != null) queue.end(mixingFrom); continue; } current.trackTime += currentDelta; if (mixingFrom != null) { if (current.mixTime >= current.mixDuration && current.mixTime > 0) { - queue.end(mixingFrom); current.mixingFrom = null; + queue.end(mixingFrom); animationsChanged = true; } else { mixingFrom.animationLast = mixingFrom.nextAnimationLast; @@ -237,9 +237,12 @@ public class AnimationState { } public void clearTracks () { - for (int i = 0, n = tracks.size; i < n; i++) - clearTrack(i); + for (int i = 0, n = tracks.size; i < n; i++) { + TrackEntry current = tracks.get(i); + if (current != null) clearTrack(current); + } tracks.clear(); + queue.drain(); } // BOZO - This leaves the skeleton in the last pose, with no easy way of resetting. @@ -247,22 +250,32 @@ public class AnimationState { if (trackIndex >= tracks.size) return; TrackEntry current = tracks.get(trackIndex); if (current == null) return; - freeAll(current.next); - - queue.end(current); - if (current.mixingFrom != null) queue.end(current.mixingFrom); + clearTrack(current); queue.drain(); + } - tracks.set(trackIndex, null); + private void clearTrack (TrackEntry current) { + queue.end(current); + + disposeNext(current); + + TrackEntry mixingFrom = current.mixingFrom; + if (mixingFrom != null) { + current.mixingFrom = null; + queue.end(mixingFrom); + } + + tracks.set(current.trackIndex, null); } /** @param entry May be null. */ - private void freeAll (TrackEntry entry) { - while (entry != null) { - TrackEntry next = entry.next; - trackEntryPool.free(entry); - entry = next; + private void disposeNext (TrackEntry entry) { + TrackEntry next = entry.next; + while (next != null) { + queue.dispose(next); + next = next.next; } + entry.next = null; } private TrackEntry expandToIndex (int index) { @@ -285,7 +298,7 @@ public class AnimationState { queue.interrupt(current); // If a mix is in progress, mix from the closest animation. - if (mixingFrom != null && current.mixTime / current.mixDuration < 0.5f) { + if (mixingFrom != null && (current.mixDuration == 0 || current.mixTime / current.mixDuration < 0.5f)) { entry.mixingFrom = mixingFrom; mixingFrom = current; } else @@ -347,28 +360,26 @@ public class AnimationState { return setAnimation(trackIndex, animation, loop); } - /** Sets the current animation for a track. If the track is empty, the new animation is made the current animation immediately. - * Otherwise, any queued animations are discarded and the new animation is queued to become the current animation the next time - * {@link #update(float)} is called. + /** Sets the current animation for a track, discarding any queued animations. * @return A track entry to allow further customization of animation playback. References to the track entry must not be kept * after {@link AnimationStateListener#end(TrackEntry)}. */ public TrackEntry setAnimation (int trackIndex, Animation animation, boolean loop) { if (animation == null) throw new IllegalArgumentException("animation cannot be null."); TrackEntry current = expandToIndex(trackIndex); - TrackEntry entry = trackEntry(trackIndex, animation, loop, current); - if (current == null) { - setCurrent(trackIndex, entry); - queue.drain(); - } else { - freeAll(current.next); - if (current.nextTrackLast == -1) { // If current was never applied, replace it. - setCurrent(trackIndex, entry); - queue.drain(); - } else { - current.next = entry; - entry.delay = current.nextTrackLast; - } + if (current != null) { + if (current.nextTrackLast == -1) { + // Don't mix from an entry that was never applied. + tracks.set(trackIndex, null); + queue.interrupt(current); + queue.end(current); + disposeNext(current); + current = null; + } else + disposeNext(current); } + TrackEntry entry = trackEntry(trackIndex, animation, loop, current); + setCurrent(trackIndex, entry); + queue.drain(); return entry; } @@ -696,11 +707,6 @@ public class AnimationState { return next; } - /** @param next May be null. */ - public void setNext (TrackEntry next) { - this.next = next; - } - /** Returns true if at least one loop has been completed. */ public boolean isComplete () { return trackTime >= animationEnd - animationStart; @@ -719,7 +725,7 @@ public class AnimationState { /** Seconds for mixing from the previous animation to this animation. Defaults to the value provided by * {@link AnimationStateData} based on the animation before this animation (if any). *

- * The mix duration must be set before this track entry becomes the current track entry. */ + * The mix duration must be set before the next time the animation state is updated. */ public float getMixDuration () { return mixDuration; } @@ -740,7 +746,7 @@ public class AnimationState { } static private class EventQueue { - static private final int START = 0, EVENT = 1, COMPLETE = 2, INTERRUPT = 3, END = 4; + static private final int START = 0, EVENT = 1, COMPLETE = 2, INTERRUPT = 3, END = 4, DISPOSE = 5; private final Array listeners; private final Pool trackEntryPool; @@ -779,6 +785,11 @@ public class AnimationState { eventTypes.add(END); } + public void dispose (TrackEntry entry) { + objects.add(entry); + eventTypes.add(DISPOSE); + } + public void drain () { if (draining) return; // Not reentrant. draining = true; @@ -810,6 +821,11 @@ public class AnimationState { if (entry.listener != null) entry.listener.end(entry); for (int i = 0; i < listeners.size; i++) listeners.get(i).end(entry); + // Fall through. + case DISPOSE: + if (entry.listener != null) entry.listener.end(entry); + for (int i = 0; i < listeners.size; i++) + listeners.get(i).dispose(entry); trackEntryPool.free(entry); break; default: @@ -830,31 +846,28 @@ public class AnimationState { } static public interface AnimationStateListener { - /** Invoked just after this animation is set as the current animation. */ + /** Invoked just after this entry is set as the current entry. */ public void start (TrackEntry entry); - /** Invoked just after another animation is set as the current animation. The animation may continue being applied if there - * is a mix duration. */ + /** Invoked just after another entry is set to replace this entry as the current entry. This entry may continue being + * applied for mixing. */ public void interrupt (TrackEntry entry); - /** Invoked when this animation will no longer be applied. After this method returns, no references to the track entry - * should be kept because it may be reused. */ + /** Invoked just before this entry will no longer be the current entry and will never be applied again. */ public void end (TrackEntry entry); - /** Invoked every time this animation completes a loop. */ + /** Invoked just before this track entry will be disposed. References to the entry should not be kept after dispose is + * called, as it may be destroyed or reused. */ + public void dispose (TrackEntry entry); + + /** Invoked every time this entry's animation completes a loop. */ public void complete (TrackEntry entry); - /** Invoked when this animation triggers an event. */ + /** Invoked when this entry's animation triggers an event. */ public void event (TrackEntry entry, Event event); } static public abstract class AnimationStateAdapter implements AnimationStateListener { - public void event (TrackEntry entry, Event event) { - } - - public void complete (TrackEntry entry) { - } - public void start (TrackEntry entry) { } @@ -863,5 +876,14 @@ public class AnimationState { public void end (TrackEntry entry) { } + + public void dispose (TrackEntry entry) { + } + + public void event (TrackEntry entry, Event event) { + } + + public void complete (TrackEntry entry) { + } } }