extract execution of behaviors from draw function default tip

Tue, 06 May 2025 23:04:54 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 06 May 2025 23:04:54 +0200
changeset 112
3e956c96dd6c
parent 111
ee4b58dfcf7f

extract execution of behaviors from draw function

fixes #646

src/ascension/behavior.h file | annotate | diff | comparison | revisions
src/ascension/scene.h file | annotate | diff | comparison | revisions
src/behavior.c file | annotate | diff | comparison | revisions
src/scene.c file | annotate | diff | comparison | revisions
src/window.c file | annotate | diff | comparison | revisions
--- a/src/ascension/behavior.h	Tue May 06 22:54:38 2025 +0200
+++ b/src/ascension/behavior.h	Tue May 06 23:04:54 2025 +0200
@@ -41,6 +41,7 @@
     asc_behavior_destroy_func destroy_func;
     AscSceneNode *node;
     void *data;
+    bool enabled;
     // TODO: more useful attributes, e.g. timing settings
 };
 
--- a/src/ascension/scene.h	Tue May 06 22:54:38 2025 +0200
+++ b/src/ascension/scene.h	Tue May 06 23:04:54 2025 +0200
@@ -65,6 +65,8 @@
     return &scene->camera;
 }
 
+void asc_scene_execute_behaviors(AscScene *scene);
+
 /**
  * Draws the scene with the specified root node.
  *
--- a/src/behavior.c	Tue May 06 22:54:38 2025 +0200
+++ b/src/behavior.c	Tue May 06 23:04:54 2025 +0200
@@ -27,8 +27,10 @@
 
 #include "ascension/behavior.h"
 #include "ascension/error.h"
+#include "ascension/scene.h"
 
 #include <cx/array_list.h>
+#include <cx/tree.h>
 
 static void asc_behavior_destroy(void *b) {
     AscBehavior *behavior = b;
@@ -54,6 +56,7 @@
         asc_error("Failed to add behavior to scene node.");
         return NULL;
     }
+    behavior->enabled = true;
     behavior->node = node;
     behavior->func = args.func;
     behavior->destroy_func = args.destroy_func;
--- a/src/scene.c	Tue May 06 22:54:38 2025 +0200
+++ b/src/scene.c	Tue May 06 23:04:54 2025 +0200
@@ -59,6 +59,21 @@
     asc_scene_node_free(scene->root);
 }
 
+void asc_scene_execute_behaviors(AscScene *scene) {
+    CxTreeVisitor iter = cx_tree_visitor(scene->root,
+        offsetof(AscSceneNode, children),
+        offsetof(AscSceneNode, next)
+    );
+    cx_foreach(AscSceneNode*, node, iter) {
+        CxIterator behavior_iter = cxListIterator(node->behaviors);
+        cx_foreach(AscBehavior*, behavior, behavior_iter) {
+            if (behavior->enabled) {
+                behavior->func(behavior);
+            }
+        }
+    }
+}
+
 void asc_scene_draw(AscScene *scene) {
     if (scene->root == NULL) return;
 
@@ -93,13 +108,6 @@
             cxTreeVisitorContinue(iter);
         }
 
-        // execute behaviors, first
-        // TODO: move to a separate iteration that is decoupled from drawing - issue #646
-        CxIterator behavior_iter = cxListIterator(node->behaviors);
-        cx_foreach(AscBehavior*, behavior, behavior_iter) {
-            behavior->func(behavior);
-        }
-
         // TODO: implement culling
 
         // check if geometry needs update
--- a/src/window.c	Tue May 06 22:54:38 2025 +0200
+++ b/src/window.c	Tue May 06 23:04:54 2025 +0200
@@ -154,6 +154,13 @@
     glViewport(0, 0, window_width, window_height);
     glClear(GL_COLOR_BUFFER_BIT);
 
+    // Execute all behaviors
+    // TODO: this can eventually be parallelized
+    for (unsigned int i = 0; i < ASC_MAX_SCENES; i++) {
+        asc_scene_execute_behaviors(&window->scenes[i]);
+    }
+    asc_scene_execute_behaviors(&window->ui);
+
     // Draw all scenes
     for (unsigned int i = 0; i < ASC_MAX_SCENES; i++) {
         asc_scene_draw(&window->scenes[i]);

mercurial