mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-21 01:36:02 +08:00
spine-c updated to v3.1.
This commit is contained in:
parent
ca0372c415
commit
421789e6f7
@ -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.
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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. */
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -108,7 +108,8 @@ 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. */
|
||||
} else {
|
||||
if (self->data->inheritRotation) { /* No scale inheritance. */
|
||||
pa = 1;
|
||||
pb = 0;
|
||||
pc = 0;
|
||||
@ -130,14 +131,6 @@ 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;
|
||||
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;
|
||||
@ -177,6 +170,12 @@ 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 {
|
||||
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;
|
||||
@ -185,11 +184,6 @@ void spBone_updateWorldTransformWith (spBone* self, float x, float y, float rota
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,11 +36,13 @@ void _spMeshAttachment_dispose (spAttachment* attachment) {
|
||||
spMeshAttachment* self = SUB_CAST(spMeshAttachment, attachment);
|
||||
_spAttachment_deinit(attachment);
|
||||
FREE(self->path);
|
||||
FREE(self->uvs);
|
||||
if (!self->parentMesh) {
|
||||
FREE(self->vertices);
|
||||
FREE(self->regionUVs);
|
||||
FREE(self->uvs);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,9 +36,20 @@
|
||||
#include <spine/extension.h>
|
||||
#include <spine/AtlasAttachmentLoader.h>
|
||||
|
||||
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,11 +694,25 @@ 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);
|
||||
|
||||
color = Json_getString(attachmentMap, "color", 0);
|
||||
if (color) {
|
||||
mesh->r = toColor(color, 0);
|
||||
mesh->g = toColor(color, 1);
|
||||
mesh->b = toColor(color, 2);
|
||||
mesh->a = toColor(color, 3);
|
||||
}
|
||||
|
||||
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);
|
||||
@ -679,14 +732,6 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
|
||||
|
||||
spMeshAttachment_updateUVs(mesh);
|
||||
|
||||
color = Json_getString(attachmentMap, "color", 0);
|
||||
if (color) {
|
||||
mesh->r = toColor(color, 0);
|
||||
mesh->g = toColor(color, 1);
|
||||
mesh->b = toColor(color, 2);
|
||||
mesh->a = toColor(color, 3);
|
||||
}
|
||||
|
||||
mesh->hullLength = Json_getInt(attachmentMap, "hull", 0);
|
||||
|
||||
entry = Json_getItem(attachmentMap, "edges");
|
||||
@ -696,18 +741,34 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
|
||||
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;
|
||||
} 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);
|
||||
|
||||
color = Json_getString(attachmentMap, "color", 0);
|
||||
if (color) {
|
||||
mesh->r = toColor(color, 0);
|
||||
mesh->g = toColor(color, 1);
|
||||
mesh->b = toColor(color, 2);
|
||||
mesh->a = toColor(color, 3);
|
||||
}
|
||||
|
||||
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);
|
||||
@ -750,14 +811,6 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
|
||||
|
||||
spWeightedMeshAttachment_updateUVs(mesh);
|
||||
|
||||
color = Json_getString(attachmentMap, "color", 0);
|
||||
if (color) {
|
||||
mesh->r = toColor(color, 0);
|
||||
mesh->g = toColor(color, 1);
|
||||
mesh->b = toColor(color, 2);
|
||||
mesh->a = toColor(color, 3);
|
||||
}
|
||||
|
||||
mesh->hullLength = Json_getInt(attachmentMap, "hull", 0);
|
||||
|
||||
entry = Json_getItem(attachmentMap, "edges");
|
||||
@ -767,9 +820,11 @@ spSkeletonData* spSkeletonJson_readSkeletonData (spSkeletonJson* self, const cha
|
||||
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;
|
||||
} 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);
|
||||
|
||||
@ -36,12 +36,14 @@ void _spWeightedMeshAttachment_dispose (spAttachment* attachment) {
|
||||
spWeightedMeshAttachment* self = SUB_CAST(spWeightedMeshAttachment, attachment);
|
||||
_spAttachment_deinit(attachment);
|
||||
FREE(self->path);
|
||||
FREE(self->uvs);
|
||||
if (!self->parentMesh) {
|
||||
FREE(self->regionUVs);
|
||||
FREE(self->bones);
|
||||
FREE(self->weights);
|
||||
FREE(self->regionUVs);
|
||||
FREE(self->uvs);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user