From c9fdfdf501ab03bc9bb4426c2a59071f0805fca5 Mon Sep 17 00:00:00 2001 From: NathanSweet Date: Tue, 23 Aug 2016 18:08:49 +0200 Subject: [PATCH] Added mixDuration resetTrack, added set/addEmptyAnimation methods. --- .../spine/AnimationStateTest.java | 2 +- .../spine/AnimationState.java | 68 ++++++++++--------- .../spine/SkeletonViewer.java | 25 +++++-- 3 files changed, 57 insertions(+), 38 deletions(-) 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 6b3f7fd94..0ea6c62a6 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 @@ -665,7 +665,7 @@ public class AnimationStateTest { state.addAnimation(0, "events1", false, 0); run(0.1f, 10, new TestListener() { public void frame (float time) { - if (MathUtils.isEqual(time, 0.7f)) state.resetTrack(0); + if (MathUtils.isEqual(time, 0.7f)) state.resetTrack(0, 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 f319791c3..45092b930 100644 --- a/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java +++ b/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java @@ -240,11 +240,11 @@ public class AnimationState { /** Removes all animations from all tracks, leaving skeletons in their last pose. */ public void clearTracks () { - for (int i = 0, n = tracks.size; i < n; i++) { - TrackEntry current = tracks.get(i); - if (current != null) clearTrack(current); - } + queue.drainDisabled = true; + for (int i = 0, n = tracks.size; i < n; i++) + clearTrack(i); tracks.clear(); + queue.drainDisabled = false; queue.drain(); } @@ -253,11 +253,7 @@ public class AnimationState { if (trackIndex >= tracks.size) return; TrackEntry current = tracks.get(trackIndex); if (current == null) return; - clearTrack(current); - queue.drain(); - } - private void clearTrack (TrackEntry current) { queue.end(current); disposeNext(current); @@ -269,35 +265,30 @@ public class AnimationState { } tracks.set(current.trackIndex, null); - } - /** Removes all queued animations for all tracks and sets track entries which mix out the current animations, so any changes - * the animations have made to skeletons are reverted to the setup pose. */ - public void resetTracks () { - for (int i = 0, n = tracks.size; i < n; i++) { - TrackEntry current = tracks.get(i); - if (current != null) resetTrack(current); - } queue.drain(); } - /** Removes all queued animations and sets a track entry which mixes out the current animation, so any changes the animation - * has made to skeletons are reverted to the setup pose. */ - public void resetTrack (int trackIndex) { + /** Removes all queued animations for all tracks and sets empty animations to mix out the current animations, so any changes + * the current animations have made to skeletons are reverted to the setup pose. */ + public void resetTracks (float mixDuration) { + queue.drainDisabled = true; + for (int i = 0, n = tracks.size; i < n; i++) + resetTrack(i, mixDuration); + queue.drainDisabled = false; + queue.drain(); + } + + /** Removes all queued animations and sets an empty animation to mix out the current animation, so any changes the current + * animation has made to skeletons are reverted to the setup pose. */ + public void resetTrack (int trackIndex, float mixDuration) { if (trackIndex >= tracks.size) return; TrackEntry current = tracks.get(trackIndex); if (current == null) return; - resetTrack(current); + setEmptyAnimation(current.trackIndex, mixDuration); queue.drain(); } - private void resetTrack (TrackEntry current) { - TrackEntry entry = trackEntry(current.trackIndex, emptyAnimation, false, current); - entry.mixDuration = 0; - current.trackTime = 0; - setCurrent(current.trackIndex, entry); - } - /** @param entry May be null. */ private void disposeNext (TrackEntry entry) { TrackEntry next = entry.next; @@ -395,7 +386,6 @@ public class AnimationState { * after {@link AnimationStateListener#end(TrackEntry)}. */ public TrackEntry setAnimation (int trackIndex, Animation animation, boolean loop) { if (animation == null) throw new IllegalArgumentException("animation cannot be null."); - // if (animation == null) animation = emptyAnimation; // BOZO - Test. TrackEntry current = expandToIndex(trackIndex); if (current != null) { if (current.nextTrackLast == -1) { @@ -455,6 +445,20 @@ public class AnimationState { return entry; } + public TrackEntry setEmptyAnimation (int trackIndex, float mixDuration) { + TrackEntry entry = setAnimation(trackIndex, emptyAnimation, false); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + + public TrackEntry addEmptyAnimation (int trackIndex, float mixDuration, float delay) { + TrackEntry entry = addAnimation(trackIndex, emptyAnimation, false, delay); + entry.mixDuration = mixDuration; + entry.trackEnd = mixDuration; + return entry; + } + /** @param last May be null. */ private TrackEntry trackEntry (int trackIndex, Animation animation, boolean loop, TrackEntry last) { TrackEntry entry = trackEntryPool.obtain(); @@ -783,7 +787,7 @@ public class AnimationState { private final Pool trackEntryPool; private final Array objects = new Array(); private final IntArray eventTypes = new IntArray(); // If > 0 it's loop count for a complete event. - private boolean draining; + boolean drainDisabled; public EventQueue (Array listeners, Pool trackEntryPool) { this.listeners = listeners; @@ -822,8 +826,8 @@ public class AnimationState { } public void drain () { - if (draining) return; // Not reentrant. - draining = true; + if (drainDisabled) return; // Not reentrant. + drainDisabled = true; Array objects = this.objects; IntArray eventTypes = this.eventTypes; @@ -867,7 +871,7 @@ public class AnimationState { } clear(); - draining = false; + drainDisabled = false; } public void clear () { diff --git a/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewer.java b/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewer.java index 5fd32bad3..3ccd74708 100644 --- a/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewer.java +++ b/spine-libgdx/spine-skeletonviewer/src/com/esotericsoftware/spine/SkeletonViewer.java @@ -211,8 +211,16 @@ public class SkeletonViewer extends ApplicationAdapter { } void setAnimation () { - TrackEntry entry = state.setAnimation(0, ui.animationList.getSelected(), ui.loopCheckbox.isChecked()); - entry.setTrackEnd(Integer.MAX_VALUE); + TrackEntry current = state.getCurrent(0); + if (current == null) { + state.setEmptyAnimation(0, 0); + TrackEntry entry = state.addAnimation(0, ui.animationList.getSelected(), ui.loopCheckbox.isChecked(), 0); + entry.setMixDuration(ui.mixSlider.getValue()); + entry.setTrackEnd(Integer.MAX_VALUE); + } else { + TrackEntry entry = state.setAnimation(0, ui.animationList.getSelected(), ui.loopCheckbox.isChecked()); + entry.setTrackEnd(Integer.MAX_VALUE); + } } public void render () { @@ -263,16 +271,23 @@ public class SkeletonViewer extends ApplicationAdapter { ui.stage.act(); ui.stage.draw(); - // Draw indicator for timeline position. + // Draw indicator lines for animation and mix times. if (state != null) { ShapeRenderer shapes = debugRenderer.getShapeRenderer(); TrackEntry entry = state.getCurrent(0); if (entry != null) { + shapes.begin(ShapeType.Line); + float percent = entry.getAnimationTime() / entry.getAnimationEnd(); float x = ui.window.getRight() + (Gdx.graphics.getWidth() - ui.window.getRight()) * percent; shapes.setColor(Color.CYAN); - shapes.begin(ShapeType.Line); shapes.line(x, 0, x, 20); + + percent = entry.getMixTime() / entry.getMixDuration(); + x = ui.window.getRight() + (Gdx.graphics.getWidth() - ui.window.getRight()) * percent; + shapes.setColor(Color.RED); + shapes.line(x, 0, x, 20); + shapes.end(); } } @@ -488,7 +503,7 @@ public class SkeletonViewer extends ApplicationAdapter { if (state != null) { String name = animationList.getSelected(); if (name == null) - state.resetTrack(0); + state.resetTrack(0, ui.mixSlider.getValue()); else setAnimation(); }