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
SceneManager.cpp
Go to the documentation of this file.
1
7
8#include <fstream>
9#include <sstream>
10
11#include <nlohmann/json.hpp>
12
17#include "galaxy/math/ZLib.hpp"
20
21#include "SceneManager.hpp"
22
23namespace galaxy
24{
25 namespace scene
26 {
28 {
29 }
30
32 {
33 clear();
34 }
35
36 std::shared_ptr<Scene> SceneManager::create(const std::string& scene)
37 {
38 const auto hash = math::fnv1a(scene.c_str());
39 if (!m_scenes.contains(hash))
40 {
41 m_scenes[hash] = std::make_shared<Scene>(scene);
42 return m_scenes[hash];
43 }
44 else
45 {
46 GALAXY_LOG(GALAXY_ERROR, "Failed to create scene '{0}'.", scene);
47 return nullptr;
48 }
49 }
50
51 void SceneManager::set(const std::string& scene)
52 {
53 pop_all();
54 push(scene);
55 }
56
57 void SceneManager::push(const std::string& scene)
58 {
59 const auto hash = math::fnv1a(scene.c_str());
60 m_stack.push_back(m_scenes[hash]);
61 m_stack.back()->load();
62 }
63
65 {
66 if (m_stack.size() > 0)
67 {
68 m_stack.back()->unload();
69 m_stack.pop_back();
70 }
71 }
72
74 {
75 while (m_stack.size() > 0)
76 {
77 pop();
78 }
79 }
80
81 std::shared_ptr<Scene> SceneManager::top() noexcept
82 {
83 return m_stack.back();
84 }
85
87 {
88 for (auto&& scene : m_stack)
89 {
90 scene->update(m_registry);
91 }
92 }
93
95 {
96 for (auto&& scene : m_stack)
97 {
98 scene->render();
99 }
100 }
101
102 void SceneManager::load_app(const std::string& appdata_file)
103 {
104 std::ifstream in(appdata_file, std::ifstream::in);
105
106 std::stringstream buffer;
107 buffer << in.rdbuf();
108
109 auto data = buffer.str();
110 if (!data.empty())
111 {
112 if constexpr (!GALAXY_DEBUG_BUILD)
113 {
114 data = math::decode_zlib(data);
115 if (!data.empty())
116 {
117 data = math::decode_base64(data);
118 if (data.empty())
119 {
120 GALAXY_LOG(GALAXY_ERROR, "Failed to decode base64 appdata '{0}'.", appdata_file);
121 }
122 }
123 else
124 {
125 GALAXY_LOG(GALAXY_ERROR, "Failed to decode zlib appdata '{0}'.", appdata_file);
126 }
127
128 if (data.empty())
129 {
130 return;
131 }
132 }
133
134 const auto parsed = nlohmann::json::parse(data);
135
136 if (!parsed.empty())
137 {
138 deserialize(parsed);
139 }
140 else
141 {
142 GALAXY_LOG(GALAXY_ERROR, "Failed to parse scenemanger JSON data from memory.");
143 }
144 }
145 else
146 {
147 GALAXY_LOG(GALAXY_ERROR, "Failed to load appdata '{0}'.", appdata_file);
148 }
149 }
150
151 void SceneManager::save_app(const std::string& file)
152 {
153 const auto json = serialize();
154 auto data = json::dump(json);
155
156 if constexpr (!GALAXY_DEBUG_BUILD)
157 {
158 data = math::encode_base64(data);
159 if (!data.empty())
160 {
161 data = math::encode_zlib(data);
162 if (data.empty())
163 {
164 GALAXY_LOG(GALAXY_ERROR, "Failed to encode scenemanager to zlib '{0}'.", file);
165 }
166 }
167 else
168 {
169 GALAXY_LOG(GALAXY_ERROR, "Failed to encode scenemanager to base64 '{0}'.", file);
170 }
171
172 if (data.empty())
173 {
174 return;
175 }
176 }
177
178 auto& fs = entt::locator<fs::VirtualFileSystem>::value();
179 if (!fs.write(data, file))
180 {
181 GALAXY_LOG(GALAXY_ERROR, "Failed to save '{0}' to disk.", file);
182 }
183 }
184
186 {
188 m_stack.clear();
189 m_scenes.clear();
190 }
191
192 bool SceneManager::empty() const noexcept
193 {
194 return m_scenes.size() == 0;
195 }
196
197 nlohmann::json SceneManager::serialize()
198 {
199 auto& em = entt::locator<meta::EntityFactory>::value();
200
201 nlohmann::json json = "{\"scenes\":{}}"_json;
202
203 for (auto& [id, scene] : m_scenes)
204 {
205 json["scenes"][scene->name()] = scene->serialize();
206 }
207
208 for (auto i = 0; i < m_stack.size(); i++)
209 {
210 json["stack"][std::to_string(i)] = m_stack[i]->name();
211 }
212
213 json["entities"] = nlohmann::json::array();
214 for (const auto& [entity] : m_registry.m_entt.view<entt::entity>(entt::exclude<flags::NotSerializable>).each())
215 {
216 json["entities"].push_back(em.serialize_entity(entity, m_registry.m_entt));
217 }
218
219 return json;
220 }
221
222 void SceneManager::deserialize(const nlohmann::json& json)
223 {
224 auto& em = entt::locator<meta::EntityFactory>::value();
225
226 pop_all();
227 clear();
228
229 const auto& scenes = json.at("scenes");
230 m_scenes.reserve(scenes.size());
231 for (const auto& [name, data] : scenes.items())
232 {
233 auto scene = create(name);
234 if (scene)
235 {
236 scene->deserialize(data);
237 }
238 }
239
240 const auto& stack = json.at("stack");
241 m_stack.reserve(stack.size());
242 for (const auto& [index, name] : stack.items())
243 {
244 const auto hash = math::fnv1a(name.get<std::string>().c_str());
245 m_stack.insert(m_stack.begin() + std::stoi(index), m_scenes[hash]);
246 }
247
248 const auto& entity_json = json.at("entities");
249 for (const auto& data : entity_json)
250 {
251 const auto entity = em.deserialize_entity(data, m_registry.m_entt);
252
253 if (!m_registry.m_entt.all_of<components::Tag>(entity))
254 {
255 auto& tag = m_registry.m_entt.emplace<components::Tag>(entity);
256 tag.m_tag = "Untagged";
257 }
258 }
259 }
260 } // namespace scene
261} // namespace galaxy
#define GALAXY_LOG(level, msg,...)
Definition Log.hpp:29
#define GALAXY_ERROR
Definition Log.hpp:25
Tag an entity.
Definition Tag.hpp:21
std::string m_tag
Tag.
Definition Tag.hpp:87
void clear()
Clear any pending data.
Definition Registry.cpp:124
entt::registry m_entt
Scene entities.
Definition Registry.hpp:169
void save_app(const std::string &file)
Save all active scenes and sub data within those scenes.
bool empty() const noexcept
Are there any scenes.
std::shared_ptr< Scene > top() noexcept
Get top scene.
SceneManager() noexcept
Constructor.
void pop()
Remove scene on top of stack.
void set(const std::string &scene)
Clears all from stack and sets as active.
core::Registry m_registry
Entity data.
std::shared_ptr< Scene > create(const std::string &scene)
Create scene in engine.
void clear()
Deletes all scene data.
void deserialize(const nlohmann::json &json) override
Deserializes from object.
void update()
Process events and updates.
void render()
Render scenes.
ankerl::unordered_dense::map< std::uint64_t, std::shared_ptr< Scene > > m_scenes
Scene storage.
nlohmann::json serialize() override
Serializes object.
void pop_all()
Pop all scenes.
std::vector< std::shared_ptr< Scene > > m_stack
Active scenes.
void load_app(const std::string &appdata_file)
Load app data file into scene manager.
virtual ~SceneManager() noexcept
Destructor.
void push(const std::string &scene)
Push a scene onto the top of stack.
std::string dump(const nlohmann::json &json)
Dump json to string.
Definition JSON.cpp:38
std::string encode_base64(const std::string &input)
Compresses string into Base64.
Definition Base64.cpp:51
std::string decode_base64(const std::string &input)
Decompresses string into Base64.
Definition Base64.cpp:105
constexpr bits fnv1a(const char *const str, const bits value=fnv_1a_params< bits >::offset) noexcept
Convert string to hash.
Definition FNV1a.hpp:64
std::string encode_zlib(const std::string &input)
Compresses string into ZLib.
Definition ZLib.cpp:234
std::string decode_zlib(const std::string &input)
Decompresses string into ZLib.
Definition ZLib.cpp:276
Timer.hpp galaxy.
Definition Async.hpp:17