Added Atlas.

Compiles with C89.
Minor refactoring.
This commit is contained in:
NathanSweet 2013-03-29 00:26:51 +01:00
parent 146a456beb
commit de53ad3f4f
17 changed files with 340 additions and 36 deletions

View File

@ -35,6 +35,7 @@
<option id="gnu.c.compiler.option.include.paths.2051361089" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath"> <option id="gnu.c.compiler.option.include.paths.2051361089" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" valueType="includePath">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/src}&quot;"/> <listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/src}&quot;"/>
</option> </option>
<option id="gnu.c.compiler.option.misc.other.1829716988" superClass="gnu.c.compiler.option.misc.other" value="-c -fmessage-length=0 -std=c89" valueType="string"/>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.603555848" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.603555848" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
</tool> </tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.debug.1030541714" name="MinGW C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.debug"/> <tool id="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.debug.1030541714" name="MinGW C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.mingw.exe.debug"/>

View File

@ -2,7 +2,7 @@
#include <stdlib.h> #include <stdlib.h>
void SfmlSkeleton_dispose (Skeleton* skeleton) { void SfmlSkeleton_dispose (Skeleton* skeleton) {
// SfmlSkeleton* this = (SfmlSkeleton*)skeleton; /* SfmlSkeleton* this = (SfmlSkeleton*)skeleton; */
} }
Skeleton* Skeleton_create (SkeletonData* data) { Skeleton* Skeleton_create (SkeletonData* data) {

View File

@ -4,24 +4,27 @@
#include <spine/spine.h> #include <spine/spine.h>
#include "SfmlSkeleton.h" #include "SfmlSkeleton.h"
#include "SfmlRegionAttachment.h"
#include "spine/cJSON.h" #include "spine/cJSON.h"
Attachment* loadAttachment (AttachmentType type, const char* name) {
return (Attachment*)SfmlRegionAttachment_create(name);
}
int main (void) { int main (void) {
//BoneData *boneData = BoneData_create("meow"); Attachment_setAttachmentLoader(loadAttachment);
//printf("name: %s\n", boneData->name);
//printf("length struct: %f\n", boneData->length);
//SkeletonData* data =
SkeletonJson_readSkeletonDataFile("data/spineboy-skeleton.json"); SkeletonJson_readSkeletonDataFile("data/spineboy-skeleton.json");
printf("error: %s\n", SkeletonJson_getError()); if (SkeletonJson_getError()) printf("error: %s\n", SkeletonJson_getError());
SkeletonData *skeletonData = SkeletonData_create(); SkeletonData *skeletonData = SkeletonData_create();
Skeleton* skeleton = Skeleton_create(skeletonData); Skeleton* skeleton = Skeleton_create(skeletonData);
//Skeleton_something(skeleton);
printf("meow? %d\n", ((SfmlSkeleton*)skeleton)->meow); printf("meow? %d\n", ((SfmlSkeleton*)skeleton)->meow);
Skeleton_dispose(skeleton); Skeleton_dispose(skeleton);
printf("meow? %d\n", ((SfmlSkeleton*)skeleton)->meow); printf("meow? %d\n", ((SfmlSkeleton*)skeleton)->meow);
Atlas* atlas = Atlas_readAtlasFile("data/spineboy.atlas");
printf("%s %d", atlas->regions->name, atlas->regions->y);
return 0; return 0;
} }

232
spine-c/src/spine/Atlas.c Normal file
View File

@ -0,0 +1,232 @@
#include <spine/Atlas.h>
#include <ctype.h>
#include <spine/util.h>
AtlasPage* AtlasPage_create () {
AtlasPage* this = calloc(1, sizeof(AtlasPage));
return this;
}
/**/
AtlasRegion* AtlasRegion_create () {
AtlasRegion* this = calloc(1, sizeof(AtlasRegion));
return this;
}
/**/
typedef struct {
const char* begin;
const char* end;
} Str;
static void trim (Str* str) {
while (isspace(*str->begin) && str->begin < str->end)
(str->begin)++;
if (str->begin == str->end) return;
str->end--;
while (isspace(*str->end) && str->end >= str->begin)
str->end--;
str->end++;
}
/** Tokenize string without modification. Returns 0 on failure. */
static int readLine (const char* data, Str* str) {
static const char* nextStart;
if (data) {
nextStart = data;
return 1;
}
if (*nextStart == '\0') return 0;
str->begin = nextStart;
/* Find next delimiter. */
do {
nextStart++;
} while (*nextStart != '\0' && *nextStart != '\n');
str->end = nextStart;
trim(str);
if (*nextStart != '\0') nextStart++;
return 1;
}
/** 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) {
char lastSkippedChar = *begin;
if (begin == str->end) return 0;
begin++;
if (lastSkippedChar == c) break;
}
str->begin = begin;
return 1;
}
/* Returns 0 on failure. */
static int readValue (Str* str) {
readLine(0, str);
if (!beginPast(str, ':')) return 0;
trim(str);
return 1;
}
/** Returns the number of tuple values read (2, 4, or 0 for failure). */
static int readTuple (Str tuple[]) {
Str str;
readLine(0, &str);
if (!beginPast(&str, ':')) return 0;
int i = 0;
for (i = 0; i < 3; i++) {
tuple[i].begin = str.begin;
if (!beginPast(&str, ',')) {
if (i == 0) return 0;
break;
}
tuple[i].end = str.begin - 2;
trim(&tuple[i]);
}
tuple[i].begin = str.begin;
tuple[i].end = str.end;
trim(&tuple[i]);
return i + 1;
}
static char* mallocString (Str* str) {
int length = str->end - str->begin;
char* string = malloc(length + 1);
memcpy(string, str->begin, length);
string[length] = '\0';
return string;
}
static int indexOf (const char** array, int count, Str* str) {
int length = str->end - str->begin;
int i;
for (i = count - 1; i >= 0; i--)
if (strncmp(array[i], str->begin, length) == 0) return i;
return -1;
}
static int equals (Str* str, char* other) {
return strncmp(other, str->begin, str->end - str->begin) == 0;
}
static int toInt (Str* str) {
return strtol(str->begin, (char**)&str->end, 10);
}
static const char* formatNames[] = {"Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888", "RGBA8888"};
static const char* textureFilterNames[] = {"Nearest", "Linear", "MipMap", "MipMapNearestNearest", "MipMapLinearNearest",
"MipMapNearestLinear", "MipMapLinearLinear"};
Atlas* Atlas_readAtlas (const char* data) {
Atlas* this = calloc(1, sizeof(Atlas));
AtlasPage *page = 0;
AtlasPage *lastPage = 0;
AtlasRegion *lastRegion = 0;
Str str;
Str tuple[4];
readLine(data, 0);
while (readLine(0, &str)) {
if (str.end - str.begin == 0) {
page = 0;
} else if (!page) {
page = AtlasPage_create();
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);
if (!readTuple(tuple)) return 0;
page->minFilter = (AtlasFilter)indexOf(textureFilterNames, 7, tuple);
page->magFilter = (AtlasFilter)indexOf(textureFilterNames, 7, tuple + 1);
if (!readValue(&str)) return 0;
if (!equals(&str, "none")) {
page->uWrap = *str.begin == 'x' ? ATLAS_REPEAT : (*str.begin == 'y' ? ATLAS_CLAMPTOEDGE : ATLAS_REPEAT);
page->vWrap = *str.begin == 'x' ? ATLAS_CLAMPTOEDGE : (*str.begin == 'y' ? ATLAS_REPEAT : ATLAS_REPEAT);
}
} else {
AtlasRegion *region = AtlasRegion_create();
if (lastRegion)
lastRegion->next = region;
else
this->regions = region;
lastRegion = region;
region->page = page;
region->name = mallocString(&str);
if (!readValue(&str)) return 0;
region->rotate = equals(&str, "true");
if (readTuple(tuple) != 2) return 0;
region->x = toInt(tuple);
region->y = toInt(tuple + 1);
if (readTuple(tuple) != 2) return 0;
region->width = toInt(tuple);
region->height = toInt(tuple + 1);
int count;
if (!(count = readTuple(tuple))) return 0;
if (count == 4) { /* split is optional */
region->splits = malloc(sizeof(int) * 4);
region->splits[0] = toInt(tuple);
region->splits[1] = toInt(tuple + 1);
region->splits[2] = toInt(tuple + 2);
region->splits[3] = toInt(tuple + 3);
if (!(count = readTuple(tuple))) return 0;
if (count == 4) { /* pad is optional, but only present with splits */
region->pads = malloc(sizeof(int) * 4);
region->pads[0] = toInt(tuple);
region->pads[1] = toInt(tuple + 1);
region->pads[2] = toInt(tuple + 2);
region->pads[3] = toInt(tuple + 3);
if (!readTuple(tuple)) return 0;
}
}
region->originalWidth = toInt(tuple);
region->originalHeight = toInt(tuple + 1);
readTuple(tuple);
region->offsetX = (float)toInt(tuple);
region->offsetY = (float)toInt(tuple + 1);
if (!readValue(&str)) return 0;
region->index = toInt(&str);
}
}
return this;
}
Atlas* Atlas_readAtlasFile (const char* path) {
const char* data = readFile(path);
if (!data) return 0;
Atlas* atlas = Atlas_readAtlas(data);
FREE(data)
return atlas;
}
void Atlas_dispose (Atlas* this) {
FREE(this)
}
AtlasRegion* Atlas_findRegion (Atlas* atlas, const char* name) {
return 0;
}

67
spine-c/src/spine/Atlas.h Normal file
View File

@ -0,0 +1,67 @@
#ifndef SPINE_ATLAS_H_
#define SPINE_ATLAS_H_
#ifdef __cplusplus
namespace spine {
extern "C" {
#endif
typedef enum {
ATLAS_ALPHA, ATLAS_INTENSITY, ATLAS_LUMINANCEALPHA, ATLAS_RGB565, ATLAS_RGBA4444, ATLAS_RGB888, ATLAS_RGBA8888
} AtlasFormat;
typedef enum {
ATLAS_NEAREST,
ATLAS_LINEAR,
ATLAS_MIPMAP,
ATLAS_MIPMAPNEARESTNEAREST,
ATLAS_MIPMAPLINEARNEAREST,
ATLAS_MIPMAPNEARESTLINEAR,
ATLAS_MIPMAPLINEARLINEAR
} AtlasFilter;
typedef enum {
ATLAS_MIRROREDREPEAT, ATLAS_CLAMPTOEDGE, ATLAS_REPEAT
} AtlasWrap;
typedef struct AtlasPage AtlasPage;
struct AtlasPage {
const char* name;
AtlasFormat format;
AtlasFilter minFilter, magFilter;
AtlasWrap uWrap, vWrap;
AtlasPage* next;
};
typedef struct AtlasRegion AtlasRegion;
struct AtlasRegion {
const char* name;
int x, y, width, height;
float offsetX, offsetY;
int originalWidth, originalHeight;
int index;
int/*bool*/rotate;
int/*bool*/flip;
int* splits;
int* pads;
AtlasPage* page;
AtlasRegion* next;
};
typedef struct {
AtlasPage* pages;
AtlasRegion* regions;
} Atlas;
Atlas* Atlas_readAtlas (const char* data);
Atlas* Atlas_readAtlasFile (const char* path);
void Atlas_dispose (Atlas* atlas);
AtlasRegion* Atlas_findRegion (Atlas* atlas, const char* name);
#ifdef __cplusplus
}
}
#endif
#endif /* SPINE_ATLAS_H_ */

View File

@ -16,13 +16,13 @@ struct Bone {
float rotation; float rotation;
float scaleX, scaleY; float scaleX, scaleY;
float const m00, m01, worldX; // a b x float const m00, m01, worldX; /* a b x */
float const m10, m11, worldY; // c d y float const m10, m11, worldY; /* c d y */
float const worldRotation; float const worldRotation;
float const worldScaleX, worldScaleY; float const worldScaleX, worldScaleY;
}; };
void Bone_setYDown (int yDown); void Bone_setYDown (int/*bool*/yDown);
/** @param parent May be zero. */ /** @param parent May be zero. */
Bone* Bone_create (BoneData* data, Bone* parent); Bone* Bone_create (BoneData* data, Bone* parent);
@ -30,7 +30,7 @@ void Bone_dispose (Bone* bone);
void Bone_setToBindPose (Bone* bone); void Bone_setToBindPose (Bone* bone);
void Bone_updateWorldTransform (Bone* bone, int flipX, int flipY); void Bone_updateWorldTransform (Bone* bone, int/*bool*/flipX, int/*bool*/flipY);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -15,7 +15,7 @@ struct RegionAttachment {
float offset[8]; float offset[8];
}; };
void RegionAttachment_init (RegionAttachment* this, const char* name); void RegionAttachment_init (RegionAttachment* attachment, const char* name);
void RegionAttachment_dispose (RegionAttachment* attachment); void RegionAttachment_dispose (RegionAttachment* attachment);
void RegionAttachment_updateOffset (RegionAttachment* attachment); void RegionAttachment_updateOffset (RegionAttachment* attachment);

View File

@ -11,7 +11,7 @@ void Skeleton_init (Skeleton* this, SkeletonData* data) {
BoneData* boneData = this->data->bones[i]; BoneData* boneData = this->data->bones[i];
Bone* parent = 0; Bone* parent = 0;
if (boneData->parent) { if (boneData->parent) {
// Find parent bone. /* Find parent bone. */
for (ii = 0; ii < this->boneCount; ++ii) { for (ii = 0; ii < this->boneCount; ++ii) {
if (data->bones[ii] == boneData->parent) { if (data->bones[ii] == boneData->parent) {
parent = this->bones[ii]; parent = this->bones[ii];
@ -27,7 +27,7 @@ void Skeleton_init (Skeleton* this, SkeletonData* data) {
for (i = 0; i < this->slotCount; ++i) { for (i = 0; i < this->slotCount; ++i) {
SlotData *slotData = data->slots[i]; SlotData *slotData = data->slots[i];
// Find bone for the slotData's boneData. /* Find bone for the slotData's boneData. */
Bone *bone; Bone *bone;
for (ii = 0; ii < this->boneCount; ++ii) { for (ii = 0; ii < this->boneCount; ++ii) {
if (data->bones[ii] == slotData->boneData) { if (data->bones[ii] == slotData->boneData) {
@ -51,9 +51,9 @@ void Skeleton_dispose (Skeleton* this) {
Bone_dispose(this->bones[i]); Bone_dispose(this->bones[i]);
FREE(this->bones) FREE(this->bones)
FREE(this->slots)
for (i = 0; i < this->slotCount; ++i) for (i = 0; i < this->slotCount; ++i)
Slot_dispose(this->slots[i]); Slot_dispose(this->slots[i]);
FREE(this->slots)
FREE(this->drawOrder) FREE(this->drawOrder)
@ -125,8 +125,8 @@ int Skeleton_setSkinByName (Skeleton* this, const char* skinName) {
void Skeleton_setSkin (Skeleton* this, Skin* newSkin) { void Skeleton_setSkin (Skeleton* this, Skin* newSkin) {
if (this->skin && newSkin) { if (this->skin && newSkin) {
// Attach each attachment in the new skin if the corresponding attachment in the old skin is currently attached. /* Attach each attachment in the new skin if the corresponding attachment in the old skin is currently attached. */
const SkinEntry *entry = this->skin->entryList; const SkinEntry *entry = this->skin->entries;
while (entry) { while (entry) {
Slot *slot = this->slots[entry->slotIndex]; Slot *slot = this->slots[entry->slotIndex];
if (slot->attachment == entry->attachment) { if (slot->attachment == entry->attachment) {

View File

@ -24,7 +24,7 @@ struct Skeleton {
Skin* const skin; Skin* const skin;
float r, g, b, a; float r, g, b, a;
float time; float time;
int flipX, flipY; int/*bool*/flipX, flipY;
void (*_dispose) (Skeleton* skeleton); void (*_dispose) (Skeleton* skeleton);
}; };
@ -57,11 +57,11 @@ 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); 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* this, int slotIndex, const char* attachmentName); 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); int Skeleton_setAttachment (Skeleton* skeleton, const char* slotName, const char* attachmentName);
void Skeleton_update (Skeleton* this, float deltaTime); void Skeleton_update (Skeleton* skeleton, float deltaTime);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -42,10 +42,10 @@ static float toColor (const char* value, int index) {
} }
SkeletonData* SkeletonJson_readSkeletonDataFile (const char* path) { SkeletonData* SkeletonJson_readSkeletonDataFile (const char* path) {
char* data = readFile(path); const char* data = readFile(path);
if (!data) return SkeletonJson_setError(0, "Unable to read file: ", path); if (!data) return SkeletonJson_setError(0, "Unable to read file: ", path);
SkeletonData* skeletonData = SkeletonJson_readSkeletonData(data); SkeletonData* skeletonData = SkeletonJson_readSkeletonData(data);
free(data); FREE(data)
return skeletonData; return skeletonData;
} }

View File

@ -14,7 +14,7 @@ void SkeletonJson_setScale (float scale);
SkeletonData* SkeletonJson_readSkeletonData (const char* json); SkeletonData* SkeletonJson_readSkeletonData (const char* json);
SkeletonData* SkeletonJson_readSkeletonDataFile (const char* path); SkeletonData* SkeletonJson_readSkeletonDataFile (const char* path);
// Animation* readAnimation (char* json, const SkeletonData *skeletonData) const; /* Animation* readAnimation (char* json, const SkeletonData *skeletonData) const; */
const char* SkeletonJson_getError (); const char* SkeletonJson_getError ();

View File

@ -16,7 +16,7 @@ void SkinEntry_dispose (SkinEntry* entry) {
FREE(entry) FREE(entry)
} }
// /**/
Skin* Skin_create (const char* name) { Skin* Skin_create (const char* name) {
Skin* this = calloc(1, sizeof(Skin)); Skin* this = calloc(1, sizeof(Skin));
@ -25,14 +25,14 @@ Skin* Skin_create (const char* name) {
} }
void Skin_dispose (Skin* this) { void Skin_dispose (Skin* this) {
SkinEntry_dispose((SkinEntry*)this->entryList); SkinEntry_dispose((SkinEntry*)this->entries);
FREE(this->name) FREE(this->name)
FREE(this) FREE(this)
} }
void Skin_addAttachment (Skin* this, int slotIndex, const char* name, Attachment* attachment) { void Skin_addAttachment (Skin* this, int slotIndex, const char* name, Attachment* attachment) {
SkinEntry* newEntry = SkinEntry_create(slotIndex, name, attachment); SkinEntry* newEntry = SkinEntry_create(slotIndex, name, attachment);
SkinEntry* entry = (SkinEntry*)this->entryList; SkinEntry* entry = (SkinEntry*)this->entries;
if (!entry) if (!entry)
entry = newEntry; entry = newEntry;
else { else {
@ -43,7 +43,7 @@ void Skin_addAttachment (Skin* this, int slotIndex, const char* name, Attachment
} }
Attachment* Skin_getAttachment (const Skin* this, int slotIndex, const char* name) { Attachment* Skin_getAttachment (const Skin* this, int slotIndex, const char* name) {
const SkinEntry* entry = this->entryList; const SkinEntry* entry = this->entries;
while (entry) { while (entry) {
if (entry->slotIndex == slotIndex && strcmp(entry->name, name) == 0) return entry->attachment; if (entry->slotIndex == slotIndex && strcmp(entry->name, name) == 0) return entry->attachment;
entry = entry->next; entry = entry->next;

View File

@ -18,7 +18,7 @@ struct SkinEntry {
typedef struct { typedef struct {
const char* const name; const char* const name;
const SkinEntry* const entryList; const SkinEntry* const entries;
} Skin; } Skin;
Skin* Skin_create (const char* name); Skin* Skin_create (const char* name);

View File

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

View File

@ -1,6 +1,7 @@
#ifndef SPINE_SPINE_H_ #ifndef SPINE_SPINE_H_
#define SPINE_SPINE_H_ #define SPINE_SPINE_H_
#include <spine/Atlas.h>
#include <spine/Attachment.h> #include <spine/Attachment.h>
#include <spine/Bone.h> #include <spine/Bone.h>
#include <spine/BoneData.h> #include <spine/BoneData.h>

View File

@ -1,6 +1,7 @@
#include <spine/util.h> #include <spine/util.h>
#include <stdio.h>
char* readFile (const char* path) { const char* readFile (const char* path) {
FILE *file = fopen(path, "rb"); FILE *file = fopen(path, "rb");
if (!file) return 0; if (!file) return 0;
@ -8,8 +9,8 @@ char* readFile (const char* path) {
long length = ftell(file); long length = ftell(file);
fseek(file, 0, SEEK_SET); fseek(file, 0, SEEK_SET);
char* data = (char*)malloc(sizeof(char) * length + 1); char* data = (char*)malloc(length + 1);
fread(data, sizeof(char), length, file); fread(data, 1, length, file);
fclose(file); fclose(file);
data[length] = '\0'; data[length] = '\0';

View File

@ -1,9 +1,8 @@
#ifndef SPINE_UTIL_H_ #ifndef SPINE_UTIL_H_
#define SPINE_UTIL_H_ #define SPINE_UTIL_H_
#include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.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 CAST(TYPE,VALUE) *(TYPE*)&VALUE
@ -12,6 +11,6 @@
#define FREE(E) free((void*)E); #define FREE(E) free((void*)E);
char* readFile (const char* path); const char* readFile (const char* path);
#endif /* SPINE_UTIL_H_ */ #endif /* SPINE_UTIL_H_ */