Sun, 16 Nov 2025 21:12:20 +0100
behaviors do not need names
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * Copyright 2025 Mike Becker. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "ascension/behavior.h" #include "ascension/context.h" #include "ascension/scene.h" #include "ascension/util.h" #include "ascension/error.h" #include <cx/linked_list.h> #include <cx/tree.h> #include <assert.h> static void asc_behavior_destroy(void *b) { AscBehavior *behavior = b; asc_dprintf("Destroy behavior: %"CX_PRIstr, CX_SFMT(behavior->name)); cx_strfree(&behavior->name); if (behavior->destroy_func) { behavior->destroy_func(behavior); } } static CxList *asc_behavior_new_list(void) { CxList *list = cxLinkedListCreateSimple(sizeof(AscBehavior)); cxDefineDestructor(list, asc_behavior_destroy); return list; } AscBehavior *asc_behavior_add_(AscSceneNode *node, struct asc_behavior_create_args args) { if (node->behaviors == NULL) { node->behaviors = asc_behavior_new_list(); } AscBehavior *behavior = cxListEmplace(node->behaviors); assert(behavior != NULL); behavior->enabled = !args.start_disabled; behavior->always_enabled = args.always_enabled; behavior->killed = false; behavior->reactivated = false; behavior->node = node; behavior->func = args.func; behavior->destroy_func = args.destroy_func; behavior->data = args.data; behavior->interval = args.interval; behavior->last_execution = 0; behavior->disable_while_hidden = args.disable_while_hidden; behavior->name = args.name == NULL ? asc_util_gen_name("behavior") : cx_mutstr(strdup(args.name)); asc_dprintf("Create behavior: %"CX_PRIstr, CX_SFMT(behavior->name)); return behavior; } void asc_behavior_remove(AscBehavior *behavior) { asc_dprintf("Remove behavior: %"CX_PRIstr, CX_SFMT(behavior->name)); behavior->killed = true; behavior->enabled = false; } void asc_behavior_trigger(AscBehavior *behavior) { // the behavior is not enabled at the moment if (!behavior->enabled) { behavior->reactivated = true; return; } // the behavior is not scheduled for execution if (behavior->last_execution + behavior->interval > asc_context.total_nanos) { return; } // the behavior is disabled while the node is hidden if (!behavior->always_enabled && behavior->disable_while_hidden && asc_scene_node_is_hidden(behavior->node)) { behavior->reactivated = true; return; } behavior->func(behavior); behavior->reactivated = false; behavior->last_execution = asc_context.total_nanos; } void asc_behavior_enable_all(AscSceneNode *node) { CxIterator iter = cxListIterator(node->behaviors); cx_foreach(AscBehavior*, behavior, iter) { asc_behavior_enable(behavior); } } void asc_behavior_disable_all(AscSceneNode *node) { CxIterator iter = cxListIterator(node->behaviors); cx_foreach(AscBehavior*, behavior, iter) { asc_behavior_disable(behavior); } } void asc_behavior_disable_all_while_hidden(AscSceneNode *node) { CxIterator iter = cxListIterator(node->behaviors); cx_foreach(AscBehavior*, behavior, iter) { asc_behavior_disable_while_hidden(behavior); } } void asc_behavior_enable_all_while_hidden(AscSceneNode *node) { CxIterator iter = cxListIterator(node->behaviors); cx_foreach(AscBehavior*, behavior, iter) { asc_behavior_enable_while_hidden(behavior); } }