mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2026-02-10 17:18:44 +08:00
Refactored loading files.
This commit is contained in:
parent
ad67dae2e0
commit
6af401e888
@ -92,6 +92,12 @@ RegionAttachment* RegionAttachment_new (const char* name, AtlasRegion* region) {
|
||||
|
||||
/**/
|
||||
|
||||
char* _Util_readFile (const char* path, int* length) {
|
||||
return _readFile(path, length);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
int main (void) {
|
||||
Atlas* atlas = Atlas_readAtlasFile("data/spineboy.atlas");
|
||||
printf("First region name: %s, x: %d, y: %d\n", atlas->regions->name, atlas->regions->x, atlas->regions->y);
|
||||
|
||||
@ -90,7 +90,7 @@ typedef struct {
|
||||
AtlasRegion* regions;
|
||||
} Atlas;
|
||||
|
||||
Atlas* Atlas_readAtlas (const char* data);
|
||||
Atlas* Atlas_readAtlas (const char* data, unsigned long length);
|
||||
Atlas* Atlas_readAtlasFile (const char* path);
|
||||
void Atlas_free (Atlas* atlas);
|
||||
|
||||
|
||||
@ -54,7 +54,6 @@ struct Skeleton {
|
||||
const void* const vtable;
|
||||
};
|
||||
|
||||
Skeleton* Skeleton_new (SkeletonData* data);
|
||||
void Skeleton_free (Skeleton* skeleton);
|
||||
|
||||
void Skeleton_updateWorldTransform (const Skeleton* skeleton);
|
||||
|
||||
@ -76,7 +76,11 @@
|
||||
/* Frees memory. Can be used on const. */
|
||||
#define FREE(VALUE) free((void*)VALUE)
|
||||
|
||||
/* 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)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <spine/Skeleton.h>
|
||||
#include <spine/RegionAttachment.h>
|
||||
#include <spine/Animation.h>
|
||||
@ -89,19 +93,21 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Public API that must be implemented:
|
||||
* Functions that must be implemented:
|
||||
*/
|
||||
|
||||
Skeleton* Skeleton_new (SkeletonData* data);
|
||||
|
||||
RegionAttachment* RegionAttachment_new (const char* name, AtlasRegion* region);
|
||||
|
||||
AtlasPage* AtlasPage_new (const char* name);
|
||||
|
||||
char* _Util_readFile (const char* path, int* length);
|
||||
|
||||
/*
|
||||
* Internal API available for extension:
|
||||
*/
|
||||
|
||||
char* _readFile (const char* path, int* length);
|
||||
|
||||
typedef struct _SkeletonVtable {
|
||||
void (*free) (Skeleton* skeleton);
|
||||
} _SkeletonVtable;
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
#include <spine/Animation.h>
|
||||
#include <math.h>
|
||||
#include <spine/extension.h>
|
||||
#include <spine/util.h>
|
||||
|
||||
Animation* Animation_new (int timelineCount) {
|
||||
Animation* self = NEW(Animation);
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
#include <spine/Atlas.h>
|
||||
#include <ctype.h>
|
||||
#include <spine/extension.h>
|
||||
#include <spine/util.h>
|
||||
|
||||
void _AtlasPage_init (AtlasPage* self, const char* name) {
|
||||
CONST_CAST(_AtlasPageVtable*, self->vtable) = NEW(_AtlasPageVtable);
|
||||
@ -73,24 +72,24 @@ static void trim (Str* str) {
|
||||
}
|
||||
|
||||
/* Tokenize string without modification. Returns 0 on failure. */
|
||||
static int readLine (const char* data, Str* str) {
|
||||
static int readLine (const char* begin, const char* end, Str* str) {
|
||||
static const char* nextStart;
|
||||
if (data) {
|
||||
nextStart = data;
|
||||
if (begin) {
|
||||
nextStart = begin;
|
||||
return 1;
|
||||
}
|
||||
if (*nextStart == '\0') return 0;
|
||||
if (nextStart == end) return 0;
|
||||
str->begin = nextStart;
|
||||
|
||||
/* Find next delimiter. */
|
||||
do {
|
||||
nextStart++;
|
||||
} while (*nextStart != '\0' && *nextStart != '\n');
|
||||
} while (nextStart != end && *nextStart != '\n');
|
||||
|
||||
str->end = nextStart;
|
||||
trim(str);
|
||||
|
||||
if (*nextStart != '\0') nextStart++;
|
||||
if (nextStart != end) nextStart++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -108,17 +107,17 @@ static int beginPast (Str* str, char c) {
|
||||
}
|
||||
|
||||
/* Returns 0 on failure. */
|
||||
static int readValue (Str* str) {
|
||||
readLine(0, str);
|
||||
static int readValue (const char* end, Str* str) {
|
||||
readLine(0, end, 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[]) {
|
||||
static int readTuple (const char* end, Str tuple[]) {
|
||||
Str str;
|
||||
readLine(0, &str);
|
||||
readLine(0, end, &str);
|
||||
if (!beginPast(&str, ':')) return 0;
|
||||
int i = 0;
|
||||
for (i = 0; i < 3; ++i) {
|
||||
@ -160,7 +159,7 @@ static int toInt (Str* str) {
|
||||
return strtol(str->begin, (char**)&str->end, 10);
|
||||
}
|
||||
|
||||
static Atlas* abort (Atlas* self) {
|
||||
static Atlas* abortAtlas (Atlas* self) {
|
||||
Atlas_free(self);
|
||||
return 0;
|
||||
}
|
||||
@ -169,7 +168,9 @@ static const char* formatNames[] = {"Alpha", "Intensity", "LuminanceAlpha", "RGB
|
||||
static const char* textureFilterNames[] = {"Nearest", "Linear", "MipMap", "MipMapNearestNearest", "MipMapLinearNearest",
|
||||
"MipMapNearestLinear", "MipMapLinearLinear"};
|
||||
|
||||
Atlas* Atlas_readAtlas (const char* data) {
|
||||
Atlas* Atlas_readAtlas (const char* begin, unsigned long length) {
|
||||
const char* end = begin + length;
|
||||
|
||||
Atlas* self = NEW(Atlas);
|
||||
|
||||
AtlasPage *page = 0;
|
||||
@ -177,8 +178,8 @@ Atlas* Atlas_readAtlas (const char* data) {
|
||||
AtlasRegion *lastRegion = 0;
|
||||
Str str;
|
||||
Str tuple[4];
|
||||
readLine(data, 0);
|
||||
while (readLine(0, &str)) {
|
||||
readLine(begin, 0, 0);
|
||||
while (readLine(0, end, &str)) {
|
||||
if (str.end - str.begin == 0) {
|
||||
page = 0;
|
||||
} else if (!page) {
|
||||
@ -189,14 +190,14 @@ Atlas* Atlas_readAtlas (const char* data) {
|
||||
self->pages = page;
|
||||
lastPage = page;
|
||||
|
||||
if (!readValue(&str)) return abort(self);
|
||||
if (!readValue(end, &str)) return abortAtlas(self);
|
||||
page->format = (AtlasFormat)indexOf(formatNames, 7, &str);
|
||||
|
||||
if (!readTuple(tuple)) return abort(self);
|
||||
if (!readTuple(end, tuple)) return abortAtlas(self);
|
||||
page->minFilter = (AtlasFilter)indexOf(textureFilterNames, 7, tuple);
|
||||
page->magFilter = (AtlasFilter)indexOf(textureFilterNames, 7, tuple + 1);
|
||||
|
||||
if (!readValue(&str)) return abort(self);
|
||||
if (!readValue(end, &str)) return abortAtlas(self);
|
||||
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);
|
||||
@ -212,19 +213,19 @@ Atlas* Atlas_readAtlas (const char* data) {
|
||||
region->page = page;
|
||||
region->name = mallocString(&str);
|
||||
|
||||
if (!readValue(&str)) return abort(self);
|
||||
if (!readValue(end, &str)) return abortAtlas(self);
|
||||
region->rotate = equals(&str, "true");
|
||||
|
||||
if (readTuple(tuple) != 2) return abort(self);
|
||||
if (readTuple(end, tuple) != 2) return abortAtlas(self);
|
||||
region->x = toInt(tuple);
|
||||
region->y = toInt(tuple + 1);
|
||||
|
||||
if (readTuple(tuple) != 2) return abort(self);
|
||||
if (readTuple(end, tuple) != 2) return abortAtlas(self);
|
||||
region->width = toInt(tuple);
|
||||
region->height = toInt(tuple + 1);
|
||||
|
||||
int count;
|
||||
if (!(count = readTuple(tuple))) return abort(self);
|
||||
if (!(count = readTuple(end, tuple))) return abortAtlas(self);
|
||||
if (count == 4) { /* split is optional */
|
||||
region->splits = MALLOC(int, 4);
|
||||
region->splits[0] = toInt(tuple);
|
||||
@ -232,7 +233,7 @@ Atlas* Atlas_readAtlas (const char* data) {
|
||||
region->splits[2] = toInt(tuple + 2);
|
||||
region->splits[3] = toInt(tuple + 3);
|
||||
|
||||
if (!(count = readTuple(tuple))) return abort(self);
|
||||
if (!(count = readTuple(end, tuple))) return abortAtlas(self);
|
||||
if (count == 4) { /* pad is optional, but only present with splits */
|
||||
region->pads = MALLOC(int, 4);
|
||||
region->pads[0] = toInt(tuple);
|
||||
@ -240,18 +241,18 @@ Atlas* Atlas_readAtlas (const char* data) {
|
||||
region->pads[2] = toInt(tuple + 2);
|
||||
region->pads[3] = toInt(tuple + 3);
|
||||
|
||||
if (!readTuple(tuple)) return abort(self);
|
||||
if (!readTuple(end, tuple)) return abortAtlas(self);
|
||||
}
|
||||
}
|
||||
|
||||
region->originalWidth = toInt(tuple);
|
||||
region->originalHeight = toInt(tuple + 1);
|
||||
|
||||
readTuple(tuple);
|
||||
readTuple(end, tuple);
|
||||
region->offsetX = (float)toInt(tuple);
|
||||
region->offsetY = (float)toInt(tuple + 1);
|
||||
|
||||
if (!readValue(&str)) return abort(self);
|
||||
if (!readValue(end, &str)) return abortAtlas(self);
|
||||
region->index = toInt(&str);
|
||||
}
|
||||
}
|
||||
@ -260,9 +261,10 @@ Atlas* Atlas_readAtlas (const char* data) {
|
||||
}
|
||||
|
||||
Atlas* Atlas_readAtlasFile (const char* path) {
|
||||
const char* data = readFile(path);
|
||||
int length;
|
||||
const char* data = _Util_readFile(path, &length);
|
||||
if (!data) return 0;
|
||||
Atlas* atlas = Atlas_readAtlas(data);
|
||||
Atlas* atlas = Atlas_readAtlas(data, length);
|
||||
FREE(data);
|
||||
return atlas;
|
||||
}
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
#include <spine/AtlasAttachmentLoader.h>
|
||||
#include <stdio.h>
|
||||
#include <spine/extension.h>
|
||||
#include <spine/util.h>
|
||||
|
||||
void _AtlasAttachmentLoader_free (AttachmentLoader* self) {
|
||||
_AttachmentLoader_deinit(self);
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
#include <spine/Attachment.h>
|
||||
#include <spine/extension.h>
|
||||
#include <spine/util.h>
|
||||
#include <spine/Slot.h>
|
||||
|
||||
void _Attachment_init (Attachment* self, const char* name, AttachmentType type) {
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
#include <spine/AttachmentLoader.h>
|
||||
#include <spine/extension.h>
|
||||
#include <spine/util.h>
|
||||
|
||||
void _AttachmentLoader_init (AttachmentLoader* self) {
|
||||
CONST_CAST(_AttachmentLoaderVtable*, self->vtable) = NEW(_AttachmentLoaderVtable);
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
#include <spine/BoneData.h>
|
||||
#include <spine/extension.h>
|
||||
#include <spine/util.h>
|
||||
|
||||
BoneData* BoneData_new (const char* name, BoneData* parent) {
|
||||
BoneData* self = NEW(BoneData);
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <spine/util.h>
|
||||
#include <spine/extension.h>
|
||||
|
||||
static const char* ep;
|
||||
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <spine/extension.h>
|
||||
#include <spine/util.h>
|
||||
#include <spine/Json.h>
|
||||
#include <spine/RegionAttachment.h>
|
||||
#include <spine/AtlasAttachmentLoader.h>
|
||||
@ -82,7 +81,8 @@ static float toColor (const char* value, int index) {
|
||||
}
|
||||
|
||||
SkeletonData* SkeletonJson_readSkeletonDataFile (SkeletonJson* self, const char* path) {
|
||||
const char* json = readFile(path);
|
||||
int length;
|
||||
const char* json = _Util_readFile(path, &length);
|
||||
if (!json) {
|
||||
_SkeletonJson_setError(self, 0, "Unable to read skeleton file: ", path);
|
||||
return 0;
|
||||
@ -240,13 +240,14 @@ SkeletonData* SkeletonJson_readSkeletonData (SkeletonJson* self, const char* jso
|
||||
}
|
||||
|
||||
Animation* SkeletonJson_readAnimationFile (SkeletonJson* self, const char* path, const SkeletonData *skeletonData) {
|
||||
const char* data = readFile(path);
|
||||
if (!data) {
|
||||
int length;
|
||||
const char* json = _Util_readFile(path, &length);
|
||||
if (!json) {
|
||||
_SkeletonJson_setError(self, 0, "Unable to read animation file: ", path);
|
||||
return 0;
|
||||
}
|
||||
Animation* animation = SkeletonJson_readAnimation(self, data, skeletonData);
|
||||
FREE(data);
|
||||
Animation* animation = SkeletonJson_readAnimation(self, json, skeletonData);
|
||||
FREE(json);
|
||||
return animation;
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
#include <spine/Skin.h>
|
||||
#include <spine/extension.h>
|
||||
#include <spine/util.h>
|
||||
|
||||
SkinEntry* _SkinEntry_new (int slotIndex, const char* name, Attachment* attachment) {
|
||||
SkinEntry* self = NEW(SkinEntry);
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
#include <spine/SlotData.h>
|
||||
#include <spine/extension.h>
|
||||
#include <spine/util.h>
|
||||
|
||||
SlotData* SlotData_new (const char* name, BoneData* boneData) {
|
||||
SlotData* self = NEW(SlotData);
|
||||
|
||||
@ -23,21 +23,20 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <spine/util.h>
|
||||
#include <spine/extension.h>
|
||||
#include <stdio.h>
|
||||
|
||||
const char* readFile (const char* path) {
|
||||
char* _readFile (const char* path, int* length) {
|
||||
FILE *file = fopen(path, "rb");
|
||||
if (!file) return 0;
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
long length = ftell(file);
|
||||
*length = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
char* data = MALLOC(char, length + 1);
|
||||
fread(data, 1, length, file);
|
||||
char* data = MALLOC(char, *length);
|
||||
fread(data, 1, *length, file);
|
||||
fclose(file);
|
||||
data[length] = '\0';
|
||||
|
||||
return data;
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013, Esoteric Software
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef SPINE_UTIL_H_
|
||||
#define SPINE_UTIL_H_
|
||||
|
||||
#include <string.h>
|
||||
#include <spine/extension.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace spine {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* 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)
|
||||
|
||||
/* Read file at specific path to a new char[]. Return value must be freed. */
|
||||
const char* readFile (const char* path);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SPINE_UTIL_H_ */
|
||||
Loading…
x
Reference in New Issue
Block a user