107 lines
3.3 KiB
C++
107 lines
3.3 KiB
C++
#pragma once
|
|
|
|
#include <vector>
|
|
#include "common/std.hpp"
|
|
#include "common/UsefulException.hpp"
|
|
#include "common/ougge_format.hpp"
|
|
#include "common/type_name_demangled.hpp"
|
|
#include <type_traits>
|
|
#include <memory>
|
|
#include <iostream>
|
|
|
|
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<std::unique_ptr<IEngineModule>> modules;
|
|
bool loop_running = false;
|
|
|
|
public:
|
|
u32 fps_max = 60;
|
|
f64 deltaTime;
|
|
std::vector<std::string> 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<typename ModuleT, typename... ConstructorArgsT>
|
|
ModuleT& createModule(ConstructorArgsT&&... args){
|
|
static_assert(std::is_base_of<IEngineModule, ModuleT>::value);
|
|
|
|
auto& module_type_name = ougge_type_name<ModuleT>();
|
|
//TODO: replace with some logger call
|
|
std::cout<<"Initializing module '"<<module_type_name<<"'"<<std::endl;
|
|
|
|
size_t module_index;
|
|
bool module_exists;
|
|
getOrCreateModuleIndex<ModuleT>(&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<ModuleT>(*this, args...));
|
|
return *static_cast<ModuleT*>(modules[module_index].get());
|
|
}
|
|
|
|
//TODO: add std::enable_if
|
|
template<typename ModuleT>
|
|
ModuleT& getModule(){
|
|
static_assert(std::is_base_of<IEngineModule, ModuleT>::value);
|
|
|
|
size_t module_index;
|
|
bool module_exists;
|
|
getOrCreateModuleIndex<ModuleT>(&module_index, &module_exists);
|
|
if(!module_exists){
|
|
auto& module_type_name = ougge_type_name<ModuleT>();
|
|
throw UsefulException(ougge_format("engine has no module '%s'",
|
|
module_type_name.c_str()));
|
|
}
|
|
return *static_cast<ModuleT*>(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<typename ModuleT>
|
|
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();
|
|
}
|
|
};
|
|
}
|