src/scene.c

Mon, 26 Feb 2024 21:16:00 +0100

author
Mike Becker <universe@uap-core.de>
date
Mon, 26 Feb 2024 21:16:00 +0100
changeset 31
8324037e0148
parent 30
fceda550ebcb
child 32
86468a71dd73
permissions
-rw-r--r--

use tree iterator to free scene nodes

universe@21 1 /*
universe@21 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
universe@21 3 * Copyright 2023 Mike Becker. All rights reserved.
universe@21 4 *
universe@21 5 * Redistribution and use in source and binary forms, with or without
universe@21 6 * modification, are permitted provided that the following conditions are met:
universe@21 7 *
universe@21 8 * 1. Redistributions of source code must retain the above copyright
universe@21 9 * notice, this list of conditions and the following disclaimer.
universe@21 10 *
universe@21 11 * 2. Redistributions in binary form must reproduce the above copyright
universe@21 12 * notice, this list of conditions and the following disclaimer in the
universe@21 13 * documentation and/or other materials provided with the distribution.
universe@21 14 *
universe@21 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@21 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@21 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@21 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@21 19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@21 20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@21 21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@21 22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@21 23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@21 24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@21 25 * POSSIBILITY OF SUCH DAMAGE.
universe@21 26 */
universe@21 27
universe@21 28 #include "ascension/scene.h"
universe@21 29 #include "ascension/error.h"
universe@21 30
universe@29 31 #include <cx/tree.h>
universe@29 32
universe@21 33 #include <assert.h>
universe@21 34
universe@30 35 #define node_layout_ \
universe@29 36 offsetof(AscSceneNode, parent), offsetof(AscSceneNode, children), \
universe@29 37 offsetof(AscSceneNode, prev), offsetof(AscSceneNode, next)
universe@30 38 #define child_list_off_ \
universe@30 39 offsetof(AscSceneNode, children), offsetof(AscSceneNode, next)
universe@29 40
universe@21 41 void asc_scene_init(AscScene *scene) {
universe@21 42 if (scene->root != NULL) {
universe@21 43 asc_error("Scene is already initialized.");
universe@21 44 return;
universe@21 45 }
universe@29 46 scene->root = asc_scene_node_empty();
universe@21 47 }
universe@21 48
universe@21 49 void asc_scene_destroy(AscScene *scene) {
universe@21 50 asc_scene_node_free(scene->root);
universe@21 51 }
universe@21 52
universe@29 53 void asc_scene_add(AscScene *scene, AscSceneNode *node) {
universe@29 54 asc_scene_node_link(scene->root, node);
universe@29 55 }
universe@29 56
universe@30 57 void asc_scene_draw(AscScene const *scene) {
universe@30 58 // TODO: don't visit the tree, visit the render groups
universe@30 59 CxTreeIterator iter = cx_tree_iterator(scene->root, false, child_list_off_);
universe@30 60 cx_foreach(AscSceneNode*, node, iter) {
universe@30 61 if (node->draw_func != NULL) {
universe@30 62 node->draw_func(node);
universe@30 63 }
universe@29 64 }
universe@29 65 }
universe@29 66
universe@29 67 AscSceneNode *asc_scene_node_empty(void) {
universe@27 68 // TODO: check if this can remain a calloc or if it's too expensive
universe@27 69 AscSceneNode *node = calloc(1, sizeof(AscSceneNode));
universe@21 70 assert(node != NULL);
universe@29 71 node->free_func = (asc_scene_free_func) free;
universe@21 72 return node;
universe@21 73 }
universe@21 74
universe@21 75 void asc_scene_node_free(AscSceneNode *node) {
universe@21 76 if (node == NULL) return;
universe@27 77
universe@27 78 // remove this node from its parent
universe@27 79 asc_scene_node_unlink(node);
universe@27 80
universe@31 81 // free the entire subtree
universe@31 82 CxTreeIterator iter = cx_tree_iterator(node, true, child_list_off_);
universe@31 83 cx_foreach(AscSceneNode*, child, iter) {
universe@31 84 if (!iter.exiting) continue;
universe@31 85 if (child->free_func != NULL) {
universe@31 86 child->free_func(child);
universe@31 87 } else {
universe@31 88 free(child);
universe@31 89 }
universe@21 90 }
universe@21 91 }
universe@21 92
universe@29 93 void asc_scene_node_link(AscSceneNode * restrict parent, AscSceneNode * restrict node) {
universe@30 94 cx_tree_link(parent, node, node_layout_);
universe@29 95 }
universe@29 96
universe@21 97 void asc_scene_node_unlink(AscSceneNode *node) {
universe@30 98 cx_tree_unlink(node, node_layout_);
universe@21 99 }

mercurial