Moved firing complete event to apply. Fixed missing keys on last frame when animation changes.

This commit is contained in:
NathanSweet 2013-10-17 16:06:18 +02:00
parent 98e4c0e7e5
commit dbd6ae87ad
5 changed files with 116 additions and 122 deletions

View File

@ -54,26 +54,16 @@ public class AnimationState {
var current:TrackEntry = _tracks[i];
if (!current) continue;
var trackDelta:Number = delta * current.timeScale;
var time:Number = current.time + trackDelta;
var endTime:Number = current.endTime;
current.time = time;
var trackDelta:Number = delta * current.timeScale;
current.time += trackDelta;
if (current.previous) {
current.previous.time += trackDelta;
current.mixTime += trackDelta;
}
// Check if completed the animation or a loop iteration.
if (current.loop ? (current.lastTime % endTime > time % endTime) : (current.lastTime < endTime && time >= endTime)) {
var count:int = (int)(time / endTime);
if (current.onComplete != null) current.onComplete(i, count);
if (onComplete != null) onComplete(i, count);
}
var next:TrackEntry = current.next;
if (next) {
if (time - trackDelta > next.delay) setCurrent(i, next);
if (current.lastTime >= 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);
@ -89,8 +79,10 @@ public class AnimationState {
_events.length = 0;
var time:Number = current.time;
var lastTime:Number = current.lastTime;
var endTime:Number = current.endTime;
var loop:Boolean = current.loop;
if (!loop && time > current.endTime) time = current.endTime;
if (!loop && time > endTime) time = endTime;
var previous:TrackEntry = current.previous;
if (!previous)
@ -112,7 +104,14 @@ public class AnimationState {
if (current.onEvent != null) current.onEvent(i, event);
if (onEvent != null) onEvent(i, event);
}
// Check if completed the animation or a loop iteration.
if (loop ? (lastTime % endTime > time % endTime) : (lastTime < endTime && time >= endTime)) {
var count:int = (int)(time / endTime);
if (current.onComplete != null) current.onComplete(i, count);
if (onComplete != null) onComplete(i, count);
}
current.lastTime = current.time;
}
}

View File

@ -85,33 +85,21 @@ void spAnimationState_dispose (spAnimationState* self) {
void spAnimationState_update (spAnimationState* self, float delta) {
int i;
float time, endTime, trackDelta;
float trackDelta;
delta *= self->timeScale;
for (i = 0; i < self->trackCount; i++) {
spTrackEntry* current = self->tracks[i];
if (!current) continue;
trackDelta = delta * current->timeScale;
time = current->time + trackDelta;
endTime = current->endTime;
current->time = time;
current->time += trackDelta;
if (current->previous) {
current->previous->time += trackDelta;
current->mixTime += trackDelta;
}
/* Check if completed the animation or a loop iteration. */
if (current->loop ?
(FMOD(current->lastTime, endTime) > FMOD(time, endTime)) : (current->lastTime < endTime && time >= endTime)) {
int count = (int)(time / endTime);
if (current->listener) current->listener(self, i, ANIMATION_COMPLETE, 0, count);
if (self->listener) self->listener(self, i, ANIMATION_COMPLETE, 0, count);
if (i >= self->trackCount || self->tracks[i] != current) continue;
}
if (current->next) {
if (time - trackDelta >= current->next->delay) _spAnimationState_setCurrent(self, i, current->next);
if (current->lastTime >= current->next->delay) _spAnimationState_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) spAnimationState_clearTrack(self, i);
@ -137,8 +125,7 @@ void spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
previous = current->previous;
if (!previous) {
spAnimation_apply(current->animation, skeleton, current->lastTime, time, current->loop, internal->events,
&eventCount);
spAnimation_apply(current->animation, skeleton, current->lastTime, time, current->loop, internal->events, &eventCount);
} else {
float alpha = current->mixTime / current->mixDuration;
@ -151,8 +138,8 @@ void spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
_spTrackEntry_dispose(current->previous);
current->previous = 0;
}
spAnimation_mix(current->animation, skeleton, current->lastTime, time, current->loop, internal->events,
&eventCount, alpha);
spAnimation_mix(current->animation, skeleton, current->lastTime, time, current->loop, internal->events, &eventCount,
alpha);
}
for (ii = 0; ii < eventCount; ii++) {
@ -161,6 +148,15 @@ void spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
if (self->listener) self->listener(self, i, ANIMATION_EVENT, event, 0);
}
/* Check if completed the animation or a loop iteration. */
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);
if (self->listener) self->listener(self, i, ANIMATION_COMPLETE, 0, count);
if (i >= self->trackCount || self->tracks[i] != current) continue;
}
if (i >= self->trackCount || self->tracks[i] != current) continue;
current->lastTime = current->time;
}
@ -222,7 +218,8 @@ void _spAnimationState_setCurrent (spAnimationState* self, int index, spTrackEnt
if (self->listener) self->listener(self, index, ANIMATION_START, 0, 0);
}
spTrackEntry* spAnimationState_setAnimationByName (spAnimationState* self, int trackIndex, const char* animationName, int/*bool*/loop) {
spTrackEntry* spAnimationState_setAnimationByName (spAnimationState* self, int trackIndex, const char* animationName,
int/*bool*/loop) {
spAnimation* animation = spSkeletonData_findAnimation(self->data->skeletonData, animationName);
return spAnimationState_setAnimation(self, trackIndex, animation, loop);
}
@ -241,13 +238,14 @@ spTrackEntry* spAnimationState_setAnimation (spAnimationState* self, int trackIn
return entry;
}
spTrackEntry* spAnimationState_addAnimationByName (spAnimationState* self, int trackIndex, const char* animationName, int/*bool*/loop,
float delay) {
spTrackEntry* spAnimationState_addAnimationByName (spAnimationState* self, int trackIndex, const char* animationName,
int/*bool*/loop, float delay) {
spAnimation* animation = spSkeletonData_findAnimation(self->data->skeletonData, animationName);
return spAnimationState_addAnimation(self, trackIndex, animation, loop, delay);
}
spTrackEntry* spAnimationState_addAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop, float delay) {
spTrackEntry* spAnimationState_addAnimation (spAnimationState* self, int trackIndex, spAnimation* animation, int/*bool*/loop,
float delay) {
spTrackEntry* last;
spTrackEntry* entry = _spTrackEntry_create();

View File

@ -142,7 +142,7 @@ spine.Slot.prototype = {
this.g = data.g;
this.b = data.b;
this.a = data.a;
var slotDatas = this.skeleton.data.slots;
for (var i = 0, n = slotDatas.length; i < n; i++) {
if (slotDatas[i] == data) {
@ -969,27 +969,17 @@ spine.AnimationState.prototype = {
for (var i = 0; i < this.tracks.length; i++) {
var current = this.tracks[i];
if (!current) continue;
var trackDelta = delta * current.timeScale;
var time = current.time + trackDelta;
var endTime = current.endTime;
current.time = time;
current.time += trackDelta;
if (current.previous) {
current.previous.time += trackDelta;
current.mixTime += trackDelta;
}
// Check if completed the animation or a loop iteration.
if (current.loop ? (current.lastTime % endTime > time % endTime) : (current.lastTime < endTime && time >= endTime)) {
var count = Math.floor(time / endTime);
if (current.onComplete) current.onComplete(i, count);
if (this.onComplete) this.onComplete(i, count);
}
var next = current.next;
if (next) {
if (time - trackDelta > next.delay) this.setCurrent(i, next);
if (current.lastTime >= next.delay) this.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) this.clearTrack(i);
@ -1000,13 +990,15 @@ spine.AnimationState.prototype = {
for (var i = 0; i < this.tracks.length; i++) {
var current = this.tracks[i];
if (!current) continue;
this.events.length = 0;
var time = current.time;
var lastTime = current.lastTime;
var endTime = current.endTime;
var loop = current.loop;
if (!loop && time > current.endTime) time = current.endTime;
if (!loop && time > endTime) time = endTime;
var previous = current.previous;
if (!previous)
current.animation.apply(skeleton, current.lastTime, time, loop, this.events);
@ -1014,7 +1006,7 @@ spine.AnimationState.prototype = {
var previousTime = previous.time;
if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime;
previous.animation.apply(skeleton, previousTime, previousTime, previous.loop, null);
var alpha = current.mixTime / current.mixDuration;
if (alpha >= 1) {
alpha = 1;
@ -1022,17 +1014,24 @@ spine.AnimationState.prototype = {
}
current.animation.mix(skeleton, current.lastTime, time, loop, this.events, alpha);
}
for (var ii = 0, nn = this.events.length; ii < nn; ii++) {
var event = this.events[ii];
if (current.onEvent != null) current.onEvent(i, event);
if (this.onEvent != null) this.onEvent(i, event);
}
// Check if completed the animation or a loop iteration.
if (loop ? (lastTime % endTime > time % endTime) : (lastTime < endTime && time >= endTime)) {
var count = Math.floor(time / endTime);
if (current.onComplete) current.onComplete(i, count);
if (this.onComplete) this.onComplete(i, count);
}
current.lastTime = current.time;
}
},
clearTracks: function () {
clearTracks: function () {
for (var i = 0, n = this.tracks.length; i < n; i++)
this.clearTrack(i);
this.tracks.length = 0;
@ -1057,19 +1056,19 @@ spine.AnimationState.prototype = {
var current = this._expandToIndex(index);
if (current) {
current.previous = null;
if (current.onEnd != null) current.onEnd(index);
if (this.onEnd != null) this.onEnd(index);
entry.mixDuration = this.data.getMix(current.animation, entry.animation);
if (entry.mixDuration > 0) {
entry.mixTime = 0;
entry.previous = current;
}
}
this.tracks[index] = entry;
if (entry.onStart != null) entry.onStart(index);
if (this.onStart != null) this.onStart(index);
},
@ -1099,7 +1098,7 @@ spine.AnimationState.prototype = {
entry.animation = animation;
entry.loop = loop;
entry.endTime = animation.duration;
var last = this._expandToIndex(trackIndex);
if (last) {
while (last.next)
@ -1107,7 +1106,7 @@ spine.AnimationState.prototype = {
last.next = entry;
} else
this.tracks[trackIndex] = entry;
if (delay <= 0) {
if (last) {
if (last.time < last.endTime) delay += last.endTime - last.time;
@ -1116,9 +1115,9 @@ spine.AnimationState.prototype = {
delay = 0;
}
entry.delay = delay;
return entry;
},
},
/** May be null. */
getCurrent: function (trackIndex) {
if (trackIndex >= this.tracks.length) return null;
@ -1669,7 +1668,7 @@ spine.SkeletonBounds.prototype = {
var boundingBoxes = this.boundingBoxes;
var polygonPool = this.polygonPool;
var polygons = this.polygons;
boundingBoxes.length = 0;
for (var i = 0, n = polygons.length; i < n; i++)
polygonPool.push(polygons[i]);
@ -1756,7 +1755,7 @@ spine.SkeletonBounds.prototype = {
},
/** Returns true if the polygon contains the point. */
polygonContainsPoint: function (polygon, x, y) {
var nn = polygon.length;
var nn = polygon.length;
var prevIndex = nn - 2;
var inside = false;
for (var ii = 0; ii < nn; ii += 2) {

View File

@ -57,26 +57,15 @@ public class AnimationState {
if (current == null) continue;
float trackDelta = delta * current.timeScale;
float time = current.time + trackDelta;
float endTime = current.endTime;
current.time = time;
current.time += trackDelta;
if (current.previous != null) {
current.previous.time += trackDelta;
current.mixTime += trackDelta;
}
// Check if completed the animation or a loop iteration.
if (current.loop ? (current.lastTime % endTime > time % endTime) : (current.lastTime < endTime && time >= endTime)) {
int count = (int)(time / endTime);
if (current.listener != null) current.listener.complete(i, count);
for (int ii = 0, nn = listeners.size; ii < nn; ii++)
listeners.get(ii).complete(i, count);
}
TrackEntry next = current.next;
if (next != null) {
if (time - trackDelta > next.delay) setCurrent(i, next);
if (current.lastTime >= 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);
@ -95,12 +84,14 @@ public class AnimationState {
events.size = 0;
float time = current.time;
float lastTime = current.lastTime;
float endTime = current.endTime;
boolean loop = current.loop;
if (!loop && time > current.endTime) time = current.endTime;
if (!loop && time > endTime) time = endTime;
TrackEntry previous = current.previous;
if (previous == null)
current.animation.apply(skeleton, current.lastTime, time, loop, events);
current.animation.apply(skeleton, lastTime, time, loop, events);
else {
float previousTime = previous.time;
if (!previous.loop && previousTime > previous.endTime) previousTime = previous.endTime;
@ -112,7 +103,7 @@ public class AnimationState {
Pools.free(previous);
current.previous = null;
}
current.animation.mix(skeleton, current.lastTime, time, loop, events, alpha);
current.animation.mix(skeleton, lastTime, time, loop, events, alpha);
}
for (int ii = 0, nn = events.size; ii < nn; ii++) {
@ -122,6 +113,14 @@ public class AnimationState {
listeners.get(iii).event(i, event);
}
// Check if completed the animation or a loop iteration.
if (loop ? (lastTime % endTime > time % endTime) : (lastTime < endTime && time >= endTime)) {
int count = (int)(time / endTime);
if (current.listener != null) current.listener.complete(i, count);
for (int ii = 0, nn = listeners.size; ii < nn; ii++)
listeners.get(ii).complete(i, count);
}
current.lastTime = current.time;
}
}

View File

@ -48,10 +48,10 @@ function AnimationState.new (data)
local current = self.tracks[index]
if current then
current.previous = nil
if current.onEnd then current.onEnd(index) end
if self.onEnd then self.onEnd(index) end
entry.mixDuration = self.data:getMix(current.animation.name, entry.animation.name)
if entry.mixDuration > 0 then
entry.mixTime = 0
@ -70,31 +70,15 @@ function AnimationState.new (data)
for i,current in pairs(self.tracks) do
if current then
local trackDelta = delta * current.timeScale
local time = current.time + trackDelta
local endTime = current.endTime
current.time = time
current.time = current.time + trackDelta
if current.previous then
current.previous.time = current.previous.time + trackDelta
current.mixTime = current.mixTime + trackDelta
end
-- Check if completed the animation or a loop iteration.
local complete
if current.loop then
complete = current.lastTime % endTime > time % endTime
else
complete = current.lastTime < endTime and time >= endTime
end
if complete then
local count = math.floor(time / endTime)
if current.onComplete then current.onComplete(i, count) end
if self.onComplete then self.onComplete(i, count) end
end
local next = current.next
if next then
if time - trackDelta > next.delay then setCurrent(i, next) end
if current.lastTime >= next.delay then setCurrent(i, next) end
else
-- End non-looping animation when it reaches its end time and there is no next entry.
if not current.loop and current.lastTime >= current.endTime then self:clearTrack(i) end
@ -102,14 +86,16 @@ function AnimationState.new (data)
end
end
end
function self:apply(skeleton)
for i,current in pairs(self.tracks) do
if current then
if current then
local time = current.time
local lastTime = current.lastTime
local endTime = current.endTime
local loop = current.loop
if not loop and time > current.endTime then time = current.endTime end
if not loop and time > endTime then time = endTime end
local previous = current.previous
if not previous then
current.animation:apply(skeleton, current.lastTime, time, loop, self.events)
@ -117,7 +103,7 @@ function AnimationState.new (data)
local previousTime = previous.time
if not previous.loop and previousTime > previous.endTime then previousTime = previous.endTime end
previous.animation:apply(skeleton, previousTime, previousTime, previous.loop, nil)
local alpha = current.mixTime / current.mixDuration
if alpha >= 1 then
alpha = 1
@ -125,7 +111,7 @@ function AnimationState.new (data)
end
current.animation:mix(skeleton, current.lastTime, time, loop, self.events, alpha)
end
local eventCount = #self.events
for ii = 1, eventCount, 1 do
local event = self.events[ii]
@ -136,18 +122,31 @@ function AnimationState.new (data)
table.remove(self.events)
end
-- Check if completed the animation or a loop iteration.
local complete
if current.loop then
complete = lastTime % endTime > time % endTime
else
complete = lastTime < endTime and time >= endTime
end
if complete then
local count = math.floor(time / endTime)
if current.onComplete then current.onComplete(i, count) end
if self.onComplete then self.onComplete(i, count) end
end
current.lastTime = current.time
end
end
end
function self:clearTracks ()
for i,current in pairs(self.tracks) do
self.clearTrack(i)
end
self.tracks = {}
end
function self:clearTrack (trackIndex)
local current = self.tracks[trackIndex]
if not current then return end
@ -157,7 +156,7 @@ function AnimationState.new (data)
self.tracks[trackIndex] = nil
end
function self:setAnimationByName (trackIndex, animationName, loop)
local animation = self.data.skeletonData:findAnimation(animationName)
if not animation then error("Animation not found: " + animationName) end
@ -173,7 +172,7 @@ function AnimationState.new (data)
setCurrent(trackIndex, entry)
return entry
end
function self:addAnimationByName (trackIndex, animationName, loop, delay)
local animation = self.data.skeletonData:findAnimation(animationName)
if not animation then error("Animation not found: " + animationName) end
@ -187,7 +186,7 @@ function AnimationState.new (data)
entry.animation = animation
entry.loop = loop
entry.endTime = animation.duration
local last = self.tracks[trackIndex]
if last then
while (last.next) do
@ -197,7 +196,7 @@ function AnimationState.new (data)
else
self.tracks[trackIndex] = entry
end
delay = delay or 0
if delay <= 0 then
if last then
@ -208,7 +207,7 @@ function AnimationState.new (data)
end
end
entry.delay = delay
return entry
end