Thu, 09 Oct 2025 19:15:02 +0200
make behaviors aware of being unpaused
demo/snake/snake.c | file | annotate | diff | comparison | revisions | |
src/ascension/behavior.h | file | annotate | diff | comparison | revisions | |
src/behavior.c | file | annotate | diff | comparison | revisions |
--- a/demo/snake/snake.c Thu Oct 09 19:03:32 2025 +0200 +++ b/demo/snake/snake.c Thu Oct 09 19:15:02 2025 +0200 @@ -192,9 +192,7 @@ } static void game_over_text_keep_centered(AscBehavior *behavior) { - if (!asc_active_window->resized) return; - - // TODO: if we could react on some sort of "unhidden" event, we could pause this behavior while hidden + if (!behavior->unpaused && !asc_active_window->resized) return; AscSceneNode *node = behavior->node; // center the "game over" text in the game field viewport @@ -207,16 +205,16 @@ static AscSceneNode *game_over_create_text(void) { AscSceneNode *node = asc_text( - .name = "game_over_text", - .text = "Game Over\nPress R to Restart", - .color = ASC_RGB(1, 1, 1), - .font = asc_font(ASC_FONT_REGULAR, 36), - .alignment = ASC_TEXT_ALIGN_CENTER, - .centered = true, - ); + .name = "game_over_text", + .text = "Game Over\nPress R to Restart", + .color = ASC_RGB(1, 1, 1), + .font = asc_font(ASC_FONT_REGULAR, 36), + .alignment = ASC_TEXT_ALIGN_CENTER, + .centered = true, + ); asc_scene_node_hide(node); - asc_behavior_add(node, game_over_text_keep_centered); + asc_behavior_add(node, game_over_text_keep_centered, .pause_while_hidden = true); asc_ui_add_node(node); return node;
--- a/src/ascension/behavior.h Thu Oct 09 19:03:32 2025 +0200 +++ b/src/ascension/behavior.h Thu Oct 09 19:15:02 2025 +0200 @@ -43,6 +43,9 @@ asc_behavior_func func; asc_behavior_destroy_func destroy_func; void *data; + /** + * Game tick of the last execution (zero when the behavior was not yet executed). + */ uint64_t last_execution; uint64_t interval; cxmutstr name; @@ -50,6 +53,10 @@ bool always_enabled; bool enabled; bool killed; + /** + * Indicates whether the next execution is the first execution after the behavior has been disabled temporarily. + */ + bool unpaused; }; struct asc_behavior_create_args {
--- a/src/behavior.c Thu Oct 09 19:03:32 2025 +0200 +++ b/src/behavior.c Thu Oct 09 19:15:02 2025 +0200 @@ -63,6 +63,7 @@ behavior->enabled = !args.start_disabled; behavior->always_enabled = args.always_enabled; behavior->killed = false; + behavior->unpaused = false; behavior->node = node; behavior->func = args.func; behavior->destroy_func = args.destroy_func; @@ -82,11 +83,23 @@ } void asc_behavior_trigger(AscBehavior *behavior) { - if (!behavior->enabled) return; - if (behavior->last_execution + behavior->interval > asc_context.total_nanos) return; - if (!behavior->always_enabled && behavior->pause_while_hidden && asc_scene_node_is_hidden(behavior->node)) return; + // the behavior is not enabled at the moment + if (!behavior->enabled) { + behavior->unpaused = true; + return; + } + // the behavior is not scheduled for execution + if (behavior->last_execution + behavior->interval > asc_context.total_nanos) { + return; + } + // the behavior is paused while the node is hidden + if (!behavior->always_enabled && behavior->pause_while_hidden && asc_scene_node_is_hidden(behavior->node)) { + behavior->unpaused = true; + return; + } behavior->func(behavior); + behavior->unpaused = false; behavior->last_execution = asc_context.total_nanos; }