[c] Ported Animation State changes, see #908

This commit is contained in:
badlogic 2017-05-24 12:53:40 +02:00
parent eb8cc49ed1
commit 7593da8cb8
2 changed files with 32 additions and 24 deletions

View File

@ -61,7 +61,7 @@ struct spTrackEntry {
float eventThreshold, attachmentThreshold, drawOrderThreshold; float eventThreshold, attachmentThreshold, drawOrderThreshold;
float animationStart, animationEnd, animationLast, nextAnimationLast; float animationStart, animationEnd, animationLast, nextAnimationLast;
float delay, trackTime, trackLast, nextTrackLast, trackEnd, timeScale; float delay, trackTime, trackLast, nextTrackLast, trackEnd, timeScale;
float alpha, mixTime, mixDuration, interruptAlpha; float alpha, mixTime, mixDuration, interruptAlpha, totalAlpha;
spIntArray* timelineData; spIntArray* timelineData;
spTrackEntryArray* timelineDipMix; spTrackEntryArray* timelineDipMix;
float* timelinesRotation; float* timelinesRotation;
@ -79,7 +79,7 @@ struct spTrackEntry {
eventThreshold(0), attachmentThreshold(0), drawOrderThreshold(0), eventThreshold(0), attachmentThreshold(0), drawOrderThreshold(0),
animationStart(0), animationEnd(0), animationLast(0), nextAnimationLast(0), animationStart(0), animationEnd(0), animationLast(0), nextAnimationLast(0),
delay(0), trackTime(0), trackLast(0), nextTrackLast(0), trackEnd(0), timeScale(0), delay(0), trackTime(0), trackLast(0), nextTrackLast(0), trackEnd(0), timeScale(0),
alpha(0), mixTime(0), mixDuration(0), interruptAlpha(0), alpha(0), mixTime(0), mixDuration(0), interruptAlpha(0), totalAlpha(0),
timelineData(0), timelineData(0),
timelineDipMix(0), timelineDipMix(0),
timelinesRotation(0), timelinesRotation(0),

View File

@ -35,6 +35,7 @@
#define SUBSEQUENT 0 #define SUBSEQUENT 0
#define FIRST 1 #define FIRST 1
#define DIP 2 #define DIP 2
#define DIP_MIX 3
_SP_ARRAY_IMPLEMENT_TYPE(spTrackEntryArray, spTrackEntry*) _SP_ARRAY_IMPLEMENT_TYPE(spTrackEntryArray, spTrackEntry*)
@ -48,7 +49,7 @@ void spAnimationState_disposeStatics () {
the same function order in C as we have method order in Java */ the same function order in C as we have method order in Java */
void _spAnimationState_disposeTrackEntry (spTrackEntry* entry); void _spAnimationState_disposeTrackEntry (spTrackEntry* entry);
void _spAnimationState_disposeTrackEntries (spAnimationState* state, spTrackEntry* entry); void _spAnimationState_disposeTrackEntries (spAnimationState* state, spTrackEntry* entry);
int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTrackEntry* entry, float delta, int animationCount); int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTrackEntry* entry, float delta);
float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* entry, spSkeleton* skeleton); float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* entry, spSkeleton* skeleton);
void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, int /*boolean*/ setupPose, float* timelinesRotation, int i, int /*boolean*/ firstFrame); void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* timeline, spSkeleton* skeleton, float time, float alpha, int /*boolean*/ setupPose, float* timelinesRotation, int i, int /*boolean*/ firstFrame);
void _spAnimationState_queueEvents (spAnimationState* self, spTrackEntry* entry, float animationTime); void _spAnimationState_queueEvents (spAnimationState* self, spTrackEntry* entry, float animationTime);
@ -285,7 +286,7 @@ void spAnimationState_update (spAnimationState* self, float delta) {
continue; continue;
} }
} }
if (current->mixingFrom != 0 && _spAnimationState_updateMixingFrom(self, current, delta, 2)) { if (current->mixingFrom != 0 && _spAnimationState_updateMixingFrom(self, current, delta)) {
/* End mixing from entries once all have completed. */ /* End mixing from entries once all have completed. */
spTrackEntry* from = current->mixingFrom; spTrackEntry* from = current->mixingFrom;
current->mixingFrom = 0; current->mixingFrom = 0;
@ -301,23 +302,20 @@ void spAnimationState_update (spAnimationState* self, float delta) {
_spEventQueue_drain(internal->queue); _spEventQueue_drain(internal->queue);
} }
int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTrackEntry* entry, float delta, int animationCount) { int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTrackEntry* to, float delta) {
spTrackEntry* from = entry->mixingFrom; spTrackEntry* from = to->mixingFrom;
int finished; int finished;
_spAnimationState* internal = SUB_CAST(_spAnimationState, self); _spAnimationState* internal = SUB_CAST(_spAnimationState, self);
if (!from) return -1; if (!from) return -1;
finished = _spAnimationState_updateMixingFrom(self, from, delta, animationCount + 1); finished = _spAnimationState_updateMixingFrom(self, from, delta);
/* Require mixTime > 0 to ensure the mixing from entry was applied at least once. */ /* Require mixTime > 0 to ensure the mixing from entry was applied at least once. */
if (entry->mixTime > 0 && (entry->mixTime >= entry->mixDuration || entry->timeScale == 0)) { if (to->mixTime > 0 && (to->mixTime >= to->mixDuration || to->timeScale == 0)) {
if (animationCount > 5 && from->mixingFrom == 0) { if (from->totalAlpha == 0) {
/* Limit linked list by speeding up and removing old entries. */ to->mixingFrom = from->mixingFrom;
entry->interruptAlpha = MAX(0, entry->interruptAlpha - delta * 0.66f); to->interruptAlpha = from->interruptAlpha;
if (entry->interruptAlpha <= 0) { _spEventQueue_end(internal->queue, from);
entry->mixingFrom = 0;
_spEventQueue_end(internal->queue, from);
}
} }
return finished; return finished;
} }
@ -325,7 +323,7 @@ int /*boolean*/ _spAnimationState_updateMixingFrom (spAnimationState* self, spTr
from->animationLast = from->nextAnimationLast; from->animationLast = from->nextAnimationLast;
from->trackLast = from->nextTrackLast; from->trackLast = from->nextTrackLast;
from->trackTime += delta * from->timeScale; from->trackTime += delta * from->timeScale;
entry->mixTime += delta * entry->timeScale; to->mixTime += delta * to->timeScale;
return 0; return 0;
} }
@ -371,9 +369,9 @@ void spAnimationState_apply (spAnimationState* self, spSkeleton* skeleton) {
for (ii = 0; ii < timelineCount; ii++) { for (ii = 0; ii < timelineCount; ii++) {
timeline = timelines[ii]; timeline = timelines[ii];
if (timeline->type == SP_TIMELINE_ROTATE) if (timeline->type == SP_TIMELINE_ROTATE)
_spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, mix, timelineData->items[ii] > 0, timelinesRotation, ii << 1, firstFrame); _spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, mix, timelineData->items[ii] >= FIRST, timelinesRotation, ii << 1, firstFrame);
else else
spTimeline_apply(timeline, skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, mix, timelineData->items[ii] > 0, 0); spTimeline_apply(timeline, skeleton, animationLast, animationTime, internal->events, &internal->eventsCount, mix, timelineData->items[ii] >= FIRST, 0);
} }
} }
_spAnimationState_queueEvents(self, current, animationTime); _spAnimationState_queueEvents(self, current, animationTime);
@ -432,6 +430,7 @@ float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* t
first = 0; first = 0;
alphaDip = from->alpha * to->interruptAlpha; alphaMix = alphaDip * (1 - mix); alphaDip = from->alpha * to->interruptAlpha; alphaMix = alphaDip * (1 - mix);
from->totalAlpha = 0;
for (i = 0; i < timelineCount; i++) { for (i = 0; i < timelineCount; i++) {
spTimeline* timeline = timelines[i]; spTimeline* timeline = timelines[i];
switch (timelineData->items[i]) { switch (timelineData->items[i]) {
@ -443,13 +442,18 @@ float _spAnimationState_applyMixingFrom (spAnimationState* self, spTrackEntry* t
first = 1; first = 1;
alpha = alphaMix; alpha = alphaMix;
break; break;
case DIP:
first = 1;
alpha = alphaDip;
break;
default: default:
first = 1; first = 1;
alpha = alphaDip; alpha = alphaDip;
dipMix = timelineDipMix->items[i]; dipMix = timelineDipMix->items[i];
if (dipMix != 0) alpha *= MAX(0, 1 - dipMix->mixTime / dipMix->mixDuration); alpha *= MAX(0, 1 - dipMix->mixTime / dipMix->mixDuration);
break; break;
} }
from->totalAlpha += alpha;
if (timeline->type == SP_TIMELINE_ROTATE) if (timeline->type == SP_TIMELINE_ROTATE)
_spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, alpha, first, timelinesRotation, i << 1, firstFrame); _spAnimationState_applyRotateTimeline(self, timeline, skeleton, animationTime, alpha, first, timelinesRotation, i << 1, firstFrame);
else { else {
@ -892,6 +896,7 @@ spTrackEntry* _spTrackEntry_setTimelineData(spTrackEntry* self, spTrackEntry* to
timelines = self->animation->timelines; timelines = self->animation->timelines;
timelinesCount = self->animation->timelinesCount; timelinesCount = self->animation->timelinesCount;
timelineData = spIntArray_setSize(self->timelineData, timelinesCount)->items; timelineData = spIntArray_setSize(self->timelineData, timelinesCount)->items;
spTrackEntryArray_clear(self->timelineDipMix);
timelineDipMix = spTrackEntryArray_setSize(self->timelineDipMix, timelinesCount)->items; timelineDipMix = spTrackEntryArray_setSize(self->timelineDipMix, timelinesCount)->items;
outer: outer:
@ -902,16 +907,19 @@ spTrackEntry* _spTrackEntry_setTimelineData(spTrackEntry* self, spTrackEntry* to
else if (to == 0 || !_spTrackEntry_hasTimeline(to, id)) else if (to == 0 || !_spTrackEntry_hasTimeline(to, id))
timelineData[i] = FIRST; timelineData[i] = FIRST;
else { else {
timelineData[i] = DIP;
for (ii = mixingToLast; ii >= 0; ii--) { for (ii = mixingToLast; ii >= 0; ii--) {
spTrackEntry* entry = mixingTo[ii]; spTrackEntry* entry = mixingTo[ii];
if (!_spTrackEntry_hasTimeline(entry, id)) { if (!_spTrackEntry_hasTimeline(entry, id)) {
if (entry->mixDuration > 0) timelineDipMix[i] = entry; if (entry->mixDuration > 0) {
i++; timelineData[i] = DIP_MIX;
goto outer; timelineDipMix[i] = entry;
i++;
goto outer;
}
} }
break;
} }
timelineDipMix[i] = 0; timelineData[i] = DIP;
} }
} }
return lastEntry; return lastEntry;