From da70193a366e55cb1ce6756491859d03dabaad28 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 25 Jul 2025 02:12:14 +0200 Subject: [PATCH] [c] Refactor atlas loading, fix up API consumers --- spine-c/codegen/exclusions.txt | 3 -- spine-c/src/extensions.cpp | 93 ++++++++++++---------------------- spine-c/src/extensions.h | 13 +++-- spine-c/tests/headless-test.c | 20 +++++--- spine-glfw/example/main-c.cpp | 5 +- 5 files changed, 54 insertions(+), 80 deletions(-) diff --git a/spine-c/codegen/exclusions.txt b/spine-c/codegen/exclusions.txt index 01a212684..c54e0c656 100644 --- a/spine-c/codegen/exclusions.txt +++ b/spine-c/codegen/exclusions.txt @@ -33,9 +33,6 @@ method: TrackEntry::setListener method: TrackEntry::getListener method: Atlas::Atlas -# Exclude Atlas destructor - we handle atlas disposal in extensions.cpp -method: Atlas::~Atlas - # Used in UE4/cocos2dx, not used anywhere else method: AnimationState::setRendererObject method: TrackEntry::setRendererObject diff --git a/spine-c/src/extensions.cpp b/spine-c/src/extensions.cpp index 6ae705987..ae107718a 100644 --- a/spine-c/src/extensions.cpp +++ b/spine-c/src/extensions.cpp @@ -40,10 +40,8 @@ using namespace spine; // Internal structures -struct _spine_atlas { - void *atlas; - const char **imagePaths; - int32_t numImagePaths; +struct _spine_atlas_result { + spine_atlas atlas; const char *error; }; @@ -169,7 +167,7 @@ float spine_vector_get_y(spine_vector vector) { } // Atlas functions -class LiteTextureLoad : public TextureLoader { +class SpineCTextureLoader : public TextureLoader { void load(AtlasPage &page, const String &path) { page.texture = (void *) (intptr_t) page.index; } @@ -177,20 +175,19 @@ class LiteTextureLoad : public TextureLoader { void unload(void *texture) { } }; -static LiteTextureLoad liteLoader; +static SpineCTextureLoader textureLoader; -spine_atlas spine_atlas_load(const char *atlasData) { +spine_atlas_result spine_atlas_load(const char *atlasData) { if (!atlasData) return nullptr; + _spine_atlas_result *result = SpineExtension::calloc<_spine_atlas_result>(1, __FILE__, __LINE__); int32_t length = (int32_t) strlen(atlasData); - auto atlas = new (__FILE__, __LINE__) Atlas(atlasData, length, "", &liteLoader, true); - _spine_atlas *result = SpineExtension::calloc<_spine_atlas>(1, __FILE__, __LINE__); - result->atlas = atlas; - result->numImagePaths = (int32_t) atlas->getPages().size(); - result->imagePaths = SpineExtension::calloc(result->numImagePaths, __FILE__, __LINE__); - for (int i = 0; i < result->numImagePaths; i++) { - result->imagePaths[i] = atlas->getPages()[i]->texturePath.buffer(); + auto atlas = new (__FILE__, __LINE__) Atlas(atlasData, length, "", &textureLoader, true); + if (!atlas) { + result->error = (const char *) strdup("Failed to load atlas"); + return (spine_atlas_result) result; } - return (spine_atlas) result; + result->atlas = (spine_atlas) atlas; + return (spine_atlas_result) result; } class CallbackTextureLoad : public TextureLoader { @@ -216,69 +213,45 @@ public: }; static CallbackTextureLoad callbackLoader; -spine_atlas spine_atlas_load_callback(const char *atlasData, const char *atlasDir, spine_texture_loader_load_func load, +spine_atlas_result spine_atlas_load_callback(const char *atlasData, const char *atlasDir, spine_texture_loader_load_func load, spine_texture_loader_unload_func unload) { if (!atlasData) return nullptr; + _spine_atlas_result *result = SpineExtension::calloc<_spine_atlas_result>(1, __FILE__, __LINE__); int32_t length = (int32_t) strlen(atlasData); callbackLoader.setCallbacks(load, unload); auto atlas = new (__FILE__, __LINE__) Atlas(atlasData, length, (const char *) atlasDir, &callbackLoader, true); - _spine_atlas *result = SpineExtension::calloc<_spine_atlas>(1, __FILE__, __LINE__); - result->atlas = atlas; - result->numImagePaths = (int32_t) atlas->getPages().size(); - result->imagePaths = SpineExtension::calloc(result->numImagePaths, __FILE__, __LINE__); - for (int i = 0; i < result->numImagePaths; i++) { - result->imagePaths[i] = atlas->getPages()[i]->texturePath.buffer(); + if (!atlas) { + result->error = (const char *) strdup("Failed to load atlas"); + return (spine_atlas_result) result; } - return (spine_atlas) result; + result->atlas = (spine_atlas) atlas; + return (spine_atlas_result) result; } -int32_t spine_atlas_get_num_image_paths(spine_atlas atlas) { - if (!atlas) return 0; - return ((_spine_atlas *) atlas)->numImagePaths; +const char *spine_atlas_result_get_error(spine_atlas_result result) { + if (!result) return nullptr; + return ((_spine_atlas_result *) result)->error; } -const char *spine_atlas_get_image_path(spine_atlas atlas, int32_t index) { - if (!atlas) return nullptr; - _spine_atlas *_atlas = (_spine_atlas *) atlas; - if (index < 0 || index >= _atlas->numImagePaths) return nullptr; - return _atlas->imagePaths[index]; +spine_atlas spine_atlas_result_get_atlas(spine_atlas_result result) { + if (!result) return nullptr; + return ((_spine_atlas_result *) result)->atlas; } -bool spine_atlas_is_pma(spine_atlas atlas) { - if (!atlas) return false; - Atlas *_atlas = (Atlas *) ((_spine_atlas *) atlas)->atlas; - for (size_t i = 0; i < _atlas->getPages().size(); i++) { - AtlasPage *page = _atlas->getPages()[i]; - if (page->pma) return true; +void spine_atlas_result_dispose(spine_atlas_result result) { + if (!result) return; + _spine_atlas_result *_result = (_spine_atlas_result *) result; + if (_result->error) { + SpineExtension::free(_result->error, __FILE__, __LINE__); } - return false; -} - -const char *spine_atlas_get_error(spine_atlas atlas) { - if (!atlas) return nullptr; - return ((_spine_atlas *) atlas)->error; -} - -void spine_atlas_dispose(spine_atlas atlas) { - if (!atlas) return; - _spine_atlas *_atlas = (_spine_atlas *) atlas; - if (_atlas->atlas) { - delete (Atlas *) _atlas->atlas; - } - if (_atlas->imagePaths) { - SpineExtension::free(_atlas->imagePaths, __FILE__, __LINE__); - } - if (_atlas->error) { - SpineExtension::free(_atlas->error, __FILE__, __LINE__); - } - SpineExtension::free(_atlas, __FILE__, __LINE__); + SpineExtension::free(_result, __FILE__, __LINE__); } // Skeleton data loading spine_skeleton_data_result spine_skeleton_data_load_json(spine_atlas atlas, const char *skeletonData, const char *path) { if (!atlas || !skeletonData) return nullptr; _spine_skeleton_data_result *result = SpineExtension::calloc<_spine_skeleton_data_result>(1, __FILE__, __LINE__); - SkeletonJson json((Atlas *) ((_spine_atlas *) atlas)->atlas); + SkeletonJson json((Atlas *) atlas); json.setScale(1); SkeletonData *data = json.readSkeletonData(skeletonData); @@ -314,7 +287,7 @@ spine_skeleton_data_result spine_skeleton_data_load_json(spine_atlas atlas, cons spine_skeleton_data_result spine_skeleton_data_load_binary(spine_atlas atlas, const uint8_t *skeletonData, int32_t length, const char *path) { if (!atlas || !skeletonData) return nullptr; _spine_skeleton_data_result *result = SpineExtension::calloc<_spine_skeleton_data_result>(1, __FILE__, __LINE__); - SkeletonBinary binary((Atlas *) ((_spine_atlas *) atlas)->atlas); + SkeletonBinary binary((Atlas *) atlas); binary.setScale(1); SkeletonData *data = binary.readSkeletonData((const unsigned char *) skeletonData, length); diff --git a/spine-c/src/extensions.h b/spine-c/src/extensions.h index f257c2a22..8943be052 100644 --- a/spine-c/src/extensions.h +++ b/spine-c/src/extensions.h @@ -39,6 +39,7 @@ extern "C" { #include "generated/skeleton_data.h" // Custom types for spine-c-new (not generated) +SPINE_OPAQUE_TYPE(spine_atlas_result) SPINE_OPAQUE_TYPE(spine_skeleton_data_result) SPINE_OPAQUE_TYPE(spine_bounds) SPINE_OPAQUE_TYPE(spine_vector) @@ -73,14 +74,12 @@ SPINE_C_API float spine_vector_get_x(spine_vector vector); SPINE_C_API float spine_vector_get_y(spine_vector vector); // Atlas functions -SPINE_C_API spine_atlas spine_atlas_load(const char *atlasData); -SPINE_C_API spine_atlas spine_atlas_load_callback(const char *atlasData, const char *atlasDir, spine_texture_loader_load_func load, +SPINE_C_API spine_atlas_result spine_atlas_load(const char *atlasData); +SPINE_C_API spine_atlas_result spine_atlas_load_callback(const char *atlasData, const char *atlasDir, spine_texture_loader_load_func load, spine_texture_loader_unload_func unload); -SPINE_C_API int32_t spine_atlas_get_num_image_paths(spine_atlas atlas); -SPINE_C_API const char *spine_atlas_get_image_path(spine_atlas atlas, int32_t index); -SPINE_C_API bool spine_atlas_is_pma(spine_atlas atlas); -SPINE_C_API const char *spine_atlas_get_error(spine_atlas atlas); -SPINE_C_API void spine_atlas_dispose(spine_atlas atlas); +SPINE_C_API const char *spine_atlas_result_get_error(spine_atlas_result result); +SPINE_C_API spine_atlas spine_atlas_result_get_atlas(spine_atlas_result result); +SPINE_C_API void spine_atlas_result_dispose(spine_atlas_result result); // Skeleton data functions SPINE_C_API spine_skeleton_data_result spine_skeleton_data_load_json(spine_atlas atlas, const char *skeletonData, const char *path); diff --git a/spine-c/tests/headless-test.c b/spine-c/tests/headless-test.c index 08df34289..f004368d9 100644 --- a/spine-c/tests/headless-test.c +++ b/spine-c/tests/headless-test.c @@ -161,14 +161,18 @@ int main(int argc, char *argv[]) { } // Load atlas with headless texture loader - spine_atlas atlas = spine_atlas_load_callback((const char *) atlasBytes, atlasDir, headlessTextureLoader, headlessTextureUnloader); + spine_atlas_result atlasResult = spine_atlas_load_callback((const char *) atlasBytes, atlasDir, headlessTextureLoader, headlessTextureUnloader); free(atlasBytes); - if (!atlas) { - fprintf(stderr, "Failed to load atlas\n"); + const char *atlasError = spine_atlas_result_get_error(atlasResult); + if (atlasError) { + fprintf(stderr, "Failed to load atlas: %s\n", atlasError); + spine_atlas_result_dispose(atlasResult); return 1; } + spine_atlas atlas = spine_atlas_result_get_atlas(atlasResult); + // Load skeleton data spine_skeleton_data_result result = {0}; spine_skeleton_data skeletonData = NULL; @@ -178,7 +182,7 @@ int main(int argc, char *argv[]) { uint8_t *skeletonBytes = read_file(skeletonPath, &skeletonLength); if (!skeletonBytes) { fprintf(stderr, "Failed to read skeleton file\n"); - spine_atlas_dispose(atlas); + spine_atlas_result_dispose(atlasResult); return 1; } result = spine_skeleton_data_load_json(atlas, (const char *) skeletonBytes, skeletonPath); @@ -188,7 +192,7 @@ int main(int argc, char *argv[]) { uint8_t *skeletonBytes = read_file(skeletonPath, &skeletonLength); if (!skeletonBytes) { fprintf(stderr, "Failed to read skeleton file\n"); - spine_atlas_dispose(atlas); + spine_atlas_result_dispose(atlasResult); return 1; } result = spine_skeleton_data_load_binary(atlas, skeletonBytes, skeletonLength, skeletonPath); @@ -200,7 +204,7 @@ int main(int argc, char *argv[]) { const char *error = spine_skeleton_data_result_get_error(result); fprintf(stderr, "Failed to load skeleton data: %s\n", error ? error : "Unknown error"); spine_skeleton_data_result_dispose(result); - spine_atlas_dispose(atlas); + spine_atlas_result_dispose(atlasResult); return 1; } @@ -227,7 +231,7 @@ int main(int argc, char *argv[]) { spine_animation_state_data_dispose(stateData); spine_skeleton_dispose(skeleton); spine_skeleton_data_result_dispose(result); - spine_atlas_dispose(atlas); + spine_atlas_result_dispose(atlasResult); return 1; } spine_animation_state_set_animation_1(state, 0, animationName, 1); @@ -247,7 +251,7 @@ int main(int argc, char *argv[]) { spine_animation_state_data_dispose(stateData); spine_skeleton_dispose(skeleton); spine_skeleton_data_result_dispose(result); - spine_atlas_dispose(atlas); + spine_atlas_result_dispose(atlasResult); return 0; } diff --git a/spine-glfw/example/main-c.cpp b/spine-glfw/example/main-c.cpp index 577d6f421..00eb7665a 100644 --- a/spine-glfw/example/main-c.cpp +++ b/spine-glfw/example/main-c.cpp @@ -91,11 +91,12 @@ int main() { // Load the atlas and the skeleton data int atlas_length = 0; uint8_t *atlas_bytes = read_file("data/spineboy-pma.atlas", &atlas_length); - spine_atlas atlas = spine_atlas_load_callback((const char *) atlas_bytes, "data/", load_texture, unload_texture); + spine_atlas_result result = spine_atlas_load_callback((const char *) atlas_bytes, "data/", load_texture, unload_texture); + spine_atlas atlas = spine_atlas_result_get_atlas(result); + int skeleton_length = 0; // uint8_t *skeleton_bytes = read_file("data/spineboy-pro.skel", &skeleton_length); // spine_skeleton_data_result result = spine_skeleton_data_load_binary(atlas, skeleton_bytes, skeleton_length); - uint8_t *skeleton_bytes = read_file("data/spineboy-pro.json", &skeleton_length); spine_skeleton_data_result result2 = spine_skeleton_data_load_json(atlas, (const char *) skeleton_bytes, "data/"); spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(result2);