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 } |