Extension stuff seems to be shaping up nicely!

This commit is contained in:
NathanSweet 2013-03-29 22:12:57 +01:00
parent 24538adb1a
commit 103cd30758
30 changed files with 426 additions and 216 deletions

View File

@ -1,16 +0,0 @@
#include "SfmlRegionAttachment.h"
#include <stdlib.h>
void _RegionAttachment_init (RegionAttachment* attachment, const char* name);
void SfmlRegionAttachment_dispose (Attachment* attachment) {
/* SfmlRegionAttachment* this = (SfmlRegionAttachment*)attachment; */
/* dispose something */
}
SfmlRegionAttachment* SfmlRegionAttachment_create (const char* name) {
SfmlRegionAttachment* this = calloc(1, sizeof(SfmlRegionAttachment));
_RegionAttachment_init(&this->super, name);
((Attachment*)this)->_dispose = SfmlRegionAttachment_dispose;
return this;
}

View File

@ -1,23 +0,0 @@
#ifndef SPINE_SFMLREGIONATTACHMENT_H_
#define SPINE_SFMLREGIONATTACHMENT_H_
#include <spine/RegionAttachment.h>
#ifdef __cplusplus
namespace spine {
extern "C" {
#endif
typedef struct {
RegionAttachment super;
int meow;
} SfmlRegionAttachment;
SfmlRegionAttachment* SfmlRegionAttachment_create (const char* name);
#ifdef __cplusplus
}
}
#endif
#endif /* SPINE_SFMLREGIONATTACHMENT_H_ */

View File

@ -1,18 +0,0 @@
#include "SfmlSkeleton.h"
#include <stdlib.h>
void _Skeleton_init (Skeleton* this, SkeletonData* data);
void SfmlSkeleton_dispose (Skeleton* skeleton) {
/* SfmlSkeleton* this = (SfmlSkeleton*)skeleton; */
}
Skeleton* Skeleton_create (SkeletonData* data) {
SfmlSkeleton* this = calloc(1, sizeof(SfmlSkeleton));
_Skeleton_init(&this->super, data);
this->super._dispose = SfmlSkeleton_dispose;
return &this->super;
}
void Skeleton_draw (Skeleton* skeleton) {
}

View File

@ -1,23 +0,0 @@
#ifndef SPINE_SFMLSKELETON_H_
#define SPINE_SFMLSKELETON_H_
#include <spine/Skeleton.h>
#ifdef __cplusplus
namespace spine {extern "C" {
#endif
typedef struct {
Skeleton super;
int meow;
} SfmlSkeleton;
Skeleton* Skeleton_create (SkeletonData* data);
void Skeleton_draw ();
#ifdef __cplusplus
}}
#endif
#endif /* SPINE_SFMLSKELETON_H_ */

View File

@ -1,30 +1,97 @@
/* This demonstrates implementing an extension to spine-c. spine/extension.h declares the functions that must be implemented along
* with a number of internal methods exposed to facilitate extension. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <spine/spine.h>
#include "SfmlSkeleton.h"
#include "SfmlRegionAttachment.h"
#include "spine/cJSON.h"
#include <spine/extension.h>
#include <spine/util.h>
Attachment* loadAttachment (AttachmentType type, const char* name) {
return (Attachment*)SfmlRegionAttachment_create(name);
/**/
typedef struct {
AtlasPage super;
int extraData;
} ExampleAtlasPage;
void _ExampleAtlasPage_dispose (AtlasPage* page) {
ExampleAtlasPage* this = (ExampleAtlasPage*)page;
_AtlasPage_deinit(&this->super);
this->extraData = 0;
FREE(this)
}
AtlasPage* AtlasPage_create (const char* name) {
ExampleAtlasPage* this = calloc(1, sizeof(ExampleAtlasPage));
_AtlasPage_init(&this->super, name);
this->extraData = 123;
this->super._dispose = _ExampleAtlasPage_dispose;
return &this->super;
}
/**/
typedef struct {
RegionAttachment super;
int extraData;
} ExampleRegionAttachment;
void _ExampleRegionAttachment_dispose (Attachment* attachment) {
ExampleRegionAttachment* this = (ExampleRegionAttachment*)attachment;
_RegionAttachment_deinit(&this->super);
this->extraData = 0;
FREE(this)
}
RegionAttachment* RegionAttachment_create (const char* name, AtlasRegion* region) {
ExampleRegionAttachment* this = calloc(1, sizeof(ExampleRegionAttachment));
_RegionAttachment_init(&this->super, name);
this->extraData = 456;
this->super.super._dispose = _ExampleRegionAttachment_dispose;
return &this->super;
}
/**/
typedef struct {
Skeleton super;
int extraData;
} ExampleSkeleton;
void _ExampleSkeleton_dispose (Skeleton* skeleton) {
ExampleSkeleton* this = (ExampleSkeleton*)skeleton;
_Skeleton_deinit(&this->super);
this->extraData = 0;
FREE(this)
}
Skeleton* Skeleton_create (SkeletonData* data) {
ExampleSkeleton* this = calloc(1, sizeof(ExampleSkeleton));
_Skeleton_init(&this->super, data);
this->extraData = 789;
this->super._dispose = _ExampleSkeleton_dispose;
return &this->super;
}
/**/
int main (void) {
Attachment_setAttachmentLoader(loadAttachment);
SkeletonJson_readSkeletonDataFile("data/spineboy-skeleton.json");
if (SkeletonJson_getError()) printf("error: %s\n", SkeletonJson_getError());
SkeletonData *skeletonData = SkeletonData_create();
Skeleton* skeleton = Skeleton_create(skeletonData);
printf("meow? %d\n", ((SfmlSkeleton*)skeleton)->meow);
Skeleton_dispose(skeleton);
printf("meow? %d\n", ((SfmlSkeleton*)skeleton)->meow);
Atlas* atlas = Atlas_readAtlasFile("data/spineboy.atlas");
printf("%s %d", atlas->regions->name, atlas->regions->y);
printf("First page name: %s, extraData: %d\n", atlas->pages->name, ((ExampleAtlasPage*)atlas->pages)->extraData);
printf("First region name: %s, x: %d, y: %d\n", atlas->regions->name, atlas->regions->x, atlas->regions->y);
SkeletonJson* json = SkeletonJson_create(atlas);
SkeletonData *skeletonData = SkeletonJson_readSkeletonDataFile(json, "data/spineboy-skeleton.json");
if (!skeletonData) printf("error: %s\n", json->error);
printf("Attachment extraData: %d\n", ((ExampleRegionAttachment*)skeletonData->defaultSkin->entries->attachment)->extraData);
Skeleton* skeleton = Skeleton_create(skeletonData);
printf("Skeleton extraData: %d\n", ((ExampleSkeleton*)skeleton)->extraData);
Skeleton_dispose(skeleton);
SkeletonData_dispose(skeletonData);
SkeletonJson_dispose(json);
Atlas_dispose(atlas);
return 0;
}

View File

@ -1,4 +1,5 @@
#include <spine/Animation.h>
#include <math.h>
#include <spine/util.h>
Animation* Animation_create () {
@ -14,14 +15,30 @@ void Animation_dispose (Animation* this) {
FREE(this)
}
void Animation_apply (const Animation* animation, Skeleton* skeleton, float time, int/*bool*/loop) {
void Animation_apply (const Animation* this, Skeleton* skeleton, float time, int/*bool*/loop) {
if (loop && this->duration) time = fmod(time, this->duration);
int i, n = this->timelineCount;
for (i = 0; i < n; ++i)
Timeline_apply(this->timelines[i], skeleton, time, 1);
}
void Animation_mix (const Animation* animation, Skeleton* skeleton, float time, int/*bool*/loop, float alpha) {
void Animation_mix (const Animation* this, Skeleton* skeleton, float time, int/*bool*/loop, float alpha) {
if (loop && this->duration) time = fmod(time, this->duration);
int i, n = this->timelineCount;
for (i = 0; i < n; ++i)
Timeline_apply(this->timelines[i], skeleton, time, alpha);
}
/**/
void _Timeline_init (Timeline* timeline) {
}
void _Timeline_deinit (Timeline* timeline) {
}
void Timeline_dispose (Timeline* this) {
this->_dispose(this);
}
@ -37,10 +54,12 @@ static const float CURVE_STEPPED = -1;
static const int CURVE_SEGMENTS = 10;
void _CurveTimeline_init (CurveTimeline* this, int frameCount) {
_Timeline_init(&this->super);
this->curves = calloc(1, sizeof(float) * (frameCount - 1) * 6);
}
void _CurveTimeline_deinit (CurveTimeline* this) {
_Timeline_deinit(&this->super);
FREE(this->curves)
}
@ -103,7 +122,7 @@ float CurveTimeline_getCurvePercent (CurveTimeline* this, int frameIndex, float
return y + (1 - y) * (percent - x) / (1 - x); /* Last point is 1,1. */
}
/** @param target After the first and before the last entry. */
/* @param target After the first and before the last entry. */
static int binarySearch (float *values, int valuesLength, float target, int step) {
int low = 0;
int high = valuesLength / step - 2;
@ -138,8 +157,10 @@ void _BaseTimeline_dispose (Timeline* timeline) {
FREE(this);
}
/* Many timelines have structure identical to struct BaseTimeline and extend CurveTimeline. **/
struct BaseTimeline* _BaseTimeline_create (int frameCount, int frameSize) {
struct BaseTimeline* this = calloc(1, sizeof(struct BaseTimeline));
_CurveTimeline_init(&this->super, frameCount);
((Timeline*)this)->_dispose = _BaseTimeline_dispose;
CAST(int, this->frameCount) = frameCount;
@ -193,7 +214,6 @@ void _RotateTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float
RotateTimeline* RotateTimeline_create (int frameCount) {
RotateTimeline* this = _BaseTimeline_create(frameCount, 2);
((Timeline*)this)->_apply = _RotateTimeline_apply;
_CurveTimeline_init(&this->super, frameCount);
return this;
}
@ -239,7 +259,6 @@ void _TranslateTimeline_apply (const Timeline* timeline, Skeleton* skeleton, flo
TranslateTimeline* TranslateTimeline_create (int frameCount) {
TranslateTimeline* this = _BaseTimeline_create(frameCount, 3);
((Timeline*)this)->_apply = _TranslateTimeline_apply;
_CurveTimeline_init(&this->super, frameCount);
return this;
}
@ -281,7 +300,6 @@ void _ScaleTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float t
ScaleTimeline* ScaleTimeline_create (int frameCount) {
ScaleTimeline* this = _BaseTimeline_create(frameCount, 3);
((Timeline*)this)->_apply = _ScaleTimeline_apply;
_CurveTimeline_init(&this->super, frameCount);
return this;
}
@ -343,7 +361,6 @@ void _ColorTimeline_apply (const Timeline* timeline, Skeleton* skeleton, float t
ColorTimeline* ColorTimeline_create (int frameCount) {
ColorTimeline* this = (ColorTimeline*)_BaseTimeline_create(frameCount, 5);
((Timeline*)this)->_apply = _ColorTimeline_apply;
_CurveTimeline_init(&this->super, frameCount);
return this;
}
@ -375,6 +392,7 @@ void _AttachmentTimeline_apply (const Timeline* timeline, Skeleton* skeleton, fl
}
void _AttachmentTimeline_dispose (Timeline* timeline) {
_Timeline_deinit(timeline);
AttachmentTimeline* this = (AttachmentTimeline*)timeline;
int i;
@ -382,14 +400,19 @@ void _AttachmentTimeline_dispose (Timeline* timeline) {
FREE(this->attachmentNames[i])
FREE(this->attachmentNames)
_BaseTimeline_dispose(timeline);
FREE(this)
}
AttachmentTimeline* AttachmentTimeline_create (int frameCount) {
AttachmentTimeline* this = (AttachmentTimeline*)_BaseTimeline_create(frameCount, 1);
AttachmentTimeline* this = calloc(1, sizeof(AttachmentTimeline));
_Timeline_init(&this->super);
((Timeline*)this)->_dispose = _AttachmentTimeline_dispose;
((Timeline*)this)->_apply = _AttachmentTimeline_apply;
CAST(char*, this->attachmentNames) = calloc(1, sizeof(char*) * frameCount);
CAST(int, this->frameCount) = frameCount;
CAST(float*, this->frames) = calloc(1, sizeof(float) * frameCount);
return this;
}

View File

@ -43,7 +43,7 @@ typedef struct {
void CurveTimeline_setLinear (CurveTimeline* timeline, int frameIndex);
void CurveTimeline_setStepped (CurveTimeline* timeline, int frameIndex);
/** Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
/* Sets the control handle positions for an interpolation bezier curve used to transition from this keyframe to the next.
* cx1 and cx2 are from 0 to 1, representing the percent of time between the two keyframes. cy1 and cy2 are the percent of
* the difference between the keyframe's values. */
void CurveTimeline_setCurve (CurveTimeline* timeline, int frameIndex, float cx1, float cy1, float cx2, float cy2);
@ -103,7 +103,7 @@ typedef struct {
AttachmentTimeline* AttachmentTimeline_create (int frameCount);
/** @param attachmentName May be 0. */
/* @param attachmentName May be 0. */
void AttachmentTimeline_setFrame (AttachmentTimeline* timeline, int frameIndex, float time, const char* attachmentName);
#ifdef __cplusplus

View File

@ -1,16 +1,19 @@
#include <spine/Atlas.h>
#include <ctype.h>
#include <spine/util.h>
#include <spine/extension.h>
AtlasPage* AtlasPage_create () {
AtlasPage* this = calloc(1, sizeof(AtlasPage));
return this;
void _AtlasPage_init (AtlasPage* this, const char* name) {
this->name = name; /* name is guaranteed to be memory we allocated. */
}
void _AtlasPage_deinit (AtlasPage* this) {
FREE(this->name);
}
void AtlasPage_dispose (AtlasPage* this) {
if (this->next) AtlasPage_dispose(this->next);
FREE(this->name);
FREE(this);
if (this->next) AtlasPage_dispose(this->next); /* BOZO - Don't dispose all in the list. */
this->_dispose(this);
}
/**/
@ -45,7 +48,7 @@ static void trim (Str* str) {
str->end++;
}
/** Tokenize string without modification. Returns 0 on failure. */
/* Tokenize string without modification. Returns 0 on failure. */
static int readLine (const char* data, Str* str) {
static const char* nextStart;
if (data) {
@ -67,7 +70,7 @@ static int readLine (const char* data, Str* str) {
return 1;
}
/** Moves str->begin past the first occurence of c. Returns 0 on failure. */
/* Moves str->begin past the first occurence of c. Returns 0 on failure. */
static int beginPast (Str* str, char c) {
const char* begin = str->begin;
while (1) {
@ -88,7 +91,7 @@ static int readValue (Str* str) {
return 1;
}
/** Returns the number of tuple values read (2, 4, or 0 for failure). */
/* Returns the number of tuple values read (2, 4, or 0 for failure). */
static int readTuple (Str tuple[]) {
Str str;
readLine(0, &str);
@ -150,15 +153,13 @@ Atlas* Atlas_readAtlas (const char* data) {
if (str.end - str.begin == 0) {
page = 0;
} else if (!page) {
page = AtlasPage_create();
page = AtlasPage_create(mallocString(&str));
if (lastPage)
lastPage->next = page;
else
this->pages = page;
lastPage = page;
page->name = mallocString(&str);
if (!readValue(&str)) return 0;
page->format = (AtlasFormat)indexOf(formatNames, 7, &str);

View File

@ -31,8 +31,15 @@ struct AtlasPage {
AtlasFilter minFilter, magFilter;
AtlasWrap uWrap, vWrap;
AtlasPage* next;
void (*_dispose) (AtlasPage* page);
};
AtlasPage* AtlasPage_create (const char* name);
void AtlasPage_dispose(AtlasPage * this);
/**/
typedef struct AtlasRegion AtlasRegion;
struct AtlasRegion {
const char* name;
@ -48,6 +55,11 @@ struct AtlasRegion {
AtlasRegion* next;
};
AtlasRegion* AtlasRegion_create ();
void AtlasRegion_dispose(AtlasRegion * this);
/**/
typedef struct {
AtlasPage* pages;
AtlasRegion* regions;

View File

@ -0,0 +1,32 @@
#include <spine/AtlasAttachmentLoader.h>
#include <spine/util.h>
#include <spine/extension.h>
#include <stdio.h>
void _AtlasAttachmentLoader_dispose (AttachmentLoader* this) {
_AttachmentLoader_deinit(this);
}
Attachment* _AtlasAttachmentLoader_newAttachment (AttachmentLoader* loader, AttachmentType type, const char* name) {
AtlasAttachmentLoader* this = (AtlasAttachmentLoader*)loader;
switch (type) {
case ATTACHMENT_REGION: {
AtlasRegion* region = Atlas_findRegion(this->atlas, name);
if (!region) return _AttachmentLoader_setError(loader, "Region not found: ", name);
return (Attachment*)RegionAttachment_create(name, region);
}
default: {
char buffer[16];
sprintf((char*)loader->error2, "%d", type);
return _AttachmentLoader_setError(loader, "Unknown attachment type: ", buffer);
}
}
}
AtlasAttachmentLoader* AtlasAttachmentLoader_create (Atlas* atlas) {
AtlasAttachmentLoader* this = calloc(1, sizeof(AtlasAttachmentLoader));
this->atlas = atlas;
this->super._newAttachment = _AtlasAttachmentLoader_newAttachment;
this->super._dispose = _AtlasAttachmentLoader_dispose;
return this;
}

View File

@ -0,0 +1,24 @@
#ifndef SPINE_ATLASATTACHMENTLOADER_H_
#define SPINE_ATLASATTACHMENTLOADER_H_
#include <spine/AttachmentLoader.h>
#include <spine/Atlas.h>
#ifdef __cplusplus
namespace spine {
extern "C" {
#endif
typedef struct {
AttachmentLoader super;
Atlas* atlas;
} AtlasAttachmentLoader;
AtlasAttachmentLoader* AtlasAttachmentLoader_create (Atlas* atlas);
#ifdef __cplusplus
}
}
#endif
#endif /* SPINE_ATLASATTACHMENTLOADER_H_ */

View File

@ -1,22 +1,16 @@
#include <spine/Attachment.h>
#include <spine/util.h>
static AttachmentLoader loader;
void Attachment_setAttachmentLoader (AttachmentLoader value) {
loader = value;
}
AttachmentLoader Attachment_getAttachmentLoader () {
return loader;
}
void Attachment_init (Attachment* this, const char* name) {
void _Attachment_init (Attachment* this, const char* name, int type) {
MALLOC_STR(this->name, name);
this->type = type;
}
void _Attachment_deinit (Attachment* this) {
FREE(this->name)
FREE(this)
}
void Attachment_dispose (Attachment* this) {
this->_dispose(this);
FREE(this->name)
FREE(this)
}

View File

@ -13,16 +13,11 @@ typedef enum {
typedef struct Attachment Attachment;
struct Attachment {
const char* const name;
int type;
void (*_dispose) (Attachment* attachment);
};
typedef Attachment* (*AttachmentLoader) (AttachmentType type, const char* name);
void Attachment_setAttachmentLoader (AttachmentLoader loader);
AttachmentLoader Attachment_getAttachmentLoader ();
void Attachment_init (Attachment* attachment, const char* name);
void Attachment_dispose (Attachment* attachment);
#ifdef __cplusplus

View File

@ -0,0 +1,30 @@
#include <spine/AttachmentLoader.h>
#include <spine/util.h>
void _AttachmentLoader_init (AttachmentLoader* this) {
}
void _AttachmentLoader_deinit (AttachmentLoader* this) {
FREE(this->error1)
FREE(this->error2)
}
void AttachmentLoader_dispose (AttachmentLoader* this) {
this->_dispose(this);
}
Attachment* AttachmentLoader_newAttachment (AttachmentLoader* this, AttachmentType type, const char* name) {
FREE(this->error1)
FREE(this->error2)
this->error1 = 0;
this->error2 = 0;
return this->_newAttachment(this, type, name);
}
void* _AttachmentLoader_setError (AttachmentLoader* this, const char* error1, const char* error2) {
FREE(this->error1)
FREE(this->error2)
MALLOC_STR(this->error1, error1)
MALLOC_STR(this->error2, error2)
return 0;
}

View File

@ -0,0 +1,29 @@
#ifndef SPINE_ATTACHMENTLOADER_H_
#define SPINE_ATTACHMENTLOADER_H_
#include <spine/Attachment.h>
#ifdef __cplusplus
namespace spine {
extern "C" {
#endif
typedef struct AttachmentLoader AttachmentLoader;
struct AttachmentLoader {
const char* error1;
const char* error2;
Attachment* (*_newAttachment) (AttachmentLoader* loader, AttachmentType type, const char* name);
void (*_dispose) (AttachmentLoader* loader);
};
void AttachmentLoader_dispose (AttachmentLoader* loader);
Attachment* AttachmentLoader_newAttachment (AttachmentLoader* loader, AttachmentType type, const char* name);
#ifdef __cplusplus
}
}
#endif
#endif /* SPINE_ATTACHMENTLOADER_H_ */

View File

@ -24,7 +24,7 @@ struct Bone {
void Bone_setYDown (int/*bool*/yDown);
/** @param parent May be zero. */
/* @param parent May be zero. */
Bone* Bone_create (BoneData* data, Bone* parent);
void Bone_dispose (Bone* bone);

View File

@ -1,11 +1,16 @@
#include <spine/RegionAttachment.h>
#include <math.h>
#include <spine/util.h>
#include <spine/extension.h>
void _RegionAttachment_init (RegionAttachment* this, const char* name) {
Attachment_init(&this->super, name);
this->scaleX = 1;
this->scaleY = 1;
_Attachment_init(&this->super, name, ATTACHMENT_REGION);
}
void _RegionAttachment_deinit (RegionAttachment* this) {
_Attachment_deinit(&this->super);
}
void RegionAttachment_updateOffset (RegionAttachment* this) {
@ -18,16 +23,16 @@ void RegionAttachment_updateOffset (RegionAttachment* this) {
localX2 *= this->scaleX;
localY2 *= this->scaleY;
float radians = (float)(this->rotation * 3.1415926535897932385 / 180);
float cos = cosf(radians);
float sin = sinf(radians);
float localXCos = localX * cos + this->x;
float localXSin = localX * sin;
float localYCos = localY * cos + this->y;
float localYSin = localY * sin;
float localX2Cos = localX2 * cos + this->x;
float localX2Sin = localX2 * sin;
float localY2Cos = localY2 * cos + this->y;
float localY2Sin = localY2 * sin;
float cosine = cos(radians);
float sine = sin(radians);
float localXCos = localX * cosine + this->x;
float localXSin = localX * sine;
float localYCos = localY * cosine + this->y;
float localYSin = localY * sine;
float localX2Cos = localX2 * cosine + this->x;
float localX2Sin = localX2 * sine;
float localY2Cos = localY2 * cosine + this->y;
float localY2Sin = localY2 * sine;
this->offset[0] = localXCos - localYSin;
this->offset[1] = localYCos + localXSin;
this->offset[2] = localXCos - localY2Sin;

View File

@ -2,6 +2,7 @@
#define SPINE_REGIONATTACHMENT_H_
#include <spine/Attachment.h>
#include <spine/Atlas.h>
#ifdef __cplusplus
namespace spine {
@ -17,6 +18,8 @@ struct RegionAttachment {
void RegionAttachment_updateOffset (RegionAttachment* attachment);
RegionAttachment* RegionAttachment_create (const char* name, AtlasRegion* region);
#ifdef __cplusplus
}
}

View File

@ -43,9 +43,7 @@ void _Skeleton_init (Skeleton* this, SkeletonData* data) {
memcpy(this->drawOrder, this->slots, sizeof(Slot*) * this->slotCount);
}
void Skeleton_dispose (Skeleton* this) {
if (this->_dispose) this->_dispose(this);
void _Skeleton_deinit (Skeleton* this) {
int i;
for (i = 0; i < this->boneCount; ++i)
Bone_dispose(this->bones[i]);
@ -56,8 +54,10 @@ void Skeleton_dispose (Skeleton* this) {
FREE(this->slots)
FREE(this->drawOrder)
}
FREE(this)
void Skeleton_dispose (Skeleton* this) {
this->_dispose(this);
}
void Skeleton_updateWorldTransform (const Skeleton* this) {

View File

@ -29,6 +29,7 @@ struct Skeleton {
void (*_dispose) (Skeleton* skeleton);
};
Skeleton* Skeleton_create (SkeletonData* data);
void Skeleton_dispose (Skeleton* skeleton);
void Skeleton_updateWorldTransform (const Skeleton* skeleton);
@ -38,26 +39,26 @@ void Skeleton_setBonesToBindPose (const Skeleton* skeleton);
void Skeleton_setSlotsToBindPose (const Skeleton* skeleton);
Bone* Skeleton_getRootBone (const Skeleton* skeleton);
/** Returns 0 if the bone could not be found. */
/* Returns 0 if the bone could not be found. */
Bone* Skeleton_findBone (const Skeleton* skeleton, const char* boneName);
/** Returns -1 if the bone could not be found. */
/* Returns -1 if the bone could not be found. */
int Skeleton_findBoneIndex (const Skeleton* skeleton, const char* boneName);
/** Returns 0 if the slot could not be found. */
/* Returns 0 if the slot could not be found. */
Slot* Skeleton_findSlot (const Skeleton* skeleton, const char* slotName);
/** Returns -1 if the slot could not be found. */
/* Returns -1 if the slot could not be found. */
int Skeleton_findSlotIndex (const Skeleton* skeleton, const char* slotName);
/** Returns 0 if the skin could not be found. */
/* Returns 0 if the skin could not be found. */
int Skeleton_setSkinByName (Skeleton* skeleton, const char* skinName);
/** @param skin May be 0.*/
/* @param skin May be 0.*/
void Skeleton_setSkin (Skeleton* skeleton, Skin* skin);
/** Returns 0 if the slot or attachment could not be found. */
/* Returns 0 if the slot or attachment could not be found. */
Attachment* Skeleton_getAttachmentForSlotName (const Skeleton* skeleton, const char* slotName, const char* attachmentName);
/** Returns 0 if the slot or attachment could not be found. */
/* Returns 0 if the slot or attachment could not be found. */
Attachment* Skeleton_getAttachmentForSlotIndex (const Skeleton* skeleton, int slotIndex, const char* attachmentName);
/** Returns 0 if the slot or attachment could not be found. */
/* Returns 0 if the slot or attachment could not be found. */
int Skeleton_setAttachment (Skeleton* skeleton, const char* slotName, const char* attachmentName);
void Skeleton_update (Skeleton* skeleton, float deltaTime);

View File

@ -1,33 +1,47 @@
#include <spine/SkeletonJson.h>
#include <math.h>
#include <stdio.h>
#include <spine/util.h>
#include <spine/cJSON.h>
#include <spine/RegionAttachment.h>
#include <spine/AtlasAttachmentLoader.h>
#include <stdio.h>
typedef struct {
SkeletonJson json;
int ownsLoader;
} Private;
static float scale;
static const char* error;
void SkeletonJson_setScale (float value) {
scale = value;
SkeletonJson* SkeletonJson_createWithLoader (AttachmentLoader* attachmentLoader) {
SkeletonJson* this = calloc(1, sizeof(Private));
this->scale = 1;
this->attachmentLoader = attachmentLoader;
return this;
}
void* SkeletonJson_setError (cJSON* root, const char* value1, const char* value2) {
FREE(error)
SkeletonJson* SkeletonJson_create (Atlas* atlas) {
AtlasAttachmentLoader* attachmentLoader = AtlasAttachmentLoader_create(atlas);
Private* this = (Private*)SkeletonJson_createWithLoader(&attachmentLoader->super);
this->ownsLoader = 1;
return &this->json;
}
void SkeletonJson_dispose (SkeletonJson* this) {
if (((Private*)this)->ownsLoader) AttachmentLoader_dispose(this->attachmentLoader);
FREE(this->error)
FREE(this)
}
void* _SkeletonJson_setError (SkeletonJson* this, cJSON* root, const char* value1, const char* value2) {
FREE(this->error)
char message[256];
strcpy(message, value1);
int length = strlen(value1);
if (value2) strncat(message + length, value2, 256 - length);
MALLOC_STR(error, message)
MALLOC_STR(this->error, message)
if (root) cJSON_dispose(root);
return 0;
}
const char* SkeletonJson_getError () {
return error;
}
static float toColor (const char* value, int index) {
if (strlen(value) != 8) return -1;
value += index * 2;
@ -41,20 +55,20 @@ static float toColor (const char* value, int index) {
return color / (float)255;
}
SkeletonData* SkeletonJson_readSkeletonDataFile (const char* path) {
SkeletonData* SkeletonJson_readSkeletonDataFile (SkeletonJson* this, const char* path) {
const char* data = readFile(path);
if (!data) return SkeletonJson_setError(0, "Unable to read file: ", path);
SkeletonData* skeletonData = SkeletonJson_readSkeletonData(data);
if (!data) return _SkeletonJson_setError(this, 0, "Unable to read file: ", path);
SkeletonData* skeletonData = SkeletonJson_readSkeletonData(this, data);
FREE(data)
return skeletonData;
}
SkeletonData* SkeletonJson_readSkeletonData (const char* json) {
FREE(error)
error = 0;
SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* this, const char* json) {
FREE(this->error)
CAST(char*, this->error) = 0;
cJSON* root = cJSON_Parse(json);
if (!root) return SkeletonJson_setError(0, "Invalid JSON: ", cJSON_GetErrorPtr());
if (!root) return _SkeletonJson_setError(this, 0, "Invalid JSON: ", cJSON_GetErrorPtr());
SkeletonData* skeletonData = SkeletonData_create();
int i, ii, iii;
@ -71,13 +85,13 @@ SkeletonData* SkeletonJson_readSkeletonData (const char* json) {
const char* parentName = cJSON_GetObjectString(boneMap, "parent", 0);
if (parentName) {
parent = SkeletonData_findBone(skeletonData, parentName);
if (!parent) return SkeletonJson_setError(root, "Parent bone not found: ", parentName);
if (!parent) return _SkeletonJson_setError(this, root, "Parent bone not found: ", parentName);
}
BoneData* boneData = BoneData_create(boneName, parent);
boneData->length = cJSON_GetObjectFloat(boneMap, "parent", 0) * scale;
boneData->x = cJSON_GetObjectFloat(boneMap, "x", 0) * scale;
boneData->y = cJSON_GetObjectFloat(boneMap, "y", 0) * scale;
boneData->length = cJSON_GetObjectFloat(boneMap, "parent", 0) * this->scale;
boneData->x = cJSON_GetObjectFloat(boneMap, "x", 0) * this->scale;
boneData->y = cJSON_GetObjectFloat(boneMap, "y", 0) * this->scale;
boneData->rotation = cJSON_GetObjectFloat(boneMap, "rotation", 0);
boneData->scaleX = cJSON_GetObjectFloat(boneMap, "scaleX", 1);
boneData->scaleY = cJSON_GetObjectFloat(boneMap, "scaleY", 1);
@ -97,7 +111,7 @@ SkeletonData* SkeletonJson_readSkeletonData (const char* json) {
const char* boneName = cJSON_GetObjectString(slotMap, "bone", 0);
BoneData* boneData = SkeletonData_findBone(skeletonData, boneName);
if (!boneData) return SkeletonJson_setError(root, "Slot bone not found: ", boneName);
if (!boneData) return _SkeletonJson_setError(this, root, "Slot bone not found: ", boneName);
SlotData* slotData = SlotData_create(slotName, boneData);
@ -138,7 +152,8 @@ SkeletonData* SkeletonJson_readSkeletonData (const char* json) {
int attachmentCount = cJSON_GetArraySize(attachmentsMap);
for (iii = 0; iii < attachmentCount; ++iii) {
cJSON* attachmentMap = cJSON_GetArrayItem(attachmentsMap, iii);
const char* attachmentName = attachmentMap->name;
const char* skinAttachmentName = attachmentMap->name;
const char* attachmentName = cJSON_GetObjectString(attachmentMap, "name", skinAttachmentName);
const char* typeString = cJSON_GetObjectString(attachmentMap, "type", "region");
AttachmentType type;
@ -147,24 +162,25 @@ SkeletonData* SkeletonJson_readSkeletonData (const char* json) {
else if (strcmp(typeString, "regionSequence") == 0)
type = ATTACHMENT_REGION_SEQUENCE;
else
return SkeletonJson_setError(root, "Unknown attachment type: ", typeString);
return _SkeletonJson_setError(this, root, "Unknown attachment type: ", typeString);
Attachment* attachment = Attachment_getAttachmentLoader()(type,
cJSON_GetObjectString(attachmentMap, "name", attachmentName));
Attachment* attachment = AttachmentLoader_newAttachment(this->attachmentLoader, type, attachmentName);
if (!attachment && this->attachmentLoader->error1)
return _SkeletonJson_setError(this, root, this->attachmentLoader->error1, this->attachmentLoader->error2);
if (type == ATTACHMENT_REGION || type == ATTACHMENT_REGION_SEQUENCE) {
if (attachment->type == ATTACHMENT_REGION || attachment->type == ATTACHMENT_REGION_SEQUENCE) {
RegionAttachment* regionAttachment = (RegionAttachment*)attachment;
regionAttachment->x = cJSON_GetObjectFloat(attachmentMap, "x", 0) * scale;
regionAttachment->y = cJSON_GetObjectFloat(attachmentMap, "y", 0) * scale;
regionAttachment->x = cJSON_GetObjectFloat(attachmentMap, "x", 0) * this->scale;
regionAttachment->y = cJSON_GetObjectFloat(attachmentMap, "y", 0) * this->scale;
regionAttachment->scaleX = cJSON_GetObjectFloat(attachmentMap, "scaleX", 1);
regionAttachment->scaleY = cJSON_GetObjectFloat(attachmentMap, "scaleY", 1);
regionAttachment->rotation = cJSON_GetObjectFloat(attachmentMap, "rotation", 0);
regionAttachment->width = cJSON_GetObjectFloat(attachmentMap, "width", 32) * scale;
regionAttachment->height = cJSON_GetObjectFloat(attachmentMap, "height", 32) * scale;
regionAttachment->width = cJSON_GetObjectFloat(attachmentMap, "width", 32) * this->scale;
regionAttachment->height = cJSON_GetObjectFloat(attachmentMap, "height", 32) * this->scale;
RegionAttachment_updateOffset(regionAttachment);
}
Skin_addAttachment(skin, slotIndex, attachmentName, attachment);
Skin_addAttachment(skin, slotIndex, skinAttachmentName, attachment);
}
}
}

View File

@ -2,21 +2,29 @@
#define SPINE_SKELETONJSON_H_
#include <spine/Attachment.h>
#include <spine/AttachmentLoader.h>
#include <spine/SkeletonData.h>
#include <spine/Atlas.h>
#ifdef __cplusplus
namespace spine {
extern "C" {
#endif
void SkeletonJson_setScale (float scale);
typedef struct {
float scale;
AttachmentLoader* attachmentLoader;
const char* const error;
} SkeletonJson;
SkeletonData* SkeletonJson_readSkeletonData (const char* json);
SkeletonData* SkeletonJson_readSkeletonDataFile (const char* path);
SkeletonJson* SkeletonJson_createWithLoader (AttachmentLoader* attachmentLoader);
SkeletonJson* SkeletonJson_create (Atlas* atlas);
void SkeletonJson_dispose (SkeletonJson* skeletonJson);
/* Animation* readAnimation (char* json, const SkeletonData *skeletonData) const; */
SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* skeletonJson, const char* json);
SkeletonData* SkeletonJson_readSkeletonDataFile (SkeletonJson* skeletonJson, const char* path);
const char* SkeletonJson_getError ();
/* Animation* SkeletonJson_readAnimation (SkeletonJson* skeletonJson, char* json, const SkeletonData *skeletonData); */
#ifdef __cplusplus
}

View File

@ -34,7 +34,7 @@ void Skin_addAttachment (Skin* this, int slotIndex, const char* name, Attachment
SkinEntry* newEntry = _SkinEntry_create(slotIndex, name, attachment);
SkinEntry* entry = (SkinEntry*)this->entries;
if (!entry)
entry = newEntry;
CAST(SkinEntry*, this->entries) = newEntry;
else {
while (entry->next)
entry = (SkinEntry*)entry->next;

View File

@ -24,9 +24,9 @@ typedef struct {
Skin* Skin_create (const char* name);
void Skin_dispose (Skin* skin);
/** The Skin owns the attachment. */
/* The Skin owns the attachment. */
void Skin_addAttachment (Skin* skin, int slotIndex, const char* name, Attachment* attachment);
/** May return null. */
/* May return null. */
Attachment* Skin_getAttachment (const Skin* skin, int slotIndex, const char* name);
#ifdef __cplusplus

View File

@ -24,7 +24,7 @@ void Slot_dispose (Slot* this) {
FREE(this);
}
/** @param attachment May be null. */
/* @param attachment May be null. */
void Slot_setAttachment (Slot* this, Attachment* attachment) {
CAST(Attachment*, this->attachment) = attachment;
((Private*)this)->attachmentTime = this->skeleton->time;

View File

@ -23,7 +23,7 @@ typedef struct {
Slot* Slot_create (SlotData* data, struct Skeleton* skeleton, Bone* bone);
void Slot_dispose (Slot* slot);
/** @param attachment May be null. */
/* @param attachment May be null. */
void Slot_setAttachment (Slot* slot, Attachment* attachment);
void Slot_setAttachmentTime (Slot* slot, float time);

View File

@ -18,7 +18,7 @@ typedef struct {
SlotData* SlotData_create (const char* name, BoneData* boneData);
void SlotData_dispose (SlotData* slotData);
/** @param attachmentName May be zero. */
/* @param attachmentName May be zero. */
void SlotData_setAttachmentName (SlotData* slotData, const char* attachmentName);
#ifdef __cplusplus

View File

@ -48,9 +48,7 @@ static int cJSON_strcasecmp (const char* s1, const char* s2) {
/* Internal constructor. */
static cJSON *cJSON_create_Item (void) {
cJSON* node = (cJSON*)malloc(sizeof(cJSON));
if (node) memset(node, 0, sizeof(cJSON));
return node;
return (cJSON*)calloc(1, sizeof(cJSON));
}
/* Delete a cJSON structure. */

View File

@ -0,0 +1,52 @@
#ifndef SPINE_EXTENSION_H_
#define SPINE_EXTENSION_H_
#ifdef __cplusplus
namespace spine {
extern "C" {
#endif
#include <spine/Skeleton.h>
#include <spine/RegionAttachment.h>
#include <spine/Animation.h>
#include <spine/Atlas.h>
#include <spine/AttachmentLoader.h>
/* Methods that must be implemented: **/
Skeleton* Skeleton_create (SkeletonData* data);
RegionAttachment* RegionAttachment_create (const char* name, AtlasRegion* region);
AtlasPage* AtlasPage_create (const char* name);
/* Internal methods needed for extension: **/
void _Skeleton_init (Skeleton* skeleton, SkeletonData* data);
void _Skeleton_deinit (Skeleton* skeleton);
void _Attachment_init (Attachment* attachment, const char* name, AttachmentType type);
void _Attachment_deinit (Attachment* attachment);
void _RegionAttachment_init (RegionAttachment* attachment, const char* name);
void _RegionAttachment_deinit (RegionAttachment* attachment);
void _Timeline_init (Timeline* timeline);
void _Timeline_deinit (Timeline* timeline);
void _CurveTimeline_init (CurveTimeline* timeline, int frameCount);
void _CurveTimeline_deinit (CurveTimeline* timeline);
void _AtlasPage_init (AtlasPage* page, const char* name);
void _AtlasPage_deinit (AtlasPage* page);
void _AttachmentLoader_init (AttachmentLoader* loader);
void _AttachmentLoader_deinit (AttachmentLoader* loader);
void* _AttachmentLoader_setError (AttachmentLoader* loader, const char* error1, const char* error2);
#ifdef __cplusplus
}
}
#endif
#endif /* SPINE_EXTENSION_H_ */

View File

@ -4,7 +4,7 @@
#include <stdlib.h>
#include <string.h>
/** Used to cast away const on an lvalue. */
/* Used to cast away const on an lvalue. */
#define CAST(TYPE,VALUE) *(TYPE*)&VALUE
#define MALLOC_STR(TO,FROM) strcpy(CAST(char*, TO) = malloc(strlen(FROM)), FROM);