1#ifndef LIBSBX_CORE_ENGINE_HPP_
2#define LIBSBX_CORE_ENGINE_HPP_
14#include <libsbx/utility/concepts.hpp>
15#include <libsbx/utility/noncopyable.hpp>
16#include <libsbx/utility/assert.hpp>
18#include <libsbx/units/time.hpp>
20#include <libsbx/core/module.hpp>
21#include <libsbx/core/application.hpp>
23#include <libsbx/core/cli.hpp>
29 using stage = module_manager::stage;
30 using module_base = module_manager::module_base;
31 using module_factory = module_manager::module_factory;
35 engine(std::span<std::string_view> args)
37 utility::assert_that(_instance ==
nullptr,
"Engine already exists.");
41 for (
const auto& [type, factory] : module_manager::_factories()) {
42 _create_module(type, factory);
47 for (
const auto& entry : _modules | std::views::reverse) {
48 _destroy_module(entry.first);
55 return _instance->_delta_time;
63 return _instance->_time;
66 static auto quit() ->
void {
67 _instance->_is_running =
false;
71 return _instance->_cli;
74 template<
typename Module>
75 requires (std::is_base_of_v<module_base, Module>)
76 [[nodiscard]]
static auto get_module() -> Module& {
77 const auto type = std::type_index{
typeid(Module)};
79 if (
auto entry = _instance->_modules.find(type); entry != _instance->_modules.end()) {
80 return *
static_cast<Module*
>(entry->second);
83 throw std::runtime_error{fmt::format(
"Failed to find module '{}'",
typeid(Module).name())};
86 auto run(std::unique_ptr<application>
application) ->
void {
91 using clock_type = std::chrono::high_resolution_clock;
95 auto last = clock_type::now();
100 const auto now = clock_type::now();
101 const auto delta_time = std::chrono::duration_cast<std::chrono::duration<std::float_t>>(now - last).count();
106 _instance->_time += _instance->_delta_time;
108 fixed_accumulator += _instance->_delta_time;
112 _update_stage(stage::pre);
113 _update_stage(stage::normal);
114 _update_stage(stage::post);
116 while (fixed_accumulator >= fixed_delta_time()) {
118 _update_stage(stage::fixed);
119 fixed_accumulator -= fixed_delta_time();
122 _update_stage(stage::rendering);
128 auto _create_module(
const std::type_index& type,
const module_factory& factory) ->
void {
129 if (_modules.contains(type)) {
133 for (
const auto& dependency : factory.dependencies) {
134 _create_module(dependency, module_manager::_factories().at(dependency));
137 _modules.insert({type, std::invoke(factory.create)});
138 _module_by_stage[factory.stage].push_back(type);
141 auto _destroy_module(
const std::type_index& type) ->
void {
142 if (!_modules.at(type)) {
146 auto& factory = module_manager::_factories().at(type);
148 for (
const auto& dependency : factory.dependencies) {
149 _destroy_module(dependency);
152 auto* module_instance = _modules.at(type);
153 std::invoke(factory.destroy, module_instance);
154 _modules.at(type) =
nullptr;
157 auto _update_stage(stage stage) ->
void {
158 if (
auto entry = _module_by_stage.find(stage); entry != _module_by_stage.end()) {
159 for (
const auto& type : entry->second) {
160 _modules.at(type)->update();
174 std::map<std::type_index, module_base*> _modules{};
175 std::map<stage, std::vector<std::type_index>> _module_by_stage{};
Definition: application.hpp:6
Definition: engine.hpp:27
Definition: quantity.hpp:65
Definition: noncopyable.hpp:6