A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
SceneManager.cc
1#include "SceneManager.hh"
2
3#include "egg/core/ExpHeap.hh"
4#include "egg/core/FrmHeap.hh"
5
6namespace Kinoko::EGG {
7
8/*------------*
9 Lifecycle
10 *------------*/
11
13SceneManager::SceneManager(SceneCreator *creator) {
14 m_creator = creator;
15 m_currentScene = nullptr;
16}
17
18SceneManager::~SceneManager() = default;
19
20/*----------*
21 Virtual
22 *----------*/
23
25void SceneManager::calc() {
26 calcCurrentScene();
27}
28
30void SceneManager::calcCurrentScene() {
31 if (!m_currentScene) {
32 return;
33 }
34
35 m_currentScene->calc();
36}
37
38/*----------*
39 Methods
40 *----------*/
41
43void SceneManager::createChildScene(int id, Scene *parent) {
44 outgoingParentScene(parent);
45 setNextSceneId(id);
46 setupNextSceneId();
47 createScene(id, parent);
48}
49
51void SceneManager::createScene(int id, Scene *parent) {
52 Heap *parentHeap = parent ? parent->heap() : s_rootHeap;
53
54 // We need to preserve the locked status to reinstate it later
55 bool locked = parentHeap->tstDisableAllocation();
56 if (locked) {
57 parentHeap->enableAllocation();
58 }
59
60#ifdef BUILD_DEBUG
61 ExpHeap *newHeap = ExpHeap::create(-1, parentHeap, s_heapOptionFlg);
62#else
63 Heap *newHeap = nullptr;
64 if (parentHeap == s_rootHeap) {
65 // The RootScene needs to have ExpHeap or else we can't delete the child FrmHeap
66 newHeap = ExpHeap::create(-1, parentHeap, s_heapOptionFlg);
67 } else {
68 newHeap = FrmHeap::create(-1, parentHeap, s_heapOptionFlg);
69 }
70#endif
71 s_heapForCreateScene = newHeap;
72
73 if (locked) {
74 parentHeap->disableAllocation();
75 }
76
77 newHeap->becomeCurrentHeap();
78 newHeap->setName("DefaultSceneHeap");
79
80 Scene *newScene = m_creator->create(id);
81
82 if (parent) {
83 parent->setChild(newScene);
84 }
85
86 m_currentScene = newScene;
87 newScene->setId(id);
88 newScene->setParent(parent);
89 newScene->setSceneMgr(this);
90 newScene->enter();
91}
92
94void SceneManager::destroyScene(Scene *scene) {
95 scene->exit();
96 if (scene->child()) {
97 destroyScene(scene->child());
98 }
99
100 Scene *parent = scene->parent();
101 m_creator->destroy(scene->id());
102
103 // ADDED: The original library does not actually delete the scene, but we run into leaks
104 // So, we delete the scene that's provided to the function
105 auto *heap = scene->heap();
106 EGG::egg_delete(scene);
107
108 m_currentScene = nullptr;
109
110 if (parent) {
111 parent->setChild(nullptr);
112 m_currentScene = parent;
113 }
114
115 heap->destroy();
116 Heap *parentHeap = parent ? parent->heap() : s_rootHeap;
117 parentHeap->becomeCurrentHeap();
118}
119
121void SceneManager::changeScene(int nextSceneId) {
122 while (m_currentScene) {
123 destroyCurrentSceneNoIncoming(true);
124 }
125
126 changeSiblingScene(nextSceneId);
127}
128
130void SceneManager::changeSiblingScene(int nextSceneId) {
131 setNextSceneId(nextSceneId);
132 changeSiblingScene();
133}
134
136void SceneManager::changeSiblingScene() {
137 Scene *parentScene = m_currentScene ? m_currentScene->parent() : nullptr;
138
139 if (m_currentScene) {
140 destroyScene(m_currentScene);
141 m_currentScene = nullptr;
142 }
143
144 int nextSceneId = m_nextSceneId;
145 setupNextSceneId();
146 createScene(nextSceneId, parentScene);
147}
148
150void SceneManager::incomingCurrentScene() {
151 if (!m_currentScene) {
152 return;
153 }
154
155 m_currentScene->incoming_childDestroy();
156}
157
159void SceneManager::outgoingParentScene(Scene *parent) {
160 parent->outgoing_childCreate();
161}
162
164void SceneManager::reinitCurrentScene() {
165 if (!m_currentScene) {
166 return;
167 }
168
169 m_currentScene->reinit();
170}
171
173bool SceneManager::destroyCurrentSceneNoIncoming(bool destroyRootIfNoParent) {
174 if (!m_currentScene) {
175 return false;
176 }
177
178 Scene *parent = m_currentScene->parent();
179 if (parent) {
180 destroyScene(parent->child());
181 setNextSceneId(parent->id());
182 setupNextSceneId();
183 return true;
184 } else {
185 if (destroyRootIfNoParent) {
186 destroyScene(m_currentScene);
187 setNextSceneId(-1);
188 setupNextSceneId();
189 }
190 return false;
191 }
192}
193
195bool SceneManager::destroyToSelectSceneId(int id) {
196 Scene *parent = findParentScene(id);
197 if (!parent) {
198 return false;
199 }
200
201 while (parent->id() != currentSceneId()) {
202 destroyCurrentSceneNoIncoming(false);
203 }
204 incomingCurrentScene();
205 return true;
206}
207
209Scene *SceneManager::findParentScene(int id) const {
210 Scene *scene = m_currentScene->parent();
211 for (; scene; scene = scene->parent()) {
212 if (scene->id() == id) {
213 break;
214 }
215 }
216
217 return scene;
218}
219
221void SceneManager::setupNextSceneId() {
222 m_prevSceneId = m_currentSceneId;
223 m_currentSceneId = m_nextSceneId;
224 m_nextSceneId = -1;
225}
226
227Heap *SceneManager::s_heapForCreateScene = nullptr;
228u16 SceneManager::s_heapOptionFlg = DEFAULT_OPT;
229
230Heap *SceneManager::s_rootHeap = nullptr;
231
232} // namespace Kinoko::EGG
A high-level representation of a memory heap for managing dynamic memory allocation....
Definition Heap.hh:25
Interface for creating and destroying scenes.
Base class for all scenes.
Definition Scene.hh:16
EGG core library.
Definition Allocator.hh:5