[c] 4.0 porting, complete but with bugs.

This commit is contained in:
badlogic 2021-05-26 15:17:20 +02:00
parent 4f73fbbb39
commit e6a14ff532
10 changed files with 586 additions and 274 deletions

View File

@ -117,6 +117,7 @@ struct spTimeline {
spPropertyId propertyIds[SP_MAX_PROPERTY_IDS]; spPropertyId propertyIds[SP_MAX_PROPERTY_IDS];
int propertyIdsCount; int propertyIdsCount;
spFloatArray *frames; spFloatArray *frames;
int frameCount;
int frameEntries; int frameEntries;
}; };

View File

@ -95,10 +95,16 @@ SP_API spAnimation* spSkeletonData_findAnimation (const spSkeletonData* self, co
SP_API spIkConstraintData* spSkeletonData_findIkConstraint (const spSkeletonData* self, const char* constraintName); SP_API spIkConstraintData* spSkeletonData_findIkConstraint (const spSkeletonData* self, const char* constraintName);
SP_API int spSkeletonData_findIkConstraintIndex (const spSkeletonData* self, const char* constraintName);
SP_API spTransformConstraintData* spSkeletonData_findTransformConstraint (const spSkeletonData* self, const char* constraintName); SP_API spTransformConstraintData* spSkeletonData_findTransformConstraint (const spSkeletonData* self, const char* constraintName);
SP_API int spSkeletonData_findTransformConstraintIndex (const spSkeletonData* self, const char* constraintName);
SP_API spPathConstraintData* spSkeletonData_findPathConstraint (const spSkeletonData* self, const char* constraintName); SP_API spPathConstraintData* spSkeletonData_findPathConstraint (const spSkeletonData* self, const char* constraintName);
SP_API int spSkeletonData_findPathConstraintIndex (const spSkeletonData* self, const char* constraintName);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -31,6 +31,7 @@
#define SPINE_SPINE_H_ #define SPINE_SPINE_H_
#include <spine/dll.h> #include <spine/dll.h>
#include <spine/Array.h>
#include <spine/Animation.h> #include <spine/Animation.h>
#include <spine/AnimationState.h> #include <spine/AnimationState.h>
#include <spine/AnimationStateData.h> #include <spine/AnimationStateData.h>

View File

@ -39,7 +39,9 @@ spAnimation* spAnimation_create (const char* name, spTimelineArray* timelines, f
int i, n; int i, n;
spAnimation* self = NEW(spAnimation); spAnimation* self = NEW(spAnimation);
MALLOC_STR(self->name, name); MALLOC_STR(self->name, name);
self->timelines = timelines; self->timelines = timelines != NULL ? timelines : spTimelineArray_create(1);
timelines = self->timelines;
self->timelineIds = spPropertyIdArray_create(16);
for (i = 0, n = timelines->size; i < n; i++) { for (i = 0, n = timelines->size; i < n; i++) {
spPropertyIdArray_addAllValues(self->timelineIds, timelines->items[i]->propertyIds, 0, timelines->items[i]->propertyIdsCount); spPropertyIdArray_addAllValues(self->timelineIds, timelines->items[i]->propertyIds, 0, timelines->items[i]->propertyIdsCount);
} }
@ -110,6 +112,7 @@ void _spTimeline_init (spTimeline* self,
) { ) {
int i, n; int i, n;
self->frames = spFloatArray_create(frameCount * frameEntries); self->frames = spFloatArray_create(frameCount * frameEntries);
self->frameCount = frameCount;
self->frameEntries = frameEntries; self->frameEntries = frameEntries;
self->vtable.dispose = dispose; self->vtable.dispose = dispose;
self->vtable.apply = apply; self->vtable.apply = apply;
@ -136,7 +139,7 @@ void spTimeline_setBezier(spTimeline* self, int bezier, int frame, float value,
} }
int spTimeline_getFrameCount (const spTimeline* self) { int spTimeline_getFrameCount (const spTimeline* self) {
return self->frames->size / self->frameEntries; return self->frameCount / self->frameEntries;
} }
float spTimeline_getDuration (const spTimeline* self) { float spTimeline_getDuration (const spTimeline* self) {

View File

@ -444,6 +444,15 @@ Json *Json_getItem (Json *object, const char* string) {
return c; return c;
} }
Json *Json_getItemAtIndex(Json *object, int childIndex) {
Json *current = object->child;
while (current != NULL && childIndex > 0) {
childIndex--;
current = current->next;
}
return current;
}
const char* Json_getString (Json* object, const char* name, const char* defaultValue) { const char* Json_getString (Json* object, const char* name, const char* defaultValue) {
object = Json_getItem(object, name); object = Json_getItem(object, name);
if (object) return object->valueString; if (object) return object->valueString;

View File

@ -69,6 +69,7 @@ void Json_dispose (Json* json);
/* Get item "string" from object. Case insensitive. */ /* Get item "string" from object. Case insensitive. */
Json* Json_getItem (Json* json, const char* string); Json* Json_getItem (Json* json, const char* string);
Json *Json_getItemAtIndex(Json *object, int childIndex);
const char* Json_getString (Json* json, const char* name, const char* defaultValue); const char* Json_getString (Json* json, const char* name, const char* defaultValue);
float Json_getFloat (Json* json, const char* name, float defaultValue); float Json_getFloat (Json* json, const char* name, float defaultValue);
int Json_getInt (Json* json, const char* name, int defaultValue); int Json_getInt (Json* json, const char* name, int defaultValue);

View File

@ -1139,7 +1139,7 @@ spSkeletonData* spSkeletonBinary_readSkeletonDataFile (spSkeletonBinary* self, c
spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const unsigned char* binary, spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const unsigned char* binary,
const int length) { const int length) {
int i, n, ii, nonessential; int i, n, ii, nonessential;
char buffer[16]; char buffer[32];
int lowHash, highHash; int lowHash, highHash;
spSkeletonData* skeletonData; spSkeletonData* skeletonData;
_spSkeletonBinary* internal = SUB_CAST(_spSkeletonBinary, self); _spSkeletonBinary* internal = SUB_CAST(_spSkeletonBinary, self);
@ -1155,9 +1155,8 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const
skeletonData = spSkeletonData_create(); skeletonData = spSkeletonData_create();
lowHash = readInt(input); lowHash = readInt(input);
highHash = readInt(input); highHash = readInt(input);
sprintf(buffer, "%x", highHash); sprintf(buffer, "%x%x", highHash, lowHash);
sprintf(buffer + 8, "%x", lowHash); buffer[31] = 0;
buffer[15] = 0;
skeletonData->hash = strdup(buffer); skeletonData->hash = strdup(buffer);
skeletonData->version = readString(input); skeletonData->version = readString(input);

View File

@ -136,6 +136,13 @@ spIkConstraintData* spSkeletonData_findIkConstraint (const spSkeletonData* self,
return 0; return 0;
} }
int spSkeletonData_findIkConstraintIndex (const spSkeletonData* self, const char* constraintName) {
int i;
for (i = 0; i < self->ikConstraintsCount; ++i)
if (strcmp(self->ikConstraints[i]->name, constraintName) == 0) return i;
return -1;
}
spTransformConstraintData* spSkeletonData_findTransformConstraint (const spSkeletonData* self, const char* constraintName) { spTransformConstraintData* spSkeletonData_findTransformConstraint (const spSkeletonData* self, const char* constraintName) {
int i; int i;
for (i = 0; i < self->transformConstraintsCount; ++i) for (i = 0; i < self->transformConstraintsCount; ++i)
@ -143,9 +150,23 @@ spTransformConstraintData* spSkeletonData_findTransformConstraint (const spSkele
return 0; return 0;
} }
int spSkeletonData_findTransformConstraintIndex (const spSkeletonData* self, const char* constraintName) {
int i;
for (i = 0; i < self->transformConstraintsCount; ++i)
if (strcmp(self->transformConstraints[i]->name, constraintName) == 0) return i;
return -1;
}
spPathConstraintData* spSkeletonData_findPathConstraint (const spSkeletonData* self, const char* constraintName) { spPathConstraintData* spSkeletonData_findPathConstraint (const spSkeletonData* self, const char* constraintName) {
int i; int i;
for (i = 0; i < self->pathConstraintsCount; ++i) for (i = 0; i < self->pathConstraintsCount; ++i)
if (strcmp(self->pathConstraints[i]->name, constraintName) == 0) return self->pathConstraints[i]; if (strcmp(self->pathConstraints[i]->name, constraintName) == 0) return self->pathConstraints[i];
return 0; return 0;
} }
int spSkeletonData_findPathConstraintIndex (const spSkeletonData* self, const char* constraintName) {
int i;
for (i = 0; i < self->pathConstraintsCount; ++i)
if (strcmp(self->pathConstraints[i]->name, constraintName) == 0) return i;
return -1;
}

View File

@ -104,20 +104,86 @@ static float toColor (const char* value, int index) {
return color / (float)255; return color / (float)255;
} }
static void readCurve (Json* frame, spCurveTimeline* timeline, int frameIndex) { static void toColor2(spColor *color, const char *value, int /*bool*/ hasAlpha) {
Json* curve = Json_getItem(frame, "curve"); color->r = toColor(value, 0);
if (!curve) return; color->g = toColor(value, 1);
if (curve->type == Json_String && strcmp(curve->valueString, "stepped") == 0) color->b = toColor(value, 2);
spCurveTimeline_setStepped(timeline, frameIndex); if (hasAlpha) color->a = toColor(value, 3);
else {
float c1 = Json_getFloat(frame, "curve", 0);
float c2 = Json_getFloat(frame, "c2", 0);
float c3 = Json_getFloat(frame, "c3", 1);
float c4 = Json_getFloat(frame, "c4", 1);
spCurveTimeline_setCurve(timeline, frameIndex, c1, c2, c3, c4);
}
} }
static void setBezier (spCurveTimeline *timeline, int frame, int value, int bezier, float time1, float value1, float cx1, float cy1,
float cx2, float cy2, float time2, float value2) {
spTimeline_setBezier(SUPER(timeline), bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
}
static int readCurve (Json *curve, spCurveTimeline *timeline, int bezier, int frame, int value, float time1, float time2,
float value1, float value2, float scale) {
if (curve->type == Json_String && strcmp(curve->valueString, "stepped") == 0) {
spCurveTimeline_setStepped(timeline, frame);
} else {
float cx1, cy1, cx2, cy2;
curve = Json_getItemAtIndex(curve, value << 2);
cx1 = curve->valueFloat;
curve = curve->next;
cy1 = curve->valueFloat * scale;
curve = curve->next;
cx2 = curve->valueFloat;
curve = curve->next;
cy2 = curve->valueFloat * scale;
setBezier(timeline, frame, value, bezier++, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
}
return bezier;
}
static spTimeline *readTimeline (Json *keyMap, spCurveTimeline1 *timeline, float defaultValue, float scale) {
float time = Json_getFloat(keyMap, "time", 0);
float value = Json_getFloat(keyMap, "value", defaultValue) * scale;
int frame, bezier = 0;
for (frame = 0;; frame++) {
Json *nextMap, *curve;
float time2, value2;
spCurveTimeline1_setFrame(timeline, frame, time, value);
nextMap = keyMap->next;
if (nextMap == NULL) break;
time2 = Json_getFloat(nextMap, "time", 0);
value2 = Json_getFloat(nextMap, "value", defaultValue) * scale;
curve = Json_getItem(keyMap, "curve");
if (curve != NULL) bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value, value2, scale);
time = time2;
value = value2;
keyMap = nextMap;
}
return SUPER(timeline);
}
static spTimeline *readTimeline2 (Json *keyMap, spCurveTimeline2 *timeline, const char *name1, const char *name2, float defaultValue, float scale) {
float time = Json_getFloat(keyMap, "time", 0);
float value1 = Json_getFloat(keyMap, name1, defaultValue) * scale;
float value2 = Json_getFloat(keyMap, name2, defaultValue) * scale;
int frame, bezier = 0;
for (frame = 0;; frame++) {
Json *nextMap, *curve;
float time2, nvalue1, nvalue2;
spCurveTimeline2_setFrame(timeline, frame, time, value1, value2);
nextMap = keyMap->next;
if (nextMap == NULL) break;
time2 = Json_getFloat(nextMap, "time", 0);
nvalue1 = Json_getFloat(nextMap, name1, defaultValue) * scale;
nvalue2 = Json_getFloat(nextMap, name2, defaultValue) * scale;
curve = Json_getItem(keyMap, "curve");
if (curve != NULL) {
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale);
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale);
}
time = time2;
value1 = nvalue1;
value2 = nvalue2;
keyMap = nextMap;
}
return SUPER(timeline);
}
static void _spSkeletonJson_addLinkedMesh (spSkeletonJson* self, spMeshAttachment* mesh, const char* skin, int slotIndex, static void _spSkeletonJson_addLinkedMesh (spSkeletonJson* self, spMeshAttachment* mesh, const char* skin, int slotIndex,
const char* parent, int inheritDeform const char* parent, int inheritDeform
) { ) {
@ -142,273 +208,417 @@ static void _spSkeletonJson_addLinkedMesh (spSkeletonJson* self, spMeshAttachmen
linkedMesh->inheritDeform = inheritDeform; linkedMesh->inheritDeform = inheritDeform;
} }
static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* root, spSkeletonData *skeletonData) { static void cleanUpTimelines(spTimelineArray *timelines) {
int frameIndex; int i, n;
spAnimation* animation; for (i = 0, n = timelines->size; i < n; i++) {
Json* valueMap; spTimeline_dispose(timelines->items[i]);
int timelinesCount = 0; }
spTimelineArray_dispose(timelines);
}
static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* root, spSkeletonData *skeletonData) {
spTimelineArray *timelines = spTimelineArray_create(8);
float scale = self->scale, 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* ik = Json_getItem(root, "ik"); Json* ik = Json_getItem(root, "ik");
Json* transform = Json_getItem(root, "transform"); Json* transform = Json_getItem(root, "transform");
Json* path = Json_getItem(root, "path"); Json* paths = Json_getItem(root, "path");
Json* deformJson = Json_getItem(root, "deform"); Json* deformJson = Json_getItem(root, "deform");
Json* drawOrderJson = Json_getItem(root, "drawOrder"); Json* drawOrderJson = Json_getItem(root, "drawOrder");
Json* events = Json_getItem(root, "events"); Json* events = Json_getItem(root, "events");
Json *boneMap, *slotMap, *constraintMap; Json *boneMap, *slotMap, *constraintMap, *keyMap, *nextMap, *curve, *timelineMap;
if (!drawOrderJson) drawOrderJson = Json_getItem(root, "draworder"); int frame, bezier, i, n;
spColor color, color2, newColor, newColor2;
for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next)
timelinesCount += boneMap->size;
for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next)
timelinesCount += slotMap->size;
timelinesCount += ik ? ik->size : 0;
timelinesCount += transform ? transform->size : 0;
for (constraintMap = path ? path->child : 0; constraintMap; constraintMap = constraintMap->next)
timelinesCount += constraintMap->size;
for (constraintMap = deformJson ? deformJson->child : 0; constraintMap; constraintMap = constraintMap->next)
for (slotMap = constraintMap->child; slotMap; slotMap = slotMap->next)
timelinesCount += slotMap->size;
if (drawOrderJson) ++timelinesCount;
if (events) ++timelinesCount;
animation = spAnimation_create(root->name, timelinesCount);
animation->timelinesCount = 0;
/* Slot timelines. */ /* Slot timelines. */
for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) { for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) {
Json *timelineMap; int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name);
if (slotIndex == -1) {
cleanUpTimelines(timelines);
_spSkeletonJson_setError(self, NULL, "Slot not found: ", slotMap->name);
return NULL;
}
int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name); for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) {
if (slotIndex == -1) { if (strcmp(timelineMap->name, "attachment") == 0) {
spAnimation_dispose(animation); int frameCount = timelineMap->size;
_spSkeletonJson_setError(self, root, "Slot not found: ", slotMap->name); spAttachmentTimeline *timeline = spAttachmentTimeline_create(frameCount, slotIndex);
return 0; for (keyMap = timelineMap->child, frame = 0; keyMap; keyMap = keyMap->next, ++frame) {
} spAttachmentTimeline_setFrame(timeline, frame, Json_getFloat(keyMap, "time", 0), Json_getItem(keyMap, "name")->valueString);
}
spTimelineArray_add(timelines, SUPER(timeline));
for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) { } else if (strcmp(timelineMap->name, "rgba") == 0) {
if (strcmp(timelineMap->name, "attachment") == 0) { float time;
spAttachmentTimeline *timeline = spAttachmentTimeline_create(timelineMap->size); int frameCount = timelineMap->size;
timeline->slotIndex = slotIndex; int bezierCount = frameCount << 2;
spRGBATimeline *timeline = spRGBATimeline_create(frameCount, bezierCount, slotIndex);
keyMap = timelineMap->child;
time = Json_getFloat(keyMap, "time", 0);
toColor2(&color, Json_getString(keyMap, "color", 0), 1);
for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { for (frame = 0, bezier = 0;;++frame) {
Json* name = Json_getItem(valueMap, "name"); float time2;
spAttachmentTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), spRGBATimeline_setFrame(timeline, frame, time, color.r, color.g, color.b, color.a);
name->type == Json_NULL ? 0 : name->valueString); nextMap = keyMap->next;
} if (!nextMap) break;
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); time2 = Json_getFloat(nextMap, "time", 0);
animation->duration = MAX(animation->duration, timeline->frames[timelineMap->size - 1]); toColor2(&newColor, Json_getString(nextMap, "color", 0), 1);
curve = Json_getItem(keyMap, "curve");
if (curve) {
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 0, time, time2, color.r, newColor.r, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 1, time, time2, color.g, newColor.g, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 2, time, time2, color.b, newColor.b, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 3, time, time2, color.a, newColor.a, 1);
}
time = time2;
color = newColor;
keyMap = nextMap;
}
spTimelineArray_add(timelines, SUPER(SUPER(timeline)));
} else if (strcmp(timelineMap->name, "rgb") == 0) {
float time;
int frameCount = timelineMap->size;
int bezierCount = frameCount * 3;
spRGBTimeline *timeline = spRGBTimeline_create(frameCount, bezierCount, slotIndex);
keyMap = timelineMap->child;
time = Json_getFloat(keyMap, "time", 0);
toColor2(&color, Json_getString(keyMap, "color", 0), 1);
} else if (strcmp(timelineMap->name, "color") == 0) { for (frame = 0, bezier = 0;;++frame) {
spColorTimeline *timeline = spColorTimeline_create(timelineMap->size); float time2;
timeline->slotIndex = slotIndex; spRGBTimeline_setFrame(timeline, frame, time, color.r, color.g, color.b);
nextMap = keyMap->next;
if (!nextMap) break;
time2 = Json_getFloat(nextMap, "time", 0);
toColor2(&newColor, Json_getString(nextMap, "color", 0), 1);
curve = Json_getItem(keyMap, "curve");
if (curve) {
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 0, time, time2, color.r, newColor.r, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 1, time, time2, color.g, newColor.g, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 2, time, time2, color.b, newColor.b, 1);
}
time = time2;
color = newColor;
keyMap = nextMap;
}
spTimelineArray_add(timelines, SUPER(SUPER(timeline)));
} else if (strcmp(timelineMap->name, "alpha") == 0) {
spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(spAlphaTimeline_create(timelineMap->size, timelineMap->size, slotIndex)), 0, 1));
} else if (strcmp(timelineMap->name, "rgba2") == 0) {
float time;
int frameCount = timelineMap->size;
int bezierCount = frameCount * 7;
spRGBA2Timeline *timeline = spRGBA2Timeline_create(frameCount, bezierCount, slotIndex);
keyMap = timelineMap->child;
time = Json_getFloat(keyMap, "time", 0);
toColor2(&color, Json_getString(keyMap, "light", 0), 1);
toColor2(&color2, Json_getString(keyMap, "dark", 0), 0);
for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { for (frame = 0, bezier = 0;;++frame) {
const char* s = Json_getString(valueMap, "color", 0); float time2;
spColorTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), spRGBA2Timeline_setFrame(timeline, frame, time, color.r, color.g, color.b, color.a, color2.g, color2.g, color2.b);
toColor(s, 2), toColor(s, 3)); nextMap = keyMap->next;
readCurve(valueMap, SUPER(timeline), frameIndex); if (!nextMap) break;
} time2 = Json_getFloat(nextMap, "time", 0);
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); toColor2(&newColor, Json_getString(nextMap, "light", 0), 1);
animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * COLOR_ENTRIES]); toColor2(&newColor2, Json_getString(nextMap, "dark", 0), 0);
curve = Json_getItem(keyMap, "curve");
if (curve) {
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 0, time, time2, color.r, newColor.r, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 1, time, time2, color.g, newColor.g, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 2, time, time2, color.b, newColor.b, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 3, time, time2, color.a, newColor.a, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 4, time, time2, color2.r, newColor2.r, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 5, time, time2, color2.g, newColor2.g, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 6, time, time2, color2.b, newColor2.b, 1);
}
time = time2;
color = newColor;
color2 = newColor2;
keyMap = nextMap;
}
spTimelineArray_add(timelines, SUPER(SUPER(timeline)));
} else if (strcmp(timelineMap->name, "rgb2") == 0) {
float time;
int frameCount = timelineMap->size;
int bezierCount = frameCount * 7;
spRGBA2Timeline *timeline = spRGBA2Timeline_create(frameCount, bezierCount, slotIndex);
keyMap = timelineMap->child;
time = Json_getFloat(keyMap, "time", 0);
toColor2(&color, Json_getString(keyMap, "light", 0), 0);
toColor2(&color2, Json_getString(keyMap, "dark", 0), 0);
} else if (strcmp(timelineMap->name, "twoColor") == 0) { for (frame = 0, bezier = 0;;++frame) {
spTwoColorTimeline *timeline = spTwoColorTimeline_create(timelineMap->size); float time2;
timeline->slotIndex = slotIndex; spRGBA2Timeline_setFrame(timeline, frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b);
nextMap = keyMap->next;
for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { if (!nextMap) break;
const char* s = Json_getString(valueMap, "light", 0); time2 = Json_getFloat(nextMap, "time", 0);
const char* ds = Json_getString(valueMap, "dark", 0); toColor2(&newColor, Json_getString(nextMap, "light", 0), 0);
spTwoColorTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), toColor2(&newColor2, Json_getString(nextMap, "dark", 0), 0);
toColor(s, 3), toColor(ds, 0), toColor(ds, 1), toColor(ds, 2)); curve = Json_getItem(keyMap, "curve");
readCurve(valueMap, SUPER(timeline), frameIndex); if (curve) {
} bezier = readCurve(curve, SUPER(timeline), bezier, frame, 0, time, time2, color.r, newColor.r, 1);
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); bezier = readCurve(curve, SUPER(timeline), bezier, frame, 1, time, time2, color.g, newColor.g, 1);
animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * TWOCOLOR_ENTRIES]); bezier = readCurve(curve, SUPER(timeline), bezier, frame, 2, time, time2, color.b, newColor.b, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 3, time, time2, color2.r, newColor2.r, 1);
} else { bezier = readCurve(curve, SUPER(timeline), bezier, frame, 4, time, time2, color2.g, newColor2.g, 1);
spAnimation_dispose(animation); bezier = readCurve(curve, SUPER(timeline), bezier, frame, 5, time, time2, color2.b, newColor2.b, 1);
_spSkeletonJson_setError(self, 0, "Invalid timeline type for a slot: ", timelineMap->name); }
return 0; time = time2;
} color = newColor;
} color2 = newColor2;
} keyMap = nextMap;
}
spTimelineArray_add(timelines, SUPER(SUPER(timeline)));
} else {
cleanUpTimelines(timelines);
_spSkeletonJson_setError(self, NULL, "Invalid timeline type for a slot: ", timelineMap->name);
return NULL;
}
}
}
/* Bone timelines. */ /* Bone timelines. */
for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) { for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) {
Json *timelineMap;
int boneIndex = spSkeletonData_findBoneIndex(skeletonData, boneMap->name); int boneIndex = spSkeletonData_findBoneIndex(skeletonData, boneMap->name);
if (boneIndex == -1) { if (boneIndex == -1) {
spAnimation_dispose(animation); cleanUpTimelines(timelines);
_spSkeletonJson_setError(self, root, "Bone not found: ", boneMap->name); _spSkeletonJson_setError(self, NULL, "Bone not found: ", boneMap->name);
return 0; return NULL;
} }
for (timelineMap = boneMap->child; timelineMap; timelineMap = timelineMap->next) { for (timelineMap = boneMap->child; timelineMap; timelineMap = timelineMap->next) {
if (strcmp(timelineMap->name, "rotate") == 0) { if (timelineMap->size == 0) continue;
spRotateTimeline *timeline = spRotateTimeline_create(timelineMap->size);
timeline->boneIndex = boneIndex;
for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { if (strcmp(timelineMap->name, "rotate") == 0) {
spRotateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "angle", 0)); spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(spRotateTimeline_create(timelineMap->size, timelineMap->size, boneIndex)), 0, 1));
readCurve(valueMap, SUPER(timeline), frameIndex); } else if (strcmp(timelineMap->name, "translate") == 0) {
} spTranslateTimeline *timeline = spTranslateTimeline_create(timelineMap->size, timelineMap->size << 1, boneIndex);
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); spTimelineArray_add(timelines, readTimeline2(timelineMap->child, SUPER(timeline), "x", "y", 0, scale));
animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * ROTATE_ENTRIES]); } else if (strcmp(timelineMap->name, "translatex") == 0) {
spTranslateXTimeline *timeline = spTranslateXTimeline_create(timelineMap->size, timelineMap->size, boneIndex);
} else { spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 0, scale));
int isScale = strcmp(timelineMap->name, "scale") == 0; } else if (strcmp(timelineMap->name, "translatey") == 0) {
int isTranslate = strcmp(timelineMap->name, "translate") == 0; spTranslateYTimeline *timeline = spTranslateYTimeline_create(timelineMap->size, timelineMap->size, boneIndex);
int isShear = strcmp(timelineMap->name, "shear") == 0; spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 0, scale));
if (isScale || isTranslate || isShear) { } else if (strcmp(timelineMap->name, "scale") == 0) {
float defaultValue = 0; spScaleTimeline *timeline = spScaleTimeline_create(timelineMap->size, timelineMap->size << 1, boneIndex);
float timelineScale = isTranslate ? self->scale: 1; spTimelineArray_add(timelines, readTimeline2(timelineMap->child, SUPER(timeline), "x", "y", 1, 1));
spTranslateTimeline *timeline = 0; } else if (strcmp(timelineMap->name, "scalex") == 0) {
if (isScale) { spScaleXTimeline *timeline = spScaleXTimeline_create(timelineMap->size, timelineMap->size, boneIndex);
timeline = spScaleTimeline_create(timelineMap->size); spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 1, 1));
defaultValue = 1; } else if (strcmp(timelineMap->name, "scaley") == 0) {
} spScaleYTimeline *timeline = spScaleYTimeline_create(timelineMap->size, timelineMap->size, boneIndex);
else if (isTranslate) timeline = spTranslateTimeline_create(timelineMap->size); spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 1, 1));
else if (isShear) timeline = spShearTimeline_create(timelineMap->size); } else if (strcmp(timelineMap->name, "shear") == 0) {
timeline->boneIndex = boneIndex; spShearTimeline *timeline = spShearTimeline_create(timelineMap->size, timelineMap->size << 1, boneIndex);
spTimelineArray_add(timelines, readTimeline2(timelineMap->child, SUPER(timeline), "x", "y", 0, 1));
for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { } else if (strcmp(timelineMap->name, "shearx") == 0) {
spTranslateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), spShearXTimeline *timeline = spShearXTimeline_create(timelineMap->size, timelineMap->size, boneIndex);
Json_getFloat(valueMap, "x", defaultValue) * timelineScale, spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 0, 1));
Json_getFloat(valueMap, "y", defaultValue) * timelineScale); } else if (strcmp(timelineMap->name, "sheary") == 0) {
readCurve(valueMap, SUPER(timeline), frameIndex); spShearYTimeline *timeline = spShearYTimeline_create(timelineMap->size, timelineMap->size, boneIndex);
} spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 0, 1));
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); } else {
animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * TRANSLATE_ENTRIES]); cleanUpTimelines(timelines);
_spSkeletonJson_setError(self, NULL, "Invalid timeline type for a bone: ", timelineMap->name);
} else { return NULL;
spAnimation_dispose(animation); }
_spSkeletonJson_setError(self, 0, "Invalid timeline type for a bone: ", timelineMap->name); }
return 0; }
}
}
}
}
/* IK constraint timelines. */ /* IK constraint timelines. */
for (constraintMap = ik ? ik->child : 0; constraintMap; constraintMap = constraintMap->next) { for (constraintMap = ik ? ik->child : 0; constraintMap; constraintMap = constraintMap->next) {
spIkConstraintData* constraint = spSkeletonData_findIkConstraint(skeletonData, constraintMap->name); spIkConstraintData *constraint;
spIkConstraintTimeline* timeline = spIkConstraintTimeline_create(constraintMap->size); spIkConstraintTimeline *timeline;
for (frameIndex = 0; frameIndex < skeletonData->ikConstraintsCount; ++frameIndex) { int constraintIndex;
if (constraint == skeletonData->ikConstraints[frameIndex]) { float time, mix, softness;
timeline->ikConstraintIndex = frameIndex; keyMap = constraintMap->child;
break; if (keyMap == NULL) continue;
}
} constraint = spSkeletonData_findIkConstraint(skeletonData, constraintMap->name);
for (valueMap = constraintMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { constraintIndex = spSkeletonData_findIkConstraintIndex(skeletonData, constraint->name);
spIkConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "mix", 1), Json_getFloat(valueMap, "softness", 0) * self->scale, timeline = spIkConstraintTimeline_create(constraintMap->size, constraintMap->size << 1, constraintIndex);
Json_getInt(valueMap, "bendPositive", 1) ? 1 : -1, Json_getInt(valueMap, "compress", 0) ? 1 : 0, Json_getInt(valueMap, "stretch", 0) ? 1 : 0);
readCurve(valueMap, SUPER(timeline), frameIndex); time = Json_getFloat(keyMap, "time", 0);
} mix = Json_getFloat(keyMap, "mix", 1);
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); softness = Json_getFloat(keyMap, "softness", 0) * scale;
animation->duration = MAX(animation->duration, timeline->frames[(constraintMap->size - 1) * IKCONSTRAINT_ENTRIES]);
} for (frame = 0, bezier = 0;; frame++) {
float time2, mix2, softness2;
int bendDirection = Json_getInt(keyMap, "bendPositive", 1) ? 1 : -1;
spIkConstraintTimeline_setFrame(timeline, frame, time, mix, softness, bendDirection, Json_getInt(keyMap, "compress", 0) ? 1 : 0, Json_getInt(keyMap, "stretch", 0) ? 1 : 0);
nextMap = keyMap->next;
if (!nextMap) break;
time2 = Json_getFloat(nextMap, "time", 0);
mix2 = Json_getFloat(nextMap, "mix", 1);
softness2 = Json_getFloat(nextMap, "softness", 0) * scale;
curve = Json_getItem(keyMap, "curve");
if (curve) {
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 0, time, time2, mix, mix2, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 1, time, time2, softness, softness2, scale);
}
time = time2;
mix = mix2;
softness = softness2;
keyMap = nextMap;
}
spTimelineArray_add(timelines, SUPER(SUPER(timeline)));
}
/* Transform constraint timelines. */ /* Transform constraint timelines. */
for (constraintMap = transform ? transform->child : 0; constraintMap; constraintMap = constraintMap->next) { for (constraintMap = transform ? transform->child : 0; constraintMap; constraintMap = constraintMap->next) {
spTransformConstraintData* constraint = spSkeletonData_findTransformConstraint(skeletonData, constraintMap->name); spTransformConstraintData *constraint;
spTransformConstraintTimeline* timeline = spTransformConstraintTimeline_create(constraintMap->size); spTransformConstraintTimeline *timeline;
for (frameIndex = 0; frameIndex < skeletonData->transformConstraintsCount; ++frameIndex) { int constraintIndex;
if (constraint == skeletonData->transformConstraints[frameIndex]) { float time, mixRotate, mixShearY, mixX, mixY, mixScaleX, mixScaleY;
timeline->transformConstraintIndex = frameIndex; keyMap = constraintMap->child;
break; if (keyMap == NULL) continue;
}
} constraint = spSkeletonData_findTransformConstraint(skeletonData, constraintMap->name);
for (valueMap = constraintMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { constraintIndex = spSkeletonData_findTransformConstraintIndex(skeletonData, constraint->name);
spTransformConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "rotateMix", 1), timeline = spTransformConstraintTimeline_create(constraintMap->size, constraintMap->size << 2, constraintIndex);
Json_getFloat(valueMap, "translateMix", 1), Json_getFloat(valueMap, "scaleMix", 1), Json_getFloat(valueMap, "shearMix", 1));
readCurve(valueMap, SUPER(timeline), frameIndex); time = Json_getFloat(keyMap, "time", 0);
} mixRotate = Json_getFloat(keyMap, "mixRotate", 1);
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); mixShearY = Json_getFloat(keyMap, "mixShearY", 1);
animation->duration = MAX(animation->duration, timeline->frames[(constraintMap->size - 1) * TRANSFORMCONSTRAINT_ENTRIES]); mixX = Json_getFloat(keyMap, "mixX", 1);
} mixY = Json_getFloat(keyMap, "mixY", mixX);
mixScaleX = Json_getFloat(keyMap, "mixScaleX", 1);
mixScaleY = Json_getFloat(keyMap, "mixScaleY", mixScaleX);
for (frame = 0, bezier = 0;; frame++) {
float time2, mixRotate2, mixShearY2, mixX2, mixY2, mixScaleX2, mixScaleY2;
spTransformConstraintTimeline_setFrame(timeline, frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY);
nextMap = keyMap->next;
if (!nextMap) break;
time2 = Json_getFloat(nextMap, "time", 0);
mixRotate2 = Json_getFloat(nextMap, "mixRotate", 1);
mixShearY2 = Json_getFloat(nextMap, "mixShearY", 1);
mixX2 = Json_getFloat(nextMap, "mixX", 1);
mixY2 = Json_getFloat(nextMap, "mixY", mixX2);
mixScaleX2 = Json_getFloat(nextMap, "mixScaleX", 1);
mixScaleY2 = Json_getFloat(nextMap, "mixScaleY", mixScaleX2);
curve = Json_getItem(keyMap, "curve");
if (curve) {
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 1, time, time2, mixX, mixX2, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 2, time, time2, mixY, mixY2, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1);
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1);
}
time = time2;
mixRotate = mixRotate2;
mixX = mixX2;
mixY = mixY2;
mixScaleX = mixScaleX2;
mixScaleY = mixScaleY2;
mixScaleX = mixScaleX2;
keyMap = nextMap;
}
spTimelineArray_add(timelines, SUPER(SUPER(timeline)));
}
/** Path constraint timelines. */ /** Path constraint timelines. */
for(constraintMap = path ? path->child : 0; constraintMap; constraintMap = constraintMap->next ) { for (constraintMap = paths ? paths->child : 0; constraintMap; constraintMap = constraintMap->next) {
int constraintIndex, i; spPathConstraintData *data = spSkeletonData_findPathConstraint(skeletonData, constraintMap->name);
Json* timelineMap; int index;
if (!data) {
spPathConstraintData* data = spSkeletonData_findPathConstraint(skeletonData, constraintMap->name); cleanUpTimelines(timelines);
if (!data) { _spSkeletonJson_setError(self, NULL, "Path constraint not found: ", constraintMap->name);
spAnimation_dispose(animation); return NULL;
_spSkeletonJson_setError(self, root, "Path constraint not found: ", constraintMap->name); }
return 0; index = spSkeletonData_findPathConstraintIndex(skeletonData, data->name);
} for (timelineMap = constraintMap->child; timelineMap; timelineMap = timelineMap->next) {
for (i = 0; i < skeletonData->pathConstraintsCount; i++) { const char *timelineName;
if (skeletonData->pathConstraints[i] == data) { keyMap = timelineMap->child;
constraintIndex = i; if (keyMap == NULL) continue;
break; timelineName = timelineMap->name;
} if (strcmp(timelineName, "position") == 0 ) {
} spPathConstraintPositionTimeline *timeline = spPathConstraintPositionTimeline_create(timelineMap->size, timelineMap->size, index);
spTimelineArray_add(timelines, readTimeline(keyMap, SUPER(timeline), 0, data->positionMode == SP_POSITION_MODE_FIXED ? scale : 1));
for (timelineMap = constraintMap->child; timelineMap; timelineMap = timelineMap->next) { } else if (strcmp(timelineName, "spacing") == 0) {
const char* timelineName = timelineMap->name; spCurveTimeline1 *timeline = SUPER(spPathConstraintSpacingTimeline_create(timelineMap->size, timelineMap->size, index));
if (strcmp(timelineName, "position") == 0 || strcmp(timelineName, "spacing") == 0) { spTimelineArray_add(timelines, readTimeline(keyMap, timeline, 0,
spPathConstraintPositionTimeline* timeline; data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED ? scale : 1));
float timelineScale = 1; } else if (strcmp(timelineName, "mix") == 0) {
if (strcmp(timelineName, "spacing") == 0) { spPathConstraintMixTimeline *timeline = spPathConstraintMixTimeline_create(timelineMap->size, timelineMap->size * 3, index);
timeline = (spPathConstraintPositionTimeline*)spPathConstraintSpacingTimeline_create(timelineMap->size); float time = Json_getFloat(keyMap, "time", 0);
if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) timelineScale = self->scale; float mixRotate = Json_getFloat(keyMap, "mixRotate", 1);
} else { float mixX = Json_getFloat(keyMap, "mixX", 1);
timeline = spPathConstraintPositionTimeline_create(timelineMap->size); float mixY = Json_getFloat(keyMap, "mixY", mixX);
if (data->positionMode == SP_POSITION_MODE_FIXED) timelineScale = self->scale; for (frame = 0, bezier = 0;; frame++) {
} float time2, mixRotate2, mixX2, mixY2;
timeline->pathConstraintIndex = constraintIndex; spPathConstraintMixTimeline_setFrame(timeline, frame, time, mixRotate, mixX, mixY);
for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { nextMap = keyMap->next;
spPathConstraintPositionTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, timelineName, 0) * timelineScale); if (nextMap == NULL) {
readCurve(valueMap, SUPER(timeline), frameIndex); break;
} }
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); time2 = Json_getFloat(nextMap, "time", 0);
animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * PATHCONSTRAINTPOSITION_ENTRIES]); mixRotate2 = Json_getFloat(nextMap, "mixRotate", 1);
} else if (strcmp(timelineName, "mix") == 0) { mixX2 = Json_getFloat(nextMap, "mixX", 1);
spPathConstraintMixTimeline* timeline = spPathConstraintMixTimeline_create(timelineMap->size); mixY2 = Json_getFloat(nextMap, "mixY", mixX2);
timeline->pathConstraintIndex = constraintIndex; curve = Json_getItem(keyMap, "curve");
for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { if (curve != NULL) {
spPathConstraintMixTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), bezier = readCurve(curve, SUPER(timeline), bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1);
Json_getFloat(valueMap, "rotateMix", 1), Json_getFloat(valueMap, "translateMix", 1)); bezier = readCurve(curve, SUPER(timeline), bezier, frame, 1, time, time2, mixX, mixX2, 1);
readCurve(valueMap, SUPER(timeline), frameIndex); bezier = readCurve(curve, SUPER(timeline), bezier, frame, 2, time, time2, mixY, mixY2, 1);
} }
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); time = time2;
animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * PATHCONSTRAINTMIX_ENTRIES]); mixRotate = mixRotate2;
} mixX = mixX2;
} mixY = mixY2;
} keyMap = nextMap;
}
spTimelineArray_add(timelines, SUPER(SUPER(timeline)));
}
}
}
/* Deform timelines. */ /* Deform timelines. */
for (constraintMap = deformJson ? deformJson->child : 0; constraintMap; constraintMap = constraintMap->next) { for (constraintMap = deformJson ? deformJson->child : 0; constraintMap; constraintMap = constraintMap->next) {
spSkin* skin = spSkeletonData_findSkin(skeletonData, constraintMap->name); spSkin* skin = spSkeletonData_findSkin(skeletonData, constraintMap->name);
for (slotMap = constraintMap->child; slotMap; slotMap = slotMap->next) { for (slotMap = constraintMap->child; slotMap; slotMap = slotMap->next) {
int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name); int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name);
Json* timelineMap;
for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) { for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) {
float* tempDeform; float* tempDeform;
spDeformTimeline *timeline; spVertexAttachment* attachment;
int weighted, deformLength; int weighted, deformLength;
spDeformTimeline *timeline;
float time;
keyMap = timelineMap->child;
if (keyMap == NULL) continue;
spVertexAttachment* attachment = SUB_CAST(spVertexAttachment, spSkin_getAttachment(skin, slotIndex, timelineMap->name)); attachment = SUB_CAST(spVertexAttachment, spSkin_getAttachment(skin, slotIndex, timelineMap->name));
if (!attachment) { if (!attachment) {
spAnimation_dispose(animation); cleanUpTimelines(timelines);
_spSkeletonJson_setError(self, 0, "Attachment not found: ", timelineMap->name); _spSkeletonJson_setError(self, 0, "Attachment not found: ", timelineMap->name);
return 0; return 0;
} }
weighted = attachment->bones != 0; weighted = attachment->bones != 0;
deformLength = weighted ? attachment->verticesCount / 3 * 2 : attachment->verticesCount; deformLength = weighted ? attachment->verticesCount / 3 * 2 : attachment->verticesCount;
tempDeform = MALLOC(float, deformLength); tempDeform = MALLOC(float, deformLength);
timeline = spDeformTimeline_create(timelineMap->size, deformLength, timelineMap->size, slotIndex, attachment);
timeline = spDeformTimeline_create(timelineMap->size, deformLength); time = Json_getFloat(keyMap, "time", 0);
timeline->slotIndex = slotIndex; for (frame = 0, bezier = 0;; frame++) {
timeline->attachment = SUPER(attachment); Json *vertices = Json_getItem(keyMap, "vertices");
for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) {
float* deform; float* deform;
Json* vertices = Json_getItem(valueMap, "vertices"); float time2;
if (!vertices) { if (!vertices) {
if (weighted) { if (weighted) {
deform = tempDeform; deform = tempDeform;
@ -416,7 +626,7 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
} else } else
deform = attachment->vertices; deform = attachment->vertices;
} else { } else {
int v, start = Json_getInt(valueMap, "offset", 0); int v, start = Json_getInt(keyMap, "offset", 0);
Json* vertex; Json* vertex;
deform = tempDeform; deform = tempDeform;
memset(deform, 0, sizeof(float) * start); memset(deform, 0, sizeof(float) * start);
@ -434,13 +644,20 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
deform[v] += verticesValues[v]; deform[v] += verticesValues[v];
} }
} }
spDeformTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), deform); spDeformTimeline_setFrame(timeline, frame, time, deform);
readCurve(valueMap, SUPER(timeline), frameIndex); nextMap = keyMap->next;
if (!nextMap) break;
time2 = Json_getFloat(nextMap, "time", 0);
curve = Json_getItem(keyMap, "curve");
if (curve) {
bezier = readCurve(curve, SUPER(timeline), bezier, frame, 0, time, time2, 0, 1, 1);
}
time = time2;
keyMap = nextMap;
} }
FREE(tempDeform); FREE(tempDeform);
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); spTimelineArray_add(timelines, SUPER(SUPER(timeline)));
animation->duration = MAX(animation->duration, timeline->frames[timelineMap->size - 1]);
} }
} }
} }
@ -448,10 +665,10 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
/* Draw order timeline. */ /* Draw order timeline. */
if (drawOrderJson) { if (drawOrderJson) {
spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrderJson->size, skeletonData->slotsCount); spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrderJson->size, skeletonData->slotsCount);
for (valueMap = drawOrderJson->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { for (keyMap = drawOrderJson->child, frame = 0; keyMap; keyMap = keyMap->next, ++frame) {
int ii; int ii;
int* drawOrder = 0; int* drawOrder = 0;
Json* offsets = Json_getItem(valueMap, "offsets"); Json* offsets = Json_getItem(keyMap, "offsets");
if (offsets) { if (offsets) {
Json* offsetMap; Json* offsetMap;
int* unchanged = MALLOC(int, skeletonData->slotsCount - offsets->size); int* unchanged = MALLOC(int, skeletonData->slotsCount - offsets->size);
@ -464,7 +681,7 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
for (offsetMap = offsets->child; offsetMap; offsetMap = offsetMap->next) { for (offsetMap = offsets->child; offsetMap; offsetMap = offsetMap->next) {
int slotIndex = spSkeletonData_findSlotIndex(skeletonData, Json_getString(offsetMap, "slot", 0)); int slotIndex = spSkeletonData_findSlotIndex(skeletonData, Json_getString(offsetMap, "slot", 0));
if (slotIndex == -1) { if (slotIndex == -1) {
spAnimation_dispose(animation); cleanUpTimelines(timelines);
_spSkeletonJson_setError(self, 0, "Slot not found: ", Json_getString(offsetMap, "slot", 0)); _spSkeletonJson_setError(self, 0, "Slot not found: ", Json_getString(offsetMap, "slot", 0));
return 0; return 0;
} }
@ -483,41 +700,44 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r
if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex];
FREE(unchanged); FREE(unchanged);
} }
spDrawOrderTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), drawOrder); spDrawOrderTimeline_setFrame(timeline, frame, Json_getFloat(keyMap, "time", 0), drawOrder);
FREE(drawOrder); FREE(drawOrder);
} }
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline);
animation->duration = MAX(animation->duration, timeline->frames[drawOrderJson->size - 1]); spTimelineArray_add(timelines, SUPER(timeline));
} }
/* Event timeline. */ /* Event timeline. */
if (events) { if (events) {
spEventTimeline* timeline = spEventTimeline_create(events->size); spEventTimeline* timeline = spEventTimeline_create(events->size);
for (valueMap = events->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { for (keyMap = events->child, frame = 0; keyMap; keyMap = keyMap->next, ++frame) {
spEvent* event; spEvent* event;
const char* stringValue; const char* stringValue;
spEventData* eventData = spSkeletonData_findEvent(skeletonData, Json_getString(valueMap, "name", 0)); spEventData* eventData = spSkeletonData_findEvent(skeletonData, Json_getString(keyMap, "name", 0));
if (!eventData) { if (!eventData) {
spAnimation_dispose(animation); cleanUpTimelines(timelines);
_spSkeletonJson_setError(self, 0, "Event not found: ", Json_getString(valueMap, "name", 0)); _spSkeletonJson_setError(self, 0, "Event not found: ", Json_getString(keyMap, "name", 0));
return 0; return 0;
} }
event = spEvent_create(Json_getFloat(valueMap, "time", 0), eventData); event = spEvent_create(Json_getFloat(keyMap, "time", 0), eventData);
event->intValue = Json_getInt(valueMap, "int", eventData->intValue); event->intValue = Json_getInt(keyMap, "int", eventData->intValue);
event->floatValue = Json_getFloat(valueMap, "float", eventData->floatValue); event->floatValue = Json_getFloat(keyMap, "float", eventData->floatValue);
stringValue = Json_getString(valueMap, "string", eventData->stringValue); stringValue = Json_getString(keyMap, "string", eventData->stringValue);
if (stringValue) MALLOC_STR(event->stringValue, stringValue); if (stringValue) MALLOC_STR(event->stringValue, stringValue);
if (eventData->audioPath) { if (eventData->audioPath) {
event->volume = Json_getFloat(valueMap, "volume", 1); event->volume = Json_getFloat(keyMap, "volume", 1);
event->balance = Json_getFloat(valueMap, "volume", 0); event->balance = Json_getFloat(keyMap, "volume", 0);
} }
spEventTimeline_setFrame(timeline, frameIndex, event); spEventTimeline_setFrame(timeline, frame, event);
} }
animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); spTimelineArray_add(timelines, SUPER(timeline));
animation->duration = MAX(animation->duration, timeline->frames[events->size - 1]);
} }
return animation; duration = 0;
for (i = 0, n = timelines->size; i < n; i++) {
duration = MAX(duration, spTimeline_getDuration(timelines->items[i]));
}
return spAnimation_create(root->name, timelines, duration);
} }
static void _readVertices (spSkeletonJson* self, Json* attachmentMap, spVertexAttachment* attachment, int verticesLength) { static void _readVertices (spSkeletonJson* self, Json* attachmentMap, spVertexAttachment* attachment, int verticesLength) {
@ -802,10 +1022,11 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
data->offsetScaleY = Json_getFloat(constraintMap, "scaleY", 0); data->offsetScaleY = Json_getFloat(constraintMap, "scaleY", 0);
data->offsetShearY = Json_getFloat(constraintMap, "shearY", 0); data->offsetShearY = Json_getFloat(constraintMap, "shearY", 0);
data->rotateMix = Json_getFloat(constraintMap, "rotateMix", 1); data->mixX = Json_getFloat(constraintMap, "mixX", 1);
data->translateMix = Json_getFloat(constraintMap, "translateMix", 1); data->mixY = Json_getFloat(constraintMap, "mixY", data->mixX);
data->scaleMix = Json_getFloat(constraintMap, "scaleMix", 1); data->mixScaleX = Json_getFloat(constraintMap, "mixScaleX", 1);
data->shearMix = Json_getFloat(constraintMap, "shearMix", 1); data->mixScaleY = Json_getFloat(constraintMap, "mixScaleY", data->mixScaleX);
data->mixShearY = Json_getFloat(constraintMap, "mixShearY", 1);
skeletonData->transformConstraints[i] = data; skeletonData->transformConstraints[i] = data;
} }
@ -864,8 +1085,9 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
if (data->positionMode == SP_POSITION_MODE_FIXED) data->position *= self->scale; if (data->positionMode == SP_POSITION_MODE_FIXED) data->position *= self->scale;
data->spacing = Json_getFloat(constraintMap, "spacing", 0); data->spacing = Json_getFloat(constraintMap, "spacing", 0);
if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) data->spacing *= self->scale; if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) data->spacing *= self->scale;
data->rotateMix = Json_getFloat(constraintMap, "rotateMix", 1); data->mixRotate = Json_getFloat(constraintMap, "mixRotate", 1);
data->translateMix = Json_getFloat(constraintMap, "translateMix", 1); data->mixX = Json_getFloat(constraintMap, "mixX", 1);
data->mixY = Json_getFloat(constraintMap, "mixY", 1);
skeletonData->pathConstraints[i] = data; skeletonData->pathConstraints[i] = data;
} }

View File

@ -45,7 +45,56 @@ sf::BlendMode additivePma = sf::BlendMode(sf::BlendMode::One, sf::BlendMode::One
sf::BlendMode multiplyPma = sf::BlendMode(sf::BlendMode::DstColor, sf::BlendMode::OneMinusSrcAlpha); sf::BlendMode multiplyPma = sf::BlendMode(sf::BlendMode::DstColor, sf::BlendMode::OneMinusSrcAlpha);
sf::BlendMode screenPma = sf::BlendMode(sf::BlendMode::One, sf::BlendMode::OneMinusSrcColor); sf::BlendMode screenPma = sf::BlendMode(sf::BlendMode::One, sf::BlendMode::OneMinusSrcColor);
_SP_ARRAY_IMPLEMENT_TYPE(spColorArray, spColor) spColorArray *spColorArray_create(int initialCapacity) {
spColorArray *array = ((spColorArray *) _spCalloc(1, sizeof(spColorArray), "_file_name_", 48));
array->size = 0;
array->capacity = initialCapacity;
array->items = ((spColor *) _spCalloc(initialCapacity, sizeof(spColor), "_file_name_", 48));
return array;
}
void spColorArray_dispose(spColorArray *self) {
_spFree((void *) self->items);
_spFree((void *) self);
}
void spColorArray_clear(spColorArray *self) { self->size = 0; }
spColorArray *spColorArray_setSize(spColorArray *self, int newSize) {
self->size = newSize;
if (self->capacity < newSize) {
self->capacity = ((8) > ((int) (self->size * 1.75f)) ? (8) : ((int) (self->size * 1.75f)));
self->items = ((spColor *) _spRealloc(self->items, sizeof(spColor) * (self->capacity)));
}
return self;
}
void spColorArray_ensureCapacity(spColorArray *self, int newCapacity) {
if (self->capacity >= newCapacity)return;
self->capacity = newCapacity;
self->items = ((spColor *) _spRealloc(self->items, sizeof(spColor) * (self->capacity)));
}
void spColorArray_add(spColorArray *self, spColor value) {
if (self->size == self->capacity) {
self->capacity = ((8) > ((int) (self->size * 1.75f)) ? (8) : ((int) (self->size * 1.75f)));
self->items = ((spColor *) _spRealloc(self->items, sizeof(spColor) * (self->capacity)));
}
self->items[self->size++] = value;
}
void spColorArray_addAll(spColorArray *self, spColorArray *other) {
int i = 0;
for (; i < other->size; i++) { spColorArray_add(self, other->items[i]); }
}
void spColorArray_addAllValues(spColorArray *self, spColor *values, int offset, int count) {
int i = offset, n = offset + count;
for (; i < n; i++) { spColorArray_add(self, values[i]); }
}
void spColorArray_removeAt(spColorArray *self, int index) {
self->size--;
memmove(self->items + index, self->items + index + 1, sizeof(spColor) * (self->size - index));
}
spColor spColorArray_pop(spColorArray *self) {
spColor item = self->items[--self->size];
return item;
}
spColor spColorArray_peek(spColorArray *self) { return self->items[self->size - 1]; }
void _spAtlasPage_createTexture (spAtlasPage* self, const char* path){ void _spAtlasPage_createTexture (spAtlasPage* self, const char* path){
Texture* texture = new Texture(); Texture* texture = new Texture();