From 421789e6f7ef67a465c907423997ea7f917ec2c8 Mon Sep 17 00:00:00 2001 From: NathanSweet Date: Fri, 15 Apr 2016 12:19:43 +0200 Subject: [PATCH] spine-c updated to v3.1. --- spine-c/README.md | 2 +- spine-c/include/spine/Attachment.h | 9 +- spine-c/include/spine/MeshAttachment.h | 10 +- .../include/spine/WeightedMeshAttachment.h | 10 +- spine-c/src/spine/Animation.c | 19 +- spine-c/src/spine/AtlasAttachmentLoader.c | 6 +- spine-c/src/spine/Bone.c | 156 +++++----- spine-c/src/spine/IkConstraint.c | 50 ++-- spine-c/src/spine/MeshAttachment.c | 30 +- spine-c/src/spine/Skeleton.c | 50 ++-- spine-c/src/spine/SkeletonJson.c | 266 ++++++++++++------ spine-c/src/spine/WeightedMeshAttachment.c | 37 ++- spine-cocos2d-iphone/2/README.md | 2 +- spine-cocos2d-iphone/3/README.md | 2 +- spine-cocos2dx/2/README.md | 2 +- spine-cocos2dx/3/README.md | 2 +- spine-sfml/README.md | 2 +- 17 files changed, 416 insertions(+), 239 deletions(-) diff --git a/spine-c/README.md b/spine-c/README.md index edee5e99a..75f51e952 100644 --- a/spine-c/README.md +++ b/spine-c/README.md @@ -12,7 +12,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f ## Spine version -spine-c works with data exported from the latest version of Spine, except linked meshes are [not yet supported](https://trello.com/c/bERJAFEq/73-update-runtimes-to-support-v3-1-linked-meshes). +spine-c works with data exported from the latest version of Spine. spine-c supports all Spine features. diff --git a/spine-c/include/spine/Attachment.h b/spine-c/include/spine/Attachment.h index f4a31b174..ca8b889b4 100644 --- a/spine-c/include/spine/Attachment.h +++ b/spine-c/include/spine/Attachment.h @@ -39,7 +39,12 @@ extern "C" { struct spAttachmentLoader; typedef enum { - SP_ATTACHMENT_REGION, SP_ATTACHMENT_BOUNDING_BOX, SP_ATTACHMENT_MESH, SP_ATTACHMENT_WEIGHTED_MESH + SP_ATTACHMENT_REGION, + SP_ATTACHMENT_BOUNDING_BOX, + SP_ATTACHMENT_MESH, + SP_ATTACHMENT_WEIGHTED_MESH, + SP_ATTACHMENT_LINKED_MESH, + SP_ATTACHMENT_WEIGHTED_LINKED_MESH } spAttachmentType; typedef struct spAttachment { @@ -65,6 +70,8 @@ typedef spAttachmentType AttachmentType; #define ATTACHMENT_BOUNDING_BOX SP_ATTACHMENT_BOUNDING_BOX #define ATTACHMENT_MESH SP_ATTACHMENT_MESH #define ATTACHMENT_WEIGHTED_MESH SP_ATTACHMENT_WEIGHTED_MESH +#define ATTACHMENT_LINKED_MESH SP_ATTACHMENT_LINKED_MESH +#define ATTACHMENT_WEIGHTED_LINKED_MESH SP_ATTACHMENT_WEIGHTED_LINKED_MESH typedef spAttachment Attachment; #define Attachment_dispose(...) spAttachment_dispose(__VA_ARGS__) #endif diff --git a/spine-c/include/spine/MeshAttachment.h b/spine-c/include/spine/MeshAttachment.h index 9793b794b..d50b45ad0 100644 --- a/spine-c/include/spine/MeshAttachment.h +++ b/spine-c/include/spine/MeshAttachment.h @@ -40,7 +40,8 @@ extern "C" { #endif -typedef struct spMeshAttachment { +typedef struct spMeshAttachment spMeshAttachment; +struct spMeshAttachment { spAttachment super; const char* path; @@ -54,6 +55,9 @@ typedef struct spMeshAttachment { int trianglesCount; unsigned short* triangles; + spMeshAttachment* const parentMesh; + int/*bool*/inheritFFD; + float r, g, b, a; void* rendererObject; @@ -67,17 +71,19 @@ typedef struct spMeshAttachment { int edgesCount; int* edges; float width, height; -} spMeshAttachment; +}; spMeshAttachment* spMeshAttachment_create (const char* name); void spMeshAttachment_updateUVs (spMeshAttachment* self); void spMeshAttachment_computeWorldVertices (spMeshAttachment* self, spSlot* slot, float* worldVertices); +void spMeshAttachment_setParentMesh (spMeshAttachment* self, spMeshAttachment* parentMesh); #ifdef SPINE_SHORT_NAMES typedef spMeshAttachment MeshAttachment; #define MeshAttachment_create(...) spMeshAttachment_create(__VA_ARGS__) #define MeshAttachment_updateUVs(...) spMeshAttachment_updateUVs(__VA_ARGS__) #define MeshAttachment_computeWorldVertices(...) spMeshAttachment_computeWorldVertices(__VA_ARGS__) +#define MeshAttachment_setParentMesh(...) spMeshAttachment_setParentMesh(__VA_ARGS__) #endif #ifdef __cplusplus diff --git a/spine-c/include/spine/WeightedMeshAttachment.h b/spine-c/include/spine/WeightedMeshAttachment.h index 71a54e0f9..7f6201cc6 100644 --- a/spine-c/include/spine/WeightedMeshAttachment.h +++ b/spine-c/include/spine/WeightedMeshAttachment.h @@ -39,7 +39,8 @@ extern "C" { #endif -typedef struct spWeightedMeshAttachment { +typedef struct spWeightedMeshAttachment spWeightedMeshAttachment; +struct spWeightedMeshAttachment { spAttachment super; const char* path; @@ -57,6 +58,9 @@ typedef struct spWeightedMeshAttachment { float* uvs; int hullLength; + spWeightedMeshAttachment* const parentMesh; + int/*bool*/inheritFFD; + float r, g, b, a; void* rendererObject; @@ -70,17 +74,19 @@ typedef struct spWeightedMeshAttachment { int edgesCount; int* edges; float width, height; -} spWeightedMeshAttachment; +}; spWeightedMeshAttachment* spWeightedMeshAttachment_create (const char* name); void spWeightedMeshAttachment_updateUVs (spWeightedMeshAttachment* self); void spWeightedMeshAttachment_computeWorldVertices (spWeightedMeshAttachment* self, spSlot* slot, float* worldVertices); +void spWeightedMeshAttachment_setParentMesh (spWeightedMeshAttachment* self, spWeightedMeshAttachment* parentMesh); #ifdef SPINE_SHORT_NAMES typedef spWeightedMeshAttachment WeightedMeshAttachment; #define WeightedMeshAttachment_create(...) spWeightedMeshAttachment_create(__VA_ARGS__) #define WeightedMeshAttachment_updateUVs(...) spWeightedMeshAttachment_updateUVs(__VA_ARGS__) #define WeightedMeshAttachment_computeWorldVertices(...) spWeightedMeshAttachment_computeWorldVertices(__VA_ARGS__) +#define WeightedMeshAttachment_setParentMesh(...) spWeightedMeshAttachment_setParentMesh(__VA_ARGS__) #endif #ifdef __cplusplus diff --git a/spine-c/src/spine/Animation.c b/spine-c/src/spine/Animation.c index bb57de71b..5bbef426f 100644 --- a/spine-c/src/spine/Animation.c +++ b/spine-c/src/spine/Animation.c @@ -683,7 +683,24 @@ void _spFFDTimeline_apply (const spTimeline* timeline, spSkeleton* skeleton, flo spFFDTimeline* self = (spFFDTimeline*)timeline; spSlot *slot = skeleton->slots[self->slotIndex]; - if (slot->attachment != self->attachment) return; + + if (slot->attachment != self->attachment) { + if (!slot->attachment) return; + switch (slot->attachment->type) { + case SP_ATTACHMENT_MESH: { + spMeshAttachment* mesh = SUB_CAST(spMeshAttachment, slot->attachment); + if (!mesh->inheritFFD || mesh->parentMesh != (void*)self->attachment) return; + break; + } + case SP_ATTACHMENT_WEIGHTED_MESH: { + spWeightedMeshAttachment* mesh = SUB_CAST(spWeightedMeshAttachment, slot->attachment); + if (!mesh->inheritFFD || mesh->parentMesh != (void*)self->attachment) return; + break; + } + default: + return; + } + } if (time < self->frames[0]) return; /* Time is before first frame. */ diff --git a/spine-c/src/spine/AtlasAttachmentLoader.c b/spine-c/src/spine/AtlasAttachmentLoader.c index 8e351e468..2d6017071 100644 --- a/spine-c/src/spine/AtlasAttachmentLoader.c +++ b/spine-c/src/spine/AtlasAttachmentLoader.c @@ -54,7 +54,8 @@ spAttachment* _spAtlasAttachmentLoader_createAttachment (spAttachmentLoader* loa attachment->regionOriginalHeight = region->originalHeight; return SUPER(attachment); } - case SP_ATTACHMENT_MESH: { + case SP_ATTACHMENT_MESH: + case SP_ATTACHMENT_LINKED_MESH: { spMeshAttachment* attachment; spAtlasRegion* region = spAtlas_findRegion(self->atlas, path); if (!region) { @@ -76,7 +77,8 @@ spAttachment* _spAtlasAttachmentLoader_createAttachment (spAttachmentLoader* loa attachment->regionOriginalHeight = region->originalHeight; return SUPER(attachment); } - case SP_ATTACHMENT_WEIGHTED_MESH: { + case SP_ATTACHMENT_WEIGHTED_MESH: + case SP_ATTACHMENT_WEIGHTED_LINKED_MESH: { spWeightedMeshAttachment* attachment; spAtlasRegion* region = spAtlas_findRegion(self->atlas, path); if (!region) { diff --git a/spine-c/src/spine/Bone.c b/spine-c/src/spine/Bone.c index f7f92c1b7..2432a20e2 100644 --- a/spine-c/src/spine/Bone.c +++ b/spine-c/src/spine/Bone.c @@ -108,88 +108,82 @@ void spBone_updateWorldTransformWith (spBone* self, float x, float y, float rota CONST_CAST(float, self->b) = pa * lb + pb * ld; CONST_CAST(float, self->c) = pc * la + pd * lc; CONST_CAST(float, self->d) = pc * lb + pd * ld; - } else if (self->data->inheritRotation) { /* No scale inheritance. */ - pa = 1; - pb = 0; - pc = 0; - pd = 1; - do { - cosine = COS(parent->appliedRotation * DEG_RAD); - sine = SIN(parent->appliedRotation * DEG_RAD); - temp = pa * cosine + pb * sine; - pb = pa * -sine + pb * cosine; - pa = temp; - temp = pc * cosine + pd * sine; - pd = pc * -sine + pd * cosine; - pc = temp; - - if (!parent->data->inheritRotation) break; - parent = parent->parent; - } while (parent); - CONST_CAST(float, self->a) = pa * la + pb * lc; - CONST_CAST(float, self->b) = pa * lb + pb * ld; - CONST_CAST(float, self->c) = pc * la + pd * lc; - CONST_CAST(float, self->d) = pc * lb + pd * ld; - if (self->skeleton->flipX) { - CONST_CAST(float, self->a) = -self->a; - CONST_CAST(float, self->b) = -self->b; - } - if (self->skeleton->flipY != yDown) { - CONST_CAST(float, self->c) = -self->c; - CONST_CAST(float, self->d) = -self->d; - } - } else if (self->data->inheritScale) { /* No rotation inheritance. */ - pa = 1; - pb = 0; - pc = 0; - pd = 1; - do { - float za, zb, zc, zd; - float r = parent->rotation; - float psx = parent->appliedScaleX, psy = parent->appliedScaleY; - cosine = COS(r * DEG_RAD); - sine = SIN(r * DEG_RAD); - za = cosine * psx; - zb = -sine * psy; - zc = sine * psx; - zd = cosine * psy; - temp = pa * za + pb * zc; - pb = pa * zb + pb * zd; - pa = temp; - temp = pc * za + pd * zc; - pd = pc * zb + pd * zd; - pc = temp; - - if (psx < 0) r = -r; - cosine = COS(-r * DEG_RAD); - sine = SIN(-r * DEG_RAD); - temp = pa * cosine + pb * sine; - pb = pa * -sine + pb * cosine; - pa = temp; - temp = pc * cosine + pd * sine; - pd = pc * -sine + pd * cosine; - pc = temp; - - if (!parent->data->inheritScale) break; - parent = parent->parent; - } while (parent); - CONST_CAST(float, self->a) = pa * la + pb * lc; - CONST_CAST(float, self->b) = pa * lb + pb * ld; - CONST_CAST(float, self->c) = pc * la + pd * lc; - CONST_CAST(float, self->d) = pc * lb + pd * ld; - if (self->skeleton->flipX) { - CONST_CAST(float, self->a) = -self->a; - CONST_CAST(float, self->b) = -self->b; - } - if (self->skeleton->flipY != yDown) { - CONST_CAST(float, self->c) = -self->c; - CONST_CAST(float, self->d) = -self->d; - } } else { - CONST_CAST(float, self->a) = la; - CONST_CAST(float, self->b) = lb; - CONST_CAST(float, self->c) = lc; - CONST_CAST(float, self->d) = ld; + if (self->data->inheritRotation) { /* No scale inheritance. */ + pa = 1; + pb = 0; + pc = 0; + pd = 1; + do { + cosine = COS(parent->appliedRotation * DEG_RAD); + sine = SIN(parent->appliedRotation * DEG_RAD); + temp = pa * cosine + pb * sine; + pb = pa * -sine + pb * cosine; + pa = temp; + temp = pc * cosine + pd * sine; + pd = pc * -sine + pd * cosine; + pc = temp; + + if (!parent->data->inheritRotation) break; + parent = parent->parent; + } while (parent); + CONST_CAST(float, self->a) = pa * la + pb * lc; + CONST_CAST(float, self->b) = pa * lb + pb * ld; + CONST_CAST(float, self->c) = pc * la + pd * lc; + CONST_CAST(float, self->d) = pc * lb + pd * ld; + } else if (self->data->inheritScale) { /* No rotation inheritance. */ + pa = 1; + pb = 0; + pc = 0; + pd = 1; + do { + float za, zb, zc, zd; + float r = parent->rotation; + float psx = parent->appliedScaleX, psy = parent->appliedScaleY; + cosine = COS(r * DEG_RAD); + sine = SIN(r * DEG_RAD); + za = cosine * psx; + zb = -sine * psy; + zc = sine * psx; + zd = cosine * psy; + temp = pa * za + pb * zc; + pb = pa * zb + pb * zd; + pa = temp; + temp = pc * za + pd * zc; + pd = pc * zb + pd * zd; + pc = temp; + + if (psx < 0) r = -r; + cosine = COS(-r * DEG_RAD); + sine = SIN(-r * DEG_RAD); + temp = pa * cosine + pb * sine; + pb = pa * -sine + pb * cosine; + pa = temp; + temp = pc * cosine + pd * sine; + pd = pc * -sine + pd * cosine; + pc = temp; + + if (!parent->data->inheritScale) break; + parent = parent->parent; + } while (parent); + CONST_CAST(float, self->a) = pa * la + pb * lc; + CONST_CAST(float, self->b) = pa * lb + pb * ld; + CONST_CAST(float, self->c) = pc * la + pd * lc; + CONST_CAST(float, self->d) = pc * lb + pd * ld; + } else { + CONST_CAST(float, self->a) = la; + CONST_CAST(float, self->b) = lb; + CONST_CAST(float, self->c) = lc; + CONST_CAST(float, self->d) = ld; + } + if (self->skeleton->flipX) { + CONST_CAST(float, self->a) = -self->a; + CONST_CAST(float, self->b) = -self->b; + } + if (self->skeleton->flipY != yDown) { + CONST_CAST(float, self->c) = -self->c; + CONST_CAST(float, self->d) = -self->d; + } } } diff --git a/spine-c/src/spine/IkConstraint.c b/spine-c/src/spine/IkConstraint.c index 298196630..0a338fa20 100644 --- a/spine-c/src/spine/IkConstraint.c +++ b/spine-c/src/spine/IkConstraint.c @@ -80,47 +80,54 @@ void spIkConstraint_apply1 (spBone* bone, float targetX, float targetY, float al } void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float targetY, int bendDir, float alpha) { - float px = parent->x, py = parent->y, psx = parent->scaleX, psy = parent->scaleY, csx = child->scaleX, cy = child->y; - int offset1, offset2, sign2; + float px = parent->x, py = parent->y, psx = parent->scaleX, psy = parent->scaleY; + float cx = child->x, cy = child->y, csx = child->appliedScaleX, cwx = child->worldX, cwy = child->worldY; + int o1, o2, s2, u; spBone* pp = parent->parent; - float tx, ty, dx, dy, l1, l2, a1, a2, psd, r; + float tx, ty, dx, dy, l1, l2, a1, a2, r; if (alpha == 0) return; if (psx < 0) { psx = -psx; - offset1 = 180; - sign2 = -1; + o1 = 180; + s2 = -1; } else { - offset1 = 0; - sign2 = 1; + o1 = 0; + s2 = 1; } if (psy < 0) { psy = -psy; - sign2 = -sign2; + s2 = -s2; + } + u = psx - psy; + u = u < 0 ? -u : u <= 0.0001f; + if (!u && cy != 0) { + cwx = parent->a * cx + parent->worldX; + cwy = parent->c * cx + parent->worldY; + cy = 0; } if (csx < 0) { csx = -csx; - offset2 = 180; + o2 = 180; } else - offset2 = 0; + o2 = 0; if (!pp) { tx = targetX - px; ty = targetY - py; - dx = child->worldX - px; - dy = child->worldY - py; + dx = cwx - px; + dy = cwy - py; } else { float a = pp->a, b = pp->b, c = pp->c, d = pp->d, invDet = 1 / (a * d - b * c); float wx = pp->worldX, wy = pp->worldY, x = targetX - wx, y = targetY - wy; tx = (x * d - y * b) * invDet - px; ty = (y * a - x * c) * invDet - py; - x = child->worldX - wx; - y = child->worldY - wy; + x = cwx - wx; + y = cwy - wy; dx = (x * d - y * b) * invDet - px; dy = (y * a - x * c) * invDet - py; } l1 = SQRT(dx * dx + dy * dy); l2 = child->data->length * csx; - psd = psx - psy; - if (psd < 0 ? -psd : psd <= 0.0001f) { + if (u) { float cos, a, o; l2 *= psx; cos = (tx * tx + ty * ty - l1 * l1 - l2 * l2) / (2 * l1 * l2); @@ -138,7 +145,6 @@ void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float float minAngle = 0, minDist = FLT_MAX, minX = 0, minY = 0; float maxAngle = 0, maxDist = 0, maxX = 0, maxY = 0; float x = l1 + a, dist = x * x, angle, y; - cy = 0; if (d >= 0) { float q = SQRT(d), r0, r1, ar0, ar1;; if (c1 < 0) q = -q; @@ -192,16 +198,16 @@ void spIkConstraint_apply2 (spBone* parent, spBone* child, float targetX, float } } outer: { - float offset = ATAN2(cy, child->x) * sign2; - a1 = (a1 - offset) * RAD_DEG + offset1; - a2 = (a2 + offset) * RAD_DEG * sign2 + offset2; + float offset = ATAN2(cy, child->x) * s2; + a1 = (a1 - offset) * RAD_DEG + o1; + a2 = (a2 + offset) * RAD_DEG * s2 + o2; if (a1 > 180) a1 -= 360; else if (a1 < -180) a1 += 360; if (a2 > 180) a2 -= 360; else if (a2 < -180) a2 += 360; r = parent->rotation; - spBone_updateWorldTransformWith(parent, parent->x, parent->y, r + (a1 - r) * alpha, parent->scaleX, parent->scaleY); + spBone_updateWorldTransformWith(parent, px, py, r + (a1 - r) * alpha, parent->appliedScaleX, parent->appliedScaleY); r = child->rotation; - spBone_updateWorldTransformWith(child, child->x, cy, r + (a2 - r) * alpha, child->scaleX, child->scaleY); + spBone_updateWorldTransformWith(child, cx, cy, r + (a2 - r) * alpha, child->appliedScaleX, child->appliedScaleY); } } diff --git a/spine-c/src/spine/MeshAttachment.c b/spine-c/src/spine/MeshAttachment.c index 88a76dcb8..32cb6b914 100644 --- a/spine-c/src/spine/MeshAttachment.c +++ b/spine-c/src/spine/MeshAttachment.c @@ -36,11 +36,13 @@ void _spMeshAttachment_dispose (spAttachment* attachment) { spMeshAttachment* self = SUB_CAST(spMeshAttachment, attachment); _spAttachment_deinit(attachment); FREE(self->path); - FREE(self->vertices); - FREE(self->regionUVs); FREE(self->uvs); - FREE(self->triangles); - FREE(self->edges); + if (!self->parentMesh) { + FREE(self->vertices); + FREE(self->regionUVs); + FREE(self->triangles); + FREE(self->edges); + } FREE(self); } @@ -84,3 +86,23 @@ void spMeshAttachment_computeWorldVertices (spMeshAttachment* self, spSlot* slot worldVertices[i + 1] = vx * bone->c + vy * bone->d + y; } } + +void spMeshAttachment_setParentMesh (spMeshAttachment* self, spMeshAttachment* parentMesh) { + CONST_CAST(spMeshAttachment*, self->parentMesh) = parentMesh; + if (parentMesh) { + self->vertices = parentMesh->vertices; + self->regionUVs = parentMesh->regionUVs; + self->verticesCount = parentMesh->verticesCount; + + self->triangles = parentMesh->triangles; + self->trianglesCount = parentMesh->trianglesCount; + + self->hullLength = parentMesh->hullLength; + + self->edges = parentMesh->edges; + self->edgesCount = parentMesh->edgesCount; + + self->width = parentMesh->width; + self->height = parentMesh->height; + } +} diff --git a/spine-c/src/spine/Skeleton.c b/spine-c/src/spine/Skeleton.c index 77e396807..010e81dd5 100644 --- a/spine-c/src/spine/Skeleton.c +++ b/spine-c/src/spine/Skeleton.c @@ -37,12 +37,16 @@ typedef enum { SP_UPDATE_BONE, SP_UPDATE_IK_CONSTRAINT, SP_UPDATE_TRANSFORM_CONSTRAINT } _spUpdateType; +typedef struct { + _spUpdateType type; + void* object; +} _spUpdate; + typedef struct { spSkeleton super; int updateCacheCount; - void** updateCache; - _spUpdateType* updateCacheType; + _spUpdate* updateCache; } _spSkeleton; spSkeleton* spSkeleton_create (spSkeletonData* data) { @@ -115,7 +119,6 @@ void spSkeleton_dispose (spSkeleton* self) { _spSkeleton* internal = SUB_CAST(_spSkeleton, self); FREE(internal->updateCache); - FREE(internal->updateCacheType); for (i = 0; i < self->bonesCount; ++i) spBone_dispose(self->bones[i]); @@ -139,24 +142,25 @@ void spSkeleton_dispose (spSkeleton* self) { void spSkeleton_updateCache (const spSkeleton* self) { int i, ii; + _spUpdate* update; _spSkeleton* internal = SUB_CAST(_spSkeleton, self); + int capacity = self->bonesCount + self->transformConstraintsCount + self->ikConstraintsCount; FREE(internal->updateCache); - FREE(internal->updateCacheType); - int capacity = self->bonesCount + self->transformConstraintsCount + self->ikConstraintsCount; - internal->updateCache = MALLOC(void*, capacity); - internal->updateCacheType = MALLOC(_spUpdateType, capacity); + internal->updateCache = MALLOC(_spUpdate, capacity); internal->updateCacheCount = 0; for (i = 0; i < self->bonesCount; ++i) { spBone* bone = self->bones[i]; - internal->updateCache[internal->updateCacheCount] = bone; - internal->updateCacheType[internal->updateCacheCount++] = SP_UPDATE_BONE; + update = internal->updateCache + internal->updateCacheCount++; + update->type = SP_UPDATE_BONE; + update->object = bone; for (ii = 0; ii < self->ikConstraintsCount; ++ii) { spIkConstraint* ikConstraint = self->ikConstraints[ii]; if (bone == ikConstraint->bones[ikConstraint->bonesCount - 1]) { - internal->updateCache[internal->updateCacheCount] = ikConstraint; - internal->updateCacheType[internal->updateCacheCount++] = SP_UPDATE_IK_CONSTRAINT; + update = internal->updateCache + internal->updateCacheCount++; + update->type = SP_UPDATE_IK_CONSTRAINT; + update->object = ikConstraint; break; } } @@ -165,17 +169,14 @@ void spSkeleton_updateCache (const spSkeleton* self) { for (i = 0; i < self->transformConstraintsCount; ++i) { spTransformConstraint* transformConstraint = self->transformConstraints[i]; for (ii = internal->updateCacheCount - 1; ii >= 0; --ii) { - void* updatable = internal->updateCache[ii]; - if (updatable == transformConstraint->bone || updatable == transformConstraint->target) { + void* object = internal->updateCache[ii].object; + if (object == transformConstraint->bone || object == transformConstraint->target) { int insertIndex = ii + 1; - int moveCount = (capacity-2) - insertIndex; - if (moveCount > 0) { - memmove(internal->updateCache + (insertIndex + 1), internal->updateCache + insertIndex, moveCount * sizeof(void*)); - memmove(internal->updateCacheType + (insertIndex + 1), internal->updateCacheType + insertIndex, moveCount * sizeof(_spUpdateType)); - } + update = internal->updateCache + insertIndex; + memmove(update + 1, update, (internal->updateCacheCount - insertIndex) * sizeof(_spUpdate)); + update->type = SP_UPDATE_TRANSFORM_CONSTRAINT; + update->object = transformConstraint; internal->updateCacheCount++; - internal->updateCache[insertIndex] = transformConstraint; - internal->updateCacheType[insertIndex] = SP_UPDATE_TRANSFORM_CONSTRAINT; break; } } @@ -187,15 +188,16 @@ void spSkeleton_updateWorldTransform (const spSkeleton* self) { _spSkeleton* internal = SUB_CAST(_spSkeleton, self); for (i = 0; i < internal->updateCacheCount; ++i) { - switch (internal->updateCacheType[i]) { + _spUpdate* update = internal->updateCache + i; + switch (update->type) { case SP_UPDATE_BONE: - spBone_updateWorldTransform((spBone*)internal->updateCache[i]); + spBone_updateWorldTransform((spBone*)update->object); break; case SP_UPDATE_IK_CONSTRAINT: - spIkConstraint_apply((spIkConstraint*)internal->updateCache[i]); + spIkConstraint_apply((spIkConstraint*)update->object); break; case SP_UPDATE_TRANSFORM_CONSTRAINT: - spTransformConstraint_apply((spTransformConstraint*)internal->updateCache[i]); + spTransformConstraint_apply((spTransformConstraint*)update->object); break; } } diff --git a/spine-c/src/spine/SkeletonJson.c b/spine-c/src/spine/SkeletonJson.c index 684bb4dbf..31ce8774d 100644 --- a/spine-c/src/spine/SkeletonJson.c +++ b/spine-c/src/spine/SkeletonJson.c @@ -36,9 +36,20 @@ #include #include +typedef struct { + const char* parent; + const char* skin; + int slotIndex; + spAttachment* mesh; +} _spLinkedMesh; + typedef struct { spSkeletonJson super; int ownsLoader; + + int linkedMeshCount; + int linkedMeshCapacity; + _spLinkedMesh* linkedMeshes; } _spSkeletonJson; spSkeletonJson* spSkeletonJson_createWithLoader (spAttachmentLoader* attachmentLoader) { @@ -56,7 +67,9 @@ spSkeletonJson* spSkeletonJson_create (spAtlas* atlas) { } void spSkeletonJson_dispose (spSkeletonJson* self) { - if (SUB_CAST(_spSkeletonJson, self)->ownsLoader) spAttachmentLoader_dispose(self->attachmentLoader); + _spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self); + if (internal->ownsLoader) spAttachmentLoader_dispose(self->attachmentLoader); + FREE(internal->linkedMeshes); FREE(self->error); FREE(self); } @@ -103,6 +116,28 @@ static void readCurve (spCurveTimeline* timeline, int frameIndex, Json* frame) { } } +static void _spSkeletonJson_addLinkedMesh (spSkeletonJson* self, spAttachment* mesh, const char* skin, int slotIndex, + const char* parent) { + _spLinkedMesh* linkedMesh; + _spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self); + + if (internal->linkedMeshCount == internal->linkedMeshCapacity) { + _spLinkedMesh* linkedMeshes; + internal->linkedMeshCapacity *= 2; + if (internal->linkedMeshCapacity < 8) internal->linkedMeshCapacity = 8; + linkedMeshes = MALLOC(_spLinkedMesh, internal->linkedMeshCapacity); + memcpy(linkedMeshes, internal->linkedMeshes, internal->linkedMeshCount); + FREE(internal->linkedMeshes); + internal->linkedMeshes = linkedMeshes; + } + + linkedMesh = internal->linkedMeshes + internal->linkedMeshCount++; + linkedMesh->mesh = mesh; + linkedMesh->skin = skin; + linkedMesh->slotIndex = slotIndex; + linkedMesh->parent = parent; +} + static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* root, spSkeletonData *skeletonData) { int i; spAnimation* animation; @@ -132,7 +167,6 @@ static spAnimation* _spSkeletonJson_readAnimation (spSkeletonJson* self, Json* r animation = spAnimation_create(root->name, timelinesCount); animation->timelinesCount = 0; - skeletonData->animations[skeletonData->animationsCount++] = animation; /* Slot timelines. */ for (slotMap = slots ? slots->child : 0; slotMap; slotMap = slotMap->next) { @@ -409,9 +443,11 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha spSkeletonData* skeletonData; Json *root, *skeleton, *bones, *boneMap, *ik, *transform, *slots, *skins, *animations, *events; char* oldLocale; + _spSkeletonJson* internal = SUB_CAST(_spSkeletonJson, self); FREE(self->error); CONST_CAST(char*, self->error) = 0; + internal->linkedMeshCount = 0; oldLocale = setlocale(LC_NUMERIC, "C"); root = Json_create(json); @@ -584,13 +620,12 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha skins = Json_getItem(root, "skins"); if (skins) { Json *slotMap; - skeletonData->skinsCount = skins->size; skeletonData->skins = MALLOC(spSkin*, skins->size); for (slotMap = skins->child, i = 0; slotMap; slotMap = slotMap->next, ++i) { Json *attachmentsMap; spSkin *skin = spSkin_create(slotMap->name); - skeletonData->skins[i] = skin; + skeletonData->skins[skeletonData->skinsCount++] = skin; if (strcmp(slotMap->name, "default") == 0) skeletonData->defaultSkin = skin; for (attachmentsMap = slotMap->child; attachmentsMap; attachmentsMap = attachmentsMap->next) { @@ -614,6 +649,10 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha type = SP_ATTACHMENT_MESH; else if (strcmp(typeString, "weightedmesh") == 0 || strcmp(typeString, "skinnedmesh") == 0) type = SP_ATTACHMENT_WEIGHTED_MESH; + else if (strcmp(typeString, "linkedmesh") == 0) + type = SP_ATTACHMENT_LINKED_MESH; + else if (strcmp(typeString, "weightedlinkedmesh") == 0) + type = SP_ATTACHMENT_WEIGHTED_LINKED_MESH; else if (strcmp(typeString, "boundingbox") == 0) type = SP_ATTACHMENT_BOUNDING_BOX; else { @@ -655,30 +694,12 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha spRegionAttachment_updateOffset(region); break; } - case SP_ATTACHMENT_MESH: { + case SP_ATTACHMENT_MESH: + case SP_ATTACHMENT_LINKED_MESH: { spMeshAttachment* mesh = SUB_CAST(spMeshAttachment, attachment); MALLOC_STR(mesh->path, path); - entry = Json_getItem(attachmentMap, "vertices"); - mesh->verticesCount = entry->size; - mesh->vertices = MALLOC(float, entry->size); - for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) - mesh->vertices[i] = entry->valueFloat * self->scale; - - entry = Json_getItem(attachmentMap, "triangles"); - mesh->trianglesCount = entry->size; - mesh->triangles = MALLOC(unsigned short, entry->size); - for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) - mesh->triangles[i] = (unsigned short)entry->valueInt; - - entry = Json_getItem(attachmentMap, "uvs"); - mesh->regionUVs = MALLOC(float, entry->size); - for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) - mesh->regionUVs[i] = entry->valueFloat; - - spMeshAttachment_updateUVs(mesh); - color = Json_getString(attachmentMap, "color", 0); if (color) { mesh->r = toColor(color, 0); @@ -687,69 +708,54 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha mesh->a = toColor(color, 3); } - mesh->hullLength = Json_getInt(attachmentMap, "hull", 0); - - entry = Json_getItem(attachmentMap, "edges"); - if (entry) { - mesh->edgesCount = entry->size; - mesh->edges = MALLOC(int, entry->size); - for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) - mesh->edges[i] = entry->valueInt; - } - mesh->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; mesh->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; + + entry = Json_getItem(attachmentMap, "parent"); + if (!entry) { + entry = Json_getItem(attachmentMap, "vertices"); + mesh->verticesCount = entry->size; + mesh->vertices = MALLOC(float, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->vertices[i] = entry->valueFloat * self->scale; + + entry = Json_getItem(attachmentMap, "triangles"); + mesh->trianglesCount = entry->size; + mesh->triangles = MALLOC(unsigned short, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->triangles[i] = (unsigned short)entry->valueInt; + + entry = Json_getItem(attachmentMap, "uvs"); + mesh->regionUVs = MALLOC(float, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->regionUVs[i] = entry->valueFloat; + + spMeshAttachment_updateUVs(mesh); + + mesh->hullLength = Json_getInt(attachmentMap, "hull", 0); + + entry = Json_getItem(attachmentMap, "edges"); + if (entry) { + mesh->edgesCount = entry->size; + mesh->edges = MALLOC(int, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->edges[i] = entry->valueInt; + } + } else { + mesh->inheritFFD = Json_getInt(attachmentMap, "ffd", 1); + _spSkeletonJson_addLinkedMesh(self, attachment, Json_getString(attachmentMap, "skin", 0), slotIndex, + entry->valueString); + } break; } - case SP_ATTACHMENT_WEIGHTED_MESH: { + case SP_ATTACHMENT_WEIGHTED_MESH: + case SP_ATTACHMENT_WEIGHTED_LINKED_MESH: { spWeightedMeshAttachment* mesh = SUB_CAST(spWeightedMeshAttachment, attachment); int verticesCount, b, w, nn; float* vertices; MALLOC_STR(mesh->path, path); - entry = Json_getItem(attachmentMap, "uvs"); - mesh->uvsCount = entry->size; - mesh->regionUVs = MALLOC(float, entry->size); - for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) - mesh->regionUVs[i] = entry->valueFloat; - - entry = Json_getItem(attachmentMap, "vertices"); - verticesCount = entry->size; - vertices = MALLOC(float, entry->size); - for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) - vertices[i] = entry->valueFloat; - - for (i = 0; i < verticesCount;) { - int bonesCount = (int)vertices[i]; - mesh->bonesCount += bonesCount + 1; - mesh->weightsCount += bonesCount * 3; - i += 1 + bonesCount * 4; - } - mesh->bones = MALLOC(int, mesh->bonesCount); - mesh->weights = MALLOC(float, mesh->weightsCount); - - for (i = 0, b = 0, w = 0; i < verticesCount;) { - int bonesCount = (int)vertices[i++]; - mesh->bones[b++] = bonesCount; - for (nn = i + bonesCount * 4; i < nn; i += 4, ++b, w += 3) { - mesh->bones[b] = (int)vertices[i]; - mesh->weights[w] = vertices[i + 1] * self->scale; - mesh->weights[w + 1] = vertices[i + 2] * self->scale; - mesh->weights[w + 2] = vertices[i + 3]; - } - } - - FREE(vertices); - - entry = Json_getItem(attachmentMap, "triangles"); - mesh->trianglesCount = entry->size; - mesh->triangles = MALLOC(unsigned short, entry->size); - for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) - mesh->triangles[i] = (unsigned short)entry->valueInt; - - spWeightedMeshAttachment_updateUVs(mesh); - color = Json_getString(attachmentMap, "color", 0); if (color) { mesh->r = toColor(color, 0); @@ -758,18 +764,67 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha mesh->a = toColor(color, 3); } - mesh->hullLength = Json_getInt(attachmentMap, "hull", 0); - - entry = Json_getItem(attachmentMap, "edges"); - if (entry) { - mesh->edgesCount = entry->size; - mesh->edges = MALLOC(int, entry->size); - for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) - mesh->edges[i] = entry->valueInt; - } - mesh->width = Json_getFloat(attachmentMap, "width", 32) * self->scale; mesh->height = Json_getFloat(attachmentMap, "height", 32) * self->scale; + + entry = Json_getItem(attachmentMap, "parent"); + if (!entry) { + entry = Json_getItem(attachmentMap, "uvs"); + mesh->uvsCount = entry->size; + mesh->regionUVs = MALLOC(float, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->regionUVs[i] = entry->valueFloat; + + entry = Json_getItem(attachmentMap, "vertices"); + verticesCount = entry->size; + vertices = MALLOC(float, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + vertices[i] = entry->valueFloat; + + for (i = 0; i < verticesCount;) { + int bonesCount = (int)vertices[i]; + mesh->bonesCount += bonesCount + 1; + mesh->weightsCount += bonesCount * 3; + i += 1 + bonesCount * 4; + } + mesh->bones = MALLOC(int, mesh->bonesCount); + mesh->weights = MALLOC(float, mesh->weightsCount); + + for (i = 0, b = 0, w = 0; i < verticesCount;) { + int bonesCount = (int)vertices[i++]; + mesh->bones[b++] = bonesCount; + for (nn = i + bonesCount * 4; i < nn; i += 4, ++b, w += 3) { + mesh->bones[b] = (int)vertices[i]; + mesh->weights[w] = vertices[i + 1] * self->scale; + mesh->weights[w + 1] = vertices[i + 2] * self->scale; + mesh->weights[w + 2] = vertices[i + 3]; + } + } + + FREE(vertices); + + entry = Json_getItem(attachmentMap, "triangles"); + mesh->trianglesCount = entry->size; + mesh->triangles = MALLOC(unsigned short, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->triangles[i] = (unsigned short)entry->valueInt; + + spWeightedMeshAttachment_updateUVs(mesh); + + mesh->hullLength = Json_getInt(attachmentMap, "hull", 0); + + entry = Json_getItem(attachmentMap, "edges"); + if (entry) { + mesh->edgesCount = entry->size; + mesh->edges = MALLOC(int, entry->size); + for (entry = entry->child, i = 0; entry; entry = entry->next, ++i) + mesh->edges[i] = entry->valueInt; + } + } else { + mesh->inheritFFD = Json_getInt(attachmentMap, "ffd", 1); + _spSkeletonJson_addLinkedMesh(self, attachment, Json_getString(attachmentMap, "skin", 0), slotIndex, + entry->valueString); + } break; } case SP_ATTACHMENT_BOUNDING_BOX: { @@ -791,6 +846,33 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha } } + /* Linked meshes. */ + for (i = 0; i < internal->linkedMeshCount; i++) { + spAttachment* parent; + _spLinkedMesh* linkedMesh = internal->linkedMeshes + i; + spSkin* skin = !linkedMesh->skin ? skeletonData->defaultSkin : spSkeletonData_findSkin(skeletonData, linkedMesh->skin); + if (!skin) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, 0, "Skin not found: ", linkedMesh->skin); + return 0; + } + parent = spSkin_getAttachment(skin, linkedMesh->slotIndex, linkedMesh->parent); + if (!skin) { + spSkeletonData_dispose(skeletonData); + _spSkeletonJson_setError(self, 0, "Parent mesh not found: ", linkedMesh->parent); + return 0; + } + if (linkedMesh->mesh->type == SP_ATTACHMENT_MESH) { + spMeshAttachment* mesh = SUB_CAST(spMeshAttachment, linkedMesh->mesh); + spMeshAttachment_setParentMesh(mesh, SUB_CAST(spMeshAttachment, parent)); + spMeshAttachment_updateUVs(mesh); + } else { + spWeightedMeshAttachment* mesh = SUB_CAST(spWeightedMeshAttachment, linkedMesh->mesh); + spWeightedMeshAttachment_setParentMesh(mesh, SUB_CAST(spWeightedMeshAttachment, parent)); + spWeightedMeshAttachment_updateUVs(mesh); + } + } + /* Events. */ events = Json_getItem(root, "events"); if (events) { @@ -813,8 +895,14 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha if (animations) { Json *animationMap; skeletonData->animations = MALLOC(spAnimation*, animations->size); - for (animationMap = animations->child; animationMap; animationMap = animationMap->next) - _spSkeletonJson_readAnimation(self, animationMap, skeletonData); + for (animationMap = animations->child; animationMap; animationMap = animationMap->next) { + spAnimation* animation = _spSkeletonJson_readAnimation(self, animationMap, skeletonData); + if (!animation) { + spSkeletonData_dispose(skeletonData); + return 0; + } + skeletonData->animations[skeletonData->animationsCount++] = animation; + } } Json_dispose(root); diff --git a/spine-c/src/spine/WeightedMeshAttachment.c b/spine-c/src/spine/WeightedMeshAttachment.c index f17ea759d..c88ddd89e 100644 --- a/spine-c/src/spine/WeightedMeshAttachment.c +++ b/spine-c/src/spine/WeightedMeshAttachment.c @@ -36,12 +36,14 @@ void _spWeightedMeshAttachment_dispose (spAttachment* attachment) { spWeightedMeshAttachment* self = SUB_CAST(spWeightedMeshAttachment, attachment); _spAttachment_deinit(attachment); FREE(self->path); - FREE(self->bones); - FREE(self->weights); - FREE(self->regionUVs); FREE(self->uvs); - FREE(self->triangles); - FREE(self->edges); + if (!self->parentMesh) { + FREE(self->regionUVs); + FREE(self->bones); + FREE(self->weights); + FREE(self->triangles); + FREE(self->edges); + } FREE(self); } @@ -108,3 +110,28 @@ void spWeightedMeshAttachment_computeWorldVertices (spWeightedMeshAttachment* se } } } + +void spWeightedMeshAttachment_setParentMesh (spWeightedMeshAttachment* self, spWeightedMeshAttachment* parentMesh) { + CONST_CAST(spWeightedMeshAttachment*, self->parentMesh) = parentMesh; + if (parentMesh) { + self->bones = parentMesh->bones; + self->bonesCount = parentMesh->bonesCount; + + self->weights = parentMesh->weights; + self->weightsCount = parentMesh->weightsCount; + + self->regionUVs = parentMesh->regionUVs; + self->uvsCount = parentMesh->uvsCount; + + self->triangles = parentMesh->triangles; + self->trianglesCount = parentMesh->trianglesCount; + + self->hullLength = parentMesh->hullLength; + + self->edges = parentMesh->edges; + self->edgesCount = parentMesh->edgesCount; + + self->width = parentMesh->width; + self->height = parentMesh->height; + } +} diff --git a/spine-cocos2d-iphone/2/README.md b/spine-cocos2d-iphone/2/README.md index c4e67957f..20bdb146b 100644 --- a/spine-cocos2d-iphone/2/README.md +++ b/spine-cocos2d-iphone/2/README.md @@ -10,7 +10,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f ## Spine version -spine-cocos2d-iphone v2 works with data exported from the latest version of Spine, except linked meshes are [not yet supported](https://trello.com/c/bERJAFEq/73-update-runtimes-to-support-v3-1-linked-meshes). +spine-cocos2d-iphone v2 works with data exported from the latest version of Spine. spine-cocos2d-iphone v2 supports all Spine features. diff --git a/spine-cocos2d-iphone/3/README.md b/spine-cocos2d-iphone/3/README.md index c21ee3fff..9adcd6a20 100644 --- a/spine-cocos2d-iphone/3/README.md +++ b/spine-cocos2d-iphone/3/README.md @@ -10,7 +10,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f ## Spine version -spine-cocos2d-iphone v3 works with data exported from the latest version of Spine, except linked meshes are [not yet supported](https://trello.com/c/bERJAFEq/73-update-runtimes-to-support-v3-1-linked-meshes). +spine-cocos2d-iphone v3 works with data exported from the latest version of Spine. spine-cocos2d-iphone v3 supports all Spine features. diff --git a/spine-cocos2dx/2/README.md b/spine-cocos2dx/2/README.md index 7ea859185..f756bd2f0 100644 --- a/spine-cocos2dx/2/README.md +++ b/spine-cocos2dx/2/README.md @@ -10,7 +10,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f ## Spine version -spine-cocos2dx v2 works with data exported from the latest version of Spine, except linked meshes are [not yet supported](https://trello.com/c/bERJAFEq/73-update-runtimes-to-support-v3-1-linked-meshes). +spine-cocos2dx v2 works with data exported from the latest version of Spine. spine-cocos2dx v2 supports all Spine features. diff --git a/spine-cocos2dx/3/README.md b/spine-cocos2dx/3/README.md index 2474db353..5bb0f2d82 100644 --- a/spine-cocos2dx/3/README.md +++ b/spine-cocos2dx/3/README.md @@ -10,7 +10,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f ## Spine version -spine-cocos2dx v3 works with data exported from the latest version of Spine, except linked meshes are [not yet supported](https://trello.com/c/bERJAFEq/73-update-runtimes-to-support-v3-1-linked-meshes). +spine-cocos2dx v3 works with data exported from the latest version of Spine. spine-cocos2dx v3 supports all Spine features. diff --git a/spine-sfml/README.md b/spine-sfml/README.md index 807051815..395010cd0 100644 --- a/spine-sfml/README.md +++ b/spine-sfml/README.md @@ -10,7 +10,7 @@ The Spine Runtimes are developed with the intent to be used with data exported f ## Spine version -spine-sfml works with data exported from the latest version of Spine, except linked meshes are [not yet supported](https://trello.com/c/bERJAFEq/73-update-runtimes-to-support-v3-1-linked-meshes). +spine-sfml works with data exported from the latest version of Spine. spine-sfml supports all Spine features.