Sun, 21 Jan 2024 13:58:23 +0100
improve implementation of scene graph tree
src/ascension/scene.h | file | annotate | diff | comparison | revisions | |
src/scene.c | file | annotate | diff | comparison | revisions |
--- a/src/ascension/scene.h Sun Jan 21 13:34:49 2024 +0100 +++ b/src/ascension/scene.h Sun Jan 21 13:58:23 2024 +0100 @@ -28,11 +28,11 @@ #ifndef ASCENSION_SCENE_H #define ASCENSION_SCENE_H -#include <cx/list.h> - typedef struct AscSceneNode { struct AscSceneNode *parent; - CxList *children; + struct AscSceneNode *prev; + struct AscSceneNode *next; + struct AscSceneNode *children; // TODO: add node contents } AscSceneNode;
--- a/src/scene.c Sun Jan 21 13:34:49 2024 +0100 +++ b/src/scene.c Sun Jan 21 13:58:23 2024 +0100 @@ -28,7 +28,6 @@ #include "ascension/scene.h" #include "ascension/error.h" -#include <cx/linked_list.h> #include <assert.h> void asc_scene_init(AscScene *scene) { @@ -44,24 +43,25 @@ } AscSceneNode *asc_scene_node_create(AscSceneNode *parent) { - AscSceneNode *node = malloc(sizeof(AscSceneNode)); + // TODO: check if this can remain a calloc or if it's too expensive + AscSceneNode *node = calloc(1, sizeof(AscSceneNode)); assert(node != NULL); - node->children = cxLinkedListCreateSimple(CX_STORE_POINTERS); - assert(node->children != NULL); - node->parent = NULL; asc_scene_node_link(node, parent); return node; } void asc_scene_node_free(AscSceneNode *node) { if (node == NULL) return; - while (cxListSize(node->children) > 0) { - AscSceneNode *child = cxListAt(node->children, 0); - asc_scene_node_free(child); + + // free the children recursively + while (node->children != NULL) { + asc_scene_node_free(node->children); } - if (node->parent != NULL) { - cxListFindRemove(node->parent->children, node); - } + + // remove this node from its parent + asc_scene_node_unlink(node); + + // free the node free(node); } @@ -72,13 +72,26 @@ if (node->parent == parent) return; if (node->parent != NULL || parent == NULL) asc_scene_node_unlink(node); if (parent != NULL) { - cxListAdd(parent->children, node); + if (parent->children == NULL) { + parent->children = node; + } else { + parent->children->prev = node; + node->next = parent->children; + } node->parent = parent; } } void asc_scene_node_unlink(AscSceneNode *node) { if (node->parent == NULL) return; - cxListFindRemove(node->parent->children, node); - node->parent = NULL; + 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; } \ No newline at end of file