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
Scene.cpp
Go to the documentation of this file.
1
7
8#include <entt/locator/locator.hpp>
9#include <nlohmann/json.hpp>
10#include <sol/sol.hpp>
11
22
23#include "Scene.hpp"
24
25namespace galaxy
26{
27 Scene::Scene(const std::string& name) noexcept
28 : State {name}
29 {
30 /*
31 auto& w = core::ServiceLocator<core::Window>::ref();
32 m_camera.set_viewport(w.frame_width(), w.frame_height());
33 auto& nui = core::ServiceLocator<ui::NuklearUI>::ref();
34 m_dispatcher.sink<events::WindowResized>().connect<&Scene::on_window_resized>(this);
35 m_dispatcher.sink<events::MousePressed>().connect<&ui::NuklearUI::on_mouse_pressed>(nui);
36 m_dispatcher.sink<events::MouseWheel>().connect<&ui::NuklearUI::on_mouse_wheel>(nui);
37 m_dispatcher.sink<events::KeyChar>().connect<&ui::NuklearUI::on_key_char>(nui);
38 m_dispatcher.sink<events::KeyPress>().connect<&ui::NuklearUI::on_key_press>(nui);
39 m_dispatcher.sink<events::ContentScale>().connect<&ui::NuklearUI::on_content_scale>(nui);
40 */
41 }
42
43 Scene::~Scene() noexcept
44 {
45 }
46
48 {
49 }
50
52 {
53 if (entt::locator<sol::state>::has_value())
54 {
55 entt::locator<sol::state>::value().collect_garbage();
56 }
57 }
58
59 void Scene::on_event(SDL_Event& event)
60 {
61 // nui.begin_input();
62 // nui.end_input();
63
64 /*for (auto& layer : std::views::reverse(m_LayerStack))
65 {
66 layer->OnEvent(event);
67 if (event.Handled)
68 break;
69 }
70
71 Core::EventDispatcher dispatcher(event);
72 dispatcher.Dispatch<Core::MouseButtonPressedEvent>([this](Core::MouseButtonPressedEvent& e) { return OnMouseButtonPressed(e); });
73 dispatcher.Dispatch<Core::MouseMovedEvent>([this](Core::MouseMovedEvent& e) { return OnMouseMoved(e); });
74 dispatcher.Dispatch<Core::WindowClosedEvent>([this](Core::WindowClosedEvent& e) { return OnWindowClosed(e); });
75
76 switch (event.type)
77 {
78 case SDL_EVENT_SCREEN_KEYBOARD_SHOWN:
79 case SDL_EVENT_SCREEN_KEYBOARD_HIDDEN:
80 break;
81
82 case SDL_EVENT_LOCALE_CHANGED:
83 // TODO: Handle Languages.
84 break;
85
86 case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED:
87 case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED:
88 SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED, /**< Display has changed desktop mode
89 //SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED, /**< Display has changed current mode
90 // SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, /**< Display has changed content scale
91 //SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED, /**< Display has changed usable bounds
92 // SDL_GetDisplayContentScale
93 // SDL_GetWindowDisplayScale
94 // https://wiki.libsdl.org/SDL3/README-highdpi
95 float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
96 break;
97
98 case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
99 // SDL_GetWindowSizeInPixels
100 break;
101
102 case SDL_EVENT_WINDOW_RESIZED:
103 case SDL_EVENT_WINDOW_MAXIMIZED:
104 case SDL_EVENT_WINDOW_RESTORED:
105 case SDL_EVENT_WINDOW_ENTER_FULLSCREEN:
106 case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN:
107 case SDL_EVENT_DISPLAY_USABLE_BOUNDS_CHANGED:
108 {
109 const auto size = window.get_pixel_size();
110 dispatcher.enqueue<WindowResized>(size.x, size.y);
111 }
112 break;
113
114 case SDL_EVENT_WINDOW_DISPLAY_CHANGED:
115 // TODO
116 // HANDLE RESIZE + DISPLAY SCALE + PIXEL SIZE SCALE.
117 break;
118
119 case SDL_EVENT_WINDOW_MOUSE_ENTER:
120 case SDL_EVENT_WINDOW_FOCUS_GAINED:
121 dispatcher.enqueue<GainedFocus>();
122 break;
123
124 case SDL_EVENT_WINDOW_MOUSE_LEAVE:
125 case SDL_EVENT_WINDOW_FOCUS_LOST:
126 dispatcher.enqueue<LostFocus>();
127 break;
128
129 case SDL_EVENT_KEY_DOWN:
130 {
131 dispatcher.enqueue<KeyPressed>(
132 m_events.key.scancode,
133 static_cast<Keys>(m_events.key.key),
134 static_cast<KeyMods>(m_events.key.mod),
135 m_events.key.raw,
136 m_events.key.repeat
137 );
138 }
139 break;
140
141 case SDL_EVENT_KEY_UP:
142 {
143 dispatcher.enqueue<KeyReleased>(
144 m_events.key.scancode,
145 static_cast<Keys>(m_events.key.key),
146 static_cast<KeyMods>(m_events.key.mod),
147 m_events.key.raw,
148 m_events.key.repeat
149 );
150 }
151 break;
152
153 case SDL_EVENT_TEXT_INPUT:
154 // case SDL_EVENT_TEXT_EDITING:
155 // case SDL_EVENT_TEXT_EDITING_CANDIDATES:
156 {
157 auto text = std::string(m_events.text.text);
158 dispatcher.enqueue<KeyInput>(std::move(text));
159 }
160 break;
161
162 case SDL_EVENT_MOUSE_MOTION:
163 {
164 dispatcher.enqueue<MouseMoved>(m_events.motion.x, m_events.motion.y, m_events.motion.xrel, m_events.motion.yrel);
165 }
166 break;
167
168 case SDL_EVENT_MOUSE_BUTTON_DOWN:
169 {
170 dispatcher.enqueue<MousePressed>(m_events.button.x, m_events.button.y, m_events.button.clicks, static_cast<MouseButton>(m_events.button.button));
171 }
172 break;
173
174 case SDL_EVENT_MOUSE_BUTTON_UP:
175 {
176 dispatcher.enqueue<MouseReleased>(m_events.button.x, m_events.button.y, m_events.button.clicks, static_cast<MouseButton>(m_events.button.button));
177 }
178 break;
179
180 case SDL_EVENT_MOUSE_WHEEL:
181 {
182 dispatcher.enqueue<MouseWheel>(
183 m_events.wheel.x,
184 m_events.wheel.y,
185 m_events.wheel.direction,
186 m_events.wheel.mouse_x,
187 m_events.wheel.mouse_y,
188 m_events.wheel.integer_x,
189 m_events.wheel.integer_y
190 );
191 }
192 break;
193
194 case SDL_EVENT_DROP_BEGIN:
195 // TODO
196 Drag and drop events
197 SDL_EVENT_DROP_FILE = 0x1000, /**< The system requests a file open *
198 SDL_EVENT_DROP_TEXT, /**< text/plain drag-and-drop event *
199 SDL_EVENT_DROP_BEGIN, /**< A new set of drops is beginning (NULL filename) *
200 SDL_EVENT_DROP_COMPLETE, /**< Current set of drops is now complete (NULL filename) *
201 SDL_EVENT_DROP_POSITION, /**< Position while moving over the window
202 // SDL_DropEvent
203 break;
204
205 case SDL_EVENT_JOYSTICK_AXIS_MOTION:
206 case SDL_EVENT_JOYSTICK_BALL_MOTION:
207 case SDL_EVENT_JOYSTICK_HAT_MOTION:
208 case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
209 case SDL_EVENT_JOYSTICK_BUTTON_UP:
210 case SDL_EVENT_JOYSTICK_REMOVED:
211 case SDL_EVENT_JOYSTICK_BATTERY_UPDATED:
212 case SDL_EVENT_JOYSTICK_UPDATE_COMPLETE:
213 // TODO
214 break;
215
216 case SDL_EVENT_GAMEPAD_AXIS_MOTION:
217 case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
218 case SDL_EVENT_GAMEPAD_BUTTON_UP:
219 case SDL_EVENT_GAMEPAD_REMOVED:
220 case SDL_EVENT_GAMEPAD_REMAPPED:
221 case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN:
222 case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION:
223 case SDL_EVENT_GAMEPAD_TOUCHPAD_UP:
224 case SDL_EVENT_GAMEPAD_SENSOR_UPDATE:
225 case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE:
226 case SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED:
227 // TODO
228 break;
229
230 case SDL_EVENT_FINGER_DOWN:
231 case SDL_EVENT_FINGER_UP:
232 case SDL_EVENT_FINGER_MOTION:
233 case SDL_EVENT_FINGER_CANCELED:
234 // TODO
235 break;
236
237 case SDL_EVENT_PEN_PROXIMITY_IN:
238 case SDL_EVENT_PEN_PROXIMITY_OUT:
239 case SDL_EVENT_PEN_DOWN:
240 case SDL_EVENT_PEN_UP:
241 case SDL_EVENT_PEN_BUTTON_DOWN:
242 case SDL_EVENT_PEN_BUTTON_UP:
243 case SDL_EVENT_PEN_MOTION:
244 case SDL_EVENT_PEN_AXIS:
245 // TODO
246 break;
247
248 default:
249 break;
250 }
251 */
252 }
253
255 {
256 // make sure events are propagated from top to bottom.
257 // make sure updting is from btm to top.
258
259 // graphics::Renderer::ref().flush();
260 // m_registry.update(m_b2world);
261 // world.update();
262 // m_b2world.Step(GALAXY_DT, m_velocity_iterations, m_position_iterations);
263 m_sysman.update(em, this);
264 }
265
267 {
268 // render scene
269 // then any ui layers.
270
271 /*
272 graphics::Renderer::ref().begin_post();
273
274 // Scene specific.
275 graphics::Renderer::ref().submit_camera(m_camera);
276 graphics::Renderer::ref().draw();
277
278 graphics::Renderer::ref().end_post();
279 graphics::Renderer::ref().begin_default();
280 graphics::Renderer::ref().render_post();
281 graphics::Renderer::ref().end_default();
282
283 // Scene specific.
284 auto& nui = core::ServiceLocator<ui::NuklearUI>::ref();
285
286 nui.new_frame();
287 update_ui();
288 nui.render();
289
290 graphics::Renderer::ref().end_default();
291 */
292 }
293
294 nlohmann::json Scene::serialize()
295 {
296 nlohmann::json json = "{}"_json;
297
298 /*json["camera"] = m_camera.serialize();
299 json["physics"] = nlohmann::json::object();
300 auto& physics = json.at("physics");
301
302 auto gravity = m_b2world.GetGravity();
303 physics["gravity"]["x"] = gravity.x;
304 physics["gravity"]["y"] = gravity.y;
305
306 physics["allow_sleeping"] = m_b2world.GetAllowSleeping();
307 physics["allow_autoclearforces"] = m_b2world.GetAutoClearForces();
308 physics["velocity_iterations"] = m_velocity_iterations;
309 physics["position_iterations"] = m_position_iterations;
310 json["name"] = m_name;
311 json["ldtk_world"] = m_world.file();
312 json["current_map"] = m_world.get_active() ? m_world.get_active()->name() : "";
313
314 json["camera"] = m_camera.serialize();
315 json["entities"] = nlohmann::json::array();
316
317 auto& em = core::ServiceLocator<meta::EntityMeta>::ref();
318
319 for (const auto& [entity] : m_registry.m_entt.view<entt::entity>(entt::exclude<flags::DenySerialization>).each())
320 {
321 json["entities"].push_back(em.serialize_entity(entity, m_registry.m_entt));
322 }
323
324 json["physics"] = nlohmann::json::object();
325 auto& physics = json.at("physics");
326
327 auto gravity = m_b2world.GetGravity();
328 physics["gravity"]["x"] = gravity.x;
329 physics["gravity"]["y"] = gravity.y;
330
331 physics["allow_sleeping"] = m_b2world.GetAllowSleeping();
332 physics["allow_autoclearforces"] = m_b2world.GetAutoClearForces();
333 physics["velocity_iterations"] = m_velocity_iterations;
334 physics["position_iterations"] = m_position_iterations;
335 json["name"] = m_name;
336 json["ldtk_world"] = m_world.file();
337 json["current_map"] = m_world.get_active() ? m_world.get_active()->name() : "";
338
339 nlohmann::json json = "{}"_json;
340 json["name"] = m_name;
341
342 json["systems"] = nlohmann::json::object();
343 for (auto i = 0; i < m_systems.size(); i++)
344 {
345 json["systems"][std::to_string(i)] = m_systems[i]->id();
346 }*/
347
348 return json;
349 }
350
351 void Scene::deserialize(const nlohmann::json& json)
352 {
353 /*m_name = json.at("name");
354
355 const auto& systems = json.at("systems");
356 m_systems.reserve(systems.size());
357 for (const auto& [index, name] : systems.items())
358 {
359 add_system(name.get<std::string>());
360 }
361
362 m_camera.deserialize(json.at("camera"));
363 auto& em = core::ServiceLocator<meta::EntityMeta>::ref();
364
365 const auto& physics = json.at("physics");
366 const auto& gravity = physics.at("gravity");
367
368 m_b2world.SetGravity({gravity.at("x"), gravity.at("y")});
369 m_b2world.SetAllowSleeping(physics.at("allow_sleeping"));
370 m_b2world.SetAutoClearForces(physics.at("allow_autoclearforces"));
371 m_velocity_iterations = physics.at("velocity_iterations");
372 m_position_iterations = physics.at("position_iterations");
373
374 if (load_world(json.at("ldtk_world")))
375 {
376 m_world.set_active(json.at("current_map"));
377 }
378 m_camera.deserialize(json.at("camera"));
379 auto& em = core::ServiceLocator<meta::EntityMeta>::ref();
380
381 m_registry.clear();
382
383 const auto& physics = json.at("physics");
384 const auto& gravity = physics.at("gravity");
385
386 m_b2world.SetGravity({gravity.at("x"), gravity.at("y")});
387 m_b2world.SetAllowSleeping(physics.at("allow_sleeping"));
388 m_b2world.SetAutoClearForces(physics.at("allow_autoclearforces"));
389 m_velocity_iterations = physics.at("velocity_iterations");
390 m_position_iterations = physics.at("position_iterations");
391
392 const auto& entity_json = json.at("entities");
393 for (const auto& data : entity_json)
394 {
395 const auto entity = em.deserialize_entity(data, m_registry.m_entt);
396
397 if (!m_registry.m_entt.all_of<components::Tag>(entity))
398 {
399 auto& tag = m_registry.m_entt.emplace<components::Tag>(entity);
400 tag.m_tag = "Untagged";
401 }
402 }
403
404 m_name = json.at("name");
405
406 if (load_world(json.at("ldtk_world")))
407 {
408 m_world.set_active(json.at("current_map"));
409 }*/
410 }
411
413 {
414 return m_sysman;
415 }
416
417 /*void Scene::update_ui()
418 {
419 const auto view = m_registry.m_entt.view<components::GUI>(entt::exclude<flags::Disabled>);
420 for (auto&& [entity, gui] : view.each())
421 {
422 if (gui.m_update.valid())
423 {
424 gui.m_update(gui.m_self);
425 }
426 }
427 }
428 bool Scene::load_world(const std::string& file)
429 {
430 if (m_world.load(file))
431 {
432 m_world.parse();
433 return true;
434 }
435
436 return false;
437 }
438
439
440
441 */
442} // namespace galaxy
Class for making creating and managing entities easier.
void on_push() override
When scene is pushed to the stack.
Definition Scene.cpp:47
virtual ~Scene() noexcept
Destructor.
Definition Scene.cpp:43
void deserialize(const nlohmann::json &json)
Deserializes from object.
Definition Scene.cpp:351
virtual void update(EntityManager &em)
Process events and updates.
Definition Scene.cpp:254
void on_pop() override
When scene is popped from the stack.
Definition Scene.cpp:51
virtual void on_event(SDL_Event &event)
Handle an event for a scene.
Definition Scene.cpp:59
SystemManager m_sysman
Systems only used by this scene.
Definition Scene.hpp:113
nlohmann::json serialize()
Serializes object.
Definition Scene.cpp:294
virtual void render()
Render scene.
Definition Scene.cpp:266
SystemManager & sys_man() noexcept
Get system manager.
Definition Scene.cpp:412
Scene()=delete
Constructor.
A state to use in a finite state machine.
Definition State.hpp:19
Manages the systems assigned to it.
void update(EntityManager &em, Scene *scene)
Process all systems.
Application.hpp galaxy.