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