From e6a14ff532ace76a4911c5236fa0c2b8afc28335 Mon Sep 17 00:00:00 2001 From: badlogic Date: Wed, 26 May 2021 15:17:20 +0200 Subject: [PATCH] [c] 4.0 porting, complete but with bugs. --- spine-c/spine-c/include/spine/Animation.h | 1 + spine-c/spine-c/include/spine/SkeletonData.h | 6 + spine-c/spine-c/include/spine/spine.h | 1 + spine-c/spine-c/src/spine/Animation.c | 7 +- spine-c/spine-c/src/spine/Json.c | 9 + spine-c/spine-c/src/spine/Json.h | 1 + spine-c/spine-c/src/spine/SkeletonBinary.c | 7 +- spine-c/spine-c/src/spine/SkeletonData.c | 21 + spine-c/spine-c/src/spine/SkeletonJson.c | 756 ++++++++++++------- spine-sfml/c/src/spine/spine-sfml.cpp | 51 +- 10 files changed, 586 insertions(+), 274 deletions(-) diff --git a/spine-c/spine-c/include/spine/Animation.h b/spine-c/spine-c/include/spine/Animation.h index b268ac44e..7296c6329 100644 --- a/spine-c/spine-c/include/spine/Animation.h +++ b/spine-c/spine-c/include/spine/Animation.h @@ -117,6 +117,7 @@ struct spTimeline { spPropertyId propertyIds[SP_MAX_PROPERTY_IDS]; int propertyIdsCount; spFloatArray *frames; + int frameCount; int frameEntries; }; diff --git a/spine-c/spine-c/include/spine/SkeletonData.h b/spine-c/spine-c/include/spine/SkeletonData.h index 41ecedc85..7dffbe404 100644 --- a/spine-c/spine-c/include/spine/SkeletonData.h +++ b/spine-c/spine-c/include/spine/SkeletonData.h @@ -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 int spSkeletonData_findIkConstraintIndex (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 int spSkeletonData_findPathConstraintIndex (const spSkeletonData* self, const char* constraintName); + #ifdef __cplusplus } #endif diff --git a/spine-c/spine-c/include/spine/spine.h b/spine-c/spine-c/include/spine/spine.h index ed2d586a0..5db4885a8 100644 --- a/spine-c/spine-c/include/spine/spine.h +++ b/spine-c/spine-c/include/spine/spine.h @@ -31,6 +31,7 @@ #define SPINE_SPINE_H_ #include +#include #include #include #include diff --git a/spine-c/spine-c/src/spine/Animation.c b/spine-c/spine-c/src/spine/Animation.c index 5c8acdcc8..89d9270d0 100644 --- a/spine-c/spine-c/src/spine/Animation.c +++ b/spine-c/spine-c/src/spine/Animation.c @@ -39,7 +39,9 @@ spAnimation* spAnimation_create (const char* name, spTimelineArray* timelines, f int i, n; spAnimation* self = NEW(spAnimation); 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++) { 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; self->frames = spFloatArray_create(frameCount * frameEntries); + self->frameCount = frameCount; self->frameEntries = frameEntries; self->vtable.dispose = dispose; 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) { - return self->frames->size / self->frameEntries; + return self->frameCount / self->frameEntries; } float spTimeline_getDuration (const spTimeline* self) { diff --git a/spine-c/spine-c/src/spine/Json.c b/spine-c/spine-c/src/spine/Json.c index 852e76d25..37742c6d9 100644 --- a/spine-c/spine-c/src/spine/Json.c +++ b/spine-c/spine-c/src/spine/Json.c @@ -444,6 +444,15 @@ Json *Json_getItem (Json *object, const char* string) { 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) { object = Json_getItem(object, name); if (object) return object->valueString; diff --git a/spine-c/spine-c/src/spine/Json.h b/spine-c/spine-c/src/spine/Json.h index 1742525dd..9300a683c 100644 --- a/spine-c/spine-c/src/spine/Json.h +++ b/spine-c/spine-c/src/spine/Json.h @@ -69,6 +69,7 @@ void Json_dispose (Json* json); /* Get item "string" from object. Case insensitive. */ 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); float Json_getFloat (Json* json, const char* name, float defaultValue); int Json_getInt (Json* json, const char* name, int defaultValue); diff --git a/spine-c/spine-c/src/spine/SkeletonBinary.c b/spine-c/spine-c/src/spine/SkeletonBinary.c index 557fe8d77..10c03f7c4 100644 --- a/spine-c/spine-c/src/spine/SkeletonBinary.c +++ b/spine-c/spine-c/src/spine/SkeletonBinary.c @@ -1139,7 +1139,7 @@ spSkeletonData* spSkeletonBinary_readSkeletonDataFile (spSkeletonBinary* self, c spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const unsigned char* binary, const int length) { int i, n, ii, nonessential; - char buffer[16]; + char buffer[32]; int lowHash, highHash; spSkeletonData* skeletonData; _spSkeletonBinary* internal = SUB_CAST(_spSkeletonBinary, self); @@ -1155,9 +1155,8 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const skeletonData = spSkeletonData_create(); lowHash = readInt(input); highHash = readInt(input); - sprintf(buffer, "%x", highHash); - sprintf(buffer + 8, "%x", lowHash); - buffer[15] = 0; + sprintf(buffer, "%x%x", highHash, lowHash); + buffer[31] = 0; skeletonData->hash = strdup(buffer); skeletonData->version = readString(input); diff --git a/spine-c/spine-c/src/spine/SkeletonData.c b/spine-c/spine-c/src/spine/SkeletonData.c index eee6eb1e2..04fc5ac0a 100644 --- a/spine-c/spine-c/src/spine/SkeletonData.c +++ b/spine-c/spine-c/src/spine/SkeletonData.c @@ -136,6 +136,13 @@ spIkConstraintData* spSkeletonData_findIkConstraint (const spSkeletonData* self, 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) { int i; for (i = 0; i < self->transformConstraintsCount; ++i) @@ -143,9 +150,23 @@ spTransformConstraintData* spSkeletonData_findTransformConstraint (const spSkele 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) { int i; for (i = 0; i < self->pathConstraintsCount; ++i) if (strcmp(self->pathConstraints[i]->name, constraintName) == 0) return self->pathConstraints[i]; 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; +} diff --git a/spine-c/spine-c/src/spine/SkeletonJson.c b/spine-c/spine-c/src/spine/SkeletonJson.c index c7c65af77..31495f345 100644 --- a/spine-c/spine-c/src/spine/SkeletonJson.c +++ b/spine-c/spine-c/src/spine/SkeletonJson.c @@ -104,20 +104,86 @@ static float toColor (const char* value, int index) { return color / (float)255; } -static void readCurve (Json* frame, spCurveTimeline* timeline, int frameIndex) { - Json* curve = Json_getItem(frame, "curve"); - if (!curve) return; - if (curve->type == Json_String && strcmp(curve->valueString, "stepped") == 0) - spCurveTimeline_setStepped(timeline, frameIndex); - 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 toColor2(spColor *color, const char *value, int /*bool*/ hasAlpha) { + color->r = toColor(value, 0); + color->g = toColor(value, 1); + color->b = toColor(value, 2); + if (hasAlpha) color->a = toColor(value, 3); } +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, const char* parent, int inheritDeform ) { @@ -142,273 +208,417 @@ static void _spSkeletonJson_addLinkedMesh (spSkeletonJson* self, spMeshAttachmen linkedMesh->inheritDeform = inheritDeform; } -static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* root, spSkeletonData *skeletonData) { - int frameIndex; - spAnimation* animation; - Json* valueMap; - int timelinesCount = 0; +static void cleanUpTimelines(spTimelineArray *timelines) { + int i, n; + for (i = 0, n = timelines->size; i < n; i++) { + spTimeline_dispose(timelines->items[i]); + } + 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* slots = Json_getItem(root, "slots"); Json* ik = Json_getItem(root, "ik"); 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* drawOrderJson = Json_getItem(root, "drawOrder"); Json* events = Json_getItem(root, "events"); - Json *boneMap, *slotMap, *constraintMap; - if (!drawOrderJson) drawOrderJson = Json_getItem(root, "draworder"); - - 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; + Json *boneMap, *slotMap, *constraintMap, *keyMap, *nextMap, *curve, *timelineMap; + int frame, bezier, i, n; + spColor color, color2, newColor, newColor2; /* Slot timelines. */ - for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) { - Json *timelineMap; + for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) { + 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); - if (slotIndex == -1) { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, root, "Slot not found: ", slotMap->name); - return 0; - } + for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) { + if (strcmp(timelineMap->name, "attachment") == 0) { + int frameCount = timelineMap->size; + spAttachmentTimeline *timeline = spAttachmentTimeline_create(frameCount, slotIndex); + 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) { - if (strcmp(timelineMap->name, "attachment") == 0) { - spAttachmentTimeline *timeline = spAttachmentTimeline_create(timelineMap->size); - timeline->slotIndex = slotIndex; + } else if (strcmp(timelineMap->name, "rgba") == 0) { + float time; + int frameCount = timelineMap->size; + 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) { - Json* name = Json_getItem(valueMap, "name"); - spAttachmentTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), - name->type == Json_NULL ? 0 : name->valueString); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[timelineMap->size - 1]); + for (frame = 0, bezier = 0;;++frame) { + float time2; + spRGBATimeline_setFrame(timeline, frame, time, color.r, color.g, color.b, color.a); + 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); + 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) { - spColorTimeline *timeline = spColorTimeline_create(timelineMap->size); - timeline->slotIndex = slotIndex; + for (frame = 0, bezier = 0;;++frame) { + float time2; + 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) { - const char* s = Json_getString(valueMap, "color", 0); - spColorTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), - toColor(s, 2), toColor(s, 3)); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * COLOR_ENTRIES]); + for (frame = 0, bezier = 0;;++frame) { + float time2; + spRGBA2Timeline_setFrame(timeline, frame, time, color.r, color.g, color.b, color.a, color2.g, color2.g, color2.b); + nextMap = keyMap->next; + if (!nextMap) break; + time2 = Json_getFloat(nextMap, "time", 0); + toColor2(&newColor, Json_getString(nextMap, "light", 0), 1); + 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) { - spTwoColorTimeline *timeline = spTwoColorTimeline_create(timelineMap->size); - timeline->slotIndex = slotIndex; - - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - const char* s = Json_getString(valueMap, "light", 0); - const char* ds = Json_getString(valueMap, "dark", 0); - spTwoColorTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), toColor(s, 0), toColor(s, 1), toColor(s, 2), - toColor(s, 3), toColor(ds, 0), toColor(ds, 1), toColor(ds, 2)); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * TWOCOLOR_ENTRIES]); - - } else { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, 0, "Invalid timeline type for a slot: ", timelineMap->name); - return 0; - } - } - } + for (frame = 0, bezier = 0;;++frame) { + float time2; + spRGBA2Timeline_setFrame(timeline, frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b); + nextMap = keyMap->next; + if (!nextMap) break; + time2 = Json_getFloat(nextMap, "time", 0); + toColor2(&newColor, Json_getString(nextMap, "light", 0), 0); + 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, color2.r, newColor2.r, 1); + bezier = readCurve(curve, SUPER(timeline), bezier, frame, 4, time, time2, color2.g, newColor2.g, 1); + bezier = readCurve(curve, SUPER(timeline), bezier, frame, 5, time, time2, color2.b, newColor2.b, 1); + } + 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. */ - for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) { - Json *timelineMap; + for (boneMap = bones ? bones->child : 0; boneMap; boneMap = boneMap->next) { - int boneIndex = spSkeletonData_findBoneIndex(skeletonData, boneMap->name); - if (boneIndex == -1) { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, root, "Bone not found: ", boneMap->name); - return 0; - } + int boneIndex = spSkeletonData_findBoneIndex(skeletonData, boneMap->name); + if (boneIndex == -1) { + cleanUpTimelines(timelines); + _spSkeletonJson_setError(self, NULL, "Bone not found: ", boneMap->name); + return NULL; + } - for (timelineMap = boneMap->child; timelineMap; timelineMap = timelineMap->next) { - if (strcmp(timelineMap->name, "rotate") == 0) { - spRotateTimeline *timeline = spRotateTimeline_create(timelineMap->size); - timeline->boneIndex = boneIndex; + for (timelineMap = boneMap->child; timelineMap; timelineMap = timelineMap->next) { + if (timelineMap->size == 0) continue; - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spRotateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "angle", 0)); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * ROTATE_ENTRIES]); - - } else { - int isScale = strcmp(timelineMap->name, "scale") == 0; - int isTranslate = strcmp(timelineMap->name, "translate") == 0; - int isShear = strcmp(timelineMap->name, "shear") == 0; - if (isScale || isTranslate || isShear) { - float defaultValue = 0; - float timelineScale = isTranslate ? self->scale: 1; - spTranslateTimeline *timeline = 0; - if (isScale) { - timeline = spScaleTimeline_create(timelineMap->size); - defaultValue = 1; - } - else if (isTranslate) timeline = spTranslateTimeline_create(timelineMap->size); - else if (isShear) timeline = spShearTimeline_create(timelineMap->size); - timeline->boneIndex = boneIndex; - - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spTranslateTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), - Json_getFloat(valueMap, "x", defaultValue) * timelineScale, - Json_getFloat(valueMap, "y", defaultValue) * timelineScale); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * TRANSLATE_ENTRIES]); - - } else { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, 0, "Invalid timeline type for a bone: ", timelineMap->name); - return 0; - } - } - } - } + if (strcmp(timelineMap->name, "rotate") == 0) { + spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(spRotateTimeline_create(timelineMap->size, timelineMap->size, boneIndex)), 0, 1)); + } else if (strcmp(timelineMap->name, "translate") == 0) { + spTranslateTimeline *timeline = spTranslateTimeline_create(timelineMap->size, timelineMap->size << 1, boneIndex); + spTimelineArray_add(timelines, readTimeline2(timelineMap->child, SUPER(timeline), "x", "y", 0, scale)); + } else if (strcmp(timelineMap->name, "translatex") == 0) { + spTranslateXTimeline *timeline = spTranslateXTimeline_create(timelineMap->size, timelineMap->size, boneIndex); + spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 0, scale)); + } else if (strcmp(timelineMap->name, "translatey") == 0) { + spTranslateYTimeline *timeline = spTranslateYTimeline_create(timelineMap->size, timelineMap->size, boneIndex); + spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 0, scale)); + } else if (strcmp(timelineMap->name, "scale") == 0) { + spScaleTimeline *timeline = spScaleTimeline_create(timelineMap->size, timelineMap->size << 1, boneIndex); + spTimelineArray_add(timelines, readTimeline2(timelineMap->child, SUPER(timeline), "x", "y", 1, 1)); + } else if (strcmp(timelineMap->name, "scalex") == 0) { + spScaleXTimeline *timeline = spScaleXTimeline_create(timelineMap->size, timelineMap->size, boneIndex); + spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 1, 1)); + } else if (strcmp(timelineMap->name, "scaley") == 0) { + spScaleYTimeline *timeline = spScaleYTimeline_create(timelineMap->size, timelineMap->size, boneIndex); + spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 1, 1)); + } else if (strcmp(timelineMap->name, "shear") == 0) { + spShearTimeline *timeline = spShearTimeline_create(timelineMap->size, timelineMap->size << 1, boneIndex); + spTimelineArray_add(timelines, readTimeline2(timelineMap->child, SUPER(timeline), "x", "y", 0, 1)); + } else if (strcmp(timelineMap->name, "shearx") == 0) { + spShearXTimeline *timeline = spShearXTimeline_create(timelineMap->size, timelineMap->size, boneIndex); + spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 0, 1)); + } else if (strcmp(timelineMap->name, "sheary") == 0) { + spShearYTimeline *timeline = spShearYTimeline_create(timelineMap->size, timelineMap->size, boneIndex); + spTimelineArray_add(timelines, readTimeline(timelineMap->child, SUPER(timeline), 0, 1)); + } else { + cleanUpTimelines(timelines); + _spSkeletonJson_setError(self, NULL, "Invalid timeline type for a bone: ", timelineMap->name); + return NULL; + } + } + } /* IK constraint timelines. */ - for (constraintMap = ik ? ik->child : 0; constraintMap; constraintMap = constraintMap->next) { - spIkConstraintData* constraint = spSkeletonData_findIkConstraint(skeletonData, constraintMap->name); - spIkConstraintTimeline* timeline = spIkConstraintTimeline_create(constraintMap->size); - for (frameIndex = 0; frameIndex < skeletonData->ikConstraintsCount; ++frameIndex) { - if (constraint == skeletonData->ikConstraints[frameIndex]) { - timeline->ikConstraintIndex = frameIndex; - break; - } - } - for (valueMap = constraintMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spIkConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "mix", 1), Json_getFloat(valueMap, "softness", 0) * self->scale, - 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); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(constraintMap->size - 1) * IKCONSTRAINT_ENTRIES]); - } + for (constraintMap = ik ? ik->child : 0; constraintMap; constraintMap = constraintMap->next) { + spIkConstraintData *constraint; + spIkConstraintTimeline *timeline; + int constraintIndex; + float time, mix, softness; + keyMap = constraintMap->child; + if (keyMap == NULL) continue; + + constraint = spSkeletonData_findIkConstraint(skeletonData, constraintMap->name); + constraintIndex = spSkeletonData_findIkConstraintIndex(skeletonData, constraint->name); + timeline = spIkConstraintTimeline_create(constraintMap->size, constraintMap->size << 1, constraintIndex); + + time = Json_getFloat(keyMap, "time", 0); + mix = Json_getFloat(keyMap, "mix", 1); + softness = Json_getFloat(keyMap, "softness", 0) * scale; + + 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. */ - for (constraintMap = transform ? transform->child : 0; constraintMap; constraintMap = constraintMap->next) { - spTransformConstraintData* constraint = spSkeletonData_findTransformConstraint(skeletonData, constraintMap->name); - spTransformConstraintTimeline* timeline = spTransformConstraintTimeline_create(constraintMap->size); - for (frameIndex = 0; frameIndex < skeletonData->transformConstraintsCount; ++frameIndex) { - if (constraint == skeletonData->transformConstraints[frameIndex]) { - timeline->transformConstraintIndex = frameIndex; - break; - } - } - for (valueMap = constraintMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spTransformConstraintTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, "rotateMix", 1), - Json_getFloat(valueMap, "translateMix", 1), Json_getFloat(valueMap, "scaleMix", 1), Json_getFloat(valueMap, "shearMix", 1)); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(constraintMap->size - 1) * TRANSFORMCONSTRAINT_ENTRIES]); - } + for (constraintMap = transform ? transform->child : 0; constraintMap; constraintMap = constraintMap->next) { + spTransformConstraintData *constraint; + spTransformConstraintTimeline *timeline; + int constraintIndex; + float time, mixRotate, mixShearY, mixX, mixY, mixScaleX, mixScaleY; + keyMap = constraintMap->child; + if (keyMap == NULL) continue; + + constraint = spSkeletonData_findTransformConstraint(skeletonData, constraintMap->name); + constraintIndex = spSkeletonData_findTransformConstraintIndex(skeletonData, constraint->name); + timeline = spTransformConstraintTimeline_create(constraintMap->size, constraintMap->size << 2, constraintIndex); + + time = Json_getFloat(keyMap, "time", 0); + mixRotate = Json_getFloat(keyMap, "mixRotate", 1); + mixShearY = Json_getFloat(keyMap, "mixShearY", 1); + 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. */ - for(constraintMap = path ? path->child : 0; constraintMap; constraintMap = constraintMap->next ) { - int constraintIndex, i; - Json* timelineMap; - - spPathConstraintData* data = spSkeletonData_findPathConstraint(skeletonData, constraintMap->name); - if (!data) { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, root, "Path constraint not found: ", constraintMap->name); - return 0; - } - for (i = 0; i < skeletonData->pathConstraintsCount; i++) { - if (skeletonData->pathConstraints[i] == data) { - constraintIndex = i; - break; - } - } - - for (timelineMap = constraintMap->child; timelineMap; timelineMap = timelineMap->next) { - const char* timelineName = timelineMap->name; - if (strcmp(timelineName, "position") == 0 || strcmp(timelineName, "spacing") == 0) { - spPathConstraintPositionTimeline* timeline; - float timelineScale = 1; - if (strcmp(timelineName, "spacing") == 0) { - timeline = (spPathConstraintPositionTimeline*)spPathConstraintSpacingTimeline_create(timelineMap->size); - if (data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED) timelineScale = self->scale; - } else { - timeline = spPathConstraintPositionTimeline_create(timelineMap->size); - if (data->positionMode == SP_POSITION_MODE_FIXED) timelineScale = self->scale; - } - timeline->pathConstraintIndex = constraintIndex; - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spPathConstraintPositionTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), Json_getFloat(valueMap, timelineName, 0) * timelineScale); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * PATHCONSTRAINTPOSITION_ENTRIES]); - } else if (strcmp(timelineName, "mix") == 0) { - spPathConstraintMixTimeline* timeline = spPathConstraintMixTimeline_create(timelineMap->size); - timeline->pathConstraintIndex = constraintIndex; - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spPathConstraintMixTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), - Json_getFloat(valueMap, "rotateMix", 1), Json_getFloat(valueMap, "translateMix", 1)); - readCurve(valueMap, SUPER(timeline), frameIndex); - } - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[(timelineMap->size - 1) * PATHCONSTRAINTMIX_ENTRIES]); - } - } - } + for (constraintMap = paths ? paths->child : 0; constraintMap; constraintMap = constraintMap->next) { + spPathConstraintData *data = spSkeletonData_findPathConstraint(skeletonData, constraintMap->name); + int index; + if (!data) { + cleanUpTimelines(timelines); + _spSkeletonJson_setError(self, NULL, "Path constraint not found: ", constraintMap->name); + return NULL; + } + index = spSkeletonData_findPathConstraintIndex(skeletonData, data->name); + for (timelineMap = constraintMap->child; timelineMap; timelineMap = timelineMap->next) { + const char *timelineName; + keyMap = timelineMap->child; + if (keyMap == NULL) continue; + 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)); + } else if (strcmp(timelineName, "spacing") == 0) { + spCurveTimeline1 *timeline = SUPER(spPathConstraintSpacingTimeline_create(timelineMap->size, timelineMap->size, index)); + spTimelineArray_add(timelines, readTimeline(keyMap, timeline, 0, + data->spacingMode == SP_SPACING_MODE_LENGTH || data->spacingMode == SP_SPACING_MODE_FIXED ? scale : 1)); + } else if (strcmp(timelineName, "mix") == 0) { + spPathConstraintMixTimeline *timeline = spPathConstraintMixTimeline_create(timelineMap->size, timelineMap->size * 3, index); + float time = Json_getFloat(keyMap, "time", 0); + float mixRotate = Json_getFloat(keyMap, "mixRotate", 1); + float mixX = Json_getFloat(keyMap, "mixX", 1); + float mixY = Json_getFloat(keyMap, "mixY", mixX); + for (frame = 0, bezier = 0;; frame++) { + float time2, mixRotate2, mixX2, mixY2; + spPathConstraintMixTimeline_setFrame(timeline, frame, time, mixRotate, mixX, mixY); + nextMap = keyMap->next; + if (nextMap == NULL) { + break; + } + time2 = Json_getFloat(nextMap, "time", 0); + mixRotate2 = Json_getFloat(nextMap, "mixRotate", 1); + mixX2 = Json_getFloat(nextMap, "mixX", 1); + mixY2 = Json_getFloat(nextMap, "mixY", mixX2); + curve = Json_getItem(keyMap, "curve"); + if (curve != NULL) { + 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); + } + time = time2; + mixRotate = mixRotate2; + mixX = mixX2; + mixY = mixY2; + keyMap = nextMap; + } + spTimelineArray_add(timelines, SUPER(SUPER(timeline))); + } + } + } /* Deform timelines. */ for (constraintMap = deformJson ? deformJson->child : 0; constraintMap; constraintMap = constraintMap->next) { spSkin* skin = spSkeletonData_findSkin(skeletonData, constraintMap->name); for (slotMap = constraintMap->child; slotMap; slotMap = slotMap->next) { int slotIndex = spSkeletonData_findSlotIndex(skeletonData, slotMap->name); - Json* timelineMap; + for (timelineMap = slotMap->child; timelineMap; timelineMap = timelineMap->next) { float* tempDeform; - spDeformTimeline *timeline; - int weighted, deformLength; + spVertexAttachment* attachment; + 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) { - spAnimation_dispose(animation); + cleanUpTimelines(timelines); _spSkeletonJson_setError(self, 0, "Attachment not found: ", timelineMap->name); return 0; } weighted = attachment->bones != 0; deformLength = weighted ? attachment->verticesCount / 3 * 2 : attachment->verticesCount; tempDeform = MALLOC(float, deformLength); + timeline = spDeformTimeline_create(timelineMap->size, deformLength, timelineMap->size, slotIndex, attachment); - timeline = spDeformTimeline_create(timelineMap->size, deformLength); - timeline->slotIndex = slotIndex; - timeline->attachment = SUPER(attachment); - - for (valueMap = timelineMap->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { + time = Json_getFloat(keyMap, "time", 0); + for (frame = 0, bezier = 0;; frame++) { + Json *vertices = Json_getItem(keyMap, "vertices"); float* deform; - Json* vertices = Json_getItem(valueMap, "vertices"); + float time2; + if (!vertices) { if (weighted) { deform = tempDeform; @@ -416,7 +626,7 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r } else deform = attachment->vertices; } else { - int v, start = Json_getInt(valueMap, "offset", 0); + int v, start = Json_getInt(keyMap, "offset", 0); Json* vertex; deform = tempDeform; memset(deform, 0, sizeof(float) * start); @@ -434,13 +644,20 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r deform[v] += verticesValues[v]; } } - spDeformTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), deform); - readCurve(valueMap, SUPER(timeline), frameIndex); + spDeformTimeline_setFrame(timeline, frame, time, deform); + 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); - animation->timelines[animation->timelinesCount++] = SUPER_CAST(spTimeline, timeline); - animation->duration = MAX(animation->duration, timeline->frames[timelineMap->size - 1]); + spTimelineArray_add(timelines, SUPER(SUPER(timeline))); } } } @@ -448,10 +665,10 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r /* Draw order timeline. */ if (drawOrderJson) { spDrawOrderTimeline* timeline = spDrawOrderTimeline_create(drawOrderJson->size, skeletonData->slotsCount); - for (valueMap = drawOrderJson->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - int ii; + for (keyMap = drawOrderJson->child, frame = 0; keyMap; keyMap = keyMap->next, ++frame) { + int ii; int* drawOrder = 0; - Json* offsets = Json_getItem(valueMap, "offsets"); + Json* offsets = Json_getItem(keyMap, "offsets"); if (offsets) { Json* offsetMap; 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) { int slotIndex = spSkeletonData_findSlotIndex(skeletonData, Json_getString(offsetMap, "slot", 0)); if (slotIndex == -1) { - spAnimation_dispose(animation); + cleanUpTimelines(timelines); _spSkeletonJson_setError(self, 0, "Slot not found: ", Json_getString(offsetMap, "slot", 0)); return 0; } @@ -483,41 +700,44 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r if (drawOrder[ii] == -1) drawOrder[ii] = unchanged[--unchangedIndex]; FREE(unchanged); } - spDrawOrderTimeline_setFrame(timeline, frameIndex, Json_getFloat(valueMap, "time", 0), drawOrder); + spDrawOrderTimeline_setFrame(timeline, frame, Json_getFloat(keyMap, "time", 0), 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. */ if (events) { spEventTimeline* timeline = spEventTimeline_create(events->size); - for (valueMap = events->child, frameIndex = 0; valueMap; valueMap = valueMap->next, ++frameIndex) { - spEvent* event; + for (keyMap = events->child, frame = 0; keyMap; keyMap = keyMap->next, ++frame) { + spEvent* event; 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) { - spAnimation_dispose(animation); - _spSkeletonJson_setError(self, 0, "Event not found: ", Json_getString(valueMap, "name", 0)); + cleanUpTimelines(timelines); + _spSkeletonJson_setError(self, 0, "Event not found: ", Json_getString(keyMap, "name", 0)); return 0; } - event = spEvent_create(Json_getFloat(valueMap, "time", 0), eventData); - event->intValue = Json_getInt(valueMap, "int", eventData->intValue); - event->floatValue = Json_getFloat(valueMap, "float", eventData->floatValue); - stringValue = Json_getString(valueMap, "string", eventData->stringValue); + event = spEvent_create(Json_getFloat(keyMap, "time", 0), eventData); + event->intValue = Json_getInt(keyMap, "int", eventData->intValue); + event->floatValue = Json_getFloat(keyMap, "float", eventData->floatValue); + stringValue = Json_getString(keyMap, "string", eventData->stringValue); if (stringValue) MALLOC_STR(event->stringValue, stringValue); if (eventData->audioPath) { - event->volume = Json_getFloat(valueMap, "volume", 1); - event->balance = Json_getFloat(valueMap, "volume", 0); + event->volume = Json_getFloat(keyMap, "volume", 1); + 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); - animation->duration = MAX(animation->duration, timeline->frames[events->size - 1]); + spTimelineArray_add(timelines, SUPER(timeline)); } - 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) { @@ -802,10 +1022,11 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha data->offsetScaleY = Json_getFloat(constraintMap, "scaleY", 0); data->offsetShearY = Json_getFloat(constraintMap, "shearY", 0); - data->rotateMix = Json_getFloat(constraintMap, "rotateMix", 1); - data->translateMix = Json_getFloat(constraintMap, "translateMix", 1); - data->scaleMix = Json_getFloat(constraintMap, "scaleMix", 1); - data->shearMix = Json_getFloat(constraintMap, "shearMix", 1); + data->mixX = Json_getFloat(constraintMap, "mixX", 1); + data->mixY = Json_getFloat(constraintMap, "mixY", data->mixX); + data->mixScaleX = Json_getFloat(constraintMap, "mixScaleX", 1); + data->mixScaleY = Json_getFloat(constraintMap, "mixScaleY", data->mixScaleX); + data->mixShearY = Json_getFloat(constraintMap, "mixShearY", 1); 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; data->spacing = Json_getFloat(constraintMap, "spacing", 0); 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->translateMix = Json_getFloat(constraintMap, "translateMix", 1); + data->mixRotate = Json_getFloat(constraintMap, "mixRotate", 1); + data->mixX = Json_getFloat(constraintMap, "mixX", 1); + data->mixY = Json_getFloat(constraintMap, "mixY", 1); skeletonData->pathConstraints[i] = data; } diff --git a/spine-sfml/c/src/spine/spine-sfml.cpp b/spine-sfml/c/src/spine/spine-sfml.cpp index e64ce0123..0d37050c0 100644 --- a/spine-sfml/c/src/spine/spine-sfml.cpp +++ b/spine-sfml/c/src/spine/spine-sfml.cpp @@ -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 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){ Texture* texture = new Texture();