diff -r 8acde7d27904 -r 1d001eb694dc src/scene.c --- a/src/scene.c Sun Jan 21 14:01:27 2024 +0100 +++ b/src/scene.c Tue Jan 23 21:34:12 2024 +0100 @@ -28,31 +28,63 @@ #include "ascension/scene.h" #include "ascension/error.h" +#include + #include +#define asc_scene_node_layout \ + offsetof(AscSceneNode, parent), offsetof(AscSceneNode, children), \ + offsetof(AscSceneNode, prev), offsetof(AscSceneNode, next) + void asc_scene_init(AscScene *scene) { if (scene->root != NULL) { asc_error("Scene is already initialized."); return; } - scene->root = asc_scene_node_create(NULL); + scene->root = asc_scene_node_empty(); } void asc_scene_destroy(AscScene *scene) { asc_scene_node_free(scene->root); } -AscSceneNode *asc_scene_node_create(AscSceneNode *parent) { +void asc_scene_add(AscScene *scene, AscSceneNode *node) { + asc_scene_node_link(scene->root, node); +} + +static void asc_scene_draw_node(AscSceneNode *node) { + if (node->draw_func != NULL) { + node->draw_func(node); + } + if (node->children != NULL) { + asc_scene_draw_node(node->children); + } + if (node->next != NULL) { + asc_scene_draw_node(node->next); + } +} + +void asc_scene_draw(AscScene const *scene) { + // TODO: replace with UCX tree visitor + // TODO: don't visit the tree, visit the render groups + // TODO: avoid recursion + asc_scene_draw_node(scene->root); +} + +AscSceneNode *asc_scene_node_empty(void) { // TODO: check if this can remain a calloc or if it's too expensive AscSceneNode *node = calloc(1, sizeof(AscSceneNode)); assert(node != NULL); - asc_scene_node_link(node, parent); + node->free_func = (asc_scene_free_func) free; return node; } void asc_scene_node_free(AscSceneNode *node) { if (node == NULL) return; + // TODO: replace with UCX tree visitor + // TODO: avoid recursion + // free the children recursively while (node->children != NULL) { asc_scene_node_free(node->children); @@ -62,36 +94,15 @@ asc_scene_node_unlink(node); // free the node - free(node); -} - -void asc_scene_node_link( - AscSceneNode *node, - AscSceneNode *parent -) { - if (node->parent == parent) return; - if (node->parent != NULL || parent == NULL) asc_scene_node_unlink(node); - if (parent != NULL) { - if (parent->children == NULL) { - parent->children = node; - } else { - parent->children->prev = node; - node->next = parent->children; - } - node->parent = parent; + if (node->free_func != NULL) { + node->free_func(node); } } +void asc_scene_node_link(AscSceneNode * restrict parent, AscSceneNode * restrict node) { + cx_tree_link(parent, node, asc_scene_node_layout); +} + void asc_scene_node_unlink(AscSceneNode *node) { - if (node->parent == NULL) return; - AscSceneNode *left = node->prev; - AscSceneNode *right = node->next; - assert(left == NULL || node->parent->children != node); - if (left != NULL) { - left->next = right; - } else { - node->parent->children = right; - } - if (right != NULL) right->prev = left; - node->parent = node->prev = node->next = NULL; + cx_tree_unlink(node, asc_scene_node_layout); } \ No newline at end of file