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">
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/src}&quot;"/>
</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"/>
</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"/>

View File

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

View File

@ -4,24 +4,27 @@
#include <spine/spine.h>
#include "SfmlSkeleton.h"
#include "SfmlRegionAttachment.h"
#include "spine/cJSON.h"
Attachment* loadAttachment (AttachmentType type, const char* name) {
return (Attachment*)SfmlRegionAttachment_create(name);
}
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");
printf("error: %s\n", SkeletonJson_getError());
if (SkeletonJson_getError()) printf("error: %s\n", SkeletonJson_getError());
SkeletonData *skeletonData = SkeletonData_create();
Skeleton* skeleton = Skeleton_create(skeletonData);
//Skeleton_something(skeleton);
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);
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 scaleX, scaleY;
float const m00, m01, worldX; // a b x
float const m10, m11, worldY; // c d y
float const m00, m01, worldX; /* a b x */
float const m10, m11, worldY; /* c d y */
float const worldRotation;
float const worldScaleX, worldScaleY;
};
void Bone_setYDown (int yDown);
void Bone_setYDown (int/*bool*/yDown);
/** @param parent May be zero. */
Bone* Bone_create (BoneData* data, Bone* parent);
@ -30,7 +30,7 @@ void Bone_dispose (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
}

View File

@ -15,7 +15,7 @@ struct RegionAttachment {
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_updateOffset (RegionAttachment* attachment);

View File

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

View File

@ -24,7 +24,7 @@ struct Skeleton {
Skin* const skin;
float r, g, b, a;
float time;
int flipX, flipY;
int/*bool*/flipX, flipY;
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. */
Attachment* Skeleton_getAttachmentForSlotName (const Skeleton* skeleton, const char* slotName, const char* attachmentName);
/** 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. */
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
}

View File

@ -42,10 +42,10 @@ static float toColor (const char* value, int index) {
}
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);
SkeletonData* skeletonData = SkeletonJson_readSkeletonData(data);
free(data);
FREE(data)
return skeletonData;
}

View File

@ -14,7 +14,7 @@ void SkeletonJson_setScale (float scale);
SkeletonData* SkeletonJson_readSkeletonData (const char* json);
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 ();

View File

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

View File

@ -18,7 +18,7 @@ struct SkinEntry {
typedef struct {
const char* const name;
const SkinEntry* const entryList;
const SkinEntry* const entries;
} Skin;
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);
/** @param attachmentName May be zero. */
void SlotData_setAttachmentName (SlotData* this, const char* attachmentName);
void SlotData_setAttachmentName (SlotData* slotData, const char* attachmentName);
#ifdef __cplusplus
}

View File

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

View File

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

View File

@ -1,9 +1,8 @@
#ifndef SPINE_UTIL_H_
#define SPINE_UTIL_H_
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/** Used to cast away const on an lvalue. */
#define CAST(TYPE,VALUE) *(TYPE*)&VALUE
@ -12,6 +11,6 @@
#define FREE(E) free((void*)E);
char* readFile (const char* path);
const char* readFile (const char* path);
#endif /* SPINE_UTIL_H_ */