galaxy 1.0.0
Real-Time C++23 Game Programming Framework. Built on data-driven design principles and agile software engineering.
Loading...
Searching...
No Matches
World.cpp
Go to the documentation of this file.
1
7
10
11#include "World.hpp"
12#include "Scene.hpp"
13
14namespace galaxy
15{
16 World::World() noexcept
17 {
18 }
19
20 World::~World() noexcept
21 {
22 clear();
23 }
24
25 std::shared_ptr<Scene> World::add(const std::string& name)
26 {
27 const auto hash = math::fnv1a(name.c_str());
28
29 if (!m_scenes.contains(hash))
30 {
31 m_scenes[hash] = std::make_shared<Scene>(name);
32 return m_scenes[hash];
33 }
34 else
35 {
36 GALAXY_LOG(GALAXY_WARN, "Tried to create a scene with a duplicate name of '{0}'.", name);
37 return nullptr;
38 }
39 }
40
41 std::shared_ptr<Scene> World::get(const std::string& name) noexcept
42 {
43 const auto hash = math::fnv1a(name.c_str());
44
45 if (m_scenes.contains(hash))
46 {
47 return m_scenes[hash];
48 }
49 else
50 {
51 GALAXY_LOG(GALAXY_WARN, "Scene '{0}' does not exist.", name);
52 return nullptr;
53 }
54 }
55
56 void World::remove(const std::string& name)
57 {
58 const auto hash = math::fnv1a(name.c_str());
59 m_scenes.erase(hash);
60 }
61
62 bool World::has(const std::string& name) noexcept
63 {
64 const auto hash = math::fnv1a(name.c_str());
65 return m_scenes.contains(hash);
66 }
67
68 void World::push(const std::string& name) noexcept
69 {
70 if (auto scene = get(name))
71 {
72 m_scene_stack.push_back(scene);
73 m_scene_stack.back()->load();
74 }
75 else
76 {
77 GALAXY_LOG(GALAXY_WARN, "Tried to push non-existent scene '{0}'.", name);
78 }
79 }
80
81 void World::pop() noexcept
82 {
83 if (m_scene_stack.size() > 0)
84 {
85 m_scene_stack.back()->unload();
86 m_scene_stack.pop_back();
87 }
88 }
89
90 void World::pop_all() noexcept
91 {
92 while (m_scene_stack.size() > 0)
93 {
94 pop();
95 }
96 }
97
98 std::shared_ptr<Scene> World::top() const noexcept
99 {
100 if (m_scene_stack.size() > 0)
101 {
102 return m_scene_stack.back();
103 }
104
105 return nullptr;
106 }
107
109 {
110 if (m_scene_stack.size() > 0)
111 {
112 return m_scene_stack.back()->update(m_registry);
113 }
114 }
115
117 {
118 if (m_scene_stack.size() > 0)
119 {
120 return m_scene_stack.back()->render();
121 }
122 }
123
125 {
126 m_scene_stack.clear();
127 m_scenes.clear();
128 }
129
131 {
132 return m_scenes;
133 }
134
136 {
137 return m_scene_stack;
138 }
139} // namespace galaxy
140
141/*
142void SceneManager::load_app(const std::string& appdata_file)
143 {
144 const auto data = core::ServiceLocator<fs::VirtualFileSystem>::ref().read(appdata_file);
145 if (!data.empty())
146 {
147 const auto decoded_zlib = math::decode_zlib(data);
148 if (!decoded_zlib.empty())
149
150 {
151 const auto decoded_base64 = math::decode_base64(decoded_zlib);
152 if (!decoded_base64.empty())
153 {
154 const auto parsed = nlohmann::json::parse(decoded_base64);
155
156 if (!parsed.empty())
157 {
158 deserialize(parsed);
159 }
160 else
161 {
162 GALAXY_LOG(GALAXY_ERROR, "Failed to parse scenemanger JSON data from memory.");
163 }
164 }
165 else
166 {
167 GALAXY_LOG(GALAXY_ERROR, "Failed to decode base64 appdata '{0}'.", appdata_file);
168 }
169 }
170 else
171 {
172 GALAXY_LOG(GALAXY_ERROR, "Failed to decode zlib appdata '{0}'.", appdata_file);
173 }
174 }
175 else
176 {
177 GALAXY_LOG(GALAXY_ERROR, "Failed to load appdata '{0}'.", appdata_file);
178 }
179 }
180
181 void SceneManager::save_app(const std::string& file)
182 {
183 const auto json = serialize();
184
185 if (!json::write(file, json))
186 {
187 GALAXY_LOG(GALAXY_ERROR, "Failed to save '{0}' to disk.", file);
188 }
189 }
190
191 void SceneManager::update()
192 {
193 for (auto&& system : m_systems)
194 {
195 system->update(m_current->m_registry.m_entt);
196
197 if (m_current->m_world.get_active())
198 {
199 system->update(m_current->m_world.get_active()->m_registry.m_entt);
200 }
201 }
202 }
203
204 void SceneManager::only_update_rendering()
205 {
206 if ((m_rendersystem_index >= 0 && m_rendersystem_index < m_systems.size()) && m_current != nullptr)
207 {
208 m_systems[m_rendersystem_index]->update(m_current->m_registry.m_entt);
209
210 if (m_current->m_world.get_active())
211 {
212 m_systems[m_rendersystem_index]->update(m_current->m_world.get_active()->m_registry.m_entt);
213 }
214 }
215 }
216
217 nlohmann::json SceneManager::serialize()
218 {
219 nlohmann::json json = "{\"scenes\":{}}"_json;
220
221 for (auto& [name, scene] : m_scenes)
222 {
223 json["scenes"][scene->m_name] = scene->serialize();
224 }
225
226 if (m_current)
227 {
228 json["current"] = m_current->m_name;
229 }
230
231 return json;
232 }
233
234 void SceneManager::deserialize(const nlohmann::json& json)
235 {
236 clear();
237
238 const auto& scenes = json.at("scenes");
239
240 m_scenes.reserve(scenes.size());
241 for (const auto& [name, data] : scenes.items())
242 {
243 auto scene = add(name);
244 if (scene)
245 {
246 scene->deserialize(data);
247 }
248 }
249
250 if (json.contains("current"))
251 {
252 set_scene(json.at("current"));
253 }
254 }
255
256 void SceneManager::load_app(const std::string& appdata_file)
257 {
258 std::ifstream in(appdata_file, std::ifstream::in);
259
260 std::stringstream buffer;
261 buffer << in.rdbuf();
262
263 auto data = buffer.str();
264 if (!data.empty())
265 {
266 if constexpr (!GALAXY_DEBUG_BUILD)
267 {
268 data = math::decode_zlib(data);
269 if (!data.empty())
270 {
271 data = math::decode_base64(data);
272 if (data.empty())
273 {
274 GALAXY_LOG(GALAXY_ERROR, "Failed to decode base64 appdata '{0}'.", appdata_file);
275 }
276 }
277 else
278 {
279 GALAXY_LOG(GALAXY_ERROR, "Failed to decode zlib appdata '{0}'.", appdata_file);
280 }
281
282 if (data.empty())
283 {
284 return;
285 }
286 }
287
288 const auto parsed = nlohmann::json::parse(data);
289
290 if (!parsed.empty())
291 {
292 deserialize(parsed);
293 }
294 else
295 {
296 GALAXY_LOG(GALAXY_ERROR, "Failed to parse scenemanger JSON data from memory.");
297 }
298 }
299 else
300 {
301 GALAXY_LOG(GALAXY_ERROR, "Failed to load appdata '{0}'.", appdata_file);
302 }
303 }
304
305 void SceneManager::save_app(const std::string& file)
306 {
307 const auto json = serialize();
308 auto data = json::dump(json);
309
310 if constexpr (!GALAXY_DEBUG_BUILD)
311 {
312 data = math::encode_base64(data);
313 if (!data.empty())
314 {
315 data = math::encode_zlib(data);
316 if (data.empty())
317 {
318 GALAXY_LOG(GALAXY_ERROR, "Failed to encode scenemanager to zlib '{0}'.", file);
319 }
320 }
321 else
322 {
323 GALAXY_LOG(GALAXY_ERROR, "Failed to encode scenemanager to base64 '{0}'.", file);
324 }
325
326 if (data.empty())
327 {
328 return;
329 }
330 }
331
332 auto& fs = entt::locator<fs::VirtualFileSystem>::value();
333 if (!fs.write(data, file))
334 {
335 GALAXY_LOG(GALAXY_ERROR, "Failed to save '{0}' to disk.", file);
336 }
337 }
338
339 nlohmann::json SceneManager::serialize()
340 {
341 auto& em = entt::locator<meta::EntityFactory>::value();
342
343 nlohmann::json json = "{\"scenes\":{}}"_json;
344
345 for (auto& [id, scene] : m_scenes)
346 {
347 json["scenes"][scene->name()] = scene->serialize();
348 }
349
350 for (auto i = 0; i < m_stack.size(); i++)
351 {
352 json["stack"][std::to_string(i)] = m_stack[i]->name();
353 }
354
355 json["entities"] = nlohmann::json::array();
356 for (const auto& [entity] : m_registry.m_entt.view<entt::entity>(entt::exclude<flags::NotSerializable>).each())
357 {
358 json["entities"].push_back(em.serialize_entity(entity, m_registry.m_entt));
359 }
360
361 return json;
362 }
363
364 void SceneManager::deserialize(const nlohmann::json& json)
365 {
366 auto& em = entt::locator<meta::EntityFactory>::value();
367
368 pop_all();
369 clear();
370
371 const auto& scenes = json.at("scenes");
372 m_scenes.reserve(scenes.size());
373 for (const auto& [name, data] : scenes.items())
374 {
375 auto scene = create(name);
376 if (scene)
377 {
378 scene->deserialize(data);
379 }
380 }
381
382 const auto& stack = json.at("stack");
383 m_stack.reserve(stack.size());
384 for (const auto& [index, name] : stack.items())
385 {
386 const auto hash = math::fnv1a(name.get<std::string>().c_str());
387 m_stack.insert(m_stack.begin() + std::stoi(index), m_scenes[hash]);
388 }
389
390 const auto& entity_json = json.at("entities");
391 for (const auto& data : entity_json)
392 {
393 const auto entity = em.deserialize_entity(data, m_registry.m_entt);
394
395 if (!m_registry.m_entt.all_of<components::Tag>(entity))
396 {
397 auto& tag = m_registry.m_entt.emplace<components::Tag>(entity);
398 tag.m_tag = "Untagged";
399 }
400 }
401 }
402*/
#define GALAXY_LOG(level, msg,...)
Definition Log.hpp:28
#define GALAXY_WARN
Definition Log.hpp:23
void remove(const std::string &name)
Remove a specific scene.
Definition World.cpp:56
void clear()
Removes all data.
Definition World.cpp:124
~World() noexcept
Destructor.
Definition World.cpp:20
std::shared_ptr< Scene > add(const std::string &name)
Add a new scene.
Definition World.cpp:25
SceneMap & get_scenes() noexcept
Get Scene storage.
Definition World.cpp:130
SceneMap m_scenes
Scene storage.
Definition World.hpp:139
SceneStack & get_scene_stack() noexcept
Get Scene stack.
Definition World.cpp:135
bool has(const std::string &name) noexcept
Does a scene exist.
Definition World.cpp:62
void pop_all() noexcept
Remove all scenes in stack.
Definition World.cpp:90
World() noexcept
Constructor.
Definition World.cpp:16
void update()
Process events and updates.
Definition World.cpp:108
void render()
Render scenes.
Definition World.cpp:116
std::shared_ptr< Scene > top() const noexcept
Get top scene in stack.
Definition World.cpp:98
void pop() noexcept
Remove scene on top of stack.
Definition World.cpp:81
std::vector< std::shared_ptr< Scene > > SceneStack
Definition World.hpp:24
void push(const std::string &name) noexcept
Push a scene onto the top of stack.
Definition World.cpp:68
std::shared_ptr< Scene > get(const std::string &name) noexcept
Get a specific scene.
Definition World.cpp:41
Registry m_registry
Entity data.
Definition World.hpp:134
ankerl::unordered_dense::map< std::uint64_t, std::shared_ptr< Scene > > SceneMap
Definition World.hpp:23
SceneStack m_scene_stack
Active scenes.
Definition World.hpp:144
constexpr bits fnv1a(const char *const str, const bits value=fnv_1a_params< bits >::offset) noexcept
Convert string to hash.
Definition FNV1a.hpp:64
Animated.cpp galaxy.
Definition Animated.cpp:16