[c] More skin API changes, see #841.

This commit is contained in:
badlogic 2019-05-31 11:44:49 +02:00
parent d14b5dc22a
commit 225472de93
14 changed files with 250 additions and 31 deletions

View File

@ -41,7 +41,7 @@ extern "C" {
#endif
typedef struct spPointAttachment {
spVertexAttachment super;
spAttachment super;
float x, y, rotation;
spColor color;
} spPointAttachment;

View File

@ -32,6 +32,10 @@
#include <spine/dll.h>
#include <spine/Attachment.h>
#include <spine/IkConstraintData.h>
#include <spine/TransformConstraintData.h>
#include <spine/PathConstraintData.h>
#include <spine/Array.h>
#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__)

View File

@ -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);

View File

@ -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;

View File

@ -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:

View File

@ -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)->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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -31,17 +31,24 @@
#include <spine/extension.h>
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(&copy->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;
}

View File

@ -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(&copy->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;
}

View File

@ -30,6 +30,11 @@
#include <spine/Skin.h>
#include <spine/extension.h>
_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,23 +95,44 @@ 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) {
_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;
}
if (attachment) attachment->refCount++;
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 = SUB_CAST(_spSkin, self)->entriesHashTable[hashTableIndex];
newHashEntry->next = hashTable[hashTableIndex];
SUB_CAST(_spSkin, self)->entriesHashTable[hashTableIndex] = newHashEntry;
}
}
}
spAttachment* spSkin_getAttachment (const spSkin* self, int slotIndex, const char* name) {
const _SkinHashTableEntry* hashEntry = SUB_CAST(_spSkin, self)->entriesHashTable[(unsigned int)slotIndex % SKIN_ENTRIES_HASH_TABLE_SIZE];
@ -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);
}

View File

@ -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);