[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: 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

View File

@ -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<const char *>(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<const char *>(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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);