]> git.lizzy.rs Git - shadowclad.git/blob - src/engine/scene.c
Also yeah divide by zero is a thing
[shadowclad.git] / src / engine / scene.c
1 /**
2  * Copyright 2020 Iwo 'Outfrost' Bujkiewicz
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8
9 #include "scene.h"
10
11 #include <stdlib.h>
12
13 #include "engine/logger.h"
14
15 Scene* currentScene = NULL;
16
17
18
19 Scene* newScene() {
20         Scene* scene = malloc(sizeof(Scene));
21         *scene = (Scene) { .parent = NULL,
22                            .numChildren = 0u,
23                            .children = NULL,
24                            .transform = identity(),
25                            .solid = NULL };
26         return scene;
27 }
28
29 void insertChildScene(Scene* scene, Scene* newChild) {
30         if (!scene || !newChild) {
31                 return;
32         }
33         if (newChild->parent) {
34                 logError(
35                         "Cannot insert Scene 0x%p as child of 0x%p, because it is already child of 0x%p",
36                         newChild,
37                         scene,
38                         newChild->parent);
39                 return;
40         }
41
42         scene->children = realloc(scene->children, ++(scene->numChildren) * sizeof(Scene*));
43         scene->children[scene->numChildren - 1] = newChild;
44
45         newChild->parent = scene;
46 }
47
48 void reparentScene(Scene* scene, Scene* newParent) {
49         if (!scene) {
50                 return;
51         }
52
53         if (scene->parent) {
54                 Scene* parent = scene->parent;
55                 size_t indexInParent = parent->numChildren;
56                 for (size_t i = 0; i < parent->numChildren; ++i) {
57                         if (parent->children[i] == scene) {
58                                 indexInParent = i;
59                                 break;
60                         }
61                 }
62                 // This includes the hopefully impossible case where parent->numChildren == 0
63                 if (indexInParent == parent->numChildren) {
64                         logError("Scene %p not found in children of parent %p", scene, parent);
65                 }
66                 else {
67                         for (size_t i = indexInParent; i < parent->numChildren - 1; ++i) {
68                                 parent->children[i] = parent->children[i + 1];
69                         }
70                         parent->children = realloc(parent->children, --(parent->numChildren) * sizeof(Scene*));
71                 }
72         }
73
74         scene->parent = NULL;
75
76         insertChildScene(newParent, scene);
77 }
78
79 Transform worldTransform(const Scene* scene) {
80         if (!scene) {
81                 logError("Cannot compute world space Transform of null Scene");
82                 return identity();
83         }
84
85         if (scene->parent) {
86                 return multiply(scene->transform, worldTransform(scene->parent));
87         }
88         else {
89                 return scene->transform;
90         }
91 }
92