mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-03-26 22:49:01 +08:00
FFD for spine-c and spine-sfml.
This commit is contained in:
parent
6432e43ea2
commit
99a8de4bb4
@ -32,6 +32,7 @@
|
|||||||
#define SPINE_ANIMATION_H_
|
#define SPINE_ANIMATION_H_
|
||||||
|
|
||||||
#include <spine/Event.h>
|
#include <spine/Event.h>
|
||||||
|
#include <spine/Attachment.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -81,7 +82,8 @@ typedef enum {
|
|||||||
SP_TIMELINE_COLOR,
|
SP_TIMELINE_COLOR,
|
||||||
SP_TIMELINE_ATTACHMENT,
|
SP_TIMELINE_ATTACHMENT,
|
||||||
SP_TIMELINE_EVENT,
|
SP_TIMELINE_EVENT,
|
||||||
SP_TIMELINE_DRAWORDER
|
SP_TIMELINE_DRAWORDER,
|
||||||
|
SP_TIMELINE_FFD
|
||||||
} spTimelineType;
|
} spTimelineType;
|
||||||
|
|
||||||
struct spTimeline {
|
struct spTimeline {
|
||||||
@ -135,7 +137,7 @@ typedef spCurveTimeline CurveTimeline;
|
|||||||
|
|
||||||
typedef struct spBaseTimeline {
|
typedef struct spBaseTimeline {
|
||||||
spCurveTimeline super;
|
spCurveTimeline super;
|
||||||
int const framesLength;
|
int const framesCount;
|
||||||
float* const frames; /* time, angle, ... for rotate. time, x, y, ... for translate and scale. */
|
float* const frames; /* time, angle, ... for rotate. time, x, y, ... for translate and scale. */
|
||||||
int boneIndex;
|
int boneIndex;
|
||||||
} spRotateTimeline;
|
} spRotateTimeline;
|
||||||
@ -182,7 +184,7 @@ typedef spScaleTimeline ScaleTimeline;
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spCurveTimeline super;
|
spCurveTimeline super;
|
||||||
int const framesLength;
|
int const framesCount;
|
||||||
float* const frames; /* time, r, g, b, a, ... */
|
float* const frames; /* time, r, g, b, a, ... */
|
||||||
int slotIndex;
|
int slotIndex;
|
||||||
} spColorTimeline;
|
} spColorTimeline;
|
||||||
@ -201,7 +203,7 @@ typedef spColorTimeline ColorTimeline;
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spTimeline super;
|
spTimeline super;
|
||||||
int const framesLength;
|
int const framesCount;
|
||||||
float* const frames; /* time, ... */
|
float* const frames; /* time, ... */
|
||||||
int slotIndex;
|
int slotIndex;
|
||||||
const char** const attachmentNames;
|
const char** const attachmentNames;
|
||||||
@ -222,7 +224,7 @@ typedef spAttachmentTimeline AttachmentTimeline;
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spTimeline super;
|
spTimeline super;
|
||||||
int const framesLength;
|
int const framesCount;
|
||||||
float* const frames; /* time, ... */
|
float* const frames; /* time, ... */
|
||||||
spEvent** const events;
|
spEvent** const events;
|
||||||
} spEventTimeline;
|
} spEventTimeline;
|
||||||
@ -241,7 +243,7 @@ typedef spEventTimeline EventTimeline;
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spTimeline super;
|
spTimeline super;
|
||||||
int const framesLength;
|
int const framesCount;
|
||||||
float* const frames; /* time, ... */
|
float* const frames; /* time, ... */
|
||||||
const int** const drawOrders;
|
const int** const drawOrders;
|
||||||
int const slotCount;
|
int const slotCount;
|
||||||
@ -257,6 +259,28 @@ typedef spDrawOrderTimeline DrawOrderTimeline;
|
|||||||
#define DrawOrderTimeline_setFrame(...) spDrawOrderTimeline_setFrame(__VA_ARGS__)
|
#define DrawOrderTimeline_setFrame(...) spDrawOrderTimeline_setFrame(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
spCurveTimeline super;
|
||||||
|
int const framesCount;
|
||||||
|
float* const frames; /* time, ... */
|
||||||
|
int const frameVerticesCount;
|
||||||
|
const float** const frameVertices;
|
||||||
|
int slotIndex;
|
||||||
|
spAttachment* attachment;
|
||||||
|
} spFFDTimeline;
|
||||||
|
|
||||||
|
spFFDTimeline* spFFDTimeline_create (int frameCount, int frameVerticesCount);
|
||||||
|
|
||||||
|
void spFFDTimeline_setFrame (spFFDTimeline* self, int frameIndex, float time, float* vertices);
|
||||||
|
|
||||||
|
#ifdef SPINE_SHORT_NAMES
|
||||||
|
typedef spFFDTimeline FFDTimeline;
|
||||||
|
#define FFDTimeline_create(...) spFFDTimeline_create(__VA_ARGS__)
|
||||||
|
#define FFDTimeline_setFrame(...) spFFDTimeline_setFrame(__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -48,6 +48,7 @@ typedef struct spSlot {
|
|||||||
float r, g, b, a;
|
float r, g, b, a;
|
||||||
spAttachment* const attachment;
|
spAttachment* const attachment;
|
||||||
|
|
||||||
|
int attachmentVerticesCapacity;
|
||||||
int attachmentVerticesCount;
|
int attachmentVerticesCount;
|
||||||
float* attachmentVertices;
|
float* attachmentVertices;
|
||||||
} spSlot;
|
} spSlot;
|
||||||
|
|||||||
@ -233,8 +233,8 @@ struct spBaseTimeline* _spBaseTimeline_create (int frameCount, spTimelineType ty
|
|||||||
struct spBaseTimeline* self = NEW(struct spBaseTimeline);
|
struct spBaseTimeline* self = NEW(struct spBaseTimeline);
|
||||||
_spCurveTimeline_init(SUPER(self), type, frameCount, _spBaseTimeline_dispose, apply);
|
_spCurveTimeline_init(SUPER(self), type, frameCount, _spBaseTimeline_dispose, apply);
|
||||||
|
|
||||||
CONST_CAST(int, self->framesLength) = frameCount * frameSize;
|
CONST_CAST(int, self->framesCount) = frameCount * frameSize;
|
||||||
CONST_CAST(float*, self->frames) = CALLOC(float, self->framesLength);
|
CONST_CAST(float*, self->frames) = CALLOC(float, self->framesCount);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -256,8 +256,8 @@ void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton,
|
|||||||
|
|
||||||
bone = skeleton->bones[self->boneIndex];
|
bone = skeleton->bones[self->boneIndex];
|
||||||
|
|
||||||
if (time >= self->frames[self->framesLength - 2]) { /* Time is after last frame. */
|
if (time >= self->frames[self->framesCount - 2]) { /* Time is after last frame. */
|
||||||
float amount = bone->data->rotation + self->frames[self->framesLength - 1] - bone->rotation;
|
float amount = bone->data->rotation + self->frames[self->framesCount - 1] - bone->rotation;
|
||||||
while (amount > 180)
|
while (amount > 180)
|
||||||
amount -= 360;
|
amount -= 360;
|
||||||
while (amount < -180)
|
while (amount < -180)
|
||||||
@ -266,8 +266,8 @@ void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Interpolate between the last frame and the current frame. */
|
/* Interpolate between the previous frame and the current frame. */
|
||||||
frameIndex = binarySearch(self->frames, self->framesLength, time, 2);
|
frameIndex = binarySearch(self->frames, self->framesCount, time, 2);
|
||||||
lastFrameValue = self->frames[frameIndex - 1];
|
lastFrameValue = self->frames[frameIndex - 1];
|
||||||
frameTime = self->frames[frameIndex];
|
frameTime = self->frames[frameIndex];
|
||||||
percent = 1 - (time - frameTime) / (self->frames[frameIndex + ROTATE_LAST_FRAME_TIME] - frameTime);
|
percent = 1 - (time - frameTime) / (self->frames[frameIndex + ROTATE_LAST_FRAME_TIME] - frameTime);
|
||||||
@ -314,14 +314,14 @@ void _spTranslateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleto
|
|||||||
|
|
||||||
bone = skeleton->bones[self->boneIndex];
|
bone = skeleton->bones[self->boneIndex];
|
||||||
|
|
||||||
if (time >= self->frames[self->framesLength - 3]) { /* Time is after last frame. */
|
if (time >= self->frames[self->framesCount - 3]) { /* Time is after last frame. */
|
||||||
bone->x += (bone->data->x + self->frames[self->framesLength - 2] - bone->x) * alpha;
|
bone->x += (bone->data->x + self->frames[self->framesCount - 2] - bone->x) * alpha;
|
||||||
bone->y += (bone->data->y + self->frames[self->framesLength - 1] - bone->y) * alpha;
|
bone->y += (bone->data->y + self->frames[self->framesCount - 1] - bone->y) * alpha;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Interpolate between the last frame and the current frame. */
|
/* Interpolate between the previous frame and the current frame. */
|
||||||
frameIndex = binarySearch(self->frames, self->framesLength, time, 3);
|
frameIndex = binarySearch(self->frames, self->framesCount, time, 3);
|
||||||
lastFrameX = self->frames[frameIndex - 2];
|
lastFrameX = self->frames[frameIndex - 2];
|
||||||
lastFrameY = self->frames[frameIndex - 1];
|
lastFrameY = self->frames[frameIndex - 1];
|
||||||
frameTime = self->frames[frameIndex];
|
frameTime = self->frames[frameIndex];
|
||||||
@ -358,14 +358,14 @@ void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
|
|||||||
if (time < self->frames[0]) return; /* Time is before first frame. */
|
if (time < self->frames[0]) return; /* Time is before first frame. */
|
||||||
|
|
||||||
bone = skeleton->bones[self->boneIndex];
|
bone = skeleton->bones[self->boneIndex];
|
||||||
if (time >= self->frames[self->framesLength - 3]) { /* Time is after last frame. */
|
if (time >= self->frames[self->framesCount - 3]) { /* Time is after last frame. */
|
||||||
bone->scaleX += (bone->data->scaleX - 1 + self->frames[self->framesLength - 2] - bone->scaleX) * alpha;
|
bone->scaleX += (bone->data->scaleX - 1 + self->frames[self->framesCount - 2] - bone->scaleX) * alpha;
|
||||||
bone->scaleY += (bone->data->scaleY - 1 + self->frames[self->framesLength - 1] - bone->scaleY) * alpha;
|
bone->scaleY += (bone->data->scaleY - 1 + self->frames[self->framesCount - 1] - bone->scaleY) * alpha;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Interpolate between the last frame and the current frame. */
|
/* Interpolate between the previous frame and the current frame. */
|
||||||
frameIndex = binarySearch(self->frames, self->framesLength, time, 3);
|
frameIndex = binarySearch(self->frames, self->framesCount, time, 3);
|
||||||
lastFrameX = self->frames[frameIndex - 2];
|
lastFrameX = self->frames[frameIndex - 2];
|
||||||
lastFrameY = self->frames[frameIndex - 1];
|
lastFrameY = self->frames[frameIndex - 1];
|
||||||
frameTime = self->frames[frameIndex];
|
frameTime = self->frames[frameIndex];
|
||||||
@ -406,16 +406,16 @@ void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
|
|||||||
|
|
||||||
slot = skeleton->slots[self->slotIndex];
|
slot = skeleton->slots[self->slotIndex];
|
||||||
|
|
||||||
if (time >= self->frames[self->framesLength - 5]) {
|
if (time >= self->frames[self->framesCount - 5]) {
|
||||||
/* Time is after last frame. */
|
/* Time is after last frame. */
|
||||||
int i = self->framesLength - 1;
|
int i = self->framesCount - 1;
|
||||||
r = self->frames[i - 3];
|
r = self->frames[i - 3];
|
||||||
g = self->frames[i - 2];
|
g = self->frames[i - 2];
|
||||||
b = self->frames[i - 1];
|
b = self->frames[i - 1];
|
||||||
a = self->frames[i];
|
a = self->frames[i];
|
||||||
} else {
|
} else {
|
||||||
/* Interpolate between the last frame and the current frame. */
|
/* Interpolate between the previous frame and the current frame. */
|
||||||
frameIndex = binarySearch(self->frames, self->framesLength, time, 5);
|
frameIndex = binarySearch(self->frames, self->framesCount, time, 5);
|
||||||
lastFrameR = self->frames[frameIndex - 4];
|
lastFrameR = self->frames[frameIndex - 4];
|
||||||
lastFrameG = self->frames[frameIndex - 3];
|
lastFrameG = self->frames[frameIndex - 3];
|
||||||
lastFrameB = self->frames[frameIndex - 2];
|
lastFrameB = self->frames[frameIndex - 2];
|
||||||
@ -465,10 +465,10 @@ void _spAttachmentTimeline_apply (const spTimeline* timeline, spSkeleton* skelet
|
|||||||
|
|
||||||
if (time < self->frames[0]) return; /* Time is before first frame. */
|
if (time < self->frames[0]) return; /* Time is before first frame. */
|
||||||
|
|
||||||
if (time >= self->frames[self->framesLength - 1]) /* Time is after last frame. */
|
if (time >= self->frames[self->framesCount - 1]) /* Time is after last frame. */
|
||||||
frameIndex = self->framesLength - 1;
|
frameIndex = self->framesCount - 1;
|
||||||
else
|
else
|
||||||
frameIndex = binarySearch(self->frames, self->framesLength, time, 1) - 1;
|
frameIndex = binarySearch(self->frames, self->framesCount, time, 1) - 1;
|
||||||
|
|
||||||
attachmentName = self->attachmentNames[frameIndex];
|
attachmentName = self->attachmentNames[frameIndex];
|
||||||
spSlot_setAttachment(skeleton->slots[self->slotIndex],
|
spSlot_setAttachment(skeleton->slots[self->slotIndex],
|
||||||
@ -481,7 +481,7 @@ void _spAttachmentTimeline_dispose (spTimeline* timeline) {
|
|||||||
|
|
||||||
_spTimeline_deinit(timeline);
|
_spTimeline_deinit(timeline);
|
||||||
|
|
||||||
for (i = 0; i < self->framesLength; ++i)
|
for (i = 0; i < self->framesCount; ++i)
|
||||||
FREE(self->attachmentNames[i]);
|
FREE(self->attachmentNames[i]);
|
||||||
FREE(self->attachmentNames);
|
FREE(self->attachmentNames);
|
||||||
FREE(self->frames);
|
FREE(self->frames);
|
||||||
@ -492,7 +492,7 @@ spAttachmentTimeline* spAttachmentTimeline_create (int frameCount) {
|
|||||||
spAttachmentTimeline* self = NEW(spAttachmentTimeline);
|
spAttachmentTimeline* self = NEW(spAttachmentTimeline);
|
||||||
_spTimeline_init(SUPER(self), SP_TIMELINE_ATTACHMENT, _spAttachmentTimeline_dispose, _spAttachmentTimeline_apply);
|
_spTimeline_init(SUPER(self), SP_TIMELINE_ATTACHMENT, _spAttachmentTimeline_dispose, _spAttachmentTimeline_apply);
|
||||||
|
|
||||||
CONST_CAST(int, self->framesLength) = frameCount;
|
CONST_CAST(int, self->framesCount) = frameCount;
|
||||||
CONST_CAST(float*, self->frames) = CALLOC(float, frameCount);
|
CONST_CAST(float*, self->frames) = CALLOC(float, frameCount);
|
||||||
CONST_CAST(char**, self->attachmentNames) = CALLOC(char*, frameCount);
|
CONST_CAST(char**, self->attachmentNames) = CALLOC(char*, frameCount);
|
||||||
|
|
||||||
@ -521,22 +521,22 @@ void _spEventTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f
|
|||||||
if (lastTime > time) { /* Fire events after last time for looped animations. */
|
if (lastTime > time) { /* Fire events after last time for looped animations. */
|
||||||
_spEventTimeline_apply(timeline, skeleton, lastTime, (float)INT_MAX, firedEvents, eventCount, alpha);
|
_spEventTimeline_apply(timeline, skeleton, lastTime, (float)INT_MAX, firedEvents, eventCount, alpha);
|
||||||
lastTime = -1;
|
lastTime = -1;
|
||||||
} else if (lastTime >= self->frames[self->framesLength - 1]) /* Last time is after last frame. */
|
} else if (lastTime >= self->frames[self->framesCount - 1]) /* Last time is after last frame. */
|
||||||
return;
|
return;
|
||||||
if (time < self->frames[0]) return; /* Time is before first frame. */
|
if (time < self->frames[0]) return; /* Time is before first frame. */
|
||||||
|
|
||||||
if (lastTime < self->frames[0])
|
if (lastTime < self->frames[0])
|
||||||
frameIndex = 0;
|
frameIndex = 0;
|
||||||
else {
|
else {
|
||||||
float frame;
|
float frame;
|
||||||
frameIndex = binarySearch(self->frames, self->framesLength, lastTime, 1);
|
frameIndex = binarySearch(self->frames, self->framesCount, lastTime, 1);
|
||||||
frame = self->frames[frameIndex];
|
frame = self->frames[frameIndex];
|
||||||
while (frameIndex > 0) { /* Fire multiple events with the same frame. */
|
while (frameIndex > 0) { /* Fire multiple events with the same frame. */
|
||||||
if (self->frames[frameIndex - 1] != frame) break;
|
if (self->frames[frameIndex - 1] != frame) break;
|
||||||
frameIndex--;
|
frameIndex--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (; frameIndex < self->framesLength && time >= self->frames[frameIndex]; frameIndex++) {
|
for (; frameIndex < self->framesCount && time >= self->frames[frameIndex]; frameIndex++) {
|
||||||
firedEvents[*eventCount] = self->events[frameIndex];
|
firedEvents[*eventCount] = self->events[frameIndex];
|
||||||
(*eventCount)++;
|
(*eventCount)++;
|
||||||
}
|
}
|
||||||
@ -548,7 +548,7 @@ void _spEventTimeline_dispose (spTimeline* timeline) {
|
|||||||
|
|
||||||
_spTimeline_deinit(timeline);
|
_spTimeline_deinit(timeline);
|
||||||
|
|
||||||
for (i = 0; i < self->framesLength; ++i)
|
for (i = 0; i < self->framesCount; ++i)
|
||||||
spEvent_dispose(self->events[i]);
|
spEvent_dispose(self->events[i]);
|
||||||
FREE(self->events);
|
FREE(self->events);
|
||||||
FREE(self->frames);
|
FREE(self->frames);
|
||||||
@ -559,7 +559,7 @@ spEventTimeline* spEventTimeline_create (int frameCount) {
|
|||||||
spEventTimeline* self = NEW(spEventTimeline);
|
spEventTimeline* self = NEW(spEventTimeline);
|
||||||
_spTimeline_init(SUPER(self), SP_TIMELINE_EVENT, _spEventTimeline_dispose, _spEventTimeline_apply);
|
_spTimeline_init(SUPER(self), SP_TIMELINE_EVENT, _spEventTimeline_dispose, _spEventTimeline_apply);
|
||||||
|
|
||||||
CONST_CAST(int, self->framesLength) = frameCount;
|
CONST_CAST(int, self->framesCount) = frameCount;
|
||||||
CONST_CAST(float*, self->frames) = CALLOC(float, frameCount);
|
CONST_CAST(float*, self->frames) = CALLOC(float, frameCount);
|
||||||
CONST_CAST(spEvent**, self->events) = CALLOC(spEvent*, frameCount);
|
CONST_CAST(spEvent**, self->events) = CALLOC(spEvent*, frameCount);
|
||||||
|
|
||||||
@ -584,10 +584,10 @@ void _spDrawOrderTimeline_apply (const spTimeline* timeline, spSkeleton* skeleto
|
|||||||
|
|
||||||
if (time < self->frames[0]) return; /* Time is before first frame. */
|
if (time < self->frames[0]) return; /* Time is before first frame. */
|
||||||
|
|
||||||
if (time >= self->frames[self->framesLength - 1]) /* Time is after last frame. */
|
if (time >= self->frames[self->framesCount - 1]) /* Time is after last frame. */
|
||||||
frameIndex = self->framesLength - 1;
|
frameIndex = self->framesCount - 1;
|
||||||
else
|
else
|
||||||
frameIndex = binarySearch(self->frames, self->framesLength, time, 1) - 1;
|
frameIndex = binarySearch(self->frames, self->framesCount, time, 1) - 1;
|
||||||
|
|
||||||
drawOrderToSetupIndex = self->drawOrders[frameIndex];
|
drawOrderToSetupIndex = self->drawOrders[frameIndex];
|
||||||
if (!drawOrderToSetupIndex)
|
if (!drawOrderToSetupIndex)
|
||||||
@ -604,7 +604,7 @@ void _spDrawOrderTimeline_dispose (spTimeline* timeline) {
|
|||||||
|
|
||||||
_spTimeline_deinit(timeline);
|
_spTimeline_deinit(timeline);
|
||||||
|
|
||||||
for (i = 0; i < self->framesLength; ++i)
|
for (i = 0; i < self->framesCount; ++i)
|
||||||
FREE(self->drawOrders[i]);
|
FREE(self->drawOrders[i]);
|
||||||
FREE(self->drawOrders);
|
FREE(self->drawOrders);
|
||||||
FREE(self->frames);
|
FREE(self->frames);
|
||||||
@ -615,7 +615,7 @@ spDrawOrderTimeline* spDrawOrderTimeline_create (int frameCount, int slotCount)
|
|||||||
spDrawOrderTimeline* self = NEW(spDrawOrderTimeline);
|
spDrawOrderTimeline* self = NEW(spDrawOrderTimeline);
|
||||||
_spTimeline_init(SUPER(self), SP_TIMELINE_DRAWORDER, _spDrawOrderTimeline_dispose, _spDrawOrderTimeline_apply);
|
_spTimeline_init(SUPER(self), SP_TIMELINE_DRAWORDER, _spDrawOrderTimeline_dispose, _spDrawOrderTimeline_apply);
|
||||||
|
|
||||||
CONST_CAST(int, self->framesLength) = frameCount;
|
CONST_CAST(int, self->framesCount) = frameCount;
|
||||||
CONST_CAST(float*, self->frames) = CALLOC(float, frameCount);
|
CONST_CAST(float*, self->frames) = CALLOC(float, frameCount);
|
||||||
CONST_CAST(int**, self->drawOrders) = CALLOC(int*, frameCount);
|
CONST_CAST(int**, self->drawOrders) = CALLOC(int*, frameCount);
|
||||||
CONST_CAST(int, self->slotCount) = slotCount;
|
CONST_CAST(int, self->slotCount) = slotCount;
|
||||||
@ -634,3 +634,80 @@ void spDrawOrderTimeline_setFrame (spDrawOrderTimeline* self, int frameIndex, fl
|
|||||||
memcpy(CONST_CAST(int*, self->drawOrders[frameIndex]), drawOrder, self->slotCount * sizeof(int));
|
memcpy(CONST_CAST(int*, self->drawOrders[frameIndex]), drawOrder, self->slotCount * sizeof(int));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
|
||||||
|
void _spFFDTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, float lastTime, float time, spEvent** firedEvents,
|
||||||
|
int* eventCount, float alpha) {
|
||||||
|
int frameIndex, i;
|
||||||
|
float percent, frameTime;
|
||||||
|
spFFDTimeline* self = (spFFDTimeline*)timeline;
|
||||||
|
|
||||||
|
spSlot *slot = skeleton->slots[self->slotIndex];
|
||||||
|
if (slot->attachment != self->attachment) return;
|
||||||
|
|
||||||
|
if (time < self->frames[0]) {
|
||||||
|
slot->attachmentVerticesCount = 0;
|
||||||
|
return; /* Time is before first frame. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot->attachmentVerticesCount < self->frameVerticesCount) {
|
||||||
|
if (slot->attachmentVerticesCapacity < self->frameVerticesCount) {
|
||||||
|
FREE(slot->attachmentVertices);
|
||||||
|
slot->attachmentVertices = MALLOC(float, self->frameVerticesCount);
|
||||||
|
slot->attachmentVerticesCapacity = self->frameVerticesCount;
|
||||||
|
}
|
||||||
|
slot->attachmentVerticesCount = self->frameVerticesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time >= self->frames[self->framesCount - 1]) {
|
||||||
|
/* Time is after last frame. */
|
||||||
|
const float* lastVertices = self->frameVertices[self->framesCount - 1];
|
||||||
|
if (alpha < 1) {
|
||||||
|
for (i = 0; i < self->frameVerticesCount; i++)
|
||||||
|
slot->attachmentVertices[i] += (lastVertices[i] - slot->attachmentVertices[i]) * alpha;
|
||||||
|
} else
|
||||||
|
memcpy(slot->attachmentVertices, lastVertices, self->frameVerticesCount);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interpolate between the previous frame and the current frame. */
|
||||||
|
frameIndex = binarySearch(self->frames, self->framesCount, time, 1);
|
||||||
|
frameTime = self->frames[frameIndex];
|
||||||
|
percent = 1 - (time - frameTime) / (self->frames[frameIndex - 1] - frameTime);
|
||||||
|
percent = spCurveTimeline_getCurvePercent(SUPER(self), frameIndex - 1, percent < 0 ? 0 : (percent > 1 ? 1 : percent));
|
||||||
|
|
||||||
|
const float* prevVertices = self->frameVertices[frameIndex - 1];
|
||||||
|
const float* nextVertices = self->frameVertices[frameIndex];
|
||||||
|
|
||||||
|
if (alpha < 1) {
|
||||||
|
for (i = 0; i < self->frameVerticesCount; i++) {
|
||||||
|
float prev = prevVertices[i];
|
||||||
|
slot->attachmentVertices[i] += (prev + (nextVertices[i] - prev) * percent - slot->attachmentVertices[i]) * alpha;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < self->frameVerticesCount; i++) {
|
||||||
|
float prev = prevVertices[i];
|
||||||
|
slot->attachmentVertices[i] = prev + (nextVertices[i] - prev) * percent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spFFDTimeline* spFFDTimeline_create (int frameCount, int frameVerticesCount) {
|
||||||
|
spFFDTimeline* self = SUB_CAST(spFFDTimeline, _spBaseTimeline_create(frameCount, SP_TIMELINE_FFD, 1, _spFFDTimeline_apply));
|
||||||
|
CONST_CAST(float**, self->frameVertices) = CALLOC(float*, frameCount);
|
||||||
|
CONST_CAST(int, self->frameVerticesCount) = frameVerticesCount;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void spFFDTimeline_setFrame (spFFDTimeline* self, int frameIndex, float time, float* vertices) {
|
||||||
|
self->frames[frameIndex] = time;
|
||||||
|
|
||||||
|
FREE(self->frameVertices[frameIndex]);
|
||||||
|
if (!vertices)
|
||||||
|
self->frameVertices[frameIndex] = 0;
|
||||||
|
else {
|
||||||
|
self->frameVertices[frameIndex] = MALLOC(float, self->frameVerticesCount);
|
||||||
|
memcpy(CONST_CAST(float*, self->frameVertices[frameIndex]), vertices, self->frameVerticesCount * sizeof(float));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -111,7 +111,7 @@ static const char* parse_string (Json *item, const char* str) {
|
|||||||
while (*ptr != '\"' && *ptr && ++len)
|
while (*ptr != '\"' && *ptr && ++len)
|
||||||
if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
|
if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
|
||||||
|
|
||||||
out = (char*)malloc(len + 1); /* This is how long we need for the string, roughly. */
|
out = MALLOC(char, len + 1); /* The length needed for the string, roughly. */
|
||||||
if (!out) return 0;
|
if (!out) return 0;
|
||||||
|
|
||||||
ptr = str + 1;
|
ptr = str + 1;
|
||||||
|
|||||||
@ -74,13 +74,12 @@ void spMeshAttachment_updateUVs (spMeshAttachment* self) {
|
|||||||
void spMeshAttachment_computeWorldVertices (spMeshAttachment* self, float x, float y, spSlot* slot, float* worldVertices) {
|
void spMeshAttachment_computeWorldVertices (spMeshAttachment* self, float x, float y, spSlot* slot, float* worldVertices) {
|
||||||
int i;
|
int i;
|
||||||
float* vertices = self->vertices;
|
float* vertices = self->vertices;
|
||||||
spBone* bone = slot->bone;
|
const spBone* bone = slot->bone;
|
||||||
x += bone->worldX;
|
x += bone->worldX;
|
||||||
y += bone->worldY;
|
y += bone->worldY;
|
||||||
if (slot->attachmentVerticesCount == self->verticesCount) vertices = slot->attachmentVertices;
|
if (slot->attachmentVerticesCount == self->verticesCount) vertices = slot->attachmentVertices;
|
||||||
for (i = 0; i < self->verticesCount; i += 2) {
|
for (i = 0; i < self->verticesCount; i += 2) {
|
||||||
float vx = vertices[i];
|
const float vx = vertices[i], vy = vertices[i + 1];
|
||||||
float vy = vertices[i + 1];
|
|
||||||
worldVertices[i] = vx * bone->m00 + vy * bone->m01 + x;
|
worldVertices[i] = vx * bone->m00 + vy * bone->m01 + x;
|
||||||
worldVertices[i + 1] = vx * bone->m10 + vy * bone->m11 + y;
|
worldVertices[i + 1] = vx * bone->m10 + vy * bone->m11 + y;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -105,7 +105,7 @@ void spRegionAttachment_updateOffset (spRegionAttachment* self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void spRegionAttachment_computeWorldVertices (spRegionAttachment* self, float x, float y, spBone* bone, float* vertices) {
|
void spRegionAttachment_computeWorldVertices (spRegionAttachment* self, float x, float y, spBone* bone, float* vertices) {
|
||||||
float* offset = self->offset;
|
const float* offset = self->offset;
|
||||||
x += bone->worldX;
|
x += bone->worldX;
|
||||||
y += bone->worldY;
|
y += bone->worldY;
|
||||||
vertices[SP_VERTEX_X1] = offset[SP_VERTEX_X1] * bone->m00 + offset[SP_VERTEX_Y1] * bone->m01 + x;
|
vertices[SP_VERTEX_X1] = offset[SP_VERTEX_X1] * bone->m00 + offset[SP_VERTEX_Y1] * bone->m01 + x;
|
||||||
|
|||||||
@ -104,18 +104,24 @@ static void readCurve (spCurveTimeline* timeline, int frameIndex, Json* frame) {
|
|||||||
static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* root, spSkeletonData *skeletonData) {
|
static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* root, spSkeletonData *skeletonData) {
|
||||||
int i;
|
int i;
|
||||||
spAnimation* animation;
|
spAnimation* animation;
|
||||||
|
Json* frame;
|
||||||
|
float duration;
|
||||||
|
|
||||||
Json* bones = Json_getItem(root, "bones");
|
Json* bones = Json_getItem(root, "bones");
|
||||||
Json* slots = Json_getItem(root, "slots");
|
Json* slots = Json_getItem(root, "slots");
|
||||||
|
Json* ffd = Json_getItem(root, "ffd");
|
||||||
Json* drawOrder = Json_getItem(root, "draworder");
|
Json* drawOrder = Json_getItem(root, "draworder");
|
||||||
Json* events = Json_getItem(root, "events");
|
Json* events = Json_getItem(root, "events");
|
||||||
Json *boneMap, *slotMap;
|
Json *boneMap, *slotMap, *ffdMap;
|
||||||
|
|
||||||
int timelineCount = 0;
|
int timelineCount = 0;
|
||||||
for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next)
|
for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next)
|
||||||
timelineCount += boneMap->size;
|
timelineCount += boneMap->size;
|
||||||
for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next)
|
for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next)
|
||||||
timelineCount += slotMap->size;
|
timelineCount += slotMap->size;
|
||||||
|
for (ffdMap = ffd ? ffd->child : 0; ffdMap; ffdMap = ffdMap->next)
|
||||||
|
for (slotMap = ffdMap->child; slotMap; slotMap = slotMap->next)
|
||||||
|
timelineCount += slotMap->size;
|
||||||
if (events) ++timelineCount;
|
if (events) ++timelineCount;
|
||||||
if (drawOrder) ++timelineCount;
|
if (drawOrder) ++timelineCount;
|
||||||
|
|
||||||
@ -124,6 +130,50 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
|
|||||||
skeletonData->animations[skeletonData->animationCount] = animation;
|
skeletonData->animations[skeletonData->animationCount] = animation;
|
||||||
++skeletonData->animationCount;
|
++skeletonData->animationCount;
|
||||||
|
|
||||||
|
for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) {
|
||||||
|
Json *timelineArray;
|
||||||
|
|
||||||
|
int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name);
|
||||||
|
if (slotIndex == -1) {
|
||||||
|
spAnimation_dispose(animation);
|
||||||
|
_spSkeletonJson_setError(self, root, "Slot not found: ", slotMap->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (timelineArray = slotMap->child; timelineArray; timelineArray = timelineArray->next) {
|
||||||
|
if (strcmp(timelineArray->name, "color") == 0) {
|
||||||
|
spColorTimeline *timeline = spColorTimeline_create(timelineArray->size);
|
||||||
|
timeline->slotIndex = slotIndex;
|
||||||
|
for (frame = timelineArray->child, i = 0; frame; frame = frame->next, ++i) {
|
||||||
|
const char* s = Json_getString(frame, "color", 0);
|
||||||
|
spColorTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2),
|
||||||
|
toColor(s, 3));
|
||||||
|
readCurve(SUPER(timeline), i, frame);
|
||||||
|
}
|
||||||
|
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
|
||||||
|
duration = timeline->frames[timelineArray->size * 5 - 5];
|
||||||
|
if (duration > animation->duration) animation->duration = duration;
|
||||||
|
|
||||||
|
} else if (strcmp(timelineArray->name, "attachment") == 0) {
|
||||||
|
spAttachmentTimeline *timeline = spAttachmentTimeline_create(timelineArray->size);
|
||||||
|
timeline->slotIndex = slotIndex;
|
||||||
|
for (frame = timelineArray->child, i = 0; frame; frame = frame->next, ++i) {
|
||||||
|
Json* name = Json_getItem(frame, "name");
|
||||||
|
spAttachmentTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0),
|
||||||
|
name->type == Json_NULL ? 0 : name->valueString);
|
||||||
|
}
|
||||||
|
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
|
||||||
|
duration = timeline->frames[timelineArray->size - 1];
|
||||||
|
if (duration > animation->duration) animation->duration = duration;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
spAnimation_dispose(animation);
|
||||||
|
_spSkeletonJson_setError(self, 0, "Invalid timeline type for a slot: ", timelineArray->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) {
|
for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) {
|
||||||
Json *timelineArray;
|
Json *timelineArray;
|
||||||
|
|
||||||
@ -135,9 +185,6 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (timelineArray = boneMap->child; timelineArray; timelineArray = timelineArray->next) {
|
for (timelineArray = boneMap->child; timelineArray; timelineArray = timelineArray->next) {
|
||||||
Json* frame;
|
|
||||||
float duration;
|
|
||||||
|
|
||||||
if (strcmp(timelineArray->name, "rotate") == 0) {
|
if (strcmp(timelineArray->name, "rotate") == 0) {
|
||||||
spRotateTimeline *timeline = spRotateTimeline_create(timelineArray->size);
|
spRotateTimeline *timeline = spRotateTimeline_create(timelineArray->size);
|
||||||
timeline->boneIndex = boneIndex;
|
timeline->boneIndex = boneIndex;
|
||||||
@ -145,7 +192,7 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
|
|||||||
spRotateTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), Json_getFloat(frame, "angle", 0));
|
spRotateTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), Json_getFloat(frame, "angle", 0));
|
||||||
readCurve(SUPER(timeline), i, frame);
|
readCurve(SUPER(timeline), i, frame);
|
||||||
}
|
}
|
||||||
animation->timelines[animation->timelineCount++] = (spTimeline*)timeline;
|
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
|
||||||
duration = timeline->frames[timelineArray->size * 2 - 2];
|
duration = timeline->frames[timelineArray->size * 2 - 2];
|
||||||
if (duration > animation->duration) animation->duration = duration;
|
if (duration > animation->duration) animation->duration = duration;
|
||||||
|
|
||||||
@ -161,7 +208,7 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
|
|||||||
Json_getFloat(frame, "y", 0) * scale);
|
Json_getFloat(frame, "y", 0) * scale);
|
||||||
readCurve(SUPER(timeline), i, frame);
|
readCurve(SUPER(timeline), i, frame);
|
||||||
}
|
}
|
||||||
animation->timelines[animation->timelineCount++] = (spTimeline*)timeline;
|
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
|
||||||
duration = timeline->frames[timelineArray->size * 3 - 3];
|
duration = timeline->frames[timelineArray->size * 3 - 3];
|
||||||
if (duration > animation->duration) animation->duration = duration;
|
if (duration > animation->duration) animation->duration = duration;
|
||||||
} else {
|
} else {
|
||||||
@ -173,83 +220,75 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) {
|
for (ffdMap = ffd ? ffd->child : 0; ffdMap; ffdMap = ffdMap->next) {
|
||||||
Json *timelineArray;
|
spSkin* skin = spSkeletonData_findSkin(skeletonData, ffdMap->name);
|
||||||
|
for (slotMap = ffdMap->child; slotMap; slotMap = slotMap->next) {
|
||||||
|
int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name);
|
||||||
|
Json* timelineArray;
|
||||||
|
for (timelineArray = slotMap->child; timelineArray; timelineArray = timelineArray->next) {
|
||||||
|
Json* frame;
|
||||||
|
int verticesCount;
|
||||||
|
float* tempVertices;
|
||||||
|
spFFDTimeline *timeline;
|
||||||
|
|
||||||
int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name);
|
spAttachment* attachment = spSkin_getAttachment(skin, slotIndex, timelineArray->name);
|
||||||
if (slotIndex == -1) {
|
if (!attachment) {
|
||||||
spAnimation_dispose(animation);
|
spAnimation_dispose(animation);
|
||||||
_spSkeletonJson_setError(self, root, "Slot not found: ", slotMap->name);
|
_spSkeletonJson_setError(self, 0, "Attachment not found: ", timelineArray->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (attachment->type == SP_ATTACHMENT_MESH)
|
||||||
|
verticesCount = SUB_CAST(spMeshAttachment, attachment)->verticesCount;
|
||||||
|
else if (attachment->type == SP_ATTACHMENT_SKINNED_MESH)
|
||||||
|
verticesCount = SUB_CAST(spSkinnedMeshAttachment, attachment)->weightsCount / 3 * 2;
|
||||||
|
|
||||||
for (timelineArray = slotMap->child; timelineArray; timelineArray = timelineArray->next) {
|
timeline = spFFDTimeline_create(timelineArray->size, verticesCount);
|
||||||
Json* frame;
|
|
||||||
float duration;
|
|
||||||
|
|
||||||
if (strcmp(timelineArray->name, "color") == 0) {
|
|
||||||
spColorTimeline *timeline = spColorTimeline_create(timelineArray->size);
|
|
||||||
timeline->slotIndex = slotIndex;
|
timeline->slotIndex = slotIndex;
|
||||||
|
timeline->attachment = attachment;
|
||||||
|
|
||||||
|
tempVertices = MALLOC(float, verticesCount);
|
||||||
for (frame = timelineArray->child, i = 0; frame; frame = frame->next, ++i) {
|
for (frame = timelineArray->child, i = 0; frame; frame = frame->next, ++i) {
|
||||||
const char* s = Json_getString(frame, "color", 0);
|
Json* vertices = Json_getItem(frame, "vertices");
|
||||||
spColorTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2),
|
float* frameVertices;
|
||||||
toColor(s, 3));
|
if (!vertices) {
|
||||||
|
if (attachment->type == SP_ATTACHMENT_MESH)
|
||||||
|
frameVertices = SUB_CAST(spMeshAttachment, attachment)->vertices;
|
||||||
|
else {
|
||||||
|
frameVertices = tempVertices;
|
||||||
|
memset(frameVertices, 0, sizeof(float) * verticesCount);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int v, start = Json_getInt(frame, "offset", 0);
|
||||||
|
Json* vertex;
|
||||||
|
frameVertices = tempVertices;
|
||||||
|
memset(frameVertices, 0, sizeof(float) * start);
|
||||||
|
if (self->scale == 1) {
|
||||||
|
for (vertex = vertices->child, v = start; vertex; vertex = vertex->next, ++v)
|
||||||
|
frameVertices[v] = vertex->valueFloat;
|
||||||
|
} else {
|
||||||
|
for (vertex = vertices->child, v = start; vertex; vertex = vertex->next, ++v)
|
||||||
|
frameVertices[v] = vertex->valueFloat * self->scale;
|
||||||
|
}
|
||||||
|
memset(frameVertices + v, 0, sizeof(float) * (verticesCount - v));
|
||||||
|
if (attachment->type == SP_ATTACHMENT_MESH) {
|
||||||
|
float* meshVertices = SUB_CAST(spMeshAttachment, attachment)->vertices;
|
||||||
|
for (v = 0; v < verticesCount; ++v)
|
||||||
|
frameVertices[v] += meshVertices[v];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spFFDTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), frameVertices);
|
||||||
readCurve(SUPER(timeline), i, frame);
|
readCurve(SUPER(timeline), i, frame);
|
||||||
}
|
}
|
||||||
animation->timelines[animation->timelineCount++] = (spTimeline*)timeline;
|
FREE(tempVertices);
|
||||||
duration = timeline->frames[timelineArray->size * 5 - 5];
|
|
||||||
if (duration > animation->duration) animation->duration = duration;
|
|
||||||
|
|
||||||
} else if (strcmp(timelineArray->name, "attachment") == 0) {
|
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
|
||||||
spAttachmentTimeline *timeline = spAttachmentTimeline_create(timelineArray->size);
|
|
||||||
timeline->slotIndex = slotIndex;
|
|
||||||
for (frame = timelineArray->child, i = 0; frame; frame = frame->next, ++i) {
|
|
||||||
Json* name = Json_getItem(frame, "name");
|
|
||||||
spAttachmentTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0),
|
|
||||||
name->type == Json_NULL ? 0 : name->valueString);
|
|
||||||
}
|
|
||||||
animation->timelines[animation->timelineCount++] = (spTimeline*)timeline;
|
|
||||||
duration = timeline->frames[timelineArray->size - 1];
|
duration = timeline->frames[timelineArray->size - 1];
|
||||||
if (duration > animation->duration) animation->duration = duration;
|
if (duration > animation->duration) animation->duration = duration;
|
||||||
|
|
||||||
} else {
|
|
||||||
spAnimation_dispose(animation);
|
|
||||||
_spSkeletonJson_setError(self, 0, "Invalid timeline type for a slot: ", timelineArray->name);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (events) {
|
|
||||||
Json* frame;
|
|
||||||
float duration;
|
|
||||||
|
|
||||||
spEventTimeline* timeline = spEventTimeline_create(events->size);
|
|
||||||
for (frame = events->child, i = 0; frame; frame = frame->next, ++i) {
|
|
||||||
spEvent* event;
|
|
||||||
const char* stringValue;
|
|
||||||
spEventData* eventData = spSkeletonData_findEvent(skeletonData, Json_getString(frame, "name", 0));
|
|
||||||
if (!eventData) {
|
|
||||||
spAnimation_dispose(animation);
|
|
||||||
_spSkeletonJson_setError(self, 0, "Event not found: ", Json_getString(frame, "name", 0));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
event = spEvent_create(eventData);
|
|
||||||
event->intValue = Json_getInt(frame, "int", eventData->intValue);
|
|
||||||
event->floatValue = Json_getFloat(frame, "float", eventData->floatValue);
|
|
||||||
stringValue = Json_getString(frame, "string", eventData->stringValue);
|
|
||||||
if (stringValue) MALLOC_STR(event->stringValue, stringValue);
|
|
||||||
spEventTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), event);
|
|
||||||
}
|
|
||||||
animation->timelines[animation->timelineCount++] = (spTimeline*)timeline;
|
|
||||||
duration = timeline->frames[events->size - 1];
|
|
||||||
if (duration > animation->duration) animation->duration = duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (drawOrder) {
|
if (drawOrder) {
|
||||||
Json* frame;
|
|
||||||
float duration;
|
|
||||||
|
|
||||||
spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrder->size, skeletonData->slotCount);
|
spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrder->size, skeletonData->slotCount);
|
||||||
for (frame = drawOrder->child, i = 0; frame; frame = frame->next, ++i) {
|
for (frame = drawOrder->child, i = 0; frame; frame = frame->next, ++i) {
|
||||||
int ii;
|
int ii;
|
||||||
@ -289,11 +328,36 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
|
|||||||
spDrawOrderTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), drawOrder);
|
spDrawOrderTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), drawOrder);
|
||||||
FREE(drawOrder);
|
FREE(drawOrder);
|
||||||
}
|
}
|
||||||
animation->timelines[animation->timelineCount++] = (spTimeline*)timeline;
|
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
|
||||||
duration = timeline->frames[drawOrder->size - 1];
|
duration = timeline->frames[drawOrder->size - 1];
|
||||||
if (duration > animation->duration) animation->duration = duration;
|
if (duration > animation->duration) animation->duration = duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (events) {
|
||||||
|
Json* frame;
|
||||||
|
|
||||||
|
spEventTimeline* timeline = spEventTimeline_create(events->size);
|
||||||
|
for (frame = events->child, i = 0; frame; frame = frame->next, ++i) {
|
||||||
|
spEvent* event;
|
||||||
|
const char* stringValue;
|
||||||
|
spEventData* eventData = spSkeletonData_findEvent(skeletonData, Json_getString(frame, "name", 0));
|
||||||
|
if (!eventData) {
|
||||||
|
spAnimation_dispose(animation);
|
||||||
|
_spSkeletonJson_setError(self, 0, "Event not found: ", Json_getString(frame, "name", 0));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
event = spEvent_create(eventData);
|
||||||
|
event->intValue = Json_getInt(frame, "int", eventData->intValue);
|
||||||
|
event->floatValue = Json_getFloat(frame, "float", eventData->floatValue);
|
||||||
|
stringValue = Json_getString(frame, "string", eventData->stringValue);
|
||||||
|
if (stringValue) MALLOC_STR(event->stringValue, stringValue);
|
||||||
|
spEventTimeline_setFrame(timeline, i, Json_getFloat(frame, "time", 0), event);
|
||||||
|
}
|
||||||
|
animation->timelines[animation->timelineCount++] = SUPER_CAST(spTimeline, timeline);
|
||||||
|
duration = timeline->frames[events->size - 1];
|
||||||
|
if (duration > animation->duration) animation->duration = duration;
|
||||||
|
}
|
||||||
|
|
||||||
return animation;
|
return animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,7 +510,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
|
|||||||
|
|
||||||
switch (attachment->type) {
|
switch (attachment->type) {
|
||||||
case SP_ATTACHMENT_REGION: {
|
case SP_ATTACHMENT_REGION: {
|
||||||
spRegionAttachment* region = (spRegionAttachment*)attachment;
|
spRegionAttachment* region = SUB_CAST(spRegionAttachment, attachment);
|
||||||
if (path) MALLOC_STR(region->path, path);
|
if (path) MALLOC_STR(region->path, path);
|
||||||
region->x = Json_getFloat(attachmentMap, "x", 0) * self->scale;
|
region->x = Json_getFloat(attachmentMap, "x", 0) * self->scale;
|
||||||
region->y = Json_getFloat(attachmentMap, "y", 0) * self->scale;
|
region->y = Json_getFloat(attachmentMap, "y", 0) * self->scale;
|
||||||
@ -468,7 +532,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SP_ATTACHMENT_MESH: {
|
case SP_ATTACHMENT_MESH: {
|
||||||
spMeshAttachment* mesh = (spMeshAttachment*)attachment;
|
spMeshAttachment* mesh = SUB_CAST(spMeshAttachment, attachment);
|
||||||
|
|
||||||
MALLOC_STR(mesh->path, path);
|
MALLOC_STR(mesh->path, path);
|
||||||
|
|
||||||
@ -515,7 +579,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SP_ATTACHMENT_SKINNED_MESH: {
|
case SP_ATTACHMENT_SKINNED_MESH: {
|
||||||
spSkinnedMeshAttachment* mesh = (spSkinnedMeshAttachment*)attachment;
|
spSkinnedMeshAttachment* mesh = SUB_CAST(spSkinnedMeshAttachment, attachment);
|
||||||
int verticesCount, b, w, nn;
|
int verticesCount, b, w, nn;
|
||||||
float* vertices;
|
float* vertices;
|
||||||
|
|
||||||
@ -545,12 +609,11 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
|
|||||||
for (i = 0, b = 0, w = 0; i < verticesCount;) {
|
for (i = 0, b = 0, w = 0; i < verticesCount;) {
|
||||||
int boneCount = (int)vertices[i++];
|
int boneCount = (int)vertices[i++];
|
||||||
mesh->bones[b++] = boneCount;
|
mesh->bones[b++] = boneCount;
|
||||||
for (nn = i + boneCount * 4; i < nn;) {
|
for (nn = i + boneCount * 4; i < nn; i += 4, ++b, w += 3) {
|
||||||
mesh->bones[b++] = (int)vertices[i];
|
mesh->bones[b] = (int)vertices[i];
|
||||||
mesh->weights[w++] = vertices[i + 1] * self->scale;
|
mesh->weights[w] = vertices[i + 1] * self->scale;
|
||||||
mesh->weights[w++] = vertices[i + 2] * self->scale;
|
mesh->weights[w + 1] = vertices[i + 2] * self->scale;
|
||||||
mesh->weights[w++] = vertices[i + 3];
|
mesh->weights[w + 2] = vertices[i + 3];
|
||||||
i += 4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,7 +650,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SP_ATTACHMENT_BOUNDING_BOX: {
|
case SP_ATTACHMENT_BOUNDING_BOX: {
|
||||||
spBoundingBoxAttachment* box = (spBoundingBoxAttachment*)attachment;
|
spBoundingBoxAttachment* box = SUB_CAST(spBoundingBoxAttachment, attachment);
|
||||||
entry = Json_getItem(attachmentMap, "vertices");
|
entry = Json_getItem(attachmentMap, "vertices");
|
||||||
box->verticesCount = entry->size;
|
box->verticesCount = entry->size;
|
||||||
box->vertices = MALLOC(float, entry->size);
|
box->vertices = MALLOC(float, entry->size);
|
||||||
|
|||||||
@ -79,11 +79,11 @@ void spSkinnedMeshAttachment_computeWorldVertices (spSkinnedMeshAttachment* self
|
|||||||
if (slot->attachmentVerticesCount == 0) {
|
if (slot->attachmentVerticesCount == 0) {
|
||||||
for (; v < self->bonesCount; w += 2) {
|
for (; v < self->bonesCount; w += 2) {
|
||||||
float wx = 0, wy = 0;
|
float wx = 0, wy = 0;
|
||||||
int nn = self->bones[v] + v;
|
const int nn = self->bones[v] + v;
|
||||||
v++;
|
v++;
|
||||||
for (; v <= nn; v++, b += 3) {
|
for (; v <= nn; v++, b += 3) {
|
||||||
spBone* bone = skeletonBones[self->bones[v]];
|
const spBone* bone = skeletonBones[self->bones[v]];
|
||||||
float vx = self->weights[b], vy = self->weights[b + 1], weight = self->weights[b + 2];
|
const float vx = self->weights[b], vy = self->weights[b + 1], weight = self->weights[b + 2];
|
||||||
wx += (vx * bone->m00 + vy * bone->m01 + bone->worldX) * weight;
|
wx += (vx * bone->m00 + vy * bone->m01 + bone->worldX) * weight;
|
||||||
wy += (vx * bone->m10 + vy * bone->m11 + bone->worldY) * weight;
|
wy += (vx * bone->m10 + vy * bone->m11 + bone->worldY) * weight;
|
||||||
}
|
}
|
||||||
@ -91,14 +91,14 @@ void spSkinnedMeshAttachment_computeWorldVertices (spSkinnedMeshAttachment* self
|
|||||||
worldVertices[w + 1] = wy + y;
|
worldVertices[w + 1] = wy + y;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
float* ffd = slot->attachmentVertices;
|
const float* ffd = slot->attachmentVertices;
|
||||||
for (; v < self->bonesCount; w += 2) {
|
for (; v < self->bonesCount; w += 2) {
|
||||||
float wx = 0, wy = 0;
|
float wx = 0, wy = 0;
|
||||||
int nn = self->bones[v] + v;
|
const int nn = self->bones[v] + v;
|
||||||
v++;
|
v++;
|
||||||
for (; v <= nn; v++, b += 3, f += 2) {
|
for (; v <= nn; v++, b += 3, f += 2) {
|
||||||
spBone* bone = skeletonBones[self->bones[v]];
|
const spBone* bone = skeletonBones[self->bones[v]];
|
||||||
float vx = self->weights[b] + ffd[f], vy = self->weights[b + 1] + ffd[f + 1], weight = self->weights[b + 2];
|
const float vx = self->weights[b] + ffd[f], vy = self->weights[b + 1] + ffd[f + 1], weight = self->weights[b + 2];
|
||||||
wx += (vx * bone->m00 + vy * bone->m01 + bone->worldX) * weight;
|
wx += (vx * bone->m00 + vy * bone->m01 + bone->worldX) * weight;
|
||||||
wy += (vx * bone->m10 + vy * bone->m11 + bone->worldY) * weight;
|
wy += (vx * bone->m10 + vy * bone->m11 + bone->worldY) * weight;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -135,7 +135,7 @@ void spineboy () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void goblins () {
|
void goblins () {
|
||||||
// Load atlas, skeleton, and animations.
|
// Load atlas, skeleton, and animations.
|
||||||
Atlas* atlas = Atlas_readAtlasFile("../data/goblins-ffd.atlas");
|
Atlas* atlas = Atlas_readAtlasFile("../data/goblins-ffd.atlas");
|
||||||
SkeletonJson* json = SkeletonJson_create(atlas);
|
SkeletonJson* json = SkeletonJson_create(atlas);
|
||||||
SkeletonData *skeletonData = SkeletonJson_readSkeletonDataFile(json, "../data/goblins-ffd.json");
|
SkeletonData *skeletonData = SkeletonJson_readSkeletonDataFile(json, "../data/goblins-ffd.json");
|
||||||
@ -154,7 +154,7 @@ void goblins () {
|
|||||||
skeleton->flipY = false;
|
skeleton->flipY = false;
|
||||||
Skeleton_setSkinByName(skeleton, "goblin");
|
Skeleton_setSkinByName(skeleton, "goblin");
|
||||||
Skeleton_setSlotsToSetupPose(skeleton);
|
Skeleton_setSlotsToSetupPose(skeleton);
|
||||||
// Skeleton_setAttachment(skeleton, "left hand item", "dagger");
|
//Skeleton_setAttachment(skeleton, "left hand item", "dagger");
|
||||||
|
|
||||||
skeleton->x = 320;
|
skeleton->x = 320;
|
||||||
skeleton->y = 590;
|
skeleton->y = 590;
|
||||||
@ -185,6 +185,6 @@ void goblins () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main () {
|
int main () {
|
||||||
// spineboy();
|
spineboy();
|
||||||
goblins();
|
goblins();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user