prepare node (/ entity) dictionary per scene default tip

Mon, 06 Apr 2026 21:04:10 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 06 Apr 2026 21:04:10 +0200
changeset 303
21ff357e773c
parent 302
066481b8b3a5

prepare node (/ entity) dictionary per scene

src/ascension/scene.h file | annotate | diff | comparison | revisions
src/ascension/scene_node.h file | annotate | diff | comparison | revisions
src/scene.c file | annotate | diff | comparison | revisions
src/scene_node.c file | annotate | diff | comparison | revisions
--- a/src/ascension/scene.h	Mon Apr 06 20:27:11 2026 +0200
+++ b/src/ascension/scene.h	Mon Apr 06 21:04:10 2026 +0200
@@ -41,6 +41,11 @@
 typedef struct asc_scene_s {
     AscCamera *camera;
     AscSceneNode *root;
+    /**
+     * Maps names to a list of nodes that share the same name.
+     * Does not contain nodes with auto-generated names.
+     */
+    AscSceneNodeDict *nodes_dict;
     cxmutstr name;
     struct {
         CxList *render_groups[ASC_RENDER_GROUP_COUNT];
@@ -99,5 +104,7 @@
 
 void asc_scene_add_node(AscScene *scene, AscSceneNode *node);
 
+void asc_scene_remove_node(AscSceneNode *node);
+
 #endif // ASCENSION_SCENE_H
 
--- a/src/ascension/scene_node.h	Mon Apr 06 20:27:11 2026 +0200
+++ b/src/ascension/scene_node.h	Mon Apr 06 21:04:10 2026 +0200
@@ -38,6 +38,23 @@
 typedef struct asc_scene_node_s AscSceneNode;
 typedef struct asc_camera_s AscCamera; // avoids full include of camera.h
 
+
+typedef struct asc_scene_node_dict_entry_s {
+    AscSceneNode **node;
+    /**
+     * Number of nodes with the same name.
+     */
+    unsigned int count;
+} AscSceneNodeDictEntry;
+
+/**
+ * A dictionary that maps names to lists of nodes.
+ */
+typedef CxMap AscSceneNodeDict;
+
+AscSceneNodeDict *asc_scene_node_dict_create(void);
+void asc_scene_node_dict_free(AscSceneNodeDict *dict);
+
 typedef void(*asc_scene_node_destroy_func)(AscSceneNode*);
 typedef void(*asc_scene_node_update_func)(AscSceneNode*);
 typedef void(*asc_scene_node_draw_func)(const AscCamera*,const AscSceneNode*);
@@ -56,6 +73,10 @@
     AscSceneNode *next;
     AscSceneNode *children;
     AscSceneNode *last_child;
+    /**
+     * A reference to the scene's node dictionary when this node is part of a scene.
+     */
+    AscSceneNodeDict *dict;
     cxmutstr name;
     /**
      * List of AscBehavior structs.
@@ -106,6 +127,10 @@
  */
 #define ASC_SCENE_NODE_TRANSFORM_UPDATED      0x08000000
 /**
+ * The node has a name which is not auto-generated.
+ */
+#define ASC_SCENE_NODE_HAS_NAME               0x40000000
+/**
  * Set when the node is not supposed to be shown on screen.
  */
 #define ASC_SCENE_NODE_HIDDEN                 0x80000000
--- a/src/scene.c	Mon Apr 06 20:27:11 2026 +0200
+++ b/src/scene.c	Mon Apr 06 21:04:10 2026 +0200
@@ -43,7 +43,9 @@
 void asc_scene_init(AscScene *scene, const char *name, AscCamera *camera) {
     assert(scene->root == NULL);
     scene->camera = camera;
+    scene->nodes_dict = asc_scene_node_dict_create();
     scene->root = asc_scene_node_empty();
+    scene->root->dict = scene->nodes_dict;
     for (unsigned i = 0 ; i < ASC_RENDER_GROUP_COUNT ; i++) {
         scene->internal.render_groups[i] = cxArrayListCreate(NULL, CX_STORE_POINTERS, 32);
     }
@@ -61,6 +63,7 @@
         cxListFree(scene->internal.render_groups[i]);
         scene->internal.render_groups[i] = NULL;
     }
+    asc_scene_node_dict_free(scene->nodes_dict);
     asc_scene_node_free(scene->root);
     scene->root = NULL;
     asc_dprintf("Destroyed scene %"CX_PRIstr, CX_SFMT(scene->name));
--- a/src/scene_node.c	Mon Apr 06 20:27:11 2026 +0200
+++ b/src/scene_node.c	Mon Apr 06 21:04:10 2026 +0200
@@ -31,10 +31,33 @@
 
 #include <cx/tree.h>
 #include <cx/linked_list.h>
+#include <cx/hash_map.h>
 #include <cx/printf.h>
 
 #include <assert.h>
 
+AscSceneNodeDict *asc_scene_node_dict_create(void) {
+    return cxHashMapCreate(cxDefaultAllocator, sizeof(AscSceneNodeDictEntry), 0);
+}
+
+void asc_scene_node_dict_free(AscSceneNodeDict *dict) {
+    cxMapFree(dict);
+}
+
+static void asc_scene_node_dict_add(AscSceneNodeDict *dict, AscSceneNode *node) {
+    if (dict == NULL || !asc_test_flag(node->flags, ASC_SCENE_NODE_HAS_NAME)) {
+        return;
+    }
+    // TODO: add a new dict entry or add the node the the list if it's not already present
+}
+
+static void asc_scene_node_dict_remove(AscSceneNodeDict *dict, AscSceneNode *node) {
+    if (dict == NULL || !asc_test_flag(node->flags, ASC_SCENE_NODE_HAS_NAME)) {
+        return;
+    }
+    // TODO: find entries for node's name and remove it from the list - erase the entry when it was the last
+}
+
 static CxTreeIterator asc_scene_node_iterator(
         AscSceneNode *node,
         bool visit_on_exit
@@ -143,9 +166,14 @@
 }
 
 void asc_scene_node_name(AscSceneNode *node, const char *name) {
+    asc_scene_node_dict_remove(node->dict, node);
     cx_strfree(&node->name);
-    if (name != NULL) {
+    if (name == NULL) {
+        asc_clear_flag(node->flags, ASC_SCENE_NODE_HAS_NAME);
+    } else {
+        asc_set_flag(node->flags, ASC_SCENE_NODE_HAS_NAME);
         node->name = cx_strdup(name);
+        asc_scene_node_dict_add(node->dict, node);
     }
 }
 
@@ -168,6 +196,7 @@
 }
 
 void asc_scene_node_add(AscSceneNode * restrict parent, AscSceneNode * restrict node) {
+    asc_scene_node_dict_add(parent->dict, node);
     cx_tree_add(
             parent, node,
             offsetof(AscSceneNode, parent),
@@ -180,6 +209,7 @@
 }
 
 void asc_scene_node_remove(AscSceneNode *node) {
+    asc_scene_node_dict_remove(node->dict, node);
     cx_tree_remove(
             node,
             offsetof(AscSceneNode, parent),

mercurial