aboutsummaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorAndre Weissflog <floooh@gmail.com>2022-09-26 17:29:18 +0200
committerAndre Weissflog <floooh@gmail.com>2022-09-26 17:29:18 +0200
commitddf9aa88652dec934ba3a37bd9d2028d2fdeebc2 (patch)
treed2a0c3b2e0c764c6c59d2279b80ad68005c8ecfd /util
parentb7aed826e15e0723b69933b2004816c646ed639f (diff)
sokol_spine.h: start with skinset functions
Diffstat (limited to 'util')
-rw-r--r--util/sokol_spine.h167
1 files changed, 155 insertions, 12 deletions
diff --git a/util/sokol_spine.h b/util/sokol_spine.h
index 1c28d91b..ffb8571a 100644
--- a/util/sokol_spine.h
+++ b/util/sokol_spine.h
@@ -106,12 +106,14 @@ extern "C" {
enum {
SSPINE_INVALID_ID = 0,
+ SSPINE_MAX_SKINSET_SKINS = 32,
};
typedef struct sspine_context { uint32_t id; } sspine_context;
typedef struct sspine_atlas { uint32_t id; } sspine_atlas;
typedef struct sspine_skeleton { uint32_t id; } sspine_skeleton;
typedef struct sspine_instance { uint32_t id; } sspine_instance;
+typedef struct sspine_skinset { uint32_t id; } sspine_skinset;
typedef struct sspine_range { const void* ptr; size_t size; } sspine_range;
typedef struct sspine_vec2 { float x, y; } sspine_vec2;
@@ -198,6 +200,12 @@ typedef struct sspine_skeleton_desc {
sspine_range binary_data;
} sspine_skeleton_desc;
+typedef struct sspine_skinset_desc {
+ sspine_skeleton skeleton;
+ const char* name;
+ const char* skins[SSPINE_MAX_SKINSET_SKINS];
+} sspine_skinset_desc;
+
typedef struct sspine_anim_info {
bool valid;
const char* name;
@@ -276,6 +284,7 @@ typedef struct sspine_desc {
int context_pool_size;
int atlas_pool_size;
int skeleton_pool_size;
+ int skinset_pool_size;
int instance_pool_size;
sg_pixel_format color_format;
sg_pixel_format depth_format;
@@ -298,14 +307,20 @@ SOKOL_SPINE_API_DECL sspine_context sspine_default_context(void);
// create and destroy spine objects
SOKOL_SPINE_API_DECL sspine_atlas sspine_make_atlas(const sspine_atlas_desc* desc);
SOKOL_SPINE_API_DECL sspine_skeleton sspine_make_skeleton(const sspine_skeleton_desc* desc);
+SOKOL_SPINE_API_DECL sspine_skinset sspine_make_skinset(const sspine_skinset_desc* desc);
SOKOL_SPINE_API_DECL sspine_instance sspine_make_instance(const sspine_instance_desc* desc);
SOKOL_SPINE_API_DECL void sspine_destroy_atlas(sspine_atlas atlas);
SOKOL_SPINE_API_DECL void sspine_destroy_skeleton(sspine_skeleton skeleton);
+SOKOL_SPINE_API_DECL void sspine_destroy_skinset(sspine_skinset skinset);
SOKOL_SPINE_API_DECL void sspine_destroy_instance(sspine_instance instance);
// mark a new frame (call at start of a frame before any sspine_draw_instance())
SOKOL_SPINE_API_DECL void sspine_new_frame(void);
+// configure instance appearance via skinsets
+SOKOL_SPINE_API_DECL void sspine_set_default_skinset(sspine_instance instance);
+SOKOL_SPINE_API_DECL void sspine_set_skinset(sspine_instance instance, sspine_skinset skinset);
+
// update instance animations before drawing
SOKOL_SPINE_API_DECL void sspine_update_instance(sspine_instance instance, float delta_time);
@@ -1504,6 +1519,7 @@ static const char* _sspine_fs_source_dummy = "";
#define _SSPINE_DEFAULT_CONTEXT_POOL_SIZE (4)
#define _SSPINE_DEFAULT_ATLAS_POOL_SIZE (64)
#define _SSPINE_DEFAULT_SKELETON_POOL_SIZE (64)
+#define _SSPINE_DEFAULT_SKINSET_POOL_SIZE (64)
#define _SSPINE_DEFAULT_INSTANCE_POOL_SIZE (1024)
#define _SSPINE_DEFAULT_MAX_VERTICES (1<<16)
#define _SSPINE_DEFAULT_MAX_COMMANDS (1<<14)
@@ -1573,8 +1589,25 @@ typedef struct {
typedef struct {
_sspine_slot_t slot;
+ _sspine_skeleton_ref_t skel;
+ spSkin* sp_skin;
+} _sspine_skinset_t;
+
+typedef struct {
+ _sspine_pool_t pool;
+ _sspine_skinset_t* items;
+} _sspine_skinset_pool_t;
+
+typedef struct {
+ uint32_t id;
+ _sspine_skinset_t* ptr;
+} _sspine_skinset_ref_t;
+
+typedef struct {
+ _sspine_slot_t slot;
_sspine_atlas_ref_t atlas;
_sspine_skeleton_ref_t skel;
+ _sspine_skinset_ref_t skin;
spSkeleton* sp_skel;
spAnimationState* sp_anim_state;
spSkeletonClipping* sp_clip;
@@ -1659,6 +1692,7 @@ typedef struct {
_sspine_context_pool_t context_pool;
_sspine_atlas_pool_t atlas_pool;
_sspine_skeleton_pool_t skeleton_pool;
+ _sspine_skinset_pool_t skinset_pool;
_sspine_instance_pool_t instance_pool;
} _sspine_t;
static _sspine_t _sspine;
@@ -1717,6 +1751,10 @@ static bool _sspine_skeleton_ref_valid(const _sspine_skeleton_ref_t* ref) {
return ref->ptr && (ref->ptr->slot.id == ref->id);
}
+static bool _sspine_skinset_ref_valid(const _sspine_skinset_ref_t* ref) {
+ return ref->ptr && (ref->ptr->slot.id == ref->id);
+}
+
static bool _sspine_skeleton_and_deps_valid(_sspine_skeleton_t* skeleton) {
return skeleton && _sspine_atlas_ref_valid(&skeleton->atlas);
}
@@ -1865,17 +1903,15 @@ static _sspine_context_t* _sspine_lookup_context(uint32_t id) {
static sspine_context _sspine_alloc_context(void) {
_sspine_context_pool_t* p = &_sspine.context_pool;
- sspine_context res;
int slot_index = _sspine_pool_alloc_index(&p->pool);
if (_SSPINE_INVALID_SLOT_INDEX != slot_index) {
uint32_t id = _sspine_slot_init(&p->pool, &p->items[slot_index].slot, slot_index);
- res = _sspine_make_context_handle(id);
+ return _sspine_make_context_handle(id);
}
else {
// pool exhausted
- res = _sspine_make_context_handle(SSPINE_INVALID_ID);
+ return _sspine_make_context_handle(SSPINE_INVALID_ID);
}
- return res;
}
static sspine_resource_state _sspine_init_context(_sspine_context_t* ctx, const sspine_context_desc* desc) {
@@ -2033,17 +2069,15 @@ static _sspine_atlas_t* _sspine_lookup_atlas(uint32_t id) {
static sspine_atlas _sspine_alloc_atlas(void) {
_sspine_atlas_pool_t* p = &_sspine.atlas_pool;
- sspine_atlas res;
int slot_index = _sspine_pool_alloc_index(&p->pool);
if (_SSPINE_INVALID_SLOT_INDEX != slot_index) {
uint32_t id = _sspine_slot_init(&p->pool, &p->items[slot_index].slot, slot_index);
- res = _sspine_make_atlas_handle(id);
+ return _sspine_make_atlas_handle(id);
}
else {
// pool exhausted
- res = _sspine_make_atlas_handle(SSPINE_INVALID_ID);
+ return _sspine_make_atlas_handle(SSPINE_INVALID_ID);
}
- return res;
}
void _spAtlasPage_disposeTexture(spAtlasPage* self) {
@@ -2171,17 +2205,15 @@ static _sspine_skeleton_t* _sspine_lookup_skeleton(uint32_t id) {
static sspine_skeleton _sspine_alloc_skeleton(void) {
_sspine_skeleton_pool_t* p = &_sspine.skeleton_pool;
- sspine_skeleton res;
int slot_index = _sspine_pool_alloc_index(&p->pool);
if (_SSPINE_INVALID_SLOT_INDEX != slot_index) {
uint32_t id = _sspine_slot_init(&p->pool, &p->items[slot_index].slot, slot_index);
- res = _sspine_make_skeleton_handle(id);
+ return _sspine_make_skeleton_handle(id);
}
else {
// pool exhausted
- res = _sspine_make_skeleton_handle(SSPINE_INVALID_ID);
+ return _sspine_make_skeleton_handle(SSPINE_INVALID_ID);
}
- return res;
}
static sspine_resource_state _sspine_init_skeleton(_sspine_skeleton_t* skeleton, const sspine_skeleton_desc* desc) {
@@ -2297,6 +2329,114 @@ static sspine_skeleton_desc _sspine_skeleton_desc_defaults(const sspine_skeleton
return res;
}
+//=== SKINSET POOL FUNCTIONS ===================================================
+static void _sspine_setup_skinset_pool(int pool_size) {
+ _sspine_skinset_pool_t* p = &_sspine.skinset_pool;
+ _sspine_init_item_pool(&p->pool, pool_size, (void**)&p->items, sizeof(_sspine_skinset_t));
+}
+
+static void _sspine_discard_skinset_pool(void) {
+ _sspine_skinset_pool_t* p = &_sspine.skinset_pool;
+ _sspine_discard_item_pool(&p->pool, (void**)&p->items);
+}
+
+static sspine_skinset _sspine_make_skinset_handle(uint32_t id) {
+ sspine_skinset handle = { id };
+ return handle;
+}
+
+static _sspine_skinset_t* _sspine_skinset_at(uint32_t id) {
+ SOKOL_ASSERT(SSPINE_INVALID_ID != id);
+ const _sspine_skinset_pool_t* p = &_sspine.skinset_pool;
+ int slot_index = _sspine_slot_index(id);
+ SOKOL_ASSERT((slot_index > _SSPINE_INVALID_SLOT_INDEX) && (slot_index < p->pool.size));
+ return &p->items[slot_index];
+}
+
+static _sspine_skinset_t* _sspine_lookup_skinset(uint32_t id) {
+ if (SSPINE_INVALID_ID != id) {
+ _sspine_skinset_t* skinset = _sspine_skinset_at(id);
+ if (skinset->slot.id == id) {
+ return skinset;
+ }
+ }
+ return 0;
+}
+
+static sspine_skinset _sspine_alloc_skinset(void) {
+ _sspine_skinset_pool_t* p = &_sspine.skinset_pool;
+ int slot_index = _sspine_pool_alloc_index(&p->pool);
+ if (_SSPINE_INVALID_SLOT_INDEX != slot_index) {
+ uint32_t id = _sspine_slot_init(&p->pool, &p->items[slot_index].slot, slot_index);
+ return _sspine_make_skinset_handle(id);
+ }
+ else {
+ // pool exhausted
+ return _sspine_make_skinset_handle(SSPINE_INVALID_ID);
+ }
+}
+
+static sspine_resource_state _sspine_init_skinset(_sspine_skinset_t* skinset, const sspine_skinset_desc* desc) {
+ SOKOL_ASSERT(skinset && (skinset->slot.state == SSPINE_RESOURCESTATE_ALLOC));
+ SOKOL_ASSERT(desc && desc->name);
+ skinset->skel.id = desc->skeleton.id;
+ skinset->skel.ptr = _sspine_lookup_skeleton(desc->skeleton.id);
+ if (!_sspine_skeleton_ref_valid(&skinset->skel)) {
+ return SSPINE_RESOURCESTATE_FAILED;
+ }
+ _sspine_skeleton_t* skel = skinset->skel.ptr;
+ if (SSPINE_RESOURCESTATE_VALID != skel->slot.state) {
+ return SSPINE_RESOURCESTATE_FAILED;
+ }
+ SOKOL_ASSERT(skel->sp_skel_data);
+ skinset->sp_skin = spSkin_create(desc->name);
+ for (int i = 0; i < SSPINE_MAX_SKINSET_SKINS; i++) {
+ if (desc->skins[i]) {
+ spSkin* skin = spSkeletonData_findSkin(skel->sp_skel_data, desc->skins[i]);
+ if (0 == skin) {
+ return SSPINE_RESOURCESTATE_FAILED;
+ }
+ spSkin_addSkin(skinset->sp_skin, skin);
+ }
+ else {
+ break;
+ }
+ }
+ return SSPINE_RESOURCESTATE_VALID;
+}
+
+static void _sspine_deinit_skinset(_sspine_skinset_t* skinset) {
+ if (skinset->sp_skin) {
+ spSkin_clear(skinset->sp_skin);
+ spSkin_dispose(skinset->sp_skin);
+ skinset->sp_skin = 0;
+ }
+}
+
+static void _sspine_destroy_skinset(sspine_skinset skinset_id) {
+ _sspine_skinset_t* skinset = _sspine_lookup_skinset(skinset_id.id);
+ if (skinset) {
+ _sspine_deinit_skinset(skinset);
+ _sspine_skinset_pool_t* p = &_sspine.skinset_pool;
+ _sspine_clear(skinset, sizeof(_sspine_skinset_t));
+ _sspine_pool_free_index(&p->pool, _sspine_slot_index(skinset_id.id));
+ }
+}
+
+static void _sspine_destroy_all_skinsets(void) {
+ _sspine_skinset_pool_t* p = &_sspine.skinset_pool;
+ for (int i = 0; i < p->pool.size; i++) {
+ _sspine_skinset_t* skinset = &p->items[i];
+ _sspine_destroy_skinset(_sspine_make_skinset_handle(skinset->slot.id));
+ }
+}
+
+static sspine_skinset_desc _sspine_skinset_desc_defaults(const sspine_skinset_desc* desc) {
+ sspine_skinset_desc res = *desc;
+ res.name = _sspine_def(desc->name, "skinset");
+ return res;
+}
+
//=== INSTANCE POOL FUNCTIONS ==================================================
static void _sspine_setup_instance_pool(int pool_size) {
_sspine_instance_pool_t* p = &_sspine.instance_pool;
@@ -2592,6 +2732,7 @@ static sspine_desc _sspine_desc_defaults(const sspine_desc* desc) {
res.context_pool_size = _sspine_def(desc->context_pool_size, _SSPINE_DEFAULT_CONTEXT_POOL_SIZE);
res.atlas_pool_size = _sspine_def(desc->atlas_pool_size, _SSPINE_DEFAULT_ATLAS_POOL_SIZE);
res.skeleton_pool_size = _sspine_def(desc->skeleton_pool_size, _SSPINE_DEFAULT_SKELETON_POOL_SIZE);
+ res.skinset_pool_size = _sspine_def(desc->skinset_pool_size, _SSPINE_DEFAULT_SKINSET_POOL_SIZE);
res.instance_pool_size = _sspine_def(desc->instance_pool_size, _SSPINE_DEFAULT_INSTANCE_POOL_SIZE);
return res;
}
@@ -3062,6 +3203,7 @@ SOKOL_API_IMPL void sspine_setup(const sspine_desc* desc) {
_sspine_setup_context_pool(_sspine.desc.context_pool_size);
_sspine_setup_atlas_pool(_sspine.desc.atlas_pool_size);
_sspine_setup_skeleton_pool(_sspine.desc.skeleton_pool_size);
+ _sspine_setup_skinset_pool(_sspine.desc.skinset_pool_size);
_sspine_setup_instance_pool(_sspine.desc.instance_pool_size);
const sspine_context_desc ctx_desc = _sspine_as_context_desc(&_sspine.desc);
_sspine.def_ctx_id = sspine_make_context(&ctx_desc);
@@ -3072,6 +3214,7 @@ SOKOL_API_IMPL void sspine_setup(const sspine_desc* desc) {
SOKOL_API_IMPL void sspine_shutdown(void) {
SOKOL_ASSERT(_SSPINE_INIT_COOKIE == _sspine.init_cookie);
_sspine_destroy_all_instances();
+ _sspine_destroy_all_skinsets();
_sspine_destroy_all_skeletons();
_sspine_destroy_all_atlases();
_sspine_destroy_all_contexts();