--- a/src/scene_node.c Sun Jul 13 17:17:15 2025 +0200 +++ b/src/scene_node.c Mon Jul 14 21:56:53 2025 +0200 @@ -55,6 +55,9 @@ static void asc_scene_node_destroy(AscSceneNode *node) { cxListFree(node->behaviors); + if (node->user_data_free_func != NULL) { + node->user_data_free_func((void*)node->user_data_allocator, node->user_data); + } if (node->destroy_func != NULL) { node->destroy_func(node); } @@ -135,7 +138,7 @@ offsetof(AscSceneNode, prev), offsetof(AscSceneNode, next) ); - asc_node_update_transform(node); + asc_scene_node_update_transform(node); } void asc_scene_node_unlink(AscSceneNode *node) { @@ -147,14 +150,14 @@ offsetof(AscSceneNode, prev), offsetof(AscSceneNode, next) ); - asc_node_update_transform(node); + asc_scene_node_update_transform(node); } -void asc_node_update(AscSceneNode *node) { +void asc_scene_node_update(AscSceneNode *node) { asc_set_flag(node->flags, ASC_SCENE_NODE_UPDATE_GRAPHICS); } -void asc_node_update_transform(AscSceneNode *node) { +void asc_scene_node_update_transform(AscSceneNode *node) { // fast skip if node is already marked if (asc_test_flag(node->flags, ASC_SCENE_NODE_UPDATE_TRANSFORM)) { return; @@ -168,3 +171,15 @@ asc_set_flag(n->flags, ASC_SCENE_NODE_UPDATE_TRANSFORM); } } + +void asc_scene_node_allocate_data(AscSceneNode *node, size_t n) { + if (node->user_data != NULL) { + asc_dprintf("WARNING: Node %"CX_PRIstr" already has user data!", CX_SFMT(node->name)); + if (node->user_data_free_func != NULL) { + node->user_data_free_func((void*)node->user_data_allocator, node->user_data); + } + } + node->user_data = cxZallocDefault(n); + node->user_data_allocator = cxDefaultAllocator; + node->user_data_free_func = (cx_destructor_func2) cxFree; +} \ No newline at end of file