diff --git a/spine-c/src/spine/extension.h b/spine-c/include/spine/extension.h similarity index 60% rename from spine-c/src/spine/extension.h rename to spine-c/include/spine/extension.h index 4c84f15fc..b9c92cacb 100644 --- a/spine-c/src/spine/extension.h +++ b/spine-c/include/spine/extension.h @@ -23,22 +23,74 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************/ +/* + Implementation notes: + + - An OOP style is used where each "class" is made up of a struct and a number of functions prefixed with the struct name. + + - struct fields that are const are readonly. Either they are set in a constructor and can never be changed, or they can only be + changed by calling a function. + + - Inheritance is done using a struct field named "super" as the first field, allowing the struct to be cast to its "super class". + + - Classes intended for inheritance provide init/deinit functions which subclasses must call in their new/free functions. + + - Polymorphism is done by a base class providing a "vtable" pointer to a struct containing function pointers. The public API + delegates to the appropriate vtable function. Subclasses may change the vtable pointers. + + - Subclasses do not provide a free function, instead the base class' free function should be used, which will delegate to a free + function in its vtable. + + - Classes not designed for inheritance cannot be extended. They may use an internal subclass to hide private data and don't + expose a vtable. + + - The public API hides implementation details such as vtable structs and init/deinit functions. An internal API is exposed in + extension.h to allow classes to be extended. + + - OOP in C tends to lose type safety. Macros are provided in extension.h to give more context about why a cast is being done. + */ + #ifndef SPINE_EXTENSION_H_ #define SPINE_EXTENSION_H_ +/* All allocation uses these. */ +#define MALLOC(TYPE,COUNT) ((TYPE*)malloc(sizeof(TYPE) * COUNT)) +#define CALLOC(TYPE,COUNT) ((TYPE*)calloc(1, sizeof(TYPE) * COUNT)) +#define NEW(TYPE) CALLOC(TYPE,1) + +/* Gets the direct super class. Type safe. */ +#define SUPER(VALUE) (&VALUE->super) + +/* Cast to a super class. Not type safe, use with care. */ +#define SUPER_CAST(TYPE,VALUE) ((TYPE*)VALUE) + +/* Cast to a sub class. Not type safe, use with care. */ +#define SUB_CAST(TYPE,VALUE) ((TYPE*)VALUE) + +/* Casts away const. Can be used as an lvalue. Not type safe, use with care. */ +#define CONST_CAST(TYPE,VALUE) (*(TYPE*)&VALUE) + +/* Gets the vtable for the specified type. Can be used as an lvalue. */ +#define VTABLE(TYPE,VALUE) ((_##TYPE##Vtable*)((TYPE*)VALUE)->vtable) + +/* Frees memory. Can be used on const. */ +#define FREE(VALUE) free((void*)VALUE) + +#include #include #include #include #include #include -#include #ifdef __cplusplus namespace spine { extern "C" { #endif -/* Public API that must be implemented: **/ +/* + * Public API that must be implemented: + */ Skeleton* Skeleton_new (SkeletonData* data); @@ -46,7 +98,9 @@ RegionAttachment* RegionAttachment_new (const char* name, AtlasRegion* region); AtlasPage* AtlasPage_new (const char* name); -/* Internal API available for extension: **/ +/* + * Internal API available for extension: + */ typedef struct _SkeletonVtable { void (*free) (Skeleton* skeleton); @@ -74,7 +128,7 @@ void _RegionAttachment_deinit (RegionAttachment* attachment); typedef struct _TimelineVtable { void (*apply) (const Timeline* timeline, Skeleton* skeleton, float time, float alpha); - void (*dispose) (Timeline* timeline); + void (*free) (Timeline* timeline); } _TimelineVtable; void _Timeline_init (Timeline* timeline); diff --git a/spine-c/src/spine/Animation.c b/spine-c/src/spine/Animation.c index a50e48462..3ed218609 100644 --- a/spine-c/src/spine/Animation.c +++ b/spine-c/src/spine/Animation.c @@ -26,6 +26,7 @@ #include #include #include +#include Animation* Animation_new (int timelineCount) { Animation* self = NEW(Animation); @@ -69,7 +70,7 @@ void _Timeline_deinit (Timeline* self) { } void Timeline_free (Timeline* self) { - VTABLE(Timeline, self) ->dispose(self); + VTABLE(Timeline, self) ->free(self); } void Timeline_apply (const Timeline* self, Skeleton* skeleton, float time, float alpha) { @@ -190,7 +191,7 @@ void _BaseTimeline_free (Timeline* timeline) { struct BaseTimeline* _BaseTimeline_new (int frameCount, int frameSize) { struct BaseTimeline* self = NEW(struct BaseTimeline); _CurveTimeline_init(SUPER(self), frameCount); - VTABLE(Timeline, self) ->dispose = _BaseTimeline_free; + VTABLE(Timeline, self) ->free = _BaseTimeline_free; CONST_CAST(int, self->framesLength) = frameCount * frameSize; CONST_CAST(float*, self->frames) = CALLOC(float, self->framesLength); @@ -435,7 +436,7 @@ void _AttachmentTimeline_free (Timeline* timeline) { AttachmentTimeline* AttachmentTimeline_new (int frameCount) { AttachmentTimeline* self = NEW(AttachmentTimeline); _Timeline_init(SUPER(self)); - VTABLE(Timeline, self) ->dispose = _AttachmentTimeline_free; + VTABLE(Timeline, self) ->free = _AttachmentTimeline_free; VTABLE(Timeline, self) ->apply = _AttachmentTimeline_apply; CONST_CAST(char**, self->attachmentNames) = CALLOC(char*, frameCount); diff --git a/spine-c/src/spine/Atlas.c b/spine-c/src/spine/Atlas.c index e71c4b1df..f317301db 100644 --- a/spine-c/src/spine/Atlas.c +++ b/spine-c/src/spine/Atlas.c @@ -26,6 +26,7 @@ #include #include #include +#include void _AtlasPage_init (AtlasPage* self, const char* name) { CONST_CAST(_AtlasPageVtable*, self->vtable) = NEW(_AtlasPageVtable); diff --git a/spine-c/src/spine/AtlasAttachmentLoader.c b/spine-c/src/spine/AtlasAttachmentLoader.c index c7b4915da..4c8362578 100644 --- a/spine-c/src/spine/AtlasAttachmentLoader.c +++ b/spine-c/src/spine/AtlasAttachmentLoader.c @@ -24,8 +24,9 @@ ******************************************************************************/ #include -#include #include +#include +#include void _AtlasAttachmentLoader_free (AttachmentLoader* self) { _AttachmentLoader_deinit(self); diff --git a/spine-c/src/spine/Attachment.c b/spine-c/src/spine/Attachment.c index d17e7badb..f2c835a9c 100644 --- a/spine-c/src/spine/Attachment.c +++ b/spine-c/src/spine/Attachment.c @@ -25,6 +25,7 @@ #include #include +#include #include void _Attachment_init (Attachment* self, const char* name, AttachmentType type) { diff --git a/spine-c/src/spine/AttachmentLoader.c b/spine-c/src/spine/AttachmentLoader.c index 3d9759333..9a6e59ba4 100644 --- a/spine-c/src/spine/AttachmentLoader.c +++ b/spine-c/src/spine/AttachmentLoader.c @@ -25,6 +25,7 @@ #include #include +#include void _AttachmentLoader_init (AttachmentLoader* self) { CONST_CAST(_AttachmentLoaderVtable*, self->vtable) = NEW(_AttachmentLoaderVtable); diff --git a/spine-c/src/spine/Bone.c b/spine-c/src/spine/Bone.c index 5c4452bad..997330528 100644 --- a/spine-c/src/spine/Bone.c +++ b/spine-c/src/spine/Bone.c @@ -25,7 +25,7 @@ #include #include -#include +#include static int yDown; diff --git a/spine-c/src/spine/BoneData.c b/spine-c/src/spine/BoneData.c index 4a7f4d45d..ea1732574 100644 --- a/spine-c/src/spine/BoneData.c +++ b/spine-c/src/spine/BoneData.c @@ -24,6 +24,7 @@ ******************************************************************************/ #include +#include #include BoneData* BoneData_new (const char* name, BoneData* parent) { diff --git a/spine-c/src/spine/Skeleton.c b/spine-c/src/spine/Skeleton.c index a1e39cfd9..b94e50318 100644 --- a/spine-c/src/spine/Skeleton.c +++ b/spine-c/src/spine/Skeleton.c @@ -24,6 +24,7 @@ ******************************************************************************/ #include +#include #include void _Skeleton_init (Skeleton* self, SkeletonData* data) { diff --git a/spine-c/src/spine/SkeletonData.c b/spine-c/src/spine/SkeletonData.c index cb3d85e8d..463dff7c5 100644 --- a/spine-c/src/spine/SkeletonData.c +++ b/spine-c/src/spine/SkeletonData.c @@ -24,7 +24,8 @@ ******************************************************************************/ #include -#include +#include +#include SkeletonData* SkeletonData_new () { return NEW(SkeletonData); diff --git a/spine-c/src/spine/SkeletonJson.c b/spine-c/src/spine/SkeletonJson.c index 86078ee29..b96c0fabd 100644 --- a/spine-c/src/spine/SkeletonJson.c +++ b/spine-c/src/spine/SkeletonJson.c @@ -26,8 +26,9 @@ #include #include #include -#include #include +#include +#include #include #include #include diff --git a/spine-c/src/spine/Skin.c b/spine-c/src/spine/Skin.c index 1bc59c5fa..5bace7530 100644 --- a/spine-c/src/spine/Skin.c +++ b/spine-c/src/spine/Skin.c @@ -24,6 +24,7 @@ ******************************************************************************/ #include +#include #include SkinEntry* _SkinEntry_new (int slotIndex, const char* name, Attachment* attachment) { diff --git a/spine-c/src/spine/Slot.c b/spine-c/src/spine/Slot.c index a41da8bb7..c55f88588 100644 --- a/spine-c/src/spine/Slot.c +++ b/spine-c/src/spine/Slot.c @@ -24,7 +24,7 @@ ******************************************************************************/ #include -#include +#include #include typedef struct { diff --git a/spine-c/src/spine/SlotData.c b/spine-c/src/spine/SlotData.c index 1981c25d1..5dc1ef827 100644 --- a/spine-c/src/spine/SlotData.c +++ b/spine-c/src/spine/SlotData.c @@ -24,6 +24,7 @@ ******************************************************************************/ #include +#include #include SlotData* SlotData_new (const char* name, BoneData* boneData) { diff --git a/spine-c/src/spine/util.h b/spine-c/src/spine/util.h index c458ae84e..8c606bf7e 100644 --- a/spine-c/src/spine/util.h +++ b/spine-c/src/spine/util.h @@ -26,40 +26,17 @@ #ifndef SPINE_UTIL_H_ #define SPINE_UTIL_H_ -#include #include +#include #ifdef __cplusplus namespace spine { extern "C" { #endif -/* All allocation uses these. */ -#define MALLOC(TYPE,COUNT) ((TYPE*)malloc(sizeof(TYPE) * COUNT)) -#define CALLOC(TYPE,COUNT) ((TYPE*)calloc(1, sizeof(TYPE) * COUNT)) -#define NEW(TYPE) CALLOC(TYPE,1) - -/* Casts away const. Can be used as an lvalue. Not type safe, use with care. */ -#define CONST_CAST(TYPE,VALUE) (*(TYPE*)&VALUE) - -/* Gets the direct super class. Type safe. */ -#define SUPER(VALUE) (&VALUE->super) - -/* Cast to a super class. Not type safe, use with care. */ -#define SUPER_CAST(TYPE,VALUE) ((TYPE*)VALUE) - -/* Cast to a sub class. Not type safe, use with care. */ -#define SUB_CAST(TYPE,VALUE) ((TYPE*)VALUE) - -/* Gets the vtable for the specified type. Can be used as an lvalue. */ -#define VTABLE(TYPE,VALUE) ((_##TYPE##Vtable*)((TYPE*)VALUE)->vtable) - /* Allocates a new char[], assigns it to TO, and copies FROM to it. Can be used on const. */ #define MALLOC_STR(TO,FROM) strcpy(CONST_CAST(char*, TO) = (char*)malloc(strlen(FROM)), FROM) -/* Frees memory. Can be used on const. */ -#define FREE(VALUE) free((void*)VALUE) - /* Read file at specific path to a new char[]. Return value must be freed. */ const char* readFile (const char* path);