소스 검색

[c] 4.0 porting, texture atlas parsing and key value storage in regions.

badlogic 4 년 전
부모
커밋
5411717c1a
3개의 변경된 파일215개의 추가작업 그리고 145개의 파일을 삭제
  1. 9 3
      spine-c/spine-c/include/spine/Atlas.h
  2. 205 141
      spine-c/spine-c/src/spine/Atlas.c
  3. 1 1
      spine-cpp/spine-cpp/src/spine/Atlas.cpp

+ 9 - 3
spine-c/spine-c/include/spine/Atlas.h

@@ -31,6 +31,7 @@
 #define SPINE_ATLAS_H_
 #define SPINE_ATLAS_H_
 
 
 #include <spine/dll.h>
 #include <spine/dll.h>
+#include <spine/Array.h>
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
@@ -84,6 +85,13 @@ struct spAtlasPage {
 SP_API spAtlasPage* spAtlasPage_create (spAtlas* atlas, const char* name);
 SP_API spAtlasPage* spAtlasPage_create (spAtlas* atlas, const char* name);
 SP_API void spAtlasPage_dispose (spAtlasPage* self);
 SP_API void spAtlasPage_dispose (spAtlasPage* self);
 
 
+/**/
+typedef struct spKeyValue {
+    char *name;
+    float values[5];
+} spKeyValue;
+_SP_ARRAY_DECLARE_TYPE(spKeyValueArray, spKeyValue)
+
 /**/
 /**/
 typedef struct spAtlasRegion spAtlasRegion;
 typedef struct spAtlasRegion spAtlasRegion;
 struct spAtlasRegion {
 struct spAtlasRegion {
@@ -96,9 +104,7 @@ struct spAtlasRegion {
 	int degrees;
 	int degrees;
 	int* splits;
 	int* splits;
 	int* pads;
 	int* pads;
-	char** names;
-	float* values;
-	int numValues;
+	spKeyValueArray *keyValues;
 
 
 	spAtlasPage* page;
 	spAtlasPage* page;
 
 

+ 205 - 141
spine-c/spine-c/src/spine/Atlas.c

@@ -31,6 +31,63 @@
 #include <ctype.h>
 #include <ctype.h>
 #include <spine/extension.h>
 #include <spine/extension.h>
 
 
+spKeyValueArray *spKeyValueArray_create(int initialCapacity) {
+    spKeyValueArray *array = ((spKeyValueArray *) _spCalloc(1, sizeof(spKeyValueArray), "_file_name_", 39));
+    array->size = 0;
+    array->capacity = initialCapacity;
+    array->items = ((spKeyValue *) _spCalloc(initialCapacity, sizeof(spKeyValue), "_file_name_", 39));
+    return array;
+}
+void spKeyValueArray_dispose(spKeyValueArray *self) {
+    _spFree((void *) self->items);
+    _spFree((void *) self);
+}
+void spKeyValueArray_clear(spKeyValueArray *self) { self->size = 0; }
+spKeyValueArray *spKeyValueArray_setSize(spKeyValueArray *self, int newSize) {
+    self->size = newSize;
+    if (self->capacity < newSize) {
+        self->capacity = ((8) > ((int) (self->size * 1.75f)) ? (8) : ((int) (self->size * 1.75f)));
+        self->items = ((spKeyValue *) _spRealloc(self->items, sizeof(spKeyValue) * (self->capacity)));
+    }
+    return self;
+}
+void spKeyValueArray_ensureCapacity(spKeyValueArray *self, int newCapacity) {
+    if (self->capacity >= newCapacity)return;
+    self->capacity = newCapacity;
+    self->items = ((spKeyValue *) _spRealloc(self->items, sizeof(spKeyValue) * (self->capacity)));
+}
+void spKeyValueArray_add(spKeyValueArray *self, spKeyValue value) {
+    if (self->size == self->capacity) {
+        self->capacity = ((8) > ((int) (self->size * 1.75f)) ? (8) : ((int) (self->size * 1.75f)));
+        self->items = ((spKeyValue *) _spRealloc(self->items, sizeof(spKeyValue) * (self->capacity)));
+    }
+    self->items[self->size++] = value;
+}
+void spKeyValueArray_addAll(spKeyValueArray *self, spKeyValueArray *other) {
+    int i = 0;
+    for (; i < other->size; i++) { spKeyValueArray_add(self, other->items[i]); }
+}
+void spKeyValueArray_addAllValues(spKeyValueArray *self, spKeyValue *values, int offset, int count) {
+    int i = offset, n = offset + count;
+    for (; i < n; i++) { spKeyValueArray_add(self, values[i]); }
+}
+void spKeyValueArray_removeAt(spKeyValueArray *self, int index) {
+    self->size--;
+    __builtin___memmove_chk(self->items + index, self->items + index + 1, sizeof(spKeyValue) * (self->size - index),
+                            __builtin_object_size(self->items + index, 0));
+}
+int spKeyValueArray_contains(spKeyValueArray *self, spKeyValue value) {
+    spKeyValue *items = self->items;
+    int i, n;
+    for (i = 0, n = self->size; i < n; i++) { if (!strcmp(items[i].name, value.name))return -1; }
+    return 0;
+}
+spKeyValue spKeyValueArray_pop(spKeyValueArray *self) {
+    spKeyValue item = self->items[--self->size];
+    return item;
+}
+spKeyValue spKeyValueArray_peek(spKeyValueArray *self) { return self->items[self->size - 1]; }
+
 spAtlasPage* spAtlasPage_create(spAtlas* atlas, const char* name) {
 spAtlasPage* spAtlasPage_create(spAtlas* atlas, const char* name) {
 	spAtlasPage* self = NEW(spAtlasPage);
 	spAtlasPage* self = NEW(spAtlasPage);
 	CONST_CAST(spAtlas*, self->atlas) = atlas;
 	CONST_CAST(spAtlas*, self->atlas) = atlas;
@@ -47,19 +104,20 @@ void spAtlasPage_dispose(spAtlasPage* self) {
 /**/
 /**/
 
 
 spAtlasRegion* spAtlasRegion_create() {
 spAtlasRegion* spAtlasRegion_create() {
-	return NEW(spAtlasRegion);
+	spAtlasRegion *region = NEW(spAtlasRegion);
+	region->keyValues = spKeyValueArray_create(2);
+	return region;
 }
 }
 
 
 void spAtlasRegion_dispose(spAtlasRegion* self) {
 void spAtlasRegion_dispose(spAtlasRegion* self) {
-  int i, n;
+    int i, n;
 	FREE(self->name);
 	FREE(self->name);
 	FREE(self->splits);
 	FREE(self->splits);
 	FREE(self->pads);
 	FREE(self->pads);
-	for (i = 0, n = self->numValues; i < n; i++) {
-    FREE(self->names[i]);
-  }
-	FREE(self->names);
-	FREE(self->values);
+	for (i = 0, n = self->keyValues->size; i < n; i++) {
+	    FREE(self->keyValues->items[i].name);
+	}
+	spKeyValueArray_dispose(self->keyValues);
 	FREE(self);
 	FREE(self);
 }
 }
 
 
@@ -183,156 +241,162 @@ static int ai_readEntry(SimpleString entry[5], SimpleString *line) {
   }
   }
 }
 }
 
 
-static spAtlas* abortAtlas(spAtlas* self) {
-	spAtlas_dispose(self);
-	return 0;
-}
-
 static const char *formatNames[] = {"", "Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888",
 static const char *formatNames[] = {"", "Alpha", "Intensity", "LuminanceAlpha", "RGB565", "RGBA4444", "RGB888",
                                     "RGBA8888"};
                                     "RGBA8888"};
 static const char *textureFilterNames[] = {"", "Nearest", "Linear", "MipMap", "MipMapNearestNearest",
 static const char *textureFilterNames[] = {"", "Nearest", "Linear", "MipMap", "MipMapNearestNearest",
                                            "MipMapLinearNearest",
                                            "MipMapLinearNearest",
                                            "MipMapNearestLinear", "MipMapLinearLinear"};
                                            "MipMapNearestLinear", "MipMapLinearLinear"};
 
 
+int indexOf(const char **array, int count, SimpleString *str) {
+    int i;
+    for (i = 0; i < count; i++)
+        if (ss_equals(str, array[i])) return i;
+    return 0;
+}
+
 spAtlas* spAtlas_create(const char* begin, int length, const char* dir, void* rendererObject) {
 spAtlas* spAtlas_create(const char* begin, int length, const char* dir, void* rendererObject) {
 	spAtlas* self;
 	spAtlas* self;
+    AtlasInput reader;
+    SimpleString *line;
+    SimpleString entry[5];
+    spAtlasPage *page = NULL;
+    spAtlasPage *lastPage = NULL;
+    spAtlasRegion *lastRegion = NULL;
 
 
 	int count;
 	int count;
-	const char* end = begin + length;
 	int dirLength = (int)strlen(dir);
 	int dirLength = (int)strlen(dir);
 	int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\';
 	int needsSlash = dirLength > 0 && dir[dirLength - 1] != '/' && dir[dirLength - 1] != '\\';
 
 
-	spAtlasPage *page = 0;
-	spAtlasPage *lastPage = 0;
-	spAtlasRegion *lastRegion = 0;
-	Str str;
-	Str tuple[4];
-
 	self = NEW(spAtlas);
 	self = NEW(spAtlas);
 	self->rendererObject = rendererObject;
 	self->rendererObject = rendererObject;
 
 
-	while (readLine(&begin, end, &str)) {
-		if (str.end - str.begin == 0)
-			page = 0;
-		else if (!page) {
-			char* name = mallocString(&str);
-			char* path = MALLOC(char, dirLength + needsSlash + strlen(name) + 1);
-			memcpy(path, dir, dirLength);
-			if (needsSlash) path[dirLength] = '/';
-			strcpy(path + dirLength + needsSlash, name);
-
-			page = spAtlasPage_create(self, name);
-			FREE(name);
-			if (lastPage)
-				lastPage->next = page;
-			else
-				self->pages = page;
-			lastPage = page;
-
-			switch (readTuple(&begin, end, tuple)) {
-			case 0:
-				return abortAtlas(self);
-			case 2: /* size is only optional for an atlas packed with an old TexturePacker. */
-				page->width = toInt(tuple);
-				page->height = toInt(tuple + 1);
-				if (!readTuple(&begin, end, tuple)) return abortAtlas(self);
-			}
-			page->format = (spAtlasFormat)indexOf(formatNames, 8, tuple);
-
-			if (!readTuple(&begin, end, tuple)) return abortAtlas(self);
-			page->minFilter = (spAtlasFilter)indexOf(textureFilterNames, 8, tuple);
-			page->magFilter = (spAtlasFilter)indexOf(textureFilterNames, 8, tuple + 1);
-
-			if (!readValue(&begin, end, &str)) return abortAtlas(self);
-
-			page->uWrap = SP_ATLAS_CLAMPTOEDGE;
-			page->vWrap = SP_ATLAS_CLAMPTOEDGE;
-			if (!equals(&str, "none")) {
-				if (str.end - str.begin == 1) {
-					if (*str.begin == 'x')
-						page->uWrap = SP_ATLAS_REPEAT;
-					else if (*str.begin == 'y')
-						page->vWrap = SP_ATLAS_REPEAT;
-				}
-				else if (equals(&str, "xy")) {
-					page->uWrap = SP_ATLAS_REPEAT;
-					page->vWrap = SP_ATLAS_REPEAT;
-				}
-			}
-
-			_spAtlasPage_createTexture(page, path);
-			FREE(path);
-		} else {
-			spAtlasRegion *region = spAtlasRegion_create();
-			if (lastRegion)
-				lastRegion->next = region;
-			else
-				self->regions = region;
-			lastRegion = region;
-
-			region->page = page;
-			region->name = mallocString(&str);
-
-			if (!readValue(&begin, end, &str)) return abortAtlas(self);
-			if (equals(&str, "true"))
-				region->degrees = 90;
-			else if (equals(&str, "false"))
-				region->degrees = 0;
-			else
-				region->degrees = toInt(&str);
-			region->rotate = region->degrees == 90;
-
-			if (readTuple(&begin, end, tuple) != 2) return abortAtlas(self);
-			region->x = toInt(tuple);
-			region->y = toInt(tuple + 1);
-
-			if (readTuple(&begin, end, tuple) != 2) return abortAtlas(self);
-			region->width = toInt(tuple);
-			region->height = toInt(tuple + 1);
-
-			region->u = region->x / (float)page->width;
-			region->v = region->y / (float)page->height;
-			if (region->rotate) {
-				region->u2 = (region->x + region->height) / (float)page->width;
-				region->v2 = (region->y + region->width) / (float)page->height;
-			} else {
-				region->u2 = (region->x + region->width) / (float)page->width;
-				region->v2 = (region->y + region->height) / (float)page->height;
-			}
-
-			count = readTuple(&begin, end, tuple);
-			if (!count) return abortAtlas(self);
-			if (count == 4) { /* split is optional */
-				region->splits = MALLOC(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);
-
-				count = readTuple(&begin, end, tuple);
-				if (!count) return abortAtlas(self);
-				if (count == 4) { /* pad is optional, but only present with splits */
-					region->pads = MALLOC(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(&begin, end, tuple)) return abortAtlas(self);
-				}
-			}
-
-			region->originalWidth = toInt(tuple);
-			region->originalHeight = toInt(tuple + 1);
-
-			readTuple(&begin, end, tuple);
-			region->offsetX = toInt(tuple);
-			region->offsetY = toInt(tuple + 1);
-
-			if (!readValue(&begin, end, &str)) return abortAtlas(self);
-			region->index = toInt(&str);
-		}
-	}
+	reader.start = begin;
+	reader.end = begin + length;
+	reader.index = (char*)begin;
+	reader.length = length;
+
+    line = ai_readLine(&reader);
+    while (line != NULL && line->length == 0)
+        line = ai_readLine(&reader);
+
+    while (-1) {
+        if (line == NULL || line->length == 0) break;
+        if (ai_readEntry(entry, line) == 0) break;
+        line = ai_readLine(&reader);
+    }
+
+    while (-1) {
+        if (line == NULL) break;
+        if (ss_trim(line)->length == 0) {
+            page = NULL;
+            line = ai_readLine(&reader);
+        } else if (page == NULL) {
+            char *name = ss_copy(line);
+            char *path = CALLOC(char, dirLength + needsSlash + strlen(name) + 1);
+            memcpy(path, dir, dirLength);
+            if (needsSlash) path[dirLength] = '/';
+            strcpy(path + dirLength + needsSlash, name);
+            page = spAtlasPage_create(self, name);
+            FREE(name);
+
+            if (lastPage)
+                lastPage->next = page;
+            else
+                self->pages = page;
+            lastPage = page;
+
+            while (-1) {
+                line = ai_readLine(&reader);
+                if (ai_readEntry(entry, line) == 0) break;
+                if (ss_equals(&entry[0], "size")) {
+                    page->width = ss_toInt(&entry[1]);
+                    page->height = ss_toInt(&entry[2]);
+                } else if (ss_equals(&entry[0], "format")) {
+                    page->format = (spAtlasFormat) indexOf(formatNames, 8, &entry[1]);
+                } else if (ss_equals(&entry[0], "filter")) {
+                    page->minFilter = (spAtlasFilter) indexOf(textureFilterNames, 8, &entry[1]);
+                    page->magFilter = (spAtlasFilter) indexOf(textureFilterNames, 8, &entry[2]);
+                } else if (ss_equals(&entry[0], "repeat")) {
+                    page->uWrap = SP_ATLAS_CLAMPTOEDGE;
+                    page->vWrap = SP_ATLAS_CLAMPTOEDGE;
+                    if (ss_indexOf(&entry[1], 'x') != -1) page->uWrap = SP_ATLAS_REPEAT;
+                    if (ss_indexOf(&entry[1], 'y') != -1) page->vWrap = SP_ATLAS_REPEAT;
+                } else if (ss_equals(&entry[0], "pma")) {
+                    page->pma = ss_equals(&entry[1], "true");
+                }
+            }
+
+            _spAtlasPage_createTexture(page, path);
+            FREE(path);
+        } else {
+            spAtlasRegion *region = spAtlasRegion_create();
+            if (lastRegion)
+                lastRegion->next = region;
+            else
+                self->regions = region;
+            lastRegion = region;
+            region->page = page;
+            region->name = ss_copy(line);
+            while (-1) {
+                line = ai_readLine(&reader);
+                count = ai_readEntry(entry, line);
+                if (count == 0) break;
+                if (ss_equals(&entry[0], "xy")) {
+                    region->x = ss_toInt(&entry[1]);
+                    region->y = ss_toInt(&entry[2]);
+                } else if (ss_equals(&entry[0], "size")) {
+                    region->width = ss_toInt(&entry[1]);
+                    region->height = ss_toInt(&entry[2]);
+                } else if (ss_equals(&entry[0], "bounds")) {
+                    region->x = ss_toInt(&entry[1]);
+                    region->y = ss_toInt(&entry[2]);
+                    region->width = ss_toInt(&entry[3]);
+                    region->height = ss_toInt(&entry[4]);
+                } else if (ss_equals(&entry[0], "offset")) {
+                    region->offsetX = ss_toInt(&entry[1]);
+                    region->offsetY = ss_toInt(&entry[2]);
+                } else if (ss_equals(&entry[0], "orig")) {
+                    region->originalWidth = ss_toInt(&entry[1]);
+                    region->originalHeight = ss_toInt(&entry[2]);
+                } else if (ss_equals(&entry[0], "offsets")) {
+                    region->offsetX = ss_toInt(&entry[1]);
+                    region->offsetY = ss_toInt(&entry[2]);
+                    region->originalWidth = ss_toInt(&entry[3]);
+                    region->originalHeight = ss_toInt(&entry[4]);
+                } else if (ss_equals(&entry[0], "rotate")) {
+                    if (ss_equals(&entry[1], "true")) {
+                        region->degrees = 90;
+                    } else if (!ss_equals(&entry[1], "false")) {
+                        region->degrees = ss_toInt(&entry[1]);
+                    }
+                } else if (ss_equals(&entry[0], "index")) {
+                    region->index = ss_toInt(&entry[1]);
+                } else {
+                    int i = 0;
+                    spKeyValue keyValue;
+                    keyValue.name = ss_copy(&entry[0]);
+                    for (i = 0; i < count; i++) {
+                        keyValue.values[i] = ss_toInt(&entry[i + 1]);
+                    }
+                    spKeyValueArray_add(region->keyValues, keyValue);
+                }
+            }
+            if (region->originalWidth == 0 && region->originalHeight == 0) {
+                region->originalWidth = region->width;
+                region->originalHeight = region->height;
+            }
+
+            region->u = (float)region->x / page->width;
+            region->v = (float)region->y / page->height;
+            if (region->degrees == 90) {
+                region->u2 = (float)(region->x + region->height) / page->width;
+                region->v2 = (float)(region->y + region->width) / page->height;
+            } else {
+                region->u2 = (float)(region->x + region->width) / page->width;
+                region->v2 = (float)(region->y + region->height) / page->height;
+            }
+        }
+    }
 
 
 	return self;
 	return self;
 }
 }

+ 1 - 1
spine-cpp/spine-cpp/src/spine/Atlas.cpp

@@ -292,7 +292,7 @@ void Atlas::load(const char *begin, int length, const char *dir, bool createText
             region->page = page;
             region->page = page;
             region->name = String(line->copy(), true);
             region->name = String(line->copy(), true);
             while (true) {
             while (true) {
-                line = line = reader.readLine();
+                line = reader.readLine();
                 int count = reader.readEntry(entry, line);
                 int count = reader.readEntry(entry, line);
                 if (count == 0) break;
                 if (count == 0) break;
                 if (entry[0].equals("xy")) {
                 if (entry[0].equals("xy")) {