src/scene.c

changeset 27
4ccf4703999e
parent 21
1a47c57666f5
child 29
1d001eb694dc
equal deleted inserted replaced
26:139dac8ef9ee 27:4ccf4703999e
26 */ 26 */
27 27
28 #include "ascension/scene.h" 28 #include "ascension/scene.h"
29 #include "ascension/error.h" 29 #include "ascension/error.h"
30 30
31 #include <cx/linked_list.h>
32 #include <assert.h> 31 #include <assert.h>
33 32
34 void asc_scene_init(AscScene *scene) { 33 void asc_scene_init(AscScene *scene) {
35 if (scene->root != NULL) { 34 if (scene->root != NULL) {
36 asc_error("Scene is already initialized."); 35 asc_error("Scene is already initialized.");
42 void asc_scene_destroy(AscScene *scene) { 41 void asc_scene_destroy(AscScene *scene) {
43 asc_scene_node_free(scene->root); 42 asc_scene_node_free(scene->root);
44 } 43 }
45 44
46 AscSceneNode *asc_scene_node_create(AscSceneNode *parent) { 45 AscSceneNode *asc_scene_node_create(AscSceneNode *parent) {
47 AscSceneNode *node = malloc(sizeof(AscSceneNode)); 46 // TODO: check if this can remain a calloc or if it's too expensive
47 AscSceneNode *node = calloc(1, sizeof(AscSceneNode));
48 assert(node != NULL); 48 assert(node != NULL);
49 node->children = cxLinkedListCreateSimple(CX_STORE_POINTERS);
50 assert(node->children != NULL);
51 node->parent = NULL;
52 asc_scene_node_link(node, parent); 49 asc_scene_node_link(node, parent);
53 return node; 50 return node;
54 } 51 }
55 52
56 void asc_scene_node_free(AscSceneNode *node) { 53 void asc_scene_node_free(AscSceneNode *node) {
57 if (node == NULL) return; 54 if (node == NULL) return;
58 while (cxListSize(node->children) > 0) { 55
59 AscSceneNode *child = cxListAt(node->children, 0); 56 // free the children recursively
60 asc_scene_node_free(child); 57 while (node->children != NULL) {
58 asc_scene_node_free(node->children);
61 } 59 }
62 if (node->parent != NULL) { 60
63 cxListFindRemove(node->parent->children, node); 61 // remove this node from its parent
64 } 62 asc_scene_node_unlink(node);
63
64 // free the node
65 free(node); 65 free(node);
66 } 66 }
67 67
68 void asc_scene_node_link( 68 void asc_scene_node_link(
69 AscSceneNode *node, 69 AscSceneNode *node,
70 AscSceneNode *parent 70 AscSceneNode *parent
71 ) { 71 ) {
72 if (node->parent == parent) return; 72 if (node->parent == parent) return;
73 if (node->parent != NULL || parent == NULL) asc_scene_node_unlink(node); 73 if (node->parent != NULL || parent == NULL) asc_scene_node_unlink(node);
74 if (parent != NULL) { 74 if (parent != NULL) {
75 cxListAdd(parent->children, node); 75 if (parent->children == NULL) {
76 parent->children = node;
77 } else {
78 parent->children->prev = node;
79 node->next = parent->children;
80 }
76 node->parent = parent; 81 node->parent = parent;
77 } 82 }
78 } 83 }
79 84
80 void asc_scene_node_unlink(AscSceneNode *node) { 85 void asc_scene_node_unlink(AscSceneNode *node) {
81 if (node->parent == NULL) return; 86 if (node->parent == NULL) return;
82 cxListFindRemove(node->parent->children, node); 87 AscSceneNode *left = node->prev;
83 node->parent = NULL; 88 AscSceneNode *right = node->next;
89 assert(left == NULL || node->parent->children != node);
90 if (left != NULL) {
91 left->next = right;
92 } else {
93 node->parent->children = right;
94 }
95 if (right != NULL) right->prev = left;
96 node->parent = node->prev = node->next = NULL;
84 } 97 }

mercurial