src/scene.c

changeset 29
1d001eb694dc
parent 27
4ccf4703999e
child 30
fceda550ebcb
     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

mercurial