1#ifndef LIBSBX_CORE_ENGINE_HPP_
2#define LIBSBX_CORE_ENGINE_HPP_
14#include <easy/profiler.h>
16#include <libsbx/utility/concepts.hpp>
17#include <libsbx/utility/noncopyable.hpp>
18#include <libsbx/utility/assert.hpp>
20#include <libsbx/units/time.hpp>
22#include <libsbx/core/module.hpp>
23#include <libsbx/core/application.hpp>
24#include <libsbx/core/cli.hpp>
25#include <libsbx/core/profiler.hpp>
26#include <libsbx/core/settings.hpp>
32 using stage = module_manager::stage;
33 using module_base = module_manager::module_base;
34 using module_factory = module_manager::module_factory;
38 engine(std::span<std::string_view> args)
40 utility::assert_that(_instance ==
nullptr,
"Engine already exists.");
44 for (
const auto& [type, factory] : module_manager::_factories()) {
45 _create_module(type, factory);
50 for (
const auto& entry : _modules | std::views::reverse) {
51 _destroy_module(entry.first);
58 return _instance->_delta_time;
66 return _instance->_time;
69 static auto quit() ->
void {
70 _instance->_is_running =
false;
74 return _instance->_cli;
78 return _instance->_profiler;
82 return _instance->_settings;
85 template<
typename Module>
86 requires (std::is_base_of_v<module_base, Module>)
87 [[nodiscard]]
static auto get_module() -> Module& {
88 const auto type = std::type_index{
typeid(Module)};
90 if (
auto entry = _instance->_modules.find(type); entry != _instance->_modules.end()) {
91 return *
static_cast<Module*
>(entry->second);
94 throw std::runtime_error{fmt::format(
"Failed to find module '{}'",
typeid(Module).name())};
97 auto run(std::unique_ptr<application>
application) ->
void {
102 using clock_type = std::chrono::high_resolution_clock;
106 auto last = clock_type::now();
110 while (_is_running) {
111 const auto now = clock_type::now();
112 const auto delta_time = std::chrono::duration_cast<std::chrono::duration<std::float_t>>(now - last).count();
117 _instance->_time += _instance->_delta_time;
119 fixed_accumulator += _instance->_delta_time;
121 EASY_BLOCK(
"stage pre");
122 _update_stage(stage::pre);
125 EASY_BLOCK(
"application update");
129 EASY_BLOCK(
"stage normal");
130 _update_stage(stage::normal);
133 while (fixed_accumulator >= fixed_delta_time()) {
134 EASY_BLOCK(
"stage fixed");
136 _update_stage(stage::fixed);
137 fixed_accumulator -= fixed_delta_time();
141 EASY_BLOCK(
"stage post");
142 _update_stage(stage::post);
145 EASY_BLOCK(
"stage rendering");
146 _update_stage(stage::rendering);
153 auto _create_module(
const std::type_index& type,
const module_factory& factory) ->
void {
154 if (_modules.contains(type)) {
158 for (
const auto& dependency : factory.dependencies) {
159 _create_module(dependency, module_manager::_factories().at(dependency));
162 _modules.insert({type, std::invoke(factory.create)});
163 _module_by_stage[factory.stage].push_back(type);
166 auto _destroy_module(
const std::type_index& type) ->
void {
167 if (!_modules.at(type)) {
171 auto& factory = module_manager::_factories().at(type);
173 for (
const auto& dependency : factory.dependencies) {
174 _destroy_module(dependency);
177 auto* module_instance = _modules.at(type);
178 std::invoke(factory.destroy, module_instance);
179 _modules.at(type) =
nullptr;
182 auto _update_stage(stage stage) ->
void {
183 if (
auto entry = _module_by_stage.find(stage); entry != _module_by_stage.end()) {
184 for (
const auto& type : entry->second) {
185 _modules.at(type)->update();
201 std::map<std::type_index, module_base*> _modules{};
202 std::map<stage, std::vector<std::type_index>> _module_by_stage{};
208#define CONCAT_INTERNAL(x, y) x##y
209#define CONCAT(x, y) CONCAT_INTERNAL(x, y)
211#define SBX_SCOPED_TIMER(name) \
212 auto CONCAT(__scoped_timer_, __LINE__) = sbx::utility::scoped_timer{[=](const auto& measurement) { \
213 sbx::core::engine::profiler().submit(name, measurement); \
216#define SBX_SCOPED_TIMER_BLOCK(name) \
217 if (auto CONCAT(__scoped_timer_, __LINE__) = sbx::utility::scoped_timer{[=](const auto& measurement) { sbx::core::engine::profiler().submit(name, measurement); }}; true)
Definition: application.hpp:6
Definition: engine.hpp:30
Definition: profiler.hpp:15
Definition: settings.hpp:17
Definition: quantity.hpp:65
Definition: noncopyable.hpp:6