#include "./engine.hpp" #include #include #include #include #include #include #include #define LOG_CRIT(...) __LOG_CRIT( "Engine", __VA_ARGS__) #define LOG_ERROR(...) __LOG_ERROR("Engine", __VA_ARGS__) #define LOG_WARN(...) __LOG_WARN( "Engine", __VA_ARGS__) #define LOG_INFO(...) __LOG_INFO( "Engine", __VA_ARGS__) #define LOG_DEBUG(...) __LOG_DEBUG("Engine", __VA_ARGS__) #define LOG_TRACE(...) __LOG_TRACE("Engine", __VA_ARGS__) namespace MM { void Engine::setup(void) { if (!MM::Logger::initialized) { MM::Logger::init(); } MM::Logger::initSectionLogger("Engine"); } Engine::Engine(void) { setup(); _update_strategy = std::make_unique(); LOG_INFO("defaulting to Sequential (single threaded) UpdateStrategy"); //_update_strategy = std::make_unique(); //LOG_WARN("Dummy UpdateStrategy [TESTING]"); } Engine::~Engine(void) { cleanup(); } void Engine::cleanup(void) { // disable all enabled services // in reverse order for (auto s_it = _service_enable_order.rbegin(); s_it != _service_enable_order.rend(); s_it++) { auto& s_e = _services[*s_it]; if (s_e.get()->first) { if (auto* ss = s_e.get()->second.get(); ss != nullptr) { ss->disable(*this); LOG_INFO("- disabled Service '{}'", ss->name()); } } } _service_enable_order.clear(); _update_strategy.reset(); spdlog::get("Engine")->flush(); } void Engine::update(void) { FrameMarkStart("update") _update_strategy->doUpdate(*this); FrameMarkEnd("update") } #ifdef __EMSCRIPTEN__ #include static void emscripten_update(void* arg) { auto* e = (MM::Engine*)arg; e->update(); } #endif void Engine::run(void) { #ifdef __EMSCRIPTEN__ emscripten_set_main_loop_arg(emscripten_update, this, 0, 1); #else _is_running = true; while (_is_running) { update(); } #endif } void Engine::stop(void) { _is_running = false; } bool Engine::enableService(entt::id_type s_t) { if (_services.count(s_t)) { auto* ss_entry = _services[s_t].get(); if (ss_entry->first) { return false; // already enabled } _service_enable_order.emplace_back(s_t); // TODO: make sure { // tasking std::vector task_array; ss_entry->first = ss_entry->second.get()->enable(*this, task_array); if (ss_entry->first) { _update_strategy->enableService(s_t, std::move(task_array)); } } return ss_entry->first; } // not found // TODO: improve this assert(false && "first add Service"); return false; } void Engine::disableService(entt::id_type s_t) { if (_services.count(s_t)) { auto* s_entry = _services[s_t].get(); if (s_entry->first) { _update_strategy->disableService(s_t); s_entry->first = false; s_entry->second.get()->disable(*this); auto it = std::find(_service_enable_order.begin(), _service_enable_order.end(), s_t); if (it != _service_enable_order.end()) { _service_enable_order.erase(it); } } } } bool Engine::provide(entt::id_type I, entt::id_type T) { if (!_services.count(T)) { // TODO: log error assert(false && "cant provide something that does not exist!"); return false; } _services[I] = _services[T]; return true; } } // MM