#pragma once #include #include "common/std.hpp" #include "common/UsefulException.hpp" #include "common/ougge_format.hpp" #include "common/type_name_demangled.hpp" #include #include #include namespace ougge { class Engine; class IEngineModule { public: IEngineModule() = delete; IEngineModule(const IEngineModule&) = delete; IEngineModule& operator=(const IEngineModule&) = delete; IEngineModule(IEngineModule&&) = delete; IEngineModule& operator=(IEngineModule&&) = delete; Engine& engine; virtual const std::string& getName() = 0; virtual void beginFrame(); virtual void endFrame(); protected: IEngineModule(Engine& engine); }; class Engine { std::vector> modules; bool loop_running = false; public: u32 fps_max = 60; f64 deltaTime; std::vector error_messages; Engine() = default; Engine(const Engine&) = delete; Engine& operator=(const Engine&) = delete; Engine(Engine&&) = delete; Engine& operator=(Engine&&) = delete; // start game loop on the current thread void startLoop(); void stopLoop(); //TODO: add std::enable_if template ModuleT& createModule(ConstructorArgsT&&... args){ static_assert(std::is_base_of::value); auto& module_type_name = ougge_type_name(); //TODO: replace with some logger call std::cout<<"Initializing module '"<(&module_index, &module_exists); if(module_exists){ throw UsefulException(ougge_format("can't create second instance of module '%s'", module_type_name.c_str())); } //TODO: std::forward(args)... modules.push_back(std::make_unique(*this, args...)); return *static_cast(modules[module_index].get()); } //TODO: add std::enable_if template ModuleT& getModule(){ static_assert(std::is_base_of::value); size_t module_index; bool module_exists; getOrCreateModuleIndex(&module_index, &module_exists); if(!module_exists){ auto& module_type_name = ougge_type_name(); throw UsefulException(ougge_format("engine has no module '%s'", module_type_name.c_str())); } return *static_cast(modules[module_index].get()); } private: void tryDrawFrame(); void handleModuleError(IEngineModule& module, const char *type, const char *method, const char *error); //TODO: add std::enable_if template void getOrCreateModuleIndex(size_t* out_index, bool* out_module_exists){ static size_t module_index = modules.size(); *out_index = module_index; // if module_index == modules.size(), then the module hasn't been pushed to the vector yet *out_module_exists = module_index != modules.size(); } }; }