Browse Source

Clear a track if the last entry is non-looping and reached endTime.

NathanSweet 12 years ago
parent
commit
3797b7b7b0

+ 1 - 2
spine-c/include/spine/AnimationState.h

@@ -85,8 +85,7 @@ TrackEntry* AnimationState_setAnimationByName (AnimationState* self, int trackIn
 TrackEntry* AnimationState_setAnimation (AnimationState* self, int trackIndex, Animation* animation, int/*bool*/loop);
 
 /** Adds an animation to be played delay seconds after the current or last queued animation, taking into account any mix
- * duration.
- * @param animation May be 0 to queue clearing the AnimationState. */
+ * duration. */
 TrackEntry* AnimationState_addAnimationByName (AnimationState* self, int trackIndex, const char* animationName, int/*bool*/loop,
 		float delay);
 TrackEntry* AnimationState_addAnimation (AnimationState* self, int trackIndex, Animation* animation, int/*bool*/loop,

+ 16 - 9
spine-c/src/spine/AnimationState.c

@@ -39,7 +39,6 @@
 #include <spine/Skeleton.h>
 #include <spine/SkeletonData.h>
 #include <string.h>
-#include <limits.h>
 
 TrackEntry* _TrackEntry_create () {
 	TrackEntry* entry = NEW(TrackEntry);
@@ -110,11 +109,11 @@ void AnimationState_update (AnimationState* self, float delta) {
 			if (self->listener) self->listener(self, i, ANIMATION_COMPLETE, 0, count);
 		}
 
-		if (current->next && time >= current->next->delay) {
-			if (current->next->animation)
-				_AnimationState_setCurrent(self, i, current->next);
-			else
-				AnimationState_clearTrack(self, i);
+		if (current->next) {
+			if (time >= current->next->delay) _AnimationState_setCurrent(self, i, current->next);
+		} else {
+			/* End non-looping animation when it reaches its end time and there is no next entry. */
+			if (!current->loop && current->lastTime >= current->endTime) AnimationState_clearTrack(self, i);
 		}
 	}
 }
@@ -124,6 +123,7 @@ void AnimationState_apply (AnimationState* self, Skeleton* skeleton) {
 
 	int i, ii;
 	int eventCount;
+	float time;
 	TrackEntry* previous;
 	for (i = 0; i < self->trackCount; i++) {
 		TrackEntry* current = self->tracks[i];
@@ -131,19 +131,26 @@ void AnimationState_apply (AnimationState* self, Skeleton* skeleton) {
 
 		eventCount = 0;
 
+		time = current->time;
+		if (!current->loop && time > current->endTime) time = current->endTime;
+
 		previous = current->previous;
 		if (!previous) {
-			Animation_apply(current->animation, skeleton, current->lastTime, current->time, current->loop, internal->events,
+			Animation_apply(current->animation, skeleton, current->lastTime, time, current->loop, internal->events,
 					&eventCount);
 		} else {
 			float alpha = current->mixTime / current->mixDuration;
-			Animation_apply(previous->animation, skeleton, (float)INT_MAX, previous->time, previous->loop, 0, 0);
+
+			float previousTime = previous->time;
+			if (!previous->loop && previousTime > previous->endTime) previousTime = previous->endTime;
+			Animation_apply(previous->animation, skeleton, previousTime, previousTime, previous->loop, 0, 0);
+
 			if (alpha >= 1) {
 				alpha = 1;
 				_TrackEntry_dispose(current->previous);
 				current->previous = 0;
 			}
-			Animation_mix(current->animation, skeleton, current->lastTime, current->time, current->loop, internal->events,
+			Animation_mix(current->animation, skeleton, current->lastTime, time, current->loop, internal->events,
 					&eventCount, alpha);
 		}
 

+ 22 - 16
spine-csharp/src/AnimationState.cs

@@ -79,11 +79,11 @@ namespace Spine {
 				}
 
 				TrackEntry next = current.next;
-				if (next != null && time >= next.delay) {
-					if (next.animation != null)
-						SetCurrent(i, next);
-					else
-						Clear(i);
+				if (next != null) {
+					if (time >= next.delay) SetCurrent(i, next);
+				} else {
+					// End non-looping animation when it reaches its end time and there is no next entry.
+					if (!current.loop && current.lastTime >= current.endTime) ClearTrack(i);
 				}
 			}
 		}
@@ -97,17 +97,24 @@ namespace Spine {
 
 				events.Clear();
 
+				float time = current.time;
+				bool loop = current.loop;
+				if (!loop && time > current.endTime) time = current.endTime;
+
 				TrackEntry previous = current.previous;
 				if (previous == null)
-					current.animation.Apply(skeleton, current.lastTime, current.time, current.loop, events);
+					current.animation.Apply(skeleton, current.lastTime, time, loop, events);
 				else {
-					previous.animation.Apply(skeleton, int.MaxValue, previous.time, previous.loop, null);
+					float previousTime = previous.time;
+					if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime;
+					previous.animation.Apply(skeleton, previousTime, previousTime, previous.loop, null);
+
 					float alpha = current.mixTime / current.mixDuration;
 					if (alpha >= 1) {
 						alpha = 1;
 						current.previous = null;
 					}
-					current.animation.Mix(skeleton, current.lastTime, current.time, current.loop, events, alpha);
+					current.animation.Mix(skeleton, current.lastTime, time, loop, events, alpha);
 				}
 
 				for (int ii = 0, nn = events.Count; ii < nn; ii++) {
@@ -120,13 +127,13 @@ namespace Spine {
 			}
 		}
 
-		public void Clear () {
+		public void ClearTracks () {
 			for (int i = 0, n = tracks.Count; i < n; i++)
-				Clear(i);
+				ClearTrack(i);
 			tracks.Clear();
 		}
 
-		public void Clear (int trackIndex) {
+		public void ClearTrack (int trackIndex) {
 			if (trackIndex >= tracks.Count) return;
 			TrackEntry current = tracks[trackIndex];
 			if (current == null) return;
@@ -195,7 +202,7 @@ namespace Spine {
 			entry.animation = animation;
 			entry.loop = loop;
 			entry.time = 0;
-			entry.endTime = animation != null ? animation.Duration : 0;
+			entry.endTime = animation.Duration;
 
 			TrackEntry last = ExpandToIndex(trackIndex);
 			if (last != null) {
@@ -206,10 +213,9 @@ namespace Spine {
 				tracks[trackIndex] = entry;
 
 			if (delay <= 0) {
-				if (last != null) {
-					delay += last.endTime;
-					if (animation != null) delay -= data.GetMix(last.animation, animation);
-				} else
+				if (last != null)
+					delay += last.endTime - data.GetMix(last.animation, animation);
+				else
 					delay = 0;
 			}
 			entry.delay = delay;

+ 23 - 18
spine-libgdx/src/com/esotericsoftware/spine/AnimationState.java

@@ -43,7 +43,7 @@ public class AnimationState {
 	private Array<TrackEntry> tracks = new Array();
 	private final Array<Event> events = new Array();
 	private final Array<AnimationStateListener> listeners = new Array();
-	private float timeScale;
+	private float timeScale = 1;
 
 	public AnimationState (AnimationStateData data) {
 		if (data == null) throw new IllegalArgumentException("data cannot be null.");
@@ -75,11 +75,11 @@ public class AnimationState {
 			}
 
 			TrackEntry next = current.next;
-			if (next != null && time >= next.delay) {
-				if (next.animation != null)
-					setCurrent(i, next);
-				else
-					clear(i);
+			if (next != null) {
+				if (time >= next.delay) setCurrent(i, next);
+			} else {
+				// End non-looping animation when it reaches its end time and there is no next entry.
+				if (!current.loop && current.lastTime >= current.endTime) clearTrack(i);
 			}
 		}
 	}
@@ -94,18 +94,25 @@ public class AnimationState {
 
 			events.size = 0;
 
+			float time = current.time;
+			boolean loop = current.loop;
+			if (!loop && time > current.endTime) time = current.endTime;
+
 			TrackEntry previous = current.previous;
 			if (previous == null)
-				current.animation.apply(skeleton, current.lastTime, current.time, current.loop, events);
+				current.animation.apply(skeleton, current.lastTime, time, loop, events);
 			else {
-				previous.animation.apply(skeleton, Integer.MAX_VALUE, previous.time, previous.loop, null);
+				float previousTime = previous.time;
+				if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime;
+				previous.animation.apply(skeleton, previousTime, previousTime, previous.loop, null);
+
 				float alpha = current.mixTime / current.mixDuration;
 				if (alpha >= 1) {
 					alpha = 1;
 					Pools.free(previous);
 					current.previous = null;
 				}
-				current.animation.mix(skeleton, current.lastTime, current.time, current.loop, events, alpha);
+				current.animation.mix(skeleton, current.lastTime, time, loop, events, alpha);
 			}
 
 			for (int ii = 0, nn = events.size; ii < nn; ii++) {
@@ -119,13 +126,13 @@ public class AnimationState {
 		}
 	}
 
-	public void clear () {
+	public void clearTracks () {
 		for (int i = 0, n = tracks.size; i < n; i++)
-			clear(i);
+			clearTrack(i);
 		tracks.clear();
 	}
 
-	public void clear (int trackIndex) {
+	public void clearTrack (int trackIndex) {
 		if (trackIndex >= tracks.size) return;
 		TrackEntry current = tracks.get(trackIndex);
 		if (current == null) return;
@@ -210,14 +217,13 @@ public class AnimationState {
 	}
 
 	/** Adds an animation to be played delay seconds after the current or last queued animation.
-	 * @param animation May be null to queue clearing the AnimationState.
 	 * @param delay May be <= 0 to use duration of previous animation minus any mix duration plus the negative delay. */
 	public TrackEntry addAnimation (int trackIndex, Animation animation, boolean loop, float delay) {
 		TrackEntry entry = Pools.obtain(TrackEntry.class);
 		entry.animation = animation;
 		entry.loop = loop;
 		entry.time = 0;
-		entry.endTime = animation != null ? animation.getDuration() : 0;
+		entry.endTime = animation.getDuration();
 
 		TrackEntry last = expandToIndex(trackIndex);
 		if (last != null) {
@@ -228,10 +234,9 @@ public class AnimationState {
 			tracks.set(trackIndex, entry);
 
 		if (delay <= 0) {
-			if (last != null) {
-				delay += last.endTime;
-				if (animation != null) delay -= data.getMix(last.animation, animation);
-			} else
+			if (last != null)
+				delay += last.endTime - data.getMix(last.animation, animation);
+			else
 				delay = 0;
 		}
 		entry.delay = delay;