| 29 #include "ascension/context.h" |
29 #include "ascension/context.h" |
| 30 #include "ascension/error.h" |
30 #include "ascension/error.h" |
| 31 |
31 |
| 32 #include <cx/tree.h> |
32 #include <cx/tree.h> |
| 33 #include <cx/linked_list.h> |
33 #include <cx/linked_list.h> |
| |
34 #include <cx/hash_map.h> |
| 34 #include <cx/printf.h> |
35 #include <cx/printf.h> |
| 35 |
36 |
| 36 #include <assert.h> |
37 #include <assert.h> |
| |
38 |
| |
39 AscSceneNodeDict *asc_scene_node_dict_create(void) { |
| |
40 return cxHashMapCreate(cxDefaultAllocator, sizeof(AscSceneNodeDictEntry), 0); |
| |
41 } |
| |
42 |
| |
43 void asc_scene_node_dict_free(AscSceneNodeDict *dict) { |
| |
44 cxMapFree(dict); |
| |
45 } |
| |
46 |
| |
47 static void asc_scene_node_dict_add(AscSceneNodeDict *dict, AscSceneNode *node) { |
| |
48 if (dict == NULL || !asc_test_flag(node->flags, ASC_SCENE_NODE_HAS_NAME)) { |
| |
49 return; |
| |
50 } |
| |
51 // TODO: add a new dict entry or add the node the the list if it's not already present |
| |
52 } |
| |
53 |
| |
54 static void asc_scene_node_dict_remove(AscSceneNodeDict *dict, AscSceneNode *node) { |
| |
55 if (dict == NULL || !asc_test_flag(node->flags, ASC_SCENE_NODE_HAS_NAME)) { |
| |
56 return; |
| |
57 } |
| |
58 // TODO: find entries for node's name and remove it from the list - erase the entry when it was the last |
| |
59 } |
| 37 |
60 |
| 38 static CxTreeIterator asc_scene_node_iterator( |
61 static CxTreeIterator asc_scene_node_iterator( |
| 39 AscSceneNode *node, |
62 AscSceneNode *node, |
| 40 bool visit_on_exit |
63 bool visit_on_exit |
| 41 ) { |
64 ) { |
| 141 asc_transform_translate3f(temp, node->position); |
164 asc_transform_translate3f(temp, node->position); |
| 142 asc_transform_apply(node->transform, temp, temp2); |
165 asc_transform_apply(node->transform, temp, temp2); |
| 143 } |
166 } |
| 144 |
167 |
| 145 void asc_scene_node_name(AscSceneNode *node, const char *name) { |
168 void asc_scene_node_name(AscSceneNode *node, const char *name) { |
| |
169 asc_scene_node_dict_remove(node->dict, node); |
| 146 cx_strfree(&node->name); |
170 cx_strfree(&node->name); |
| 147 if (name != NULL) { |
171 if (name == NULL) { |
| |
172 asc_clear_flag(node->flags, ASC_SCENE_NODE_HAS_NAME); |
| |
173 } else { |
| |
174 asc_set_flag(node->flags, ASC_SCENE_NODE_HAS_NAME); |
| 148 node->name = cx_strdup(name); |
175 node->name = cx_strdup(name); |
| |
176 asc_scene_node_dict_add(node->dict, node); |
| 149 } |
177 } |
| 150 } |
178 } |
| 151 |
179 |
| 152 cxstring asc_scene_node_get_name(AscSceneNode *node) { |
180 cxstring asc_scene_node_get_name(AscSceneNode *node) { |
| 153 if (node->name.ptr != NULL) return cx_strcast(node->name); |
181 if (node->name.ptr != NULL) return cx_strcast(node->name); |
| 166 |
194 |
| 167 return cx_strcast(node->name); |
195 return cx_strcast(node->name); |
| 168 } |
196 } |
| 169 |
197 |
| 170 void asc_scene_node_add(AscSceneNode * restrict parent, AscSceneNode * restrict node) { |
198 void asc_scene_node_add(AscSceneNode * restrict parent, AscSceneNode * restrict node) { |
| |
199 asc_scene_node_dict_add(parent->dict, node); |
| 171 cx_tree_add( |
200 cx_tree_add( |
| 172 parent, node, |
201 parent, node, |
| 173 offsetof(AscSceneNode, parent), |
202 offsetof(AscSceneNode, parent), |
| 174 offsetof(AscSceneNode, children), |
203 offsetof(AscSceneNode, children), |
| 175 offsetof(AscSceneNode, last_child), |
204 offsetof(AscSceneNode, last_child), |
| 178 ); |
207 ); |
| 179 asc_scene_node_update_transform(node); |
208 asc_scene_node_update_transform(node); |
| 180 } |
209 } |
| 181 |
210 |
| 182 void asc_scene_node_remove(AscSceneNode *node) { |
211 void asc_scene_node_remove(AscSceneNode *node) { |
| |
212 asc_scene_node_dict_remove(node->dict, node); |
| 183 cx_tree_remove( |
213 cx_tree_remove( |
| 184 node, |
214 node, |
| 185 offsetof(AscSceneNode, parent), |
215 offsetof(AscSceneNode, parent), |
| 186 offsetof(AscSceneNode, children), |
216 offsetof(AscSceneNode, children), |
| 187 offsetof(AscSceneNode, last_child), |
217 offsetof(AscSceneNode, last_child), |