diff --git a/spine-c/include/spine/Animation.h b/spine-c/include/spine/Animation.h index 576fcefe9..769134c9a 100644 --- a/spine-c/include/spine/Animation.h +++ b/spine-c/include/spine/Animation.h @@ -84,7 +84,9 @@ typedef enum { SP_TIMELINE_EVENT, SP_TIMELINE_DRAWORDER, SP_TIMELINE_FFD, - SP_TIMELINE_IKCONSTRAINT + SP_TIMELINE_IKCONSTRAINT, + SP_TIMELINE_FLIPX, + SP_TIMELINE_FLIPY } spTimelineType; struct spTimeline { @@ -304,6 +306,25 @@ typedef spIkConstraintTimeline IkConstraintTimeline; /**/ +typedef struct { + spCurveTimeline super; + int const x; + int const framesCount; + float* const frames; /* time, flip, ... */ +} spFlipTimeline; + +spFlipTimeline* spFlipTimeline_create (int framesCount, int/*bool*/x); + +void spFlipTimeline_setFrame (spFlipTimeline* self, int frameIndex, float time, int/*bool*/flip); + +#ifdef SPINE_SHORT_NAMES +typedef spFlipTimeline FlipTimeline; +#define FlipTimeline_create(...) spFlipTimeline_create(__VA_ARGS__) +#define FlipTimeline_setFrame(...) spFlipTimeline_setFrame(__VA_ARGS__) +#endif + +/**/ + #ifdef __cplusplus } #endif diff --git a/spine-c/src/spine/Animation.c b/spine-c/src/spine/Animation.c index e4f261eed..0178cfa85 100644 --- a/spine-c/src/spine/Animation.c +++ b/spine-c/src/spine/Animation.c @@ -664,7 +664,7 @@ void _spFFDTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, flo return; /* Time is before first frame. */ } - if (slot->attachmentVerticesCount != self->frameVerticesCount) alpha = 1; // Don't mix from uninitialized slot vertices. + if (slot->attachmentVerticesCount != self->frameVerticesCount) alpha = 1; /* Don't mix from uninitialized slot vertices. */ if (slot->attachmentVerticesCount < self->frameVerticesCount) { if (slot->attachmentVerticesCapacity < self->frameVerticesCount) { FREE(slot->attachmentVertices); @@ -789,3 +789,52 @@ void spIkConstraintTimeline_setFrame (spIkConstraintTimeline* self, int frameInd self->frames[frameIndex + 1] = mix; self->frames[frameIndex + 2] = (float)bendDirection; } + +/**/ + +void _spFlipTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, + spEvent** firedEvents, int* eventsCount, float alpha) { + int frameIndex; + spFlipTimeline* self = (spFlipTimeline*)timeline; + + if (time < self->frames[0]) { + if (lastTime > time) _spFlipTimeline_apply(timeline, skeleton, lastTime, (float)INT_MAX, 0, 0, 0); + return; + } else if (lastTime > time) /**/ + lastTime = -1; + + frameIndex = (time >= self->frames[self->framesCount - 2] ? + self->framesCount : binarySearch(self->frames, self->framesCount, time, 2)) - 2; + if (self->frames[frameIndex] <= lastTime) return; + + if (self->x) + skeleton->flipX = self->frames[frameIndex + 1]; + else + skeleton->flipY = self->frames[frameIndex + 1]; +} + +void _spFlipTimeline_dispose (spTimeline* timeline) { + spFlipTimeline* self = SUB_CAST(spFlipTimeline, timeline); + _spCurveTimeline_deinit(SUPER(self)); + FREE(self->frames); + FREE(self); +} + +spFlipTimeline* spFlipTimeline_create (int framesCount, int/*bool*/x) { + spFlipTimeline* self = NEW(spFlipTimeline); + _spCurveTimeline_init(SUPER(self), x ? SP_TIMELINE_FLIPX : SP_TIMELINE_FLIPY, framesCount, + _spFlipTimeline_dispose, _spFlipTimeline_apply); + CONST_CAST(int, self->x) = x; + CONST_CAST(int, self->framesCount) = framesCount << 1; + CONST_CAST(float*, self->frames) = CALLOC(float, self->framesCount); + return self; +} + +void spFlipTimeline_setFrame (spFlipTimeline* self, int frameIndex, float time, int/*bool*/flip) { + frameIndex <<= 1; + self->frames[frameIndex] = time; + self->frames[frameIndex + 1] = flip; +} + +/**/ + diff --git a/spine-c/src/spine/SkeletonJson.c b/spine-c/src/spine/SkeletonJson.c index 4fd5615cd..33ae757c1 100644 --- a/spine-c/src/spine/SkeletonJson.c +++ b/spine-c/src/spine/SkeletonJson.c @@ -113,6 +113,8 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r Json* ffd = Json_getItem(root, "ffd"); Json* drawOrder = Json_getItem(root, "draworder"); Json* events = Json_getItem(root, "events"); + Json* flipX = Json_getItem(root, "flipx"); + Json* flipY = Json_getItem(root, "flipy"); Json *boneMap, *slotMap, *ikMap, *ffdMap; int timelinesCount = 0; @@ -124,8 +126,10 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r for (ffdMap = ffd ? ffd->child : 0; ffdMap; ffdMap = ffdMap->next) for (slotMap = ffdMap->child; slotMap; slotMap = slotMap->next) timelinesCount += slotMap->size; - if (events) ++timelinesCount; if (drawOrder) ++timelinesCount; + if (events) ++timelinesCount; + if (flipX) ++timelinesCount; + if (flipY) ++timelinesCount; animation = spAnimation_create(root->name, timelinesCount); animation->timelinesCount = 0; @@ -312,6 +316,26 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r } } + /* Flip timelines. */ + if (flipX) { + Json* frame; + spFlipTimeline* timeline = spFlipTimeline_create(flipX->size, 1); + for (frame = flipX->child, i = 0; frame; frame = frame->next, ++i) + spFlipTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), Json_getInt(frame, "x", 0)); + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + duration = timeline->frames[flipX->size * 2 - 2]; + if (duration > animation->duration) animation->duration = duration; + } + if (flipY) { + Json* frame; + spFlipTimeline* timeline = spFlipTimeline_create(flipY->size, 0); + for (frame = flipY->child, i = 0; frame; frame = frame->next, ++i) + spFlipTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), Json_getInt(frame, "y", 0)); + animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); + duration = timeline->frames[flipY->size * 2 - 2]; + if (duration > animation->duration) animation->duration = duration; + } + /* Draw order timeline. */ if (drawOrder) { spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrder->size, skeletonData->slotsCount);