diff --git a/spine-c/spine-c/include/spine/PointAttachment.h b/spine-c/spine-c/include/spine/PointAttachment.h index bdbe5d8ea..c7a847c68 100644 --- a/spine-c/spine-c/include/spine/PointAttachment.h +++ b/spine-c/spine-c/include/spine/PointAttachment.h @@ -41,7 +41,7 @@ extern "C" { #endif typedef struct spPointAttachment { - spVertexAttachment super; + spAttachment super; float x, y, rotation; spColor color; } spPointAttachment; diff --git a/spine-c/spine-c/include/spine/Skin.h b/spine-c/spine-c/include/spine/Skin.h index 19d4c2cfa..b70edb853 100644 --- a/spine-c/spine-c/include/spine/Skin.h +++ b/spine-c/spine-c/include/spine/Skin.h @@ -32,6 +32,10 @@ #include #include +#include +#include +#include +#include #ifdef __cplusplus extern "C" { @@ -42,18 +46,33 @@ extern "C" { struct spSkeleton; +_SP_ARRAY_DECLARE_TYPE(spBoneDataArray, spBoneData*) +_SP_ARRAY_DECLARE_TYPE(spIkConstraintDataArray, spIkConstraintData*) +_SP_ARRAY_DECLARE_TYPE(spTransformConstraintDataArray, spTransformConstraintData*) +_SP_ARRAY_DECLARE_TYPE(spPathConstraintDataArray, spPathConstraintData*) + typedef struct spSkin { const char* const name; + spBoneDataArray* bones; + spIkConstraintDataArray* ikConstraints; + spTransformConstraintDataArray* transformConstraints; + spPathConstraintDataArray* pathConstraints; + #ifdef __cplusplus spSkin() : - name(0) { + name(0), + bones(0), + ikConstraints(0), + transformConstraints(0), + pathConstraints(0) { } #endif } spSkin; /* Private structs, needed by Skeleton */ typedef struct _Entry _Entry; +typedef struct _Entry spSkinEntry; struct _Entry { int slotIndex; const char* name; @@ -64,7 +83,7 @@ struct _Entry { typedef struct _SkinHashTableEntry _SkinHashTableEntry; struct _SkinHashTableEntry { _Entry* entry; - _SkinHashTableEntry* next; /* list for elements with same hashes */ + _SkinHashTableEntry* next; }; typedef struct { @@ -87,6 +106,15 @@ SP_API const char* spSkin_getAttachmentName (const spSkin* self, int slotIndex, /** Attach each attachment in this skin if the corresponding attachment in oldSkin is currently attached. */ SP_API void spSkin_attachAll (const spSkin* self, struct spSkeleton* skeleton, const spSkin* oldspSkin); +/** Adds all attachments, bones, and constraints from the specified skin to this skin. */ +SP_API void spSkin_addSkin(spSkin* self, const spSkin* other); + +/** Returns all attachments in this skin. */ +SP_API spSkinEntry* spSkin_getAttachments(const spSkin* self); + +/** Clears all attachments, bones, and constraints. */ +SP_API void spSkin_clear(spSkin* self); + #ifdef SPINE_SHORT_NAMES typedef spSkin Skin; #define Skin_create(...) spSkin_create(__VA_ARGS__) diff --git a/spine-c/spine-c/include/spine/extension.h b/spine-c/spine-c/include/spine/extension.h index f9fabc228..8adc932e2 100644 --- a/spine-c/spine-c/include/spine/extension.h +++ b/spine-c/spine-c/include/spine/extension.h @@ -277,7 +277,7 @@ void _spAttachmentLoader_setUnknownTypeError (spAttachmentLoader* self, spAttach /**/ void _spAttachment_init (spAttachment* self, const char* name, spAttachmentType type, -void (*dispose) (spAttachment* self)); +void (*dispose) (spAttachment* self), spAttachment* (*copy) (spAttachment* self)); void _spAttachment_deinit (spAttachment* self); void _spVertexAttachment_init (spVertexAttachment* self); void _spVertexAttachment_deinit (spVertexAttachment* self); diff --git a/spine-c/spine-c/src/spine/AnimationState.c b/spine-c/spine-c/src/spine/AnimationState.c index 363c01303..7a7fdb06f 100644 --- a/spine-c/spine-c/src/spine/AnimationState.c +++ b/spine-c/spine-c/src/spine/AnimationState.c @@ -1004,7 +1004,7 @@ void _spTrackEntry_computeNotLast(spTrackEntry* entry, spAnimationState* state) spTimeline** timelines ; int timelinesCount; int* timelineMode; - int i, n; + int i; timelines = entry->animation->timelines; timelinesCount = entry->animation->timelinesCount; diff --git a/spine-c/spine-c/src/spine/AtlasAttachmentLoader.c b/spine-c/spine-c/src/spine/AtlasAttachmentLoader.c index 40afbcaaa..3c9664529 100644 --- a/spine-c/spine-c/src/spine/AtlasAttachmentLoader.c +++ b/spine-c/spine-c/src/spine/AtlasAttachmentLoader.c @@ -81,7 +81,7 @@ spAttachment* _spAtlasAttachmentLoader_createAttachment (spAttachmentLoader* loa case SP_ATTACHMENT_PATH: return SUPER(SUPER(spPathAttachment_create(name))); case SP_ATTACHMENT_POINT: - return SUPER(SUPER(spPointAttachment_create(name))); + return SUPER(spPointAttachment_create(name)); case SP_ATTACHMENT_CLIPPING: return SUPER(SUPER(spClippingAttachment_create(name))); default: diff --git a/spine-c/spine-c/src/spine/Attachment.c b/spine-c/spine-c/src/spine/Attachment.c index 6cc60d3c1..9c3c14170 100644 --- a/spine-c/spine-c/src/spine/Attachment.c +++ b/spine-c/spine-c/src/spine/Attachment.c @@ -33,18 +33,18 @@ typedef struct _spAttachmentVtable { void (*dispose) (spAttachment* self); + spAttachment* (*copy) (spAttachment* self); } _spAttachmentVtable; void _spAttachment_init (spAttachment* self, const char* name, spAttachmentType type, /**/ - void (*dispose) (spAttachment* self)) { + void (*dispose) (spAttachment* self), spAttachment* (*copy) (spAttachment* self)) { CONST_CAST(_spAttachmentVtable*, self->vtable) = NEW(_spAttachmentVtable); - VTABLE(spAttachment, self) ->dispose = dispose; + VTABLE(spAttachment, self)->dispose = dispose; + VTABLE(spAttachment, self)->copy = copy; MALLOC_STR(self->name, name); CONST_CAST(spAttachmentType, self->type) = type; - - self->refCount++; } void _spAttachment_deinit (spAttachment* self) { @@ -53,8 +53,12 @@ void _spAttachment_deinit (spAttachment* self) { FREE(self->name); } +spAttachment* spAttachment_copy (spAttachment* self) { + return VTABLE(spAttachment, self) ->copy(self); +} + void spAttachment_dispose (spAttachment* self) { self->refCount--; - if (self->refCount == 0) + if (self->refCount <= 0) VTABLE(spAttachment, self) ->dispose(self); } diff --git a/spine-c/spine-c/src/spine/BoundingBoxAttachment.c b/spine-c/spine-c/src/spine/BoundingBoxAttachment.c index 7acddbc1d..f55d88717 100644 --- a/spine-c/spine-c/src/spine/BoundingBoxAttachment.c +++ b/spine-c/spine-c/src/spine/BoundingBoxAttachment.c @@ -38,9 +38,13 @@ void _spBoundingBoxAttachment_dispose (spAttachment* attachment) { FREE(self); } +spAttachment* _spBoundingBoxAttachment_copy (spAttachment* attachment) { + +} + spBoundingBoxAttachment* spBoundingBoxAttachment_create (const char* name) { spBoundingBoxAttachment* self = NEW(spBoundingBoxAttachment); _spVertexAttachment_init(SUPER(self)); - _spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_BOUNDING_BOX, _spBoundingBoxAttachment_dispose); + _spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_BOUNDING_BOX, _spBoundingBoxAttachment_dispose, _spBoundingBoxAttachment_copy); return self; } diff --git a/spine-c/spine-c/src/spine/ClippingAttachment.c b/spine-c/spine-c/src/spine/ClippingAttachment.c index 9c007a295..3d0793f9c 100644 --- a/spine-c/spine-c/src/spine/ClippingAttachment.c +++ b/spine-c/spine-c/src/spine/ClippingAttachment.c @@ -38,10 +38,14 @@ void _spClippingAttachment_dispose (spAttachment* attachment) { FREE(self); } +spAttachment* _spClippingAttachment_copy (spAttachment* attachment) { + +} + spClippingAttachment* spClippingAttachment_create (const char* name) { spClippingAttachment* self = NEW(spClippingAttachment); _spVertexAttachment_init(SUPER(self)); - _spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_CLIPPING, _spClippingAttachment_dispose); + _spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_CLIPPING, _spClippingAttachment_dispose, _spClippingAttachment_copy); self->endSlot = 0; return self; } diff --git a/spine-c/spine-c/src/spine/MeshAttachment.c b/spine-c/spine-c/src/spine/MeshAttachment.c index dbe1da33a..5763255ff 100644 --- a/spine-c/spine-c/src/spine/MeshAttachment.c +++ b/spine-c/spine-c/src/spine/MeshAttachment.c @@ -44,19 +44,24 @@ void _spMeshAttachment_dispose (spAttachment* attachment) { FREE(self); } +spAttachment* _spMeshAttachment_copy (spAttachment* attachment) { + +} + spMeshAttachment* spMeshAttachment_create (const char* name) { spMeshAttachment* self = NEW(spMeshAttachment); _spVertexAttachment_init(SUPER(self)); spColor_setFromFloats(&self->color, 1, 1, 1, 1); - _spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_MESH, _spMeshAttachment_dispose); + _spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_MESH, _spMeshAttachment_dispose, _spMeshAttachment_copy); return self; } void spMeshAttachment_updateUVs (spMeshAttachment* self) { int i, n; + float* uvs; int verticesLength = SUPER(self)->worldVerticesLength; FREE(self->uvs); - float* uvs = self->uvs = MALLOC(float, verticesLength); + uvs = self->uvs = MALLOC(float, verticesLength); n = verticesLength; float u = self->regionU, v = self->regionV; float width = 0, height = 0; diff --git a/spine-c/spine-c/src/spine/PathAttachment.c b/spine-c/spine-c/src/spine/PathAttachment.c index 051c82948..5ff8f9eeb 100644 --- a/spine-c/spine-c/src/spine/PathAttachment.c +++ b/spine-c/spine-c/src/spine/PathAttachment.c @@ -39,9 +39,13 @@ void _spPathAttachment_dispose (spAttachment* attachment) { FREE(self); } +spAttachment* _spPathAttachment_copy (spAttachment* attachment) { + +} + spPathAttachment* spPathAttachment_create (const char* name) { spPathAttachment* self = NEW(spPathAttachment); _spVertexAttachment_init(SUPER(self)); - _spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_PATH, _spPathAttachment_dispose); + _spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_PATH, _spPathAttachment_dispose, _spPathAttachment_copy); return self; } diff --git a/spine-c/spine-c/src/spine/PointAttachment.c b/spine-c/spine-c/src/spine/PointAttachment.c index b8d3d41f4..e7f415b63 100644 --- a/spine-c/spine-c/src/spine/PointAttachment.c +++ b/spine-c/spine-c/src/spine/PointAttachment.c @@ -31,17 +31,24 @@ #include void _spPointAttachment_dispose (spAttachment* attachment) { - spPathAttachment* self = SUB_CAST(spPathAttachment, attachment); - - _spVertexAttachment_deinit(SUPER(self)); - + spPointAttachment* self = SUB_CAST(spPointAttachment, attachment); + _spAttachment_deinit(attachment); FREE(self); } +spAttachment* _spPointAttachment_copy (spAttachment* attachment) { + spPointAttachment* self = SUB_CAST(spPointAttachment, attachment); + spPointAttachment* copy = spPointAttachment_create(attachment->name); + copy->x = self->x; + copy->y = self->y; + copy->rotation = self->rotation; + spColor_setFromColor(©->color, &self->color); + return SUPER(copy); +} + spPointAttachment* spPointAttachment_create (const char* name) { spPointAttachment* self = NEW(spPointAttachment); - _spVertexAttachment_init(SUPER(self)); - _spAttachment_init(SUPER(SUPER(self)), name, SP_ATTACHMENT_POINT, _spPointAttachment_dispose); + _spAttachment_init(SUPER(self), name, SP_ATTACHMENT_POINT, _spPointAttachment_dispose, _spPointAttachment_copy); return self; } diff --git a/spine-c/spine-c/src/spine/RegionAttachment.c b/spine-c/spine-c/src/spine/RegionAttachment.c index 7f3100505..e098cee86 100644 --- a/spine-c/spine-c/src/spine/RegionAttachment.c +++ b/spine-c/spine-c/src/spine/RegionAttachment.c @@ -41,12 +41,36 @@ void _spRegionAttachment_dispose (spAttachment* attachment) { FREE(self); } +spAttachment* _spRegionAttachment_copy (spAttachment* attachment) { + spRegionAttachment* self = SUB_CAST(spRegionAttachment, attachment); + spRegionAttachment* copy = spRegionAttachment_create(attachment->name); + copy->regionWidth = self->regionWidth; + copy->regionHeight = self->regionHeight; + copy->regionOffsetX = self->regionOffsetX; + copy->regionOffsetY = self->regionOffsetY; + copy->regionOriginalWidth = self->regionOriginalWidth; + copy->regionOriginalHeight = self->regionOriginalHeight; + copy->rendererObject = self->rendererObject; + MALLOC_STR(copy->path, self->path); + copy->x = self->x; + copy->y = self->y; + copy->scaleX = self->scaleX; + copy->scaleY = self->scaleY; + copy->rotation = self->rotation; + copy->width = self->width; + copy->height = self->height; + memcpy(copy->uvs, self->uvs, sizeof(float) * 8); + memcpy(copy->offset, self->offset, sizeof(float) * 8); + spColor_setFromColor(©->color, &self->color); + return SUPER(copy); +} + spRegionAttachment* spRegionAttachment_create (const char* name) { spRegionAttachment* self = NEW(spRegionAttachment); self->scaleX = 1; self->scaleY = 1; spColor_setFromFloats(&self->color, 1, 1, 1, 1); - _spAttachment_init(SUPER(self), name, SP_ATTACHMENT_REGION, _spRegionAttachment_dispose); + _spAttachment_init(SUPER(self), name, SP_ATTACHMENT_REGION, _spRegionAttachment_dispose, _spRegionAttachment_copy); return self; } diff --git a/spine-c/spine-c/src/spine/Skin.c b/spine-c/spine-c/src/spine/Skin.c index 5995101e4..5ee8ec4c7 100644 --- a/spine-c/spine-c/src/spine/Skin.c +++ b/spine-c/spine-c/src/spine/Skin.c @@ -30,6 +30,11 @@ #include #include +_SP_ARRAY_IMPLEMENT_TYPE(spBoneDataArray, spBoneData*) +_SP_ARRAY_IMPLEMENT_TYPE(spIkConstraintDataArray, spIkConstraintData*) +_SP_ARRAY_IMPLEMENT_TYPE(spTransformConstraintDataArray, spTransformConstraintData*) +_SP_ARRAY_IMPLEMENT_TYPE(spPathConstraintDataArray, spPathConstraintData*) + _Entry* _Entry_create (int slotIndex, const char* name, spAttachment* attachment) { _Entry* self = NEW(_Entry); self->slotIndex = slotIndex; @@ -59,6 +64,10 @@ static void _SkinHashTableEntry_dispose (_SkinHashTableEntry* self) { spSkin* spSkin_create (const char* name) { spSkin* self = SUPER(NEW(_spSkin)); MALLOC_STR(self->name, name); + self->bones = spBoneDataArray_create(4); + self->ikConstraints = spIkConstraintDataArray_create(4); + self->transformConstraints = spTransformConstraintDataArray_create(4); + self->pathConstraints = spPathConstraintDataArray_create(4); return self; } @@ -86,21 +95,42 @@ void spSkin_dispose (spSkin* self) { } } + spBoneDataArray_dispose(self->bones); + spIkConstraintDataArray_dispose(self->ikConstraints); + spTransformConstraintDataArray_dispose(self->transformConstraints); + spPathConstraintDataArray_dispose(self->pathConstraints); FREE(self->name); FREE(self); } void spSkin_setAttachment (spSkin* self, int slotIndex, const char* name, spAttachment* attachment) { - _Entry* newEntry = _Entry_create(slotIndex, name, attachment); - newEntry->next = SUB_CAST(_spSkin, self)->entries; - SUB_CAST(_spSkin, self)->entries = newEntry; + _SkinHashTableEntry* existingEntry = 0; + const _SkinHashTableEntry* hashEntry = SUB_CAST(_spSkin, self)->entriesHashTable[(unsigned int)slotIndex % SKIN_ENTRIES_HASH_TABLE_SIZE]; + while (hashEntry) { + if (hashEntry->entry->slotIndex == slotIndex && strcmp(hashEntry->entry->name, name) == 0) { + existingEntry = hashEntry; + break; + } + hashEntry = hashEntry->next; + } - { - unsigned int hashTableIndex = (unsigned int)slotIndex % SKIN_ENTRIES_HASH_TABLE_SIZE; + if (attachment) attachment->refCount++; - _SkinHashTableEntry* newHashEntry = _SkinHashTableEntry_create(newEntry); - newHashEntry->next = SUB_CAST(_spSkin, self)->entriesHashTable[hashTableIndex]; - SUB_CAST(_spSkin, self)->entriesHashTable[hashTableIndex] = newHashEntry; + if (existingEntry) { + if (hashEntry->entry->attachment) spAttachment_dispose(hashEntry->entry->attachment); + hashEntry->entry->attachment = attachment; + } else { + _Entry* newEntry = _Entry_create(slotIndex, name, attachment); + newEntry->next = SUB_CAST(_spSkin, self)->entries; + SUB_CAST(_spSkin, self)->entries = newEntry; + { + unsigned int hashTableIndex = (unsigned int)slotIndex % SKIN_ENTRIES_HASH_TABLE_SIZE; + _SkinHashTableEntry** hashTable = SUB_CAST(_spSkin, self)->entriesHashTable; + + _SkinHashTableEntry* newHashEntry = _SkinHashTableEntry_create(newEntry); + newHashEntry->next = hashTable[hashTableIndex]; + SUB_CAST(_spSkin, self)->entriesHashTable[hashTableIndex] = newHashEntry; + } } } @@ -137,3 +167,71 @@ void spSkin_attachAll (const spSkin* self, spSkeleton* skeleton, const spSkin* o entry = entry->next; } } + +void spSkin_addSkin(spSkin* self, const spSkin* other) { + int i = 0; + + for (i = 0; i < other->bones->size; i++) { + if (!spBoneDataArray_contains(self->bones, other->bones->items[i])) + spBoneDataArray_add(self->bones, other->bones->items[i]); + } + + for (i = 0; i < other->ikConstraints->size; i++) { + if (!spIkConstraintDataArray_contains(self->ikConstraints, other->ikConstraints->items[i])) + spIkConstraintDataArray_add(self->ikConstraints, other->ikConstraints->items[i]); + } + + for (i = 0; i < other->transformConstraints->size; i++) { + if (!spTransformConstraintDataArray_contains(self->transformConstraints, other->transformConstraints->items[i])) + spTransformConstraintDataArray_add(self->transformConstraints, other->transformConstraints->items[i]); + } + + for (i = 0; i < other->pathConstraints->size; i++) { + if (!spPathConstraintDataArray_contains(self->pathConstraints, other->pathConstraints->items[i])) + spPathConstraintDataArray_add(self->pathConstraints, other->pathConstraints->items[i]); + } + + spSkinEntry* entry = spSkin_getAttachments(other); + while (entry) { + spSkin_setAttachment(self, entry->slotIndex, entry->name, entry->attachment); + entry = entry->next; + } +} + +spSkinEntry* spSkin_getAttachments(const spSkin* self) { + return SUB_CAST(_spSkin, self)->entries; +} + +void spSkin_clear(spSkin* self) { + _Entry* entry = SUB_CAST(_spSkin, self)->entries; + + while (entry) { + _Entry* nextEntry = entry->next; + _Entry_dispose(entry); + entry = nextEntry; + } + + SUB_CAST(_spSkin, self)->entries = 0; + + { + _SkinHashTableEntry** currentHashtableEntry = SUB_CAST(_spSkin, self)->entriesHashTable; + int i; + + for (i = 0; i < SKIN_ENTRIES_HASH_TABLE_SIZE; ++i, ++currentHashtableEntry) { + _SkinHashTableEntry* hashtableEntry = *currentHashtableEntry; + + while (hashtableEntry) { + _SkinHashTableEntry* nextEntry = hashtableEntry->next; + _SkinHashTableEntry_dispose(hashtableEntry); + hashtableEntry = nextEntry; + } + + SUB_CAST(_spSkin, self)->entriesHashTable[i] = 0; + } + } + + spBoneDataArray_clear(self->bones); + spIkConstraintDataArray_clear(self->ikConstraints); + spTransformConstraintDataArray_clear(self->transformConstraints); + spPathConstraintDataArray_clear(self->pathConstraints); +} diff --git a/spine-sfml/c/example/main.cpp b/spine-sfml/c/example/main.cpp index 7d7055b15..4c87447c7 100644 --- a/spine-sfml/c/example/main.cpp +++ b/spine-sfml/c/example/main.cpp @@ -446,7 +446,48 @@ void test (SkeletonData* skeletonData, Atlas* atlas) { Skeleton_dispose(skeleton); } +void testSkinsApi(SkeletonData* skeletonData, Atlas* atlas) { + SkeletonDrawable* drawable = new SkeletonDrawable(skeletonData); + drawable->timeScale = 1; + drawable->setUsePremultipliedAlpha(true); + + Skeleton* skeleton = drawable->skeleton; + + spSkin* skin = spSkin_create("test-skin"); + spSkin_addSkin(skin, spSkeletonData_findSkin(skeletonData, "goblingirl")); + spSkeleton_setSkin(skeleton, skin); + spSkeleton_setSlotsToSetupPose(skeleton); + + skeleton->x = 320; + skeleton->y = 590; + Skeleton_updateWorldTransform(skeleton); + + AnimationState_setAnimationByName(drawable->state, 0, "walk", true); + + sf::RenderWindow window(sf::VideoMode(640, 640), "Spine SFML - skins api"); + window.setFramerateLimit(60); + sf::Event event; + sf::Clock deltaClock; + while (window.isOpen()) { + while (window.pollEvent(event)) + if (event.type == sf::Event::Closed) window.close(); + + float delta = deltaClock.getElapsedTime().asSeconds(); + deltaClock.restart(); + + drawable->update(delta); + + window.clear(); + window.draw(*drawable); + window.display(); + } + + spSkin_clear(skin); + spSkin_dispose(skin); +} + int main () { + testcase(testSkinsApi, "data/goblins-pro.json", "data/goblins-pro.skel", "data/goblins-pma.atlas", 1.4f); testcase(test, "data/tank-pro.json", "data/tank-pro.skel", "data/tank-pma.atlas", 1.0f); testcase(spineboy, "data/spineboy-pro.json", "data/spineboy-pro.skel", "data/spineboy-pma.atlas", 0.6f); testcase(stretchyman, "data/stretchyman-stretchy-ik-pro.json", "data/stretchyman-stretchy-ik-pro.skel", "data/stretchyman-pma.atlas", 0.6f);