diff --git a/spine-c/spine-c/include/spine/Bone.h b/spine-c/spine-c/include/spine/Bone.h index 350ae54b9..07d331ecd 100644 --- a/spine-c/spine-c/include/spine/Bone.h +++ b/spine-c/spine-c/include/spine/Bone.h @@ -54,6 +54,7 @@ struct spBone { float const c, d, worldY; int/*bool*/ sorted; + int/*bool*/ active; #ifdef __cplusplus spBone() : @@ -68,7 +69,7 @@ struct spBone { a(0), b(0), worldX(0), c(0), d(0), worldY(0), - sorted(0) { + sorted(0), active(0) { } #endif }; diff --git a/spine-c/spine-c/include/spine/BoneData.h b/spine-c/spine-c/include/spine/BoneData.h index 9b1d5ab2a..019a6fda4 100644 --- a/spine-c/spine-c/include/spine/BoneData.h +++ b/spine-c/spine-c/include/spine/BoneData.h @@ -52,6 +52,7 @@ struct spBoneData { float length; float x, y, rotation, scaleX, scaleY, shearX, shearY; spTransformMode transformMode; + int/*bool*/ skinRequired; #ifdef __cplusplus spBoneData() : @@ -63,7 +64,8 @@ struct spBoneData { rotation(0), scaleX(0), scaleY(0), shearX(0), shearY(0), - transformMode(SP_TRANSFORMMODE_NORMAL) { + transformMode(SP_TRANSFORMMODE_NORMAL), + skinRequired(0) { } #endif }; diff --git a/spine-c/spine-c/include/spine/IkConstraint.h b/spine-c/spine-c/include/spine/IkConstraint.h index b2c529723..f56f8222a 100644 --- a/spine-c/spine-c/include/spine/IkConstraint.h +++ b/spine-c/spine-c/include/spine/IkConstraint.h @@ -52,6 +52,8 @@ typedef struct spIkConstraint { int /*boolean*/ stretch; float mix; + int /*boolean*/ active; + #ifdef __cplusplus spIkConstraint() : data(0), @@ -60,7 +62,8 @@ typedef struct spIkConstraint { target(0), bendDirection(0), stretch(0), - mix(0) { + mix(0), + active(0) { } #endif } spIkConstraint; diff --git a/spine-c/spine-c/include/spine/IkConstraintData.h b/spine-c/spine-c/include/spine/IkConstraintData.h index c2ae99036..09e35a989 100644 --- a/spine-c/spine-c/include/spine/IkConstraintData.h +++ b/spine-c/spine-c/include/spine/IkConstraintData.h @@ -40,6 +40,7 @@ extern "C" { typedef struct spIkConstraintData { const char* const name; int order; + int /*boolean*/ skinRequired; int bonesCount; spBoneData** bones; @@ -53,6 +54,8 @@ typedef struct spIkConstraintData { #ifdef __cplusplus spIkConstraintData() : name(0), + order(0), + skinRequired(0), bonesCount(0), bones(0), target(0), diff --git a/spine-c/spine-c/include/spine/PathConstraint.h b/spine-c/spine-c/include/spine/PathConstraint.h index b9895821c..7b3baead3 100644 --- a/spine-c/spine-c/include/spine/PathConstraint.h +++ b/spine-c/spine-c/include/spine/PathConstraint.h @@ -66,6 +66,8 @@ typedef struct spPathConstraint { float segments[10]; + int /*boolean*/ active; + #ifdef __cplusplus spPathConstraint() : data(0), @@ -85,7 +87,8 @@ typedef struct spPathConstraint { curvesCount(0), curves(0), lengthsCount(0), - lengths(0) { + lengths(0), + active(0) { } #endif } spPathConstraint; diff --git a/spine-c/spine-c/include/spine/PathConstraintData.h b/spine-c/spine-c/include/spine/PathConstraintData.h index f45d04ea6..060b54ac8 100644 --- a/spine-c/spine-c/include/spine/PathConstraintData.h +++ b/spine-c/spine-c/include/spine/PathConstraintData.h @@ -53,6 +53,7 @@ typedef enum { typedef struct spPathConstraintData { const char* const name; int order; + int/*bool*/ skinRequired; int bonesCount; spBoneData** const bones; spSlotData* target; @@ -65,6 +66,8 @@ typedef struct spPathConstraintData { #ifdef __cplusplus spPathConstraintData() : name(0), + order(0), + skinRequired(0), bonesCount(0), bones(0), target(0), diff --git a/spine-c/spine-c/include/spine/SkeletonData.h b/spine-c/spine-c/include/spine/SkeletonData.h index 735c0bb34..380aa88c1 100644 --- a/spine-c/spine-c/include/spine/SkeletonData.h +++ b/spine-c/spine-c/include/spine/SkeletonData.h @@ -49,6 +49,9 @@ typedef struct spSkeletonData { const char* hash; float x, y, width, height; + int stringsCount; + char** strings; + int bonesCount; spBoneData** bones; diff --git a/spine-c/spine-c/include/spine/TransformConstraint.h b/spine-c/spine-c/include/spine/TransformConstraint.h index 4ae5e3fb9..eb761ab00 100644 --- a/spine-c/spine-c/include/spine/TransformConstraint.h +++ b/spine-c/spine-c/include/spine/TransformConstraint.h @@ -46,6 +46,7 @@ typedef struct spTransformConstraint { spBone** const bones; spBone* target; float rotateMix, translateMix, scaleMix, shearMix; + int /*boolean*/ active; #ifdef __cplusplus spTransformConstraint() : @@ -56,7 +57,8 @@ typedef struct spTransformConstraint { rotateMix(0), translateMix(0), scaleMix(0), - shearMix(0) { + shearMix(0), + active(0) { } #endif } spTransformConstraint; diff --git a/spine-c/spine-c/include/spine/TransformConstraintData.h b/spine-c/spine-c/include/spine/TransformConstraintData.h index 13c1daf30..b4d572e8b 100644 --- a/spine-c/spine-c/include/spine/TransformConstraintData.h +++ b/spine-c/spine-c/include/spine/TransformConstraintData.h @@ -40,6 +40,7 @@ extern "C" { typedef struct spTransformConstraintData { const char* const name; int order; + int/*bool*/ skinRequired; int bonesCount; spBoneData** const bones; spBoneData* target; @@ -51,6 +52,8 @@ typedef struct spTransformConstraintData { #ifdef __cplusplus spTransformConstraintData() : name(0), + order(0), + skinRequired(0), bonesCount(0), bones(0), target(0), diff --git a/spine-c/spine-c/src/spine/Animation.c b/spine-c/spine-c/src/spine/Animation.c index 949ef1937..aec586d97 100644 --- a/spine-c/spine-c/src/spine/Animation.c +++ b/spine-c/spine-c/src/spine/Animation.c @@ -245,6 +245,7 @@ void _spRotateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, spRotateTimeline* self = SUB_CAST(spRotateTimeline, timeline); bone = skeleton->bones[self->boneIndex]; + if (!bone->active) return; if (time < self->frames[0]) { switch (blend) { case SP_MIX_BLEND_SETUP: @@ -333,6 +334,7 @@ void _spTranslateTimeline_apply (const spTimeline* timeline, spSkeleton* skeleto spTranslateTimeline* self = SUB_CAST(spTranslateTimeline, timeline); bone = skeleton->bones[self->boneIndex]; + if (!bone->active) return; if (time < self->frames[0]) { switch (blend) { case SP_MIX_BLEND_SETUP: @@ -415,6 +417,7 @@ void _spScaleTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f spScaleTimeline* self = SUB_CAST(spScaleTimeline, timeline); bone = skeleton->bones[self->boneIndex]; + if (!bone->active) return; if (time < self->frames[0]) { switch (blend) { case SP_MIX_BLEND_SETUP: @@ -533,6 +536,7 @@ void _spShearTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f spShearTimeline* self = SUB_CAST(spShearTimeline, timeline); bone = skeleton->bones[self->boneIndex]; + if (!bone->active) return; frames = self->frames; framesCount = self->framesCount; if (time < self->frames[0]) { @@ -614,6 +618,7 @@ void _spColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, f spColor* setup; spColorTimeline* self = (spColorTimeline*)timeline; slot = skeleton->slots[self->slotIndex]; + if (!slot->bone->active) return; if (time < self->frames[0]) { switch (blend) { @@ -706,6 +711,7 @@ void _spTwoColorTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton spColor* setupDark; spColorTimeline* self = (spColorTimeline*)timeline; slot = skeleton->slots[self->slotIndex]; + if (!slot->bone->active) return; if (time < self->frames[0]) { switch (blend) { @@ -809,6 +815,7 @@ void _spAttachmentTimeline_apply (const spTimeline* timeline, spSkeleton* skelet spAttachmentTimeline* self = (spAttachmentTimeline*)timeline; int frameIndex; spSlot* slot = skeleton->slots[self->slotIndex]; + if (!slot->bone->active) return; if (direction == SP_MIX_DIRECTION_OUT && blend == SP_MIX_BLEND_SETUP) { attachmentName = slot->data->attachmentName; @@ -893,6 +900,7 @@ void _spDeformTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, spDeformTimeline* self = (spDeformTimeline*)timeline; spSlot *slot = skeleton->slots[self->slotIndex]; + if (!slot->bone->active) return; if (!slot->attachment) return; switch (slot->attachment->type) { @@ -1295,6 +1303,7 @@ void _spIkConstraintTimeline_apply (const spTimeline* timeline, spSkeleton* skel spIkConstraintTimeline* self = (spIkConstraintTimeline*)timeline; constraint = skeleton->ikConstraints[self->ikConstraintIndex]; + if (!constraint->active) return; if (time < self->frames[0]) { switch (blend) { @@ -1410,6 +1419,8 @@ void _spTransformConstraintTimeline_apply (const spTimeline* timeline, spSkeleto int framesCount; constraint = skeleton->transformConstraints[self->transformConstraintIndex]; + if (!constraint->active) return; + if (time < self->frames[0]) { spTransformConstraintData* data = constraint->data; switch (blend) { @@ -1508,6 +1519,8 @@ void _spPathConstraintPositionTimeline_apply(const spTimeline* timeline, spSkele int framesCount; constraint = skeleton->pathConstraints[self->pathConstraintIndex]; + if (!constraint->active) return; + if (time < self->frames[0]) { switch (blend) { case SP_MIX_BLEND_SETUP: @@ -1576,6 +1589,8 @@ void _spPathConstraintSpacingTimeline_apply(const spTimeline* timeline, spSkelet int framesCount; constraint = skeleton->pathConstraints[self->pathConstraintIndex]; + if (!constraint->active) return; + if (time < self->frames[0]) { switch (blend) { case SP_MIX_BLEND_SETUP: @@ -1648,6 +1663,8 @@ void _spPathConstraintMixTimeline_apply(const spTimeline* timeline, spSkeleton* int framesCount; constraint = skeleton->pathConstraints[self->pathConstraintIndex]; + if (!constraint->active) return; + if (time < self->frames[0]) { switch (blend) { case SP_MIX_BLEND_SETUP: diff --git a/spine-c/spine-c/src/spine/AnimationState.c b/spine-c/spine-c/src/spine/AnimationState.c index 7a7fdb06f..0d1dadd81 100644 --- a/spine-c/spine-c/src/spine/AnimationState.c +++ b/spine-c/spine-c/src/spine/AnimationState.c @@ -541,6 +541,7 @@ void _spAnimationState_applyRotateTimeline (spAnimationState* self, spTimeline* rotateTimeline = SUB_CAST(spRotateTimeline, timeline); frames = rotateTimeline->frames; bone = skeleton->bones[rotateTimeline->boneIndex]; + if (!bone->active) return; if (time < frames[0]) { switch (blend) { case SP_MIX_BLEND_SETUP: diff --git a/spine-c/spine-c/src/spine/Skeleton.c b/spine-c/spine-c/src/spine/Skeleton.c index 0eac78c36..6864da921 100644 --- a/spine-c/spine-c/src/spine/Skeleton.c +++ b/spine-c/spine-c/src/spine/Skeleton.c @@ -219,6 +219,7 @@ static void _sortReset(spBone** bones, int bonesCount) { int i; for (i = 0; i < bonesCount; ++i) { spBone* bone = bones[i]; + if (!bone->active) continue; if (bone->sorted) _sortReset(bone->children, bone->childrenCount); bone->sorted = 0; } @@ -230,6 +231,10 @@ static void _sortIkConstraint (_spSkeleton* const internal, spIkConstraint* cons spBone* target = constraint->target; spBone** constrained; spBone* parent; + + constraint->active = constraint->target->active && (!constraint->data->skinRequired || (internal->super.skin != 0 && spIkConstraintDataArray_contains(internal->super.skin->ikConstraints, constraint->data))); + if (!constraint->active) return; + _sortBone(internal, target); constrained = constraint->bones; @@ -264,6 +269,10 @@ static void _sortPathConstraint(_spSkeleton* const internal, spPathConstraint* c spAttachment* attachment; spBone** constrained; spSkeleton* skeleton = SUPER_CAST(spSkeleton, internal); + + constraint->active = constraint->target->bone->active && (!constraint->data->skinRequired || (internal->super.skin != 0 && spPathConstraintDataArray_contains(internal->super.skin->pathConstraints, constraint->data))); + if (!constraint->active) return; + if (skeleton->skin) _sortPathConstraintAttachment(internal, skeleton->skin, slotIndex, slotBone); if (skeleton->data->defaultSkin && skeleton->data->defaultSkin != skeleton->skin) _sortPathConstraintAttachment(internal, skeleton->data->defaultSkin, slotIndex, slotBone); @@ -291,6 +300,10 @@ static void _sortTransformConstraint(_spSkeleton* const internal, spTransformCon spBone** constrained; spBone* child; int /*boolean*/ contains = 0; + + constraint->active = constraint->target->active && (!constraint->data->skinRequired || (internal->super.skin != 0 && spTransformConstraintDataArray_contains(internal->super.skin->transformConstraints, constraint->data))); + if (!constraint->active) return; + _sortBone(internal, constraint->target); constrained = constraint->bones; @@ -342,8 +355,23 @@ void spSkeleton_updateCache (spSkeleton* self) { internal->updateCacheResetCount = 0; bones = self->bones; - for (i = 0; i < self->bonesCount; ++i) - bones[i]->sorted = 0; + for (i = 0; i < self->bonesCount; ++i) { + spBone* bone = bones[i]; + bone->sorted = bone->data->skinRequired; + bone->active = !bone->sorted; + } + + if (self->skin) { + spBoneDataArray* skinBones = self->skin->bones; + for(i = 0; i < skinBones->size; i++) { + spBone* bone = self->bones[skinBones->items[i]->index]; + do { + bone->sorted = 0; + bone->active = -1; + bone = bone->parent; + } while (bone != 0); + } + } /* IK first, lowest hierarchy depth first. */ ikConstraints = self->ikConstraints; diff --git a/spine-c/spine-c/src/spine/SkeletonBinary.c b/spine-c/spine-c/src/spine/SkeletonBinary.c index 00fe6f8ec..0825ac19c 100644 --- a/spine-c/spine-c/src/spine/SkeletonBinary.c +++ b/spine-c/spine-c/src/spine/SkeletonBinary.c @@ -74,10 +74,6 @@ void spSkeletonBinary_dispose (spSkeletonBinary* self) { int i; _spSkeletonBinary* internal = SUB_CAST(_spSkeletonBinary, self); if (internal->ownsLoader) spAttachmentLoader_dispose(self->attachmentLoader); - for (i = 0; i < internal->linkedMeshCount; ++i) { - FREE(internal->linkedMeshes[i].parent); - FREE(internal->linkedMeshes[i].skin); - } FREE(internal->linkedMeshes); FREE(self->error); FREE(self); @@ -147,7 +143,7 @@ float readFloat (_dataInput* input) { char* readString (_dataInput* input) { int length = readVarint(input, 1); - char* string; + char *string; if (length == 0) { return 0; } @@ -158,6 +154,11 @@ char* readString (_dataInput* input) { return string; } +static char* readStringRef(_dataInput* input, spSkeletonData* skeletonData) { + int index = readVarint(input, 1); + return index == 0 ? 0 : skeletonData->strings[index - 1]; +} + static void readColor (_dataInput* input, float *r, float *g, float *b, float *a) { *r = readByte(input) / 255.0f; *g = readByte(input) / 255.0f; @@ -269,10 +270,9 @@ static spAnimation* _spSkeletonBinary_readAnimation (spSkeletonBinary* self, con timeline->slotIndex = slotIndex; for (frameIndex = 0; frameIndex < frameCount; ++frameIndex) { float time = readFloat(input); - const char* attachmentName = readString(input); + const char* attachmentName = readStringRef(input, skeletonData); /* TODO Avoid copying of attachmentName inside */ spAttachmentTimeline_setFrame(timeline, frameIndex, time, attachmentName); - FREE(attachmentName); } spTimelineArray_add(timelines, (spTimeline*)timeline); duration = MAX(duration, timeline->frames[frameCount - 1]); @@ -478,7 +478,7 @@ static spAnimation* _spSkeletonBinary_readAnimation (spSkeletonBinary* self, con float* tempDeform; spDeformTimeline *timeline; int weighted, deformLength; - const char* attachmentName = readString(input); + const char* attachmentName = readStringRef(input, skeletonData); int frameCount; spVertexAttachment* attachment = SUB_CAST(spVertexAttachment, @@ -488,10 +488,8 @@ static spAnimation* _spSkeletonBinary_readAnimation (spSkeletonBinary* self, con spTimeline_dispose(timelines->items[i]); spTimelineArray_dispose(timelines); _spSkeletonBinary_setError(self, "Attachment not found: ", attachmentName); - FREE(attachmentName); return 0; } - FREE(attachmentName); weighted = attachment->bones != 0; deformLength = weighted ? attachment->verticesCount / 3 * 2 : attachment->verticesCount; @@ -680,21 +678,22 @@ spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput spSkin* skin, int slotIndex, const char* attachmentName, spSkeletonData* skeletonData, int/*bool*/ nonessential) { int i; spAttachmentType type; - const char* name = readString(input); - int freeName = name != 0; - if (!name) { - freeName = 0; - name = attachmentName; - } + const char* name = readStringRef(input, skeletonData); + if (!name) name = attachmentName; type = (spAttachmentType)readByte(input); switch (type) { case SP_ATTACHMENT_REGION: { - const char* path = readString(input); + const char* path = readStringRef(input, skeletonData); spAttachment* attachment; spRegionAttachment* region; if (!path) MALLOC_STR(path, name); + else { + const char* tmp = 0; + MALLOC_STR(tmp, path); + path = tmp; + } attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, path); region = SUB_CAST(spRegionAttachment, attachment); region->path = path; @@ -708,7 +707,6 @@ spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput readColor(input, ®ion->color.r, ®ion->color.g, ®ion->color.b, ®ion->color.a); spRegionAttachment_updateOffset(region); spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); - if (freeName) FREE(name); return attachment; } case SP_ATTACHMENT_BOUNDING_BOX: { @@ -717,15 +715,19 @@ spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput _readVertices(self, input, SUB_CAST(spVertexAttachment, attachment), vertexCount); if (nonessential) readInt(input); /* Skip color. */ spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); - if (freeName) FREE(name); return attachment; } case SP_ATTACHMENT_MESH: { int vertexCount; spAttachment* attachment; spMeshAttachment* mesh; - const char* path = readString(input); + const char* path = readStringRef(input, skeletonData); if (!path) MALLOC_STR(path, name); + else { + const char* tmp = 0; + MALLOC_STR(tmp, path); + path = tmp; + } attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, path); mesh = SUB_CAST(spMeshAttachment, attachment); mesh->path = path; @@ -746,7 +748,6 @@ spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput mesh->height = 0; } spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); - if (freeName) FREE(name); return attachment; } case SP_ATTACHMENT_LINKED_MESH: { @@ -755,21 +756,25 @@ spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput spAttachment* attachment; spMeshAttachment* mesh; int inheritDeform; - const char* path = readString(input); + const char* path = readStringRef(input, skeletonData); if (!path) MALLOC_STR(path, name); + else { + const char* tmp = 0; + MALLOC_STR(tmp, path); + path = tmp; + } attachment = spAttachmentLoader_createAttachment(self->attachmentLoader, skin, type, name, path); mesh = SUB_CAST(spMeshAttachment, attachment); mesh->path = path; readColor(input, &mesh->color.r, &mesh->color.g, &mesh->color.b, &mesh->color.a); - skinName = readString(input); - parent = readString(input); + skinName = readStringRef(input, skeletonData); + parent = readStringRef(input, skeletonData); inheritDeform = readBoolean(input); if (nonessential) { mesh->width = readFloat(input) * self->scale; mesh->height = readFloat(input) * self->scale; } _spSkeletonBinary_addLinkedMesh(self, mesh, skinName, slotIndex, parent, inheritDeform); - if (freeName) FREE(name); return attachment; } case SP_ATTACHMENT_PATH: { @@ -786,7 +791,6 @@ spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput path->lengths[i] = readFloat(input) * self->scale; } if (nonessential) readInt(input); /* Skip color. */ - if (freeName) FREE(name); spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); return attachment; } @@ -812,30 +816,40 @@ spAttachment* spSkeletonBinary_readAttachment(spSkeletonBinary* self, _dataInput if (nonessential) readInt(input); /* Skip color. */ clip->endSlot = skeletonData->slots[endSlotIndex]; spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); - if (freeName) FREE(name); return attachment; } } - if (freeName) FREE(name); return 0; } -spSkin* spSkeletonBinary_readSkin(spSkeletonBinary* self, _dataInput* input, - const char* skinName, spSkeletonData* skeletonData, int/*bool*/ nonessential) { +spSkin* spSkeletonBinary_readSkin(spSkeletonBinary* self, _dataInput* input, int/*bool*/ defaultSkin, + spSkeletonData* skeletonData, int/*bool*/ nonessential) { spSkin* skin; - int slotCount = readVarint(input, 1); - int i, ii, nn; - if (slotCount == 0) - return 0; + int i, n, ii, nn; + const char* skinName = defaultSkin ? "default" : readStringRef(input, skeletonData); skin = spSkin_create(skinName); - for (i = 0; i < slotCount; ++i) { + + if (!defaultSkin) { + for (i = 0, n = readVarint(input, 1); i < n; i++) + spBoneDataArray_add(skin->bones, spSkeletonData_findBone(skeletonData, readVarint(input, 1))); + + for (i = 0, n = readVarint(input, 1); i < n; i++) + spIkConstraintDataArray_add(skin->ikConstraints, spSkeletonData_findIkConstraint(skeletonData, readVarint(input, 1))); + + for (i = 0, n = readVarint(input, 1); i < n; i++) + spTransformConstraintDataArray_add(skin->transformConstraints, spSkeletonData_findTransformConstraint(skeletonData, readVarint(input, 1))); + + for (i = 0, n = readVarint(input, 1); i < n; i++) + spPathConstraintDataArray_add(skin->pathConstraints, spSkeletonData_findPathConstraint(skeletonData, readVarint(input, 1))); + } + + for (i = 0, n = readVarint(input, 1); i < n; ++i) { int slotIndex = readVarint(input, 1); for (ii = 0, nn = readVarint(input, 1); ii < nn; ++ii) { - const char* name = readString(input); + const char* name = readStringRef(input, skeletonData); spAttachment* attachment = spSkeletonBinary_readAttachment(self, input, skin, slotIndex, name, skeletonData, nonessential); if (attachment) spSkin_setAttachment(skin, slotIndex, name, attachment); - FREE(name); } } return skin; @@ -856,7 +870,7 @@ spSkeletonData* spSkeletonBinary_readSkeletonDataFile (spSkeletonBinary* self, c spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const unsigned char* binary, const int length) { - int i, ii, nonessential; + int i, n, ii, nonessential; spSkeletonData* skeletonData; _spSkeletonBinary* internal = SUB_CAST(_spSkeletonBinary, self); @@ -896,6 +910,12 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const FREE(readString(input)); } + skeletonData->stringsCount = n = readVarint(input, 1); + skeletonData->strings = MALLOC(char*, skeletonData->stringsCount); + for (i = 0; i < n; i++) { + skeletonData->strings[i] = readString(input); + } + /* Bones. */ skeletonData->bonesCount = readVarint(input, 1); skeletonData->bones = MALLOC(spBoneData*, skeletonData->bonesCount); @@ -923,6 +943,7 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const case 3: data->transformMode = SP_TRANSFORMMODE_NOSCALE; break; case 4: data->transformMode = SP_TRANSFORMMODE_NOSCALEORREFLECTION; break; } + data->skinRequired = readBoolean(input); if (nonessential) readInt(input); /* Skip bone color. */ skeletonData->bones[i] = data; } @@ -932,6 +953,7 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const skeletonData->slots = MALLOC(spSlotData*, skeletonData->slotsCount); for (i = 0; i < skeletonData->slotsCount; ++i) { int r, g, b, a; + const char* attachmentName; const char* slotName = readString(input); spBoneData* boneData = skeletonData->bones[readVarint(input, 1)]; /* TODO Avoid copying of slotName */ @@ -946,7 +968,9 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const slotData->darkColor = spColor_create(); spColor_setFromFloats(slotData->darkColor, r / 255.0f, g / 255.0f, b / 255.0f, 1); } - slotData->attachmentName = readString(input); + attachmentName = readStringRef(input, skeletonData); + if (attachmentName) MALLOC_STR(slotData->attachmentName, attachmentName); + else slotData->attachmentName = 0; slotData->blendMode = (spBlendMode)readVarint(input, 1); skeletonData->slots[i] = slotData; } @@ -959,6 +983,7 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const /* TODO Avoid copying of name */ spIkConstraintData* data = spIkConstraintData_create(name); data->order = readVarint(input, 1); + data->skinRequired = readBoolean(input); FREE(name); data->bonesCount = readVarint(input, 1); data->bones = MALLOC(spBoneData*, data->bonesCount); @@ -982,6 +1007,7 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const /* TODO Avoid copying of name */ spTransformConstraintData* data = spTransformConstraintData_create(name); data->order = readVarint(input, 1); + data->skinRequired = readBoolean(input); FREE(name); data->bonesCount = readVarint(input, 1); CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, data->bonesCount); @@ -1011,6 +1037,7 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const /* TODO Avoid copying of name */ spPathConstraintData* data = spPathConstraintData_create(name); data->order = readVarint(input, 1); + data->skinRequired = readBoolean(input); FREE(name); data->bonesCount = readVarint(input, 1); CONST_CAST(spBoneData**, data->bones) = MALLOC(spBoneData*, data->bonesCount); @@ -1031,7 +1058,7 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const } /* Default skin. */ - skeletonData->defaultSkin = spSkeletonBinary_readSkin(self, input, "default", skeletonData, nonessential); + skeletonData->defaultSkin = spSkeletonBinary_readSkin(self, input, -1, skeletonData, nonessential); skeletonData->skinsCount = readVarint(input, 1); if (skeletonData->defaultSkin) @@ -1044,10 +1071,7 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const /* Skins. */ for (i = skeletonData->defaultSkin ? 1 : 0; i < skeletonData->skinsCount; ++i) { - const char* skinName = readString(input); - /* TODO Avoid copying of skinName */ - skeletonData->skins[i] = spSkeletonBinary_readSkin(self, input, skinName, skeletonData, nonessential); - FREE(skinName); + skeletonData->skins[i] = spSkeletonBinary_readSkin(self, input, 0, skeletonData, nonessential); } /* Linked meshes. */ @@ -1078,10 +1102,8 @@ spSkeletonData* spSkeletonBinary_readSkeletonData (spSkeletonBinary* self, const skeletonData->eventsCount = readVarint(input, 1); skeletonData->events = MALLOC(spEventData*, skeletonData->eventsCount); for (i = 0; i < skeletonData->eventsCount; ++i) { - const char* name = readString(input); - /* TODO Avoid copying of skinName */ + const char* name = readStringRef(input, skeletonData); spEventData* eventData = spEventData_create(name); - FREE(name); eventData->intValue = readVarint(input, 0); eventData->floatValue = readFloat(input); eventData->stringValue = readString(input); diff --git a/spine-c/spine-c/src/spine/SkeletonData.c b/spine-c/spine-c/src/spine/SkeletonData.c index c2074912e..f82d371f6 100644 --- a/spine-c/spine-c/src/spine/SkeletonData.c +++ b/spine-c/spine-c/src/spine/SkeletonData.c @@ -37,6 +37,11 @@ spSkeletonData* spSkeletonData_create () { void spSkeletonData_dispose (spSkeletonData* self) { int i; + + for (i = 0; i < self->stringsCount; ++i) + FREE(self->strings[i]); + FREE(self->strings); + for (i = 0; i < self->bonesCount; ++i) spBoneData_dispose(self->bones[i]); FREE(self->bones); diff --git a/spine-c/spine-c/src/spine/SkeletonJson.c b/spine-c/spine-c/src/spine/SkeletonJson.c index cd99383b7..bf6398d4b 100644 --- a/spine-c/spine-c/src/spine/SkeletonJson.c +++ b/spine-c/spine-c/src/spine/SkeletonJson.c @@ -110,13 +110,12 @@ static void readCurve (Json* frame, spCurveTimeline* timeline, int frameIndex) { if (!curve) return; if (curve->type == Json_String && strcmp(curve->valueString, "stepped") == 0) spCurveTimeline_setStepped(timeline, frameIndex); - else if (curve->type == Json_Array) { - Json* child0 = curve->child; - Json* child1 = child0->next; - Json* child2 = child1->next; - Json* child3 = child2->next; - spCurveTimeline_setCurve(timeline, frameIndex, child0->valueFloat, child1->valueFloat, child2->valueFloat, - child3->valueFloat); + 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); } } @@ -264,16 +263,20 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r 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); + 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", 0) * timelineScale, - Json_getFloat(valueMap, "y", 0) * timelineScale); + 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); @@ -648,6 +651,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha data->transformMode = SP_TRANSFORMMODE_NOSCALE; if (strcmp(transformMode, "noScaleOrReflection") == 0) data->transformMode = SP_TRANSFORMMODE_NOSCALEORREFLECTION; + data->skinRequired = Json_getInt(boneMap, "skin", 0) ? 1 : 0; skeletonData->bones[i] = data; skeletonData->bonesCount++; @@ -722,6 +726,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha spIkConstraintData* data = spIkConstraintData_create(Json_getString(constraintMap, "name", 0)); data->order = Json_getInt(constraintMap, "order", 0); + data->skinRequired = Json_getInt(constraintMap, "skin", 0) ? 1 : 0; boneMap = Json_getItem(constraintMap, "bones"); data->bonesCount = boneMap->size; @@ -764,6 +769,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha spTransformConstraintData* data = spTransformConstraintData_create(Json_getString(constraintMap, "name", 0)); data->order = Json_getInt(constraintMap, "order", 0); + data->skinRequired = Json_getInt(constraintMap, "skin", 0) ? 1 : 0; boneMap = Json_getItem(constraintMap, "bones"); data->bonesCount = boneMap->size; @@ -815,6 +821,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha spPathConstraintData* data = spPathConstraintData_create(Json_getString(constraintMap, "name", 0)); data->order = Json_getInt(constraintMap, "order", 0); + data->skinRequired = Json_getInt(constraintMap, "skin", 0) ? 1 : 0; boneMap = Json_getItem(constraintMap, "bones"); data->bonesCount = boneMap->size; @@ -870,13 +877,66 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha for (skinMap = skins->child, i = 0; skinMap; skinMap = skinMap->next, ++i) { Json *attachmentsMap; Json *curves; - spSkin *skin = spSkin_create(skinMap->name); + Json *skinPart; + spSkin *skin = spSkin_create(Json_getString(skinMap, "name", "")); + + skinPart = Json_getItem(skinMap, "bones"); + if (skinPart) { + for(skinPart = skinPart->child; skinPart; skinPart = skinPart->next) { + spBoneData* bone = spSkeletonData_findBone(skeletonData, skinPart->valueString); + if (!bone) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, "Skin bone constraint not found: ", skinPart->valueString); + return 0; + } + spBoneDataArray_add(skin->bones, bone); + } + } + + skinPart = Json_getItem(skinMap, "ik"); + if (skinPart) { + for(skinPart = skinPart->child; skinPart; skinPart = skinPart->next) { + spIkConstraintData* constraint = spSkeletonData_findIkConstraint(skeletonData, skinPart->valueString); + if (!constraint) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, "Skin IK constraint not found: ", skinPart->valueString); + return 0; + } + spIkConstraintDataArray_add(skin->ikConstraints, constraint); + } + } + + skinPart = Json_getItem(skinMap, "path"); + if (skinPart) { + for(skinPart = skinPart->child; skinPart; skinPart = skinPart->next) { + spPathConstraintData* constraint = spSkeletonData_findPathConstraint(skeletonData, skinPart->valueString); + if (!constraint) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, "Skin path constraint not found: ", skinPart->valueString); + return 0; + } + spPathConstraintDataArray_add(skin->pathConstraints, constraint); + } + } + + skinPart = Json_getItem(skinMap, "transform"); + if (skinPart) { + for(skinPart = skinPart->child; skinPart; skinPart = skinPart->next) { + spTransformConstraintData* constraint = spSkeletonData_findTransformConstraint(skeletonData, skinPart->valueString); + if (!constraint) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, root, "Skin transform constraint not found: ", skinPart->valueString); + return 0; + } + spTransformConstraintDataArray_add(skin->transformConstraints, constraint); + } + } skeletonData->skins[skeletonData->skinsCount++] = skin; - if (strcmp(skinMap->name, "default") == 0) skeletonData->defaultSkin = skin; + if (strcmp(skin->name, "default") == 0) skeletonData->defaultSkin = skin; - for (attachmentsMap = skinMap->child; attachmentsMap; attachmentsMap = attachmentsMap->next) { - int slotIndex = spSkeletonData_findSlotIndex(skeletonData, attachmentsMap->name); + for (attachmentsMap = Json_getItem(skinMap, "attachments")->child; attachmentsMap; attachmentsMap = attachmentsMap->next) { + spSlotData* slot = spSkeletonData_findSlot(skeletonData, attachmentsMap->name); Json *attachmentMap; for (attachmentMap = attachmentsMap->child; attachmentMap; attachmentMap = attachmentMap->next) { @@ -995,7 +1055,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha spAttachmentLoader_configureAttachment(self->attachmentLoader, attachment); } else { int inheritDeform = Json_getInt(attachmentMap, "deform", 1); - _spSkeletonJson_addLinkedMesh(self, SUB_CAST(spMeshAttachment, attachment), Json_getString(attachmentMap, "skin", 0), slotIndex, + _spSkeletonJson_addLinkedMesh(self, SUB_CAST(spMeshAttachment, attachment), Json_getString(attachmentMap, "skin", 0), slot->index, entry->valueString, inheritDeform); } break; @@ -1046,8 +1106,8 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha int vertexCount = 0; const char* end = Json_getString(attachmentMap, "end", 0); if (end) { - spSlotData* slot = spSkeletonData_findSlot(skeletonData, end); - clip->endSlot = slot; + spSlotData* endSlot = spSkeletonData_findSlot(skeletonData, end); + clip->endSlot = endSlot; } vertexCount = Json_getInt(attachmentMap, "vertexCount", 0) << 1; _readVertices(self, attachmentMap, SUPER(clip), vertexCount); @@ -1056,7 +1116,7 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha } } - spSkin_setAttachment(skin, slotIndex, skinAttachmentName, attachment); + spSkin_setAttachment(skin, slot->index, skinAttachmentName, attachment); } } }