src/scene.c

changeset 29
1d001eb694dc
parent 27
4ccf4703999e
child 30
fceda550ebcb
equal deleted inserted replaced
28:8acde7d27904 29:1d001eb694dc
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/tree.h>
32
31 #include <assert.h> 33 #include <assert.h>
34
35 #define asc_scene_node_layout \
36 offsetof(AscSceneNode, parent), offsetof(AscSceneNode, children), \
37 offsetof(AscSceneNode, prev), offsetof(AscSceneNode, next)
32 38
33 void asc_scene_init(AscScene *scene) { 39 void asc_scene_init(AscScene *scene) {
34 if (scene->root != NULL) { 40 if (scene->root != NULL) {
35 asc_error("Scene is already initialized."); 41 asc_error("Scene is already initialized.");
36 return; 42 return;
37 } 43 }
38 scene->root = asc_scene_node_create(NULL); 44 scene->root = asc_scene_node_empty();
39 } 45 }
40 46
41 void asc_scene_destroy(AscScene *scene) { 47 void asc_scene_destroy(AscScene *scene) {
42 asc_scene_node_free(scene->root); 48 asc_scene_node_free(scene->root);
43 } 49 }
44 50
45 AscSceneNode *asc_scene_node_create(AscSceneNode *parent) { 51 void asc_scene_add(AscScene *scene, AscSceneNode *node) {
52 asc_scene_node_link(scene->root, node);
53 }
54
55 static void asc_scene_draw_node(AscSceneNode *node) {
56 if (node->draw_func != NULL) {
57 node->draw_func(node);
58 }
59 if (node->children != NULL) {
60 asc_scene_draw_node(node->children);
61 }
62 if (node->next != NULL) {
63 asc_scene_draw_node(node->next);
64 }
65 }
66
67 void asc_scene_draw(AscScene const *scene) {
68 // TODO: replace with UCX tree visitor
69 // TODO: don't visit the tree, visit the render groups
70 // TODO: avoid recursion
71 asc_scene_draw_node(scene->root);
72 }
73
74 AscSceneNode *asc_scene_node_empty(void) {
46 // TODO: check if this can remain a calloc or if it's too expensive 75 // TODO: check if this can remain a calloc or if it's too expensive
47 AscSceneNode *node = calloc(1, sizeof(AscSceneNode)); 76 AscSceneNode *node = calloc(1, sizeof(AscSceneNode));
48 assert(node != NULL); 77 assert(node != NULL);
49 asc_scene_node_link(node, parent); 78 node->free_func = (asc_scene_free_func) free;
50 return node; 79 return node;
51 } 80 }
52 81
53 void asc_scene_node_free(AscSceneNode *node) { 82 void asc_scene_node_free(AscSceneNode *node) {
54 if (node == NULL) return; 83 if (node == NULL) return;
84
85 // TODO: replace with UCX tree visitor
86 // TODO: avoid recursion
55 87
56 // free the children recursively 88 // free the children recursively
57 while (node->children != NULL) { 89 while (node->children != NULL) {
58 asc_scene_node_free(node->children); 90 asc_scene_node_free(node->children);
59 } 91 }
60 92
61 // remove this node from its parent 93 // remove this node from its parent
62 asc_scene_node_unlink(node); 94 asc_scene_node_unlink(node);
63 95
64 // free the node 96 // free the node
65 free(node); 97 if (node->free_func != NULL) {
66 } 98 node->free_func(node);
67
68 void asc_scene_node_link(
69 AscSceneNode *node,
70 AscSceneNode *parent
71 ) {
72 if (node->parent == parent) return;
73 if (node->parent != NULL || parent == NULL) asc_scene_node_unlink(node);
74 if (parent != NULL) {
75 if (parent->children == NULL) {
76 parent->children = node;
77 } else {
78 parent->children->prev = node;
79 node->next = parent->children;
80 }
81 node->parent = parent;
82 } 99 }
83 } 100 }
84 101
102 void asc_scene_node_link(AscSceneNode * restrict parent, AscSceneNode * restrict node) {
103 cx_tree_link(parent, node, asc_scene_node_layout);
104 }
105
85 void asc_scene_node_unlink(AscSceneNode *node) { 106 void asc_scene_node_unlink(AscSceneNode *node) {
86 if (node->parent == NULL) return; 107 cx_tree_unlink(node, asc_scene_node_layout);
87 AscSceneNode *left = node->prev;
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;
97 } 108 }

mercurial