From 71956544ba01bbc0c08bd712945ecc7b3835d973 Mon Sep 17 00:00:00 2001 From: NathanSweet Date: Mon, 6 Jan 2014 21:33:58 +0100 Subject: [PATCH] Mix from closest animation if setting an animation during a mix. --- .../src/spine/animation/AnimationState.as | 8 +++++++- spine-c/src/spine/AnimationState.c | 17 +++++++++++------ spine-csharp/src/AnimationState.cs | 7 ++++++- spine-js/spine.js | 7 ++++++- .../esotericsoftware/spine/AnimationState.java | 15 ++++++++++----- spine-lua/AnimationState.lua | 8 +++++++- 6 files changed, 47 insertions(+), 15 deletions(-) diff --git a/spine-as3/spine-as3/src/spine/animation/AnimationState.as b/spine-as3/spine-as3/src/spine/animation/AnimationState.as index 354190d85..f74c022f9 100644 --- a/spine-as3/spine-as3/src/spine/animation/AnimationState.as +++ b/spine-as3/spine-as3/src/spine/animation/AnimationState.as @@ -146,6 +146,7 @@ public class AnimationState { private function setCurrent (index:int, entry:TrackEntry) : void { var current:TrackEntry = expandToIndex(index); if (current) { + var previous:TrackEntry = current.previous; current.previous = null; if (current.onEnd != null) current.onEnd(index); @@ -154,7 +155,12 @@ public class AnimationState { entry.mixDuration = _data.getMix(current.animation, entry.animation); if (entry.mixDuration > 0) { entry.mixTime = 0; - entry.previous = current; + // If a mix is in progress, mix from the closest animation. + if (previous != null && current.mixTime / current.mixDuration < 0.5) { + entry.previous = previous; + previous = current; + } else + entry.previous = current; } } diff --git a/spine-c/src/spine/AnimationState.c b/spine-c/src/spine/AnimationState.c index 2e30fd871..cc69be1ec 100644 --- a/spine-c/src/spine/AnimationState.c +++ b/spine-c/src/spine/AnimationState.c @@ -153,7 +153,7 @@ void spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) { } /* Check if completed the animation or a loop iteration. */ - if (current->loop ? (FMOD(current->lastTime, current->endTime) > FMOD(time, current->endTime)) // + if (current->loop ? (FMOD(current->lastTime, current->endTime) > FMOD(time, current->endTime)) : (current->lastTime < current->endTime && time >= current->endTime)) { int count = (int)(time / current->endTime); if (current->listener) current->listener(self, i, ANIMATION_COMPLETE, 0, count); @@ -201,10 +201,8 @@ spTrackEntry* _spAnimationState_expandToIndex (spAnimationState* self, int index void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEntry* entry) { spTrackEntry* current = _spAnimationState_expandToIndex(self, index); if (current) { - if (current->previous) { - _spTrackEntry_dispose(current->previous); - current->previous = 0; - } + spTrackEntry* previous = current->previous; + current->previous = 0; if (current->listener) current->listener(self, index, ANIMATION_END, 0, 0); if (self->listener) self->listener(self, index, ANIMATION_END, 0, 0); @@ -212,9 +210,16 @@ void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEnt entry->mixDuration = spAnimationStateData_getMix(self->data, current->animation, entry->animation); if (entry->mixDuration > 0) { entry->mixTime = 0; - entry->previous = current; + /* If a mix is in progress, mix from the closest animation. */ + if (previous && current->mixTime / current->mixDuration < 0.5f) { + entry->previous = previous; + previous = current; + } else + entry->previous = current; } else _spTrackEntry_dispose(current); + + if (previous) _spTrackEntry_dispose(previous); } self->tracks[index] = entry; diff --git a/spine-csharp/src/AnimationState.cs b/spine-csharp/src/AnimationState.cs index 0453b81e6..2cee18e18 100644 --- a/spine-csharp/src/AnimationState.cs +++ b/spine-csharp/src/AnimationState.cs @@ -154,6 +154,7 @@ namespace Spine { private void SetCurrent (int index, TrackEntry entry) { TrackEntry current = ExpandToIndex(index); if (current != null) { + TrackEntry previous = current.previous; current.previous = null; current.OnEnd(this, index); @@ -162,7 +163,11 @@ namespace Spine { entry.mixDuration = data.GetMix(current.animation, entry.animation); if (entry.mixDuration > 0) { entry.mixTime = 0; - entry.previous = current; + // If a mix is in progress, mix from the closest animation. + if (previous != null && current.mixTime / current.mixDuration < 0.5f) + entry.previous = previous; + else + entry.previous = current; } } diff --git a/spine-js/spine.js b/spine-js/spine.js index 735c2ce08..03b57aca2 100644 --- a/spine-js/spine.js +++ b/spine-js/spine.js @@ -1057,6 +1057,7 @@ spine.AnimationState.prototype = { setCurrent: function (index, entry) { var current = this._expandToIndex(index); if (current) { + var previous = current.previous; current.previous = null; if (current.onEnd != null) current.onEnd(index); @@ -1065,7 +1066,11 @@ spine.AnimationState.prototype = { entry.mixDuration = this.data.getMix(current.animation, entry.animation); if (entry.mixDuration > 0) { entry.mixTime = 0; - entry.previous = current; + // If a mix is in progress, mix from the closest animation. + if (previous && current.mixTime / current.mixDuration < 0.5) + entry.previous = previous; + else + entry.previous = current; } } diff --git a/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java b/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java index fee5739ec..a3c199811 100644 --- a/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java +++ b/spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java @@ -169,10 +169,8 @@ public class AnimationState { private void setCurrent (int index, TrackEntry entry) { TrackEntry current = expandToIndex(index); if (current != null) { - if (current.previous != null) { - trackEntryPool.free(current.previous); - current.previous = null; - } + TrackEntry previous = current.previous; + current.previous = null; if (current.listener != null) current.listener.end(index); for (int i = 0, n = listeners.size; i < n; i++) @@ -181,9 +179,16 @@ public class AnimationState { entry.mixDuration = data.getMix(current.animation, entry.animation); if (entry.mixDuration > 0) { entry.mixTime = 0; - entry.previous = current; + // If a mix is in progress, mix from the closest animation. + if (previous != null && current.mixTime / current.mixDuration < 0.5f) { + entry.previous = previous; + previous = current; + } else + entry.previous = current; } else trackEntryPool.free(current); + + if (previous != null) trackEntryPool.free(previous); } tracks.set(index, entry); diff --git a/spine-lua/AnimationState.lua b/spine-lua/AnimationState.lua index 6cd692b80..02aca6162 100644 --- a/spine-lua/AnimationState.lua +++ b/spine-lua/AnimationState.lua @@ -48,6 +48,7 @@ function AnimationState.new (data) local function setCurrent (index, entry) local current = self.tracks[index] if current then + local previous = current.previous current.previous = nil if current.onEnd then current.onEnd(index) end @@ -56,7 +57,12 @@ function AnimationState.new (data) entry.mixDuration = self.data:getMix(current.animation.name, entry.animation.name) if entry.mixDuration > 0 then entry.mixTime = 0 - entry.previous = current + -- If a mix is in progress, mix from the closest animation. + if previous and current.mixTime / current.mixDuration < 0.5 then + entry.previous = previous + else + entry.previous = current + end end end