Unravel Engine C++ Reference
Loading...
Searching...
No Matches
engine.cpp
Go to the documentation of this file.
1#include "engine.h"
9
10#include <engine/ecs/ecs.h>
11
12#include "events.h"
16#include <engine/input/input.h>
23#include <ospp/event.h>
24
25#include <crash/crash.hpp>
26#include <exception>
27#include <logging/logging.h>
28
29
30#include <seq/seq.h>
32
34
35namespace unravel
36{
37namespace
38{
39auto context_ptr() -> rtti::context*&
40{
41 static rtti::context* ctx{};
42 return ctx;
43}
44std::atomic<bool> is_shutting_down{false};
45
46void update_input_zone(const renderer& rend, input_system& input)
47{
48 const auto& window = rend.get_main_window();
49 if(window)
50 {
51 auto main_pos = window->get_window().get_position();
52 auto main_size = window->get_window().get_size();
53
54 input::zone window_zone{};
55 window_zone.x = main_pos.x;
56 window_zone.y = main_pos.y;
57 window_zone.w = int(main_size.w);
58 window_zone.h = int(main_size.h);
59
60 input.manager.set_window_zone(window_zone);
61 }
62}
63
64void print_init_error(const rtti::context& ctx)
65{
66 if(ctx.has<init_error>())
67 {
68 const auto& error = ctx.get<init_error>();
69 APPLOG_CRITICAL(error.msg);
70 }
71}
72
73// Engine crash handlers
74void engine_interrupt_handler(const crash::signal_info& info)
75{
76 APPLOG_INFO("User interrupt ({}) -> {}", info.signal_number, info.signal_name);
77
79
81}
82
83void engine_termination_handler(const crash::signal_info& info)
84{
85 APPLOG_INFO("Termination signal ({}) -> {}", info.signal_number, info.signal_name);
86
87 // Try to gracefully shutdown the engine
89
91}
92
93void engine_crash_handler(const crash::signal_info& info, const crash::trace_info& trace)
94{
95 // Log the crash with full details
96 APPLOG_CRITICAL("Crash signal ({}) -> {}\n{}", info.signal_number, info.signal_name, trace.formatted_trace);
97
98 // Try emergency cleanup
100
101 APPLOG_FLUSH();
102}
103
104void engine_exception_handler(const crash::exception_info& info, const crash::trace_info& trace)
105{
106 APPLOG_CRITICAL("{}\n{}", info.exception_message, trace.formatted_trace);
107
108 // Same emergency cleanup as crash handler
110
111 APPLOG_FLUSH();
112}
113
114} // namespace
115
117{
118 return *context_ptr();
119}
120
122{
123 context_ptr() = &ctx;
124
125 fs::path binary_path = fs::executable_path(parser.app_name().c_str()).parent_path();
126 fs::add_path_protocol("binary", binary_path);
127
128 fs::path engine_data = binary_path / "data" / "engine";
129 fs::add_path_protocol("engine", engine_data);
130
132 [](const std::string& log, const hpp::source_location& loc)
133 {
134 APPLOG_WARNING_LOC(loc.file_name(), int(loc.line()), loc.function_name(), "Serialization {}", log);
135 });
136
137 ctx.add<logging>();
138
139 // Install engine crash handlers immediately after logging is available
141 .interrupt_handler = engine_interrupt_handler,
142 .termination_handler = engine_termination_handler,
143 .crash_handler = engine_crash_handler,
144 .exception_handler = engine_exception_handler,
145 });
146
147 APPLOG_INFO("Engine crash handlers installed");
148
149 ctx.add<simulation>();
150 ctx.add<events>();
151 ctx.add<threader>();
152 ctx.add<renderer>(ctx, parser);
153 ctx.add<audio_system>();
154 ctx.add<asset_manager>(ctx);
155 ctx.add<ecs>();
156 ctx.add<rendering_system>();
157 ctx.add<transform_system>();
158 ctx.add<camera_system>();
159 ctx.add<reflection_probe_system>();
160 ctx.add<model_system>();
161 ctx.add<animation_system>();
162 ctx.add<particle_system>();
163 ctx.add<physics_system>();
164 ctx.add<input_system>();
165 ctx.add<script_system>();
166 ctx.add<ui_system>();
167 return true;
168}
169
170auto engine::init_core(const cmd_line::parser& parser) -> bool
171{
172 auto& ctx = engine::context();
173
174 if(!ctx.get_cached<threader>().init(ctx))
175 {
176 print_init_error(ctx);
177 return false;
178 }
179
180 if(!ctx.get_cached<renderer>().init(ctx, parser))
181 {
182 print_init_error(ctx);
183 return false;
184 }
185
186 if(!ctx.get_cached<audio_system>().init(ctx))
187 {
188 print_init_error(ctx);
189 return false;
190 }
191
192 if(!ctx.get_cached<asset_manager>().init(ctx))
193 {
194 print_init_error(ctx);
195 return false;
196 }
197
198 return true;
199}
200
201auto engine::init_systems(const cmd_line::parser& parser) -> bool
202{
203 auto& ctx = engine::context();
204
205 if(!ctx.get_cached<ecs>().init(ctx))
206 {
207 print_init_error(ctx);
208 return false;
209 }
210
211 if(!ctx.get_cached<rendering_system>().init(ctx))
212 {
213 print_init_error(ctx);
214 return false;
215 }
216
217 if(!ctx.get_cached<transform_system>().init(ctx))
218 {
219 print_init_error(ctx);
220 return false;
221 }
222
223 if(!ctx.get_cached<camera_system>().init(ctx))
224 {
225 print_init_error(ctx);
226 return false;
227 }
228
229 if(!ctx.get_cached<reflection_probe_system>().init(ctx))
230 {
231 print_init_error(ctx);
232 return false;
233 }
234
235 if(!ctx.get_cached<model_system>().init(ctx))
236 {
237 print_init_error(ctx);
238 return false;
239 }
240
241 if(!ctx.get_cached<animation_system>().init(ctx))
242 {
243 print_init_error(ctx);
244 return false;
245 }
246
247 if(!ctx.get_cached<physics_system>().init(ctx))
248 {
249 print_init_error(ctx);
250 return false;
251 }
252
253 if(!ctx.get_cached<particle_system>().init(ctx))
254 {
255 print_init_error(ctx);
256 return false;
257 }
258
259 if(!ctx.get_cached<input_system>().init(ctx))
260 {
261 print_init_error(ctx);
262 return false;
263 }
264
265 if(!ctx.get_cached<script_system>().init(ctx))
266 {
267 print_init_error(ctx);
268 return false;
269 }
270
271 if(!ctx.get_cached<ui_system>().init(ctx))
272 {
273 print_init_error(ctx);
274 return false;
275 }
276
277 if(!defaults::init(ctx))
278 {
279 print_init_error(ctx);
280 return false;
281 }
282
283 return true;
284}
285
286auto engine::deinit() -> bool
287{
288 auto& ctx = engine::context();
289
290 if(!defaults::deinit(ctx))
291 {
292 return false;
293 }
294
295 if(!ctx.get_cached<ui_system>().deinit(ctx))
296 {
297 return false;
298 }
299
300 if(!ctx.get_cached<script_system>().deinit(ctx))
301 {
302 return false;
303 }
304
305 if(!ctx.get_cached<particle_system>().deinit(ctx))
306 {
307 return false;
308 }
309
310 if(!ctx.get_cached<input_system>().deinit(ctx))
311 {
312 return false;
313 }
314
315 if(!ctx.get_cached<physics_system>().deinit(ctx))
316 {
317 return false;
318 }
319
320 if(!ctx.get_cached<animation_system>().deinit(ctx))
321 {
322 return false;
323 }
324
325 if(!ctx.get_cached<model_system>().deinit(ctx))
326 {
327 return false;
328 }
329
330 if(!ctx.get_cached<reflection_probe_system>().deinit(ctx))
331 {
332 return false;
333 }
334
335 if(!ctx.get_cached<camera_system>().deinit(ctx))
336 {
337 return false;
338 }
339
340 if(!ctx.get_cached<transform_system>().deinit(ctx))
341 {
342 return false;
343 }
344
345 if(!ctx.get_cached<rendering_system>().deinit(ctx))
346 {
347 return false;
348 }
349
350 if(!ctx.get_cached<ecs>().deinit(ctx))
351 {
352 return false;
353 }
354
355 if(!ctx.get_cached<asset_manager>().deinit(ctx))
356 {
357 return false;
358 }
359
360 if(!ctx.get_cached<audio_system>().deinit(ctx))
361 {
362 return false;
363 }
364
365 if(!ctx.get_cached<renderer>().deinit(ctx))
366 {
367 return false;
368 }
369
370 if(!ctx.get_cached<threader>().deinit(ctx))
371 {
372 return false;
373 }
374
375 return true;
376}
377
378auto engine::destroy() -> bool
379{
380 auto& ctx = engine::context();
381
382 ctx.remove<defaults>();
383 ctx.remove<ui_system>();
384 ctx.remove<script_system>();
385 ctx.remove<particle_system>();
386 ctx.remove<input_system>();
387 ctx.remove<physics_system>();
388 ctx.remove<animation_system>();
389 ctx.remove<model_system>();
390 ctx.remove<reflection_probe_system>();
391 ctx.remove<camera_system>();
392 ctx.remove<transform_system>();
393 ctx.remove<rendering_system>();
394 ctx.remove<ecs>();
395
396 ctx.remove<asset_manager>();
397 ctx.remove<audio_system>();
398 ctx.remove<renderer>();
399 ctx.remove<events>();
400 ctx.remove<simulation>();
401 ctx.remove<threader>();
402 ctx.remove<logging>();
403
404 ctx.remove<init_error>();
405
406 bool empty = ctx.empty();
407 if(!empty)
408 {
409 ctx.print_types();
410 }
411
412 context_ptr() = {};
413 return empty;
414}
415
416auto engine::process() -> int
417{
418 auto& ctx = engine::context();
419
420 auto& sim = ctx.get_cached<simulation>();
421 auto& ev = ctx.get_cached<events>();
422 auto& rend = ctx.get_cached<renderer>();
423 auto& thr = ctx.get_cached<threader>();
424 auto& input = ctx.get_cached<input_system>();
425
426 thr.process();
427
428 sim.run_one_frame(true);
429
430 auto dt = sim.get_delta_time();
431
432 if(ev.is_playing)
433 {
434 if(ev.frames_playing == 0)
435 {
436 dt = delta_t(0.0166);
437 }
438 ev.frames_playing++;
439 }
440
441 if(ev.is_paused)
442 {
443 dt = {};
444 }
445
446 update_input_zone(rend, input);
447
448 input.manager.before_events_update();
449
450 bool should_quit = false;
451
452 os::event e{};
453 while(os::poll_event(e))
454 {
455 ev.on_os_event(ctx, e);
456
457 input.manager.on_os_event(e);
458
459 should_quit = rend.get_main_window() == nullptr || is_shutting_down;
460 if(should_quit)
461 {
462 break;
463 }
464 }
465 input.manager.after_events_update();
466
467 if(should_quit)
468 {
469 ev.set_play_mode(ctx, false);
470 is_shutting_down = false;
471 return 0;
472 }
473
474 ev.on_frame_begin(ctx, dt);
475
476 seq::update(dt);
477
478 ev.on_frame_update(ctx, dt);
479
480 ev.on_frame_before_render(ctx, dt);
481
482 ev.on_frame_render(ctx, dt);
483
484 ev.on_frame_end(ctx, dt);
485
486 get_app_profiler()->swap();
487
488 return 1;
489}
490auto engine::interrupt() -> bool
491{
492 is_shutting_down = true;
493 return true;
494}
495
496} // namespace unravel
auto init(rtti::context &ctx) -> bool
auto deinit(rtti::context &ctx) -> bool
Manages assets, including loading, unloading, and storage.
auto init(rtti::context &ctx) -> bool
Initializes the asset manager with the given context.
auto deinit(rtti::context &ctx) -> bool
Deinitializes the asset manager with the given context.
Manages the audio operations and integrates with the audio backend.
auto init(rtti::context &ctx) -> bool
Initializes the audio system with the given context.
auto deinit(rtti::context &ctx) -> bool
Deinitializes the audio system with the given context.
auto deinit(rtti::context &ctx) -> bool
auto init(rtti::context &ctx) -> bool
auto deinit(rtti::context &ctx) -> bool
auto init(rtti::context &ctx) -> bool
System that manages and updates particle emitters in the ECS.
auto deinit(rtti::context &ctx) -> bool
Deinitializes the particle system.
auto init(rtti::context &ctx) -> bool
Initializes the particle system.
Manages the physics operations using the specified backend.
auto deinit(rtti::context &ctx) -> bool
Deinitializes the physics system with the given context.
auto init(rtti::context &ctx) -> bool
Initializes the physics system with the given context.
auto deinit(rtti::context &ctx) -> bool
auto init(rtti::context &ctx) -> bool
Base class for different rendering paths in the ACE framework.
auto init(rtti::context &ctx) -> bool
Initializes the rendering path with the given context.
auto deinit(rtti::context &ctx) -> bool
Deinitializes the rendering path with the given context.
auto init(rtti::context &ctx) -> bool
auto deinit(rtti::context &ctx) -> bool
std::chrono::duration< float > delta_t
#define APPLOG_INFO(...)
Definition logging.h:18
#define APPLOG_FLUSH()
Definition logging.h:43
#define APPLOG_CRITICAL(...)
Definition logging.h:21
#define APPLOG_WARNING_LOC(FILE_LOC, LINE_LOC, FUNC_LOC,...)
Definition logging.h:36
bool add_path_protocol(const std::string &protocol, const path &dir)
Allows us to map a protocol to a specific directory. A path protocol gives the caller the ability to ...
void update(seq_id_t id, duration_t delta)
Updates the elapsed duration of a specific action.
Definition seq.cpp:94
void set_warning_logger(const std::function< void(const std::string &, const hpp::source_location &loc)> &logger)
auto install_handlers(const crash_handlers &handlers) -> void
Install comprehensive crash handlers.
Definition crash.cpp:313
auto get_app_profiler() -> performance_profiler *
Definition profiler.cpp:6
auto has() const -> bool
Definition context.hpp:28
auto get() -> T &
Definition context.hpp:35
Provides default initialization and creation functions for various entities and assets.
Definition defaults.h:23
static auto init(rtti::context &ctx) -> bool
Initializes default settings and assets.
Definition defaults.cpp:265
static auto deinit(rtti::context &ctx) -> bool
Deinitializes default settings and assets.
Definition defaults.cpp:272
Manages the entity-component-system (ECS) operations for the ACE framework.
Definition ecs.h:12
auto deinit(rtti::context &ctx) -> bool
Deinitializes the ECS with the given context.
Definition ecs.cpp:16
auto init(rtti::context &ctx) -> bool
Initializes the ECS with the given context.
Definition ecs.cpp:9
static auto process() -> int
Definition engine.cpp:416
static auto init_systems(const cmd_line::parser &parser) -> bool
Definition engine.cpp:201
static auto destroy() -> bool
Definition engine.cpp:378
static auto context() -> rtti::context &
Definition engine.cpp:116
static auto deinit() -> bool
Definition engine.cpp:286
static auto interrupt() -> bool
Definition engine.cpp:490
static auto create(rtti::context &ctx, cmd_line::parser &parser) -> bool
Definition engine.cpp:121
static auto init_core(const cmd_line::parser &parser) -> bool
Definition engine.cpp:170
auto init(rtti::context &ctx) -> bool
Definition input.cpp:49
auto deinit(rtti::context &ctx) -> bool
Definition input.cpp:57
auto deinit(rtti::context &ctx) -> bool
Definition renderer.cpp:87
auto init(rtti::context &ctx, const cmd_line::parser &parser) -> bool
Definition renderer.cpp:47
auto init(rtti::context &ctx) -> bool
auto deinit(rtti::context &ctx) -> bool
Class responsible for timers.
Definition simulation.h:20
auto init(rtti::context &ctx) -> bool
Definition threader.cpp:30
auto deinit(rtti::context &ctx) -> bool
Definition threader.cpp:37
System responsible for managing user interface components and rendering.
Definition ui_system.h:34
auto init(rtti::context &ctx) -> bool
Initializes the UI system with the given context.
Definition ui_system.cpp:42
auto deinit(rtti::context &ctx) -> bool
Deinitializes the UI system with the given context.