diff -r 86468a71dd73 -r e7ddb52facd3 src/scene.c --- a/src/scene.c Mon Mar 04 21:16:46 2024 +0100 +++ b/src/scene.c Wed Mar 06 23:08:03 2024 +0100 @@ -32,9 +32,6 @@ #include -#define node_layout_ \ - offsetof(AscSceneNode, parent), offsetof(AscSceneNode, children), \ - offsetof(AscSceneNode, prev), offsetof(AscSceneNode, next) #define child_list_off_ \ offsetof(AscSceneNode, children), offsetof(AscSceneNode, next) @@ -61,13 +58,22 @@ // skip the root node deliberately, we know it's just the container cxIteratorNext(iter); - // draw the children + // update the children cx_foreach(AscSceneNode*, node, iter) { + // execute behaviors, first + AscBehaviorNode *behavior = node->behaviors; + while (behavior) { + behavior->func(node); + behavior = behavior->next; + } + + // check if geometry needs update if (node->need_update && node->update_func != NULL) { node->need_update = false; asc_transform_copy(node->transform, node->parent->transform); node->update_func(node); } + // TODO: don't visit the tree for drawing, visit the render groups if (node->draw_func != NULL) { node->draw_func(node); @@ -102,9 +108,45 @@ } void asc_scene_node_link(AscSceneNode * restrict parent, AscSceneNode * restrict node) { - cx_tree_link(parent, node, node_layout_); + cx_tree_link( + parent, node, + offsetof(AscSceneNode, parent), + offsetof(AscSceneNode, children), + offsetof(AscSceneNode, prev), + offsetof(AscSceneNode, next) + ); } void asc_scene_node_unlink(AscSceneNode *node) { - cx_tree_unlink(node, node_layout_); -} \ No newline at end of file + cx_tree_unlink( + node, + offsetof(AscSceneNode, parent), + offsetof(AscSceneNode, children), + offsetof(AscSceneNode, prev), + offsetof(AscSceneNode, next) + ); +} + +AscBehaviorNode *asc_scene_add_behavior(AscSceneNode *node, asc_scene_update_func behavior) { + AscBehaviorNode *behavior_node = calloc(1, sizeof(AscBehaviorNode)); + behavior_node->func = behavior; + cx_tree_link( + node, + behavior_node, + offsetof(AscBehaviorNode, parent), + offsetof(AscSceneNode, behaviors), + offsetof(AscBehaviorNode, prev), + offsetof(AscBehaviorNode, next) + ); + return behavior_node; +} + +void asc_scene_remove_behavior(AscBehaviorNode *node) { + cx_tree_unlink( + node, + offsetof(AscBehaviorNode, parent), + offsetof(AscSceneNode, behaviors), + offsetof(AscBehaviorNode, prev), + offsetof(AscBehaviorNode, next) + ); +}