1.1 --- a/src/scene.c Sun Jan 21 14:01:27 2024 +0100 1.2 +++ b/src/scene.c Tue Jan 23 21:34:12 2024 +0100 1.3 @@ -28,31 +28,63 @@ 1.4 #include "ascension/scene.h" 1.5 #include "ascension/error.h" 1.6 1.7 +#include <cx/tree.h> 1.8 + 1.9 #include <assert.h> 1.10 1.11 +#define asc_scene_node_layout \ 1.12 + offsetof(AscSceneNode, parent), offsetof(AscSceneNode, children), \ 1.13 + offsetof(AscSceneNode, prev), offsetof(AscSceneNode, next) 1.14 + 1.15 void asc_scene_init(AscScene *scene) { 1.16 if (scene->root != NULL) { 1.17 asc_error("Scene is already initialized."); 1.18 return; 1.19 } 1.20 - scene->root = asc_scene_node_create(NULL); 1.21 + scene->root = asc_scene_node_empty(); 1.22 } 1.23 1.24 void asc_scene_destroy(AscScene *scene) { 1.25 asc_scene_node_free(scene->root); 1.26 } 1.27 1.28 -AscSceneNode *asc_scene_node_create(AscSceneNode *parent) { 1.29 +void asc_scene_add(AscScene *scene, AscSceneNode *node) { 1.30 + asc_scene_node_link(scene->root, node); 1.31 +} 1.32 + 1.33 +static void asc_scene_draw_node(AscSceneNode *node) { 1.34 + if (node->draw_func != NULL) { 1.35 + node->draw_func(node); 1.36 + } 1.37 + if (node->children != NULL) { 1.38 + asc_scene_draw_node(node->children); 1.39 + } 1.40 + if (node->next != NULL) { 1.41 + asc_scene_draw_node(node->next); 1.42 + } 1.43 +} 1.44 + 1.45 +void asc_scene_draw(AscScene const *scene) { 1.46 + // TODO: replace with UCX tree visitor 1.47 + // TODO: don't visit the tree, visit the render groups 1.48 + // TODO: avoid recursion 1.49 + asc_scene_draw_node(scene->root); 1.50 +} 1.51 + 1.52 +AscSceneNode *asc_scene_node_empty(void) { 1.53 // TODO: check if this can remain a calloc or if it's too expensive 1.54 AscSceneNode *node = calloc(1, sizeof(AscSceneNode)); 1.55 assert(node != NULL); 1.56 - asc_scene_node_link(node, parent); 1.57 + node->free_func = (asc_scene_free_func) free; 1.58 return node; 1.59 } 1.60 1.61 void asc_scene_node_free(AscSceneNode *node) { 1.62 if (node == NULL) return; 1.63 1.64 + // TODO: replace with UCX tree visitor 1.65 + // TODO: avoid recursion 1.66 + 1.67 // free the children recursively 1.68 while (node->children != NULL) { 1.69 asc_scene_node_free(node->children); 1.70 @@ -62,36 +94,15 @@ 1.71 asc_scene_node_unlink(node); 1.72 1.73 // free the node 1.74 - free(node); 1.75 -} 1.76 - 1.77 -void asc_scene_node_link( 1.78 - AscSceneNode *node, 1.79 - AscSceneNode *parent 1.80 -) { 1.81 - if (node->parent == parent) return; 1.82 - if (node->parent != NULL || parent == NULL) asc_scene_node_unlink(node); 1.83 - if (parent != NULL) { 1.84 - if (parent->children == NULL) { 1.85 - parent->children = node; 1.86 - } else { 1.87 - parent->children->prev = node; 1.88 - node->next = parent->children; 1.89 - } 1.90 - node->parent = parent; 1.91 + if (node->free_func != NULL) { 1.92 + node->free_func(node); 1.93 } 1.94 } 1.95 1.96 +void asc_scene_node_link(AscSceneNode * restrict parent, AscSceneNode * restrict node) { 1.97 + cx_tree_link(parent, node, asc_scene_node_layout); 1.98 +} 1.99 + 1.100 void asc_scene_node_unlink(AscSceneNode *node) { 1.101 - if (node->parent == NULL) return; 1.102 - AscSceneNode *left = node->prev; 1.103 - AscSceneNode *right = node->next; 1.104 - assert(left == NULL || node->parent->children != node); 1.105 - if (left != NULL) { 1.106 - left->next = right; 1.107 - } else { 1.108 - node->parent->children = right; 1.109 - } 1.110 - if (right != NULL) right->prev = left; 1.111 - node->parent = node->prev = node->next = NULL; 1.112 + cx_tree_unlink(node, asc_scene_node_layout); 1.113 } 1.114 \ No newline at end of file