[c] Refactor atlas loading, fix up API consumers

This commit is contained in:
Mario Zechner 2025-07-25 02:12:14 +02:00
parent ce12249682
commit da70193a36
5 changed files with 54 additions and 80 deletions

View File

@ -33,9 +33,6 @@ method: TrackEntry::setListener
method: TrackEntry::getListener method: TrackEntry::getListener
method: Atlas::Atlas method: Atlas::Atlas
# Exclude Atlas destructor - we handle atlas disposal in extensions.cpp
method: Atlas::~Atlas
# Used in UE4/cocos2dx, not used anywhere else # Used in UE4/cocos2dx, not used anywhere else
method: AnimationState::setRendererObject method: AnimationState::setRendererObject
method: TrackEntry::setRendererObject method: TrackEntry::setRendererObject

View File

@ -40,10 +40,8 @@
using namespace spine; using namespace spine;
// Internal structures // Internal structures
struct _spine_atlas { struct _spine_atlas_result {
void *atlas; spine_atlas atlas;
const char **imagePaths;
int32_t numImagePaths;
const char *error; const char *error;
}; };
@ -169,7 +167,7 @@ float spine_vector_get_y(spine_vector vector) {
} }
// Atlas functions // Atlas functions
class LiteTextureLoad : public TextureLoader { class SpineCTextureLoader : public TextureLoader {
void load(AtlasPage &page, const String &path) { void load(AtlasPage &page, const String &path) {
page.texture = (void *) (intptr_t) page.index; page.texture = (void *) (intptr_t) page.index;
} }
@ -177,20 +175,19 @@ class LiteTextureLoad : public TextureLoader {
void unload(void *texture) { 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; if (!atlasData) return nullptr;
_spine_atlas_result *result = SpineExtension::calloc<_spine_atlas_result>(1, __FILE__, __LINE__);
int32_t length = (int32_t) strlen(atlasData); int32_t length = (int32_t) strlen(atlasData);
auto atlas = new (__FILE__, __LINE__) Atlas(atlasData, length, "", &liteLoader, true); auto atlas = new (__FILE__, __LINE__) Atlas(atlasData, length, "", &textureLoader, true);
_spine_atlas *result = SpineExtension::calloc<_spine_atlas>(1, __FILE__, __LINE__); if (!atlas) {
result->atlas = atlas; result->error = (const char *) strdup("Failed to load atlas");
result->numImagePaths = (int32_t) atlas->getPages().size(); return (spine_atlas_result) result;
result->imagePaths = SpineExtension::calloc<const char *>(result->numImagePaths, __FILE__, __LINE__);
for (int i = 0; i < result->numImagePaths; i++) {
result->imagePaths[i] = atlas->getPages()[i]->texturePath.buffer();
} }
return (spine_atlas) result; result->atlas = (spine_atlas) atlas;
return (spine_atlas_result) result;
} }
class CallbackTextureLoad : public TextureLoader { class CallbackTextureLoad : public TextureLoader {
@ -216,69 +213,45 @@ public:
}; };
static CallbackTextureLoad callbackLoader; 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) { spine_texture_loader_unload_func unload) {
if (!atlasData) return nullptr; if (!atlasData) return nullptr;
_spine_atlas_result *result = SpineExtension::calloc<_spine_atlas_result>(1, __FILE__, __LINE__);
int32_t length = (int32_t) strlen(atlasData); int32_t length = (int32_t) strlen(atlasData);
callbackLoader.setCallbacks(load, unload); callbackLoader.setCallbacks(load, unload);
auto atlas = new (__FILE__, __LINE__) Atlas(atlasData, length, (const char *) atlasDir, &callbackLoader, true); auto atlas = new (__FILE__, __LINE__) Atlas(atlasData, length, (const char *) atlasDir, &callbackLoader, true);
_spine_atlas *result = SpineExtension::calloc<_spine_atlas>(1, __FILE__, __LINE__); if (!atlas) {
result->atlas = atlas; result->error = (const char *) strdup("Failed to load atlas");
result->numImagePaths = (int32_t) atlas->getPages().size(); return (spine_atlas_result) result;
result->imagePaths = SpineExtension::calloc<const char *>(result->numImagePaths, __FILE__, __LINE__);
for (int i = 0; i < result->numImagePaths; i++) {
result->imagePaths[i] = atlas->getPages()[i]->texturePath.buffer();
} }
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) { const char *spine_atlas_result_get_error(spine_atlas_result result) {
if (!atlas) return 0; if (!result) return nullptr;
return ((_spine_atlas *) atlas)->numImagePaths; return ((_spine_atlas_result *) result)->error;
} }
const char *spine_atlas_get_image_path(spine_atlas atlas, int32_t index) { spine_atlas spine_atlas_result_get_atlas(spine_atlas_result result) {
if (!atlas) return nullptr; if (!result) return nullptr;
_spine_atlas *_atlas = (_spine_atlas *) atlas; return ((_spine_atlas_result *) result)->atlas;
if (index < 0 || index >= _atlas->numImagePaths) return nullptr;
return _atlas->imagePaths[index];
} }
bool spine_atlas_is_pma(spine_atlas atlas) { void spine_atlas_result_dispose(spine_atlas_result result) {
if (!atlas) return false; if (!result) return;
Atlas *_atlas = (Atlas *) ((_spine_atlas *) atlas)->atlas; _spine_atlas_result *_result = (_spine_atlas_result *) result;
for (size_t i = 0; i < _atlas->getPages().size(); i++) { if (_result->error) {
AtlasPage *page = _atlas->getPages()[i]; SpineExtension::free(_result->error, __FILE__, __LINE__);
if (page->pma) return true;
} }
return false; SpineExtension::free(_result, __FILE__, __LINE__);
}
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__);
} }
// Skeleton data loading // Skeleton data loading
spine_skeleton_data_result spine_skeleton_data_load_json(spine_atlas atlas, const char *skeletonData, const char *path) { spine_skeleton_data_result spine_skeleton_data_load_json(spine_atlas atlas, const char *skeletonData, const char *path) {
if (!atlas || !skeletonData) return nullptr; if (!atlas || !skeletonData) return nullptr;
_spine_skeleton_data_result *result = SpineExtension::calloc<_spine_skeleton_data_result>(1, __FILE__, __LINE__); _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); json.setScale(1);
SkeletonData *data = json.readSkeletonData(skeletonData); 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) { 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; if (!atlas || !skeletonData) return nullptr;
_spine_skeleton_data_result *result = SpineExtension::calloc<_spine_skeleton_data_result>(1, __FILE__, __LINE__); _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); binary.setScale(1);
SkeletonData *data = binary.readSkeletonData((const unsigned char *) skeletonData, length); SkeletonData *data = binary.readSkeletonData((const unsigned char *) skeletonData, length);

View File

@ -39,6 +39,7 @@ extern "C" {
#include "generated/skeleton_data.h" #include "generated/skeleton_data.h"
// Custom types for spine-c-new (not generated) // 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_skeleton_data_result)
SPINE_OPAQUE_TYPE(spine_bounds) SPINE_OPAQUE_TYPE(spine_bounds)
SPINE_OPAQUE_TYPE(spine_vector) 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); SPINE_C_API float spine_vector_get_y(spine_vector vector);
// Atlas functions // Atlas functions
SPINE_C_API spine_atlas spine_atlas_load(const char *atlasData); SPINE_C_API spine_atlas_result 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_callback(const char *atlasData, const char *atlasDir, spine_texture_loader_load_func load,
spine_texture_loader_unload_func unload); 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_result_get_error(spine_atlas_result result);
SPINE_C_API const char *spine_atlas_get_image_path(spine_atlas atlas, int32_t index); SPINE_C_API spine_atlas spine_atlas_result_get_atlas(spine_atlas_result result);
SPINE_C_API bool spine_atlas_is_pma(spine_atlas atlas); SPINE_C_API void spine_atlas_result_dispose(spine_atlas_result result);
SPINE_C_API const char *spine_atlas_get_error(spine_atlas atlas);
SPINE_C_API void spine_atlas_dispose(spine_atlas atlas);
// Skeleton data functions // Skeleton data functions
SPINE_C_API spine_skeleton_data_result spine_skeleton_data_load_json(spine_atlas atlas, const char *skeletonData, const char *path); SPINE_C_API spine_skeleton_data_result spine_skeleton_data_load_json(spine_atlas atlas, const char *skeletonData, const char *path);

View File

@ -161,14 +161,18 @@ int main(int argc, char *argv[]) {
} }
// Load atlas with headless texture loader // 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); free(atlasBytes);
if (!atlas) { const char *atlasError = spine_atlas_result_get_error(atlasResult);
fprintf(stderr, "Failed to load atlas\n"); if (atlasError) {
fprintf(stderr, "Failed to load atlas: %s\n", atlasError);
spine_atlas_result_dispose(atlasResult);
return 1; return 1;
} }
spine_atlas atlas = spine_atlas_result_get_atlas(atlasResult);
// Load skeleton data // Load skeleton data
spine_skeleton_data_result result = {0}; spine_skeleton_data_result result = {0};
spine_skeleton_data skeletonData = NULL; spine_skeleton_data skeletonData = NULL;
@ -178,7 +182,7 @@ int main(int argc, char *argv[]) {
uint8_t *skeletonBytes = read_file(skeletonPath, &skeletonLength); uint8_t *skeletonBytes = read_file(skeletonPath, &skeletonLength);
if (!skeletonBytes) { if (!skeletonBytes) {
fprintf(stderr, "Failed to read skeleton file\n"); fprintf(stderr, "Failed to read skeleton file\n");
spine_atlas_dispose(atlas); spine_atlas_result_dispose(atlasResult);
return 1; return 1;
} }
result = spine_skeleton_data_load_json(atlas, (const char *) skeletonBytes, skeletonPath); 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); uint8_t *skeletonBytes = read_file(skeletonPath, &skeletonLength);
if (!skeletonBytes) { if (!skeletonBytes) {
fprintf(stderr, "Failed to read skeleton file\n"); fprintf(stderr, "Failed to read skeleton file\n");
spine_atlas_dispose(atlas); spine_atlas_result_dispose(atlasResult);
return 1; return 1;
} }
result = spine_skeleton_data_load_binary(atlas, skeletonBytes, skeletonLength, skeletonPath); 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); const char *error = spine_skeleton_data_result_get_error(result);
fprintf(stderr, "Failed to load skeleton data: %s\n", error ? error : "Unknown error"); fprintf(stderr, "Failed to load skeleton data: %s\n", error ? error : "Unknown error");
spine_skeleton_data_result_dispose(result); spine_skeleton_data_result_dispose(result);
spine_atlas_dispose(atlas); spine_atlas_result_dispose(atlasResult);
return 1; return 1;
} }
@ -227,7 +231,7 @@ int main(int argc, char *argv[]) {
spine_animation_state_data_dispose(stateData); spine_animation_state_data_dispose(stateData);
spine_skeleton_dispose(skeleton); spine_skeleton_dispose(skeleton);
spine_skeleton_data_result_dispose(result); spine_skeleton_data_result_dispose(result);
spine_atlas_dispose(atlas); spine_atlas_result_dispose(atlasResult);
return 1; return 1;
} }
spine_animation_state_set_animation_1(state, 0, animationName, 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_animation_state_data_dispose(stateData);
spine_skeleton_dispose(skeleton); spine_skeleton_dispose(skeleton);
spine_skeleton_data_result_dispose(result); spine_skeleton_data_result_dispose(result);
spine_atlas_dispose(atlas); spine_atlas_result_dispose(atlasResult);
return 0; return 0;
} }

View File

@ -91,11 +91,12 @@ int main() {
// Load the atlas and the skeleton data // Load the atlas and the skeleton data
int atlas_length = 0; int atlas_length = 0;
uint8_t *atlas_bytes = read_file("data/spineboy-pma.atlas", &atlas_length); 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; int skeleton_length = 0;
// uint8_t *skeleton_bytes = read_file("data/spineboy-pro.skel", &skeleton_length); // 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); // 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); 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_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); spine_skeleton_data skeleton_data = spine_skeleton_data_result_get_data(result2);