diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt index 8e11d3e..f3957f7 100644 --- a/framework/CMakeLists.txt +++ b/framework/CMakeLists.txt @@ -15,11 +15,11 @@ add_subdirectory(organizer_scene) if(NOT MM_HEADLESS) add_subdirectory(sdl_service) add_subdirectory(simple_sdl_renderer) - add_subdirectory(opengl_renderer) add_subdirectory(opengl_primitives) + add_subdirectory(opengl_renderer) + add_subdirectory(imgui) add_subdirectory(input) add_subdirectory(sound) - add_subdirectory(imgui) add_subdirectory(tilemap) endif() diff --git a/framework/engine/CMakeLists.txt b/framework/engine/CMakeLists.txt index 73a82c5..a731b01 100644 --- a/framework/engine/CMakeLists.txt +++ b/framework/engine/CMakeLists.txt @@ -7,13 +7,12 @@ add_library(engine src/mm/engine.cpp src/mm/update_strategies/update_strategy.hpp + src/mm/update_strategies/dummy.hpp src/mm/services/service.hpp - src/mm/update_strategies/dependency_check_decorater.hpp - - src/mm/update_strategies/default_strategy.hpp - src/mm/update_strategies/default_strategy.cpp + src/mm/update_strategies/sequential_strategy.hpp + src/mm/update_strategies/sequential_strategy.cpp src/mm/services/scene_service_interface.hpp src/mm/services/scene_service_interface.cpp diff --git a/framework/engine/src/mm/engine.cpp b/framework/engine/src/mm/engine.cpp index 477face..d313e94 100644 --- a/framework/engine/src/mm/engine.cpp +++ b/framework/engine/src/mm/engine.cpp @@ -1,6 +1,7 @@ #include "./engine.hpp" -#include +#include +#include #include #include @@ -29,8 +30,10 @@ void Engine::setup(void) { Engine::Engine(void) { setup(); - _update_strategy = std::make_unique(); - LOG_INFO("defaulting to SingleThreadedDefault UpdateStrategy"); + _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) { @@ -59,48 +62,12 @@ void Engine::cleanup(void) { void Engine::update(void) { FrameMarkStart("update") - //if (_update_functions_modified) { - //ZoneScopedN("MM::Engine::update::sort_update_functions") - //std::sort(_update_functions.begin(), _update_functions.end(), [](const auto& a, const auto& b) { return a->priority > b->priority; }); - //_update_functions_modified = false; - //} - - //{ - //ZoneScopedN("MM::Engine::update::traverseUpdateFunctions") - //traverseUpdateFunctions(_update_functions); - //} _update_strategy->doUpdate(*this); FrameMarkEnd("update") } -//void Engine::fixedUpdate(void) { - //FrameMarkStart("fixedUpdate") - ////if (_fixed_update_functions_modified) { - ////ZoneScopedN("MM::Engine::fixedUpdate::sort_update_functions") - - ////std::sort(_fixed_update_functions.begin(), _fixed_update_functions.end(), [](const auto& a, const auto& b) { return a->priority > b->priority; }); - ////_fixed_update_functions_modified = false; - ////} - - ////{ - ////ZoneScopedN("MM::Engine::fixedUpdate::traverseUpdateFunctions") - ////traverseUpdateFunctions(_fixed_update_functions); - ////} - - ////if (!_fixed_defered.empty()) { - ////ZoneScopedN("MM::Engine::fixedUpdate::defered") - ////for (auto& fn : _fixed_defered) { - ////fn(*this); - ////} - - ////_fixed_defered.clear(); - ////} - - //FrameMarkEnd("fixedUpdate") -//} - #ifdef __EMSCRIPTEN__ #include @@ -136,14 +103,20 @@ bool Engine::enableService(entt::id_type s_t) { _service_enable_order.emplace_back(s_t); // TODO: make sure - ss_entry->first = ss_entry->second.get()->enable(*this); + { // tasking + std::vector task_array; - _update_strategy->enableService(s_t); // after service::enable() + 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; } @@ -158,7 +131,6 @@ void Engine::disableService(entt::id_type s_t) { s_entry->first = false; s_entry->second.get()->disable(*this); - //_service_enable_order.emplace_back(service_family::type); 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); @@ -170,6 +142,7 @@ void Engine::disableService(entt::id_type s_t) { 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; } diff --git a/framework/engine/src/mm/engine.hpp b/framework/engine/src/mm/engine.hpp index bcd2567..f67fb44 100644 --- a/framework/engine/src/mm/engine.hpp +++ b/framework/engine/src/mm/engine.hpp @@ -26,44 +26,21 @@ namespace Services { class Engine { friend Services::ImGuiEngineTools; - private: - //using service_family = entt::family; - public: - //using service_family_type = service_family::family_type; + using service_id_type = entt::id_type; // alias, for future proof + // UpdateStrategy protected: std::unique_ptr _update_strategy; public: UpdateStrategies::UpdateStrategy& getUpdateStrategy(void) { return *_update_strategy; } + // state private: volatile bool _is_running = false; + // ... just realisied: i never needed a getter ... - private: - void setup(void); - - public: - Engine(void); - - explicit Engine(std::unique_ptr us) { - setup(); - _update_strategy = std::move(us); - } - - public: - ~Engine(void); - - // called from destructor or explicitly - void cleanup(void); - - void update(void); - - void run(void); // calls update() until stopped - void stop(void); - - private: std::vector _service_add_order; // ? std::vector _service_enable_order; // ? @@ -75,6 +52,29 @@ class Engine { >> > _services; + + // private state helper + private: + void setup(void); + + // ctr dtr ... + public: + Engine(void); + ~Engine(void); + + explicit Engine(std::unique_ptr us) { + setup(); + _update_strategy = std::move(us); + } + + // called from destructor or explicitly (if eg "global", u need dis) + void cleanup(void); + + void update(void); + + void run(void); // calls update() until stopped + void stop(void); + public: template constexpr static auto type(void) { @@ -96,12 +96,6 @@ class Engine { _service_add_order.emplace_back(type()); - // add updates to update strategy - _update_strategy->registerService( - type(), - ss_entry.get()->second->registerUpdates() - ); - return (T&)*ss_entry.get()->second.get(); } @@ -154,13 +148,8 @@ class Engine { return provide(type(), type()); } - // TODO: reimplement??? - //template + // TODO: remove service //void removeProvider(void) { - //if (auto it = _implementation_provider.find(service_family::type); it != _implementation_provider.end()) { - //_implementation_provider.erase(it); - //} - //} }; } // MM diff --git a/framework/engine/src/mm/services/scene_service_interface.hpp b/framework/engine/src/mm/services/scene_service_interface.hpp index 4386a39..8a40fb6 100644 --- a/framework/engine/src/mm/services/scene_service_interface.hpp +++ b/framework/engine/src/mm/services/scene_service_interface.hpp @@ -11,9 +11,11 @@ namespace MM { using System = std::function; // opaque way to add a System to a Scene + [[deprecated("use organizer")]] void AddSystemToScene(::MM::Scene& scene, ::MM::System fn); // opaque way to iterate over the Systems + [[deprecated("use organizer")]] void EachSystemInScene(::MM::Scene& scene, std::function fn); } // MM @@ -35,7 +37,7 @@ namespace MM::Services { // adds a System to current Scene. // default impl. will use getScene() ! - inline virtual void addSystemToScene(::MM::System fn) { + virtual void addSystemToScene(::MM::System fn) { ::MM::AddSystemToScene(getScene(), std::move(fn)); } }; diff --git a/framework/engine/src/mm/services/service.hpp b/framework/engine/src/mm/services/service.hpp index 0dc2204..dcae752 100644 --- a/framework/engine/src/mm/services/service.hpp +++ b/framework/engine/src/mm/services/service.hpp @@ -6,7 +6,7 @@ namespace MM { class Engine; namespace UpdateStrategies { - struct UpdateCreationInfo; + struct TaskInfo; } namespace Services { @@ -17,14 +17,12 @@ namespace MM { virtual const char* name(void) = 0; - virtual bool enable(Engine& engine) = 0; + // tasks are to be filled in by the service impl + virtual bool enable(Engine& engine, std::vector& task_array) = 0; virtual void disable(Engine& engine) = 0; - - // optional, only if service actually needs to be part of the update loop - virtual std::vector registerUpdates(void) { return {}; } }; } // Services -} //MM +} // MM diff --git a/framework/engine/src/mm/update_strategies/default_strategy.cpp b/framework/engine/src/mm/update_strategies/default_strategy.cpp deleted file mode 100644 index f4e0938..0000000 --- a/framework/engine/src/mm/update_strategies/default_strategy.cpp +++ /dev/null @@ -1,236 +0,0 @@ -#include "./default_strategy.hpp" - -#include -#include - -namespace MM::UpdateStrategies { - -#define __L_ASSERT(cond) if (!(cond)) { return false; } - -SingleThreadedDefault::Graph& SingleThreadedDefault::getGraph(update_phase_t type) { - using type_t = update_phase_t; - - switch (type) { - case type_t::PRE: - return _pre_graph; - case type_t::MAIN: - return _main_graph; - case type_t::POST: - return _post_graph; - } - - return _main_graph; // unreachable -} - -std::set& SingleThreadedDefault::getActiveSet(update_phase_t type) { - using type_t = update_phase_t; - - switch (type) { - case type_t::PRE: - return _pre_active; - case type_t::MAIN: - return _main_active; - case type_t::POST: - return _post_active; - } - - return _main_active; // unreachable -} - -void SingleThreadedDefault::runType(MM::Engine& engine, update_phase_t type) { - auto aset = getActiveSet(type); // copy - const auto& graph = getGraph(type); - - while (!aset.empty()) { - for (const auto key : aset) { - // check if dependencies are resolved (or dont exist) - bool resolved = true; - for (const auto deps : graph.at(key)) { - if (aset.count(deps)) { - resolved = false; - break; - } - } - - if (resolved) { - // do task - _tasks[key].fn(engine); - - // delete task from set - aset.erase(key); - - break; // this might be optional but makes the delete easy - } else { - // continue the for / dont do anything with this task yet - } - } - } -} - -SingleThreadedDefault::~SingleThreadedDefault(void) { -} - -bool SingleThreadedDefault::registerService(const entt::id_type s_id, std::vector&& info_array) { - __L_ASSERT(_service_tasks.count(s_id) == 0); - - // early out - if (info_array.empty()) { - return true; - } - - auto& service_tasks = _service_tasks[s_id]; - - for (const UpdateCreationInfo& reg_e : info_array) { - // test if already exists - __L_ASSERT(_tasks.count(reg_e.key) == 0); - // also the graphs - __L_ASSERT(_pre_graph.count(reg_e.key) == 0); - __L_ASSERT(_main_graph.count(reg_e.key) == 0); - __L_ASSERT(_post_graph.count(reg_e.key) == 0); - - // also the enabled taks - __L_ASSERT(_pre_active.count(reg_e.key) == 0); - __L_ASSERT(_main_active.count(reg_e.key) == 0); - __L_ASSERT(_post_active.count(reg_e.key) == 0); - - // potentially check for cicles (can be done by provided decorator) - } - - for (const UpdateCreationInfo& reg_e : info_array) { - // add to tasks - { - auto& new_task = _tasks[reg_e.key]; - new_task.name = reg_e.name; - new_task.fn = reg_e.fn; - new_task.phase = reg_e.phase; - new_task.auto_enable = reg_e.auto_enable; - - new_task.enabled = false; - } - - // add relation to service - service_tasks.emplace_back(reg_e.key); - - // fill in dependencies - auto& graph = getGraph(reg_e.phase); - graph[reg_e.key].insert(reg_e.dependencies.begin(), reg_e.dependencies.end()); - } - - return true; -} - -bool SingleThreadedDefault::enable(const update_key_t key) { - __L_ASSERT(_tasks.count(key) == 1); - __L_ASSERT(_tasks[key].enabled == false); - - auto ret = getActiveSet(_tasks[key].phase).emplace(key); - _tasks[key].enabled = true; - - return ret.second; -} - -bool SingleThreadedDefault::disable(const update_key_t key) { - __L_ASSERT(_tasks.count(key) == 1); - __L_ASSERT(_tasks[key].enabled == true); - - auto& aset = getActiveSet(_tasks[key].phase); - - __L_ASSERT(aset.count(key) == 1); - - aset.erase(key); - - _tasks[key].enabled = false; - - return true; -} - -bool SingleThreadedDefault::enableService(const entt::id_type s_id) { - bool succ = true; - for (const auto id : _service_tasks[s_id]) { - auto& task = _tasks[id]; - - // there should be no task running, if the service is no enabled!! - assert(!task.enabled); - - if (task.auto_enable) { - succ &= enable(id); - } - } - - return succ; -} - -bool SingleThreadedDefault::disableService(const entt::id_type s_id) { - bool succ = true; - for (const auto id : _service_tasks[s_id]) { - auto& task = _tasks[id]; - - if (task.auto_enable) { - assert(task.enabled); // this should never happen - } - - if (task.enabled) { - succ &= disable(id); - } - } - - return succ; -} - -bool SingleThreadedDefault::depend(const update_key_t A, const update_key_t B) { - // TODO: error checking lol - - if (_tasks.count(A) == 0) { - return false; // can not add a dependecy of a non existing task - // TODO: or do we? - } - - if (_tasks.count(B) == 1) { - if (_tasks[A].phase != _tasks[B].phase) { - // cross graph tasks are not allowed - return false; - } - } - - auto& graph = getGraph(_tasks[A].phase); - auto ret = graph[A].emplace(B); - return ret.second; // returns whether it was inserted (or already existed) -} - -void SingleThreadedDefault::doUpdate(MM::Engine& engine) { - // pre - runType(engine, update_phase_t::PRE); - - // main - runType(engine, update_phase_t::MAIN); - - // post - runType(engine, update_phase_t::POST); - - // simulate async - for (size_t i = 0; !_async_queue.empty() && i < _max_async_per_tick; i++) { - _async_queue.back()(engine); - _async_queue.pop_back(); - } - - if (!_deferred_queue.empty()) { - for (auto&& fn : _deferred_queue) { - fn(engine); - } - - _deferred_queue.clear(); - } -} - -void SingleThreadedDefault::addDeferred(std::function function) { - _deferred_queue.emplace_back(std::move(function)); -} - -void SingleThreadedDefault::addAsync(std::function function) { - _async_queue.emplace_back(std::move(function)); -} - -#undef __L_ASSERT - -} // MM::UpdateStrategies - diff --git a/framework/engine/src/mm/update_strategies/default_strategy.hpp b/framework/engine/src/mm/update_strategies/default_strategy.hpp deleted file mode 100644 index 8ded6ac..0000000 --- a/framework/engine/src/mm/update_strategies/default_strategy.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once - -#include "./update_strategy.hpp" - -#include -#include -#include -#include - -// fwd -namespace MM::Services { - class ImGuiEngineTools; -} - -namespace MM::UpdateStrategies { - -class SingleThreadedDefault : public MM::UpdateStrategies::UpdateStrategy { - friend MM::Services::ImGuiEngineTools; - - private: - struct Task { - std::string name; - std::function fn; - update_phase_t phase; - bool auto_enable; - - bool enabled = false; - }; - - std::unordered_map _tasks; - - // the tasks a service has registered - std::unordered_map> _service_tasks; - - // tasks dependencies - using Graph = std::unordered_map>; - // TODO: do vector for perf? - - Graph _pre_graph; - Graph _main_graph; - Graph _post_graph; - - std::set _pre_active; - std::set _main_active; - std::set _post_active; - - std::vector> _deferred_queue; - std::vector> _async_queue; - const size_t _max_async_per_tick = 5; // prevent blocking, this should be finetuned - - private: - Graph& getGraph(update_phase_t phase); - std::set& getActiveSet(update_phase_t phase); - - void runType(MM::Engine& engine, update_phase_t phase); - - public: - SingleThreadedDefault(void) = default; - virtual ~SingleThreadedDefault(void); - - const char* name(void) override { return "SingleThreadedDefault"; } - - protected: - bool registerService(const entt::id_type s_id, std::vector&& info_array) override; - - bool enableService(const entt::id_type s_id) override; - bool disableService(const entt::id_type s_id) override; - - void doUpdate(MM::Engine& engine) override; - - public: - bool enable(const update_key_t key) override; - bool disable(const update_key_t key) override; - - bool depend(const update_key_t A, const update_key_t B) override; - - void addDeferred(std::function function) override; - - void addAsync(std::function function) override; -}; - -} // MM::UpdateStrategies - diff --git a/framework/engine/src/mm/update_strategies/dependency_check_decorater.hpp b/framework/engine/src/mm/update_strategies/dependency_check_decorater.hpp deleted file mode 100644 index 3075436..0000000 --- a/framework/engine/src/mm/update_strategies/dependency_check_decorater.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include "./update_strategy.hpp" - -#include -#include - -namespace MM::UpdateStrategies { - -// checks for cyles -template -class DependencyCheckDecorator : public T { - static_assert(std::is_base_of_v); - - public: - //DependencyCheckDecorator(void) = default; - - //template - //DependencyCheckDecorator(Args... args) : T(args) { - //} - - virtual ~DependencyCheckDecorator(void) {} - - private: - void doUpdate(MM::Engine& engine) override { - T::doUpdate(engine); - } - - bool registerService(const entt::id_type s_id, std::vector&& info_array) override { - return T::registerService(s_id, std::move(info_array)); - } - - bool enableService(const entt::id_type s_id) override { - return T::enableService(s_id); - } - - bool disableService(const entt::id_type s_id) override { - return T::disableService(s_id); - } - - public: - bool enable(const update_key_t key) override { - return T::enable(key); - } - - bool disable(const update_key_t key) override { - return T::disable(key); - } - - bool depend(const update_key_t A, const update_key_t B) override { - return T::depend(A, B); - } -}; - -} // MM::UpdateStrategies - diff --git a/framework/engine/src/mm/update_strategies/dummy.hpp b/framework/engine/src/mm/update_strategies/dummy.hpp new file mode 100644 index 0000000..fa09790 --- /dev/null +++ b/framework/engine/src/mm/update_strategies/dummy.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "./update_strategy.hpp" + +// Rezz x Deadmau5 - hypnocurrency + +namespace MM::UpdateStrategies { + +// does nothing, even less then a mock class +// for testing only! +class Dummy : public UpdateStrategy { + public: + ~Dummy(void) {} + + const char* name(void) override { return "Dummy"; } + + protected: // the engine facing interface + bool enableService(const entt::id_type, std::vector&&) override { return true; } + bool disableService(const entt::id_type) override { return true; } + void doUpdate(MM::Engine&) override {} + + public: // the user facing interface + void addDeferred(std::function) override {} + void addAsync(std::function) override {} +}; + +} // MM::UpdateStrategies + diff --git a/framework/engine/src/mm/update_strategies/sequential_strategy.cpp b/framework/engine/src/mm/update_strategies/sequential_strategy.cpp new file mode 100644 index 0000000..97b7a4d --- /dev/null +++ b/framework/engine/src/mm/update_strategies/sequential_strategy.cpp @@ -0,0 +1,126 @@ +#include "./sequential_strategy.hpp" + +#include "./tasking_utils.hpp" + +#include +#include + +#include + +namespace MM::UpdateStrategies { + +//#define __L_ASSERT(cond) if (!(cond)) { return false; } +void Sequential::doGraphSequential(MM::Engine& engine, const std::set& tasks) { + Graph graph = build_task_graph(tasks, + [this](update_key_t key) -> const TaskInfo& { + return _tasks.at(key); + } + ); + + walk_graph_sequential(graph, [this, &engine](update_key_t task_id ) { + _tasks.at(task_id)._fn(engine); + }); +} + +Sequential::~Sequential(void) { +} + +bool Sequential::enableService(const entt::id_type service_id, std::vector&& task_array) { + if (_service_tasks.count(service_id)) { + // error + return false; + } + + auto& service = _service_tasks[service_id]; + + for (const auto& task : task_array) { + _tasks.emplace(task._key, task); + service.emplace(task._key); + } + + return true; +} + +bool Sequential::disableService(const entt::id_type service_id) { + if (!_service_tasks.count(service_id)) { + // error + return false; + } + + for (const auto task_id : _service_tasks[service_id]) { + _tasks.erase(task_id); + } + + _service_tasks.erase(service_id); + + return true; +} + +void Sequential::doUpdate(MM::Engine& engine) { + ZoneScopedN("MM::UpdateStrategies::Sequential::doUpdate") + // TODO: caching + std::set pre_tasks; + std::set main_tasks; + std::set post_tasks; + + for (const auto& [task_id, task] : _tasks) { + switch (task._phase) { + case update_phase_t::PRE: + pre_tasks.emplace(task_id); + break; + case update_phase_t::MAIN: + main_tasks.emplace(task_id); + break; + case update_phase_t::POST: + post_tasks.emplace(task_id); + break; + } + } + + { // pre + ZoneScopedN("MM::UpdateStrategies::Sequential::doUpdate::pre") + doGraphSequential(engine, pre_tasks); + } + + { // main + ZoneScopedN("MM::UpdateStrategies::Sequential::doUpdate::main") + doGraphSequential(engine, main_tasks); + } + + { // post + ZoneScopedN("MM::UpdateStrategies::Sequential::doUpdate::post") + doGraphSequential(engine, post_tasks); + } + + { // simulate async + ZoneScopedN("MM::UpdateStrategies::Sequential::doUpdate::async") + for (size_t i = 0; !_async_queue.empty() && i < _max_async_per_tick; i++) { + _async_queue.back()(engine); + _async_queue.pop_back(); + } + } + + { + ZoneScopedN("MM::UpdateStrategies::Sequential::doUpdate::deferred") + if (!_deferred_queue.empty()) { + for (auto&& fn : _deferred_queue) { + fn(engine); + } + + _deferred_queue.clear(); + } + } +} + +void Sequential::addDeferred(std::function function) { + _deferred_queue.emplace_back(std::move(function)); +} + +void Sequential::addAsync(std::function function) { + _async_queue.emplace_back(std::move(function)); +} + +//#undef __L_ASSERT + +} // MM::UpdateStrategies + diff --git a/framework/engine/src/mm/update_strategies/sequential_strategy.hpp b/framework/engine/src/mm/update_strategies/sequential_strategy.hpp new file mode 100644 index 0000000..8ff2838 --- /dev/null +++ b/framework/engine/src/mm/update_strategies/sequential_strategy.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include "./update_strategy.hpp" + +#include +#include +#include +#include + +// HACK: welp +// fwd +namespace MM::Services { + class ImGuiEngineTools; +} + +namespace MM::UpdateStrategies { + +class Sequential : public MM::UpdateStrategies::UpdateStrategy { + friend MM::Services::ImGuiEngineTools; + + private: + std::unordered_map _tasks; + + // the tasks a service has registered + std::unordered_map> _service_tasks; + + std::vector> _deferred_queue; + std::vector> _async_queue; + + private: // utils + void doGraphSequential(MM::Engine& engine, const std::set& tasks); + + public: + Sequential(void) = default; + virtual ~Sequential(void); + + const char* name(void) override { return "Sequential"; } + + protected: // engine facing interface + bool enableService(const entt::id_type s_id, std::vector&& task_array) override; + bool disableService(const entt::id_type s_id) override; + + void doUpdate(MM::Engine& engine) override; + + public: // user facing interface + void addDeferred(std::function function) override; + + void addAsync(std::function function) override; + + size_t _max_async_per_tick = 5; // prevent blocking, this should be finetuned + + protected: // engine tools interface + void forEachTask(std::function fn) override { + for (auto&& t : _tasks) { + if (!fn(t.second)) { + break; + } + } + } +}; + +} // MM::UpdateStrategies + diff --git a/framework/engine/src/mm/update_strategies/tasking_utils.hpp b/framework/engine/src/mm/update_strategies/tasking_utils.hpp new file mode 100644 index 0000000..5d19242 --- /dev/null +++ b/framework/engine/src/mm/update_strategies/tasking_utils.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include + +namespace MM::UpdateStrategies { + +// all tasks and it dependencies +using Graph = std::unordered_map>; + +template +void walk_graph_sequential(const Graph& graph, FN&& fn) { + // set of all tasks, each completed task will be removed from this until none are left + std::set unworked_node_set{}; + for (auto it = graph.begin(); it != graph.end(); it++) { + unworked_node_set.emplace(it->first); + } + + // TODO: check for inf-loops + while (!unworked_node_set.empty()) { + for (auto node_it = unworked_node_set.begin(); node_it != unworked_node_set.end();) { + // check if deps are resolved + bool resolved = true; + for (const auto dep : graph.at(*node_it)) { + if (unworked_node_set.count(dep)) { + resolved = false; + break; + } + } + + if (resolved) { + // to task + fn(*node_it); + + node_it = unworked_node_set.erase(node_it); + } else { + node_it++; + } + } + } +} + +template +Graph build_task_graph(const std::set& tasks, TaskGet&& task_get) { + Graph graph; + + // phase 1: create all tasks + for (const auto task_id : tasks) { + graph[task_id]; + } + + // phase 2: do all dependencies (and dependents) + for (const auto task_id : tasks) { + auto& graph_node = graph[task_id]; + + { // dependencies + //graph_node.merge(task_get(task_id)._dependencies); + const auto& dependencies = task_get(task_id)._dependencies; + graph_node.insert(dependencies.cbegin(), dependencies.cend()); + } + + // dependents + for (const auto dependent : task_get(task_id)._dependents) { + if (graph.count(dependent)) { + graph[dependent].emplace(task_id); + } + } + } + + return graph; +} + +} // MM::UpdateStrategies + diff --git a/framework/engine/src/mm/update_strategies/update_strategy.hpp b/framework/engine/src/mm/update_strategies/update_strategy.hpp index 77533f8..8d1c6fe 100644 --- a/framework/engine/src/mm/update_strategies/update_strategy.hpp +++ b/framework/engine/src/mm/update_strategies/update_strategy.hpp @@ -2,37 +2,89 @@ #include "../engine_fwd.hpp" +#include + #include + #include #include #include +#include + +// fwd / hack +namespace MM::Services { + class ImGuiEngineTools; +} namespace MM::UpdateStrategies { using update_key_t = entt::id_type; -enum class update_phase_t { - PRE, // for on-main-thread +enum update_phase_t { + PRE = 0, // for on-main-thread MAIN, POST // for on-main-thread }; -struct UpdateCreationInfo { - update_key_t key; // key for dependencies +struct TaskInfo { + update_key_t _key; // key for dependencies + std::string _name; // unhashed key - std::string name; // for debugging + update_phase_t _phase = update_phase_t::MAIN; - std::function fn; // the actual payload - - update_phase_t phase = update_phase_t::MAIN; - - bool auto_enable = true; // whether this update is enabled with the service + // updates we make dependents + std::set _dependents {}; // this update also depends on (in the same phase) - std::vector dependencies {}; + std::set _dependencies {}; + + std::function _fn; // the actual payload + + public: // construction and assignment + TaskInfo(void) = delete; + TaskInfo(const TaskInfo&) = default; + TaskInfo(TaskInfo&&) = default; + + // TODO: is this right?? + TaskInfo& operator=(const TaskInfo&) = default; + TaskInfo& operator=(TaskInfo&&) = default; + + explicit TaskInfo(const std::string_view key_in) { + key(key_in); + } + + public: // builder interface + // TODO: does this need to be public? + TaskInfo& key(const std::string_view key) { + _name = key; + _key = entt::hashed_string::value(key.data(), key.size()); + return *this; + } + + // default phase is main + TaskInfo& phase(const update_phase_t phase) { + _phase = phase; + return *this; + } + + template + TaskInfo& fn(Fn&& fn) { + _fn = fn; + return *this; + } + + TaskInfo& precede(const std::string_view key) { + _dependents.emplace(entt::hashed_string::value(key.data(), key.size())); + return *this; + } + + TaskInfo& succeed(const std::string_view key) { + _dependencies.emplace(entt::hashed_string::value(key.data(), key.size())); + return *this; + } }; -// pure virtual interface for managing the update logic of the engine +// pure virtual interface for managing the update(-task) logic of the engine class UpdateStrategy { public: virtual ~UpdateStrategy(void) {} @@ -42,30 +94,17 @@ class UpdateStrategy { protected: // the engine facing interface friend ::MM::Engine; - // TODO: return something? - virtual bool registerService(const entt::id_type s_id, std::vector&& info_array) = 0; - // returns true on success // failure conditions may include: // - already en/dis-abled - // - is auto_enable - // - impossible dependencies - virtual bool enableService(const entt::id_type s_id) = 0; + // - impossible dependencies? + virtual bool enableService(const entt::id_type s_id, std::vector&& task_array) = 0; virtual bool disableService(const entt::id_type s_id) = 0; // runs one update virtual void doUpdate(MM::Engine& engine) = 0; public: // the user facing interface - // similar to *ableService, can only be used for non-auto_enable-updates - virtual bool enable(const update_key_t key) = 0; - virtual bool disable(const update_key_t key) = 0; - - // add extra dependencies into the tree, the user has the most knowlage about - // the order the services should execute in. - // A -> B (make A depend on B) - virtual bool depend(const update_key_t A, const update_key_t B) = 0; - // WIP: // dont use, if you are not using it to modify the engine. @@ -77,6 +116,10 @@ class UpdateStrategy { // note: the US might decide to limit the amount of executed asyncs per tick (eg. when single-threaded) virtual void addAsync(std::function function) = 0; //virtual std::future addAsync(std::function function) = 0; + protected: // engine tools inspector + friend ::MM::Services::ImGuiEngineTools; + + virtual void forEachTask(std::function fn) = 0; }; } // MM::UpdateStrategies diff --git a/framework/engine/test/CMakeLists.txt b/framework/engine/test/CMakeLists.txt index b6b2862..af95a8c 100644 --- a/framework/engine/test/CMakeLists.txt +++ b/framework/engine/test/CMakeLists.txt @@ -1,7 +1,6 @@ add_executable(engine_test update_strategy_test.cpp - default_us_test.cpp - #dependency_check_us_test.cpp + #default_us_test.cpp # old: #update_test.cpp diff --git a/framework/engine/test/update_strategy_test.cpp b/framework/engine/test/update_strategy_test.cpp index af260d3..7bd056b 100644 --- a/framework/engine/test/update_strategy_test.cpp +++ b/framework/engine/test/update_strategy_test.cpp @@ -16,37 +16,25 @@ class MockUpdateStrategy : public MM::UpdateStrategies::UpdateStrategy { public: const char* name(void) override { return "MockUpdateStrategy"; } - MOCK_METHOD( - bool, - registerService, - (const entt::id_type s_id, std::vector&& info), - (override) - ); - // protected: MOCK_METHOD(void, doUpdate, (MM::Engine& engine), (override)); - MOCK_METHOD(bool, enableService, (const entt::id_type s_id), (override)); + MOCK_METHOD(bool, enableService, (const entt::id_type s_id, std::vector&& task_array), (override)); MOCK_METHOD(bool, disableService, (const entt::id_type s_id), (override)); // public: - MOCK_METHOD(bool, enable, (const MM::UpdateStrategies::update_key_t key), (override)); - MOCK_METHOD(bool, disable, (const MM::UpdateStrategies::update_key_t key), (override)); - - MOCK_METHOD(bool, depend, (const MM::UpdateStrategies::update_key_t A, const MM::UpdateStrategies::update_key_t B), (override)); - MOCK_METHOD(void, addDeferred, (std::function function), (override)); MOCK_METHOD(void, addAsync, (std::function function), (override)); + + MOCK_METHOD(void, forEachTask, (std::function function), (override)); }; class MockService : public MM::Services::Service { public: const char* name(void) override { return "MockService"; } - MOCK_METHOD(bool, enable, (MM::Engine& engine), (override)); + MOCK_METHOD(bool, enable, (MM::Engine& engine, std::vector& task_array), (override)); MOCK_METHOD(void, disable, (MM::Engine& engine), (override)); - - MOCK_METHOD(std::vector, registerUpdates, (), (override)); }; TEST(engine_mock, update_strategy_run) { @@ -63,9 +51,7 @@ TEST(engine_mock, update_strategy_run) { TEST(engine_mock, service_update_strategy) { auto mock = std::make_unique(); - EXPECT_CALL(*mock, registerService(_, _)) - .Times(1); - EXPECT_CALL(*mock, enableService(_)) + EXPECT_CALL(*mock, enableService(_, _)) .Times(1); EXPECT_CALL(*mock, disableService(_)) .Times(1); @@ -73,12 +59,9 @@ TEST(engine_mock, service_update_strategy) { class TmpMockService : public MockService { public: TmpMockService(void) { - EXPECT_CALL(*this, registerUpdates()) + EXPECT_CALL(*this, enable(_, _)) .Times(1); - - EXPECT_CALL(*this, enable(_)) - .Times(1); - ON_CALL(*this, enable(_)) + ON_CALL(*this, enable(_, _)) .WillByDefault(Return(true)); EXPECT_CALL(*this, disable(_)) @@ -99,9 +82,7 @@ TEST(engine_mock, service_update_strategy) { TEST(engine_mock, service_update_strategy_run_1) { auto mock = std::make_unique(); - EXPECT_CALL(*mock, registerService(_, _)) - .Times(1); - EXPECT_CALL(*mock, enableService(_)) + EXPECT_CALL(*mock, enableService(_, _)) .Times(1); EXPECT_CALL(*mock, disableService(_)) .Times(1); @@ -109,23 +90,20 @@ TEST(engine_mock, service_update_strategy_run_1) { class TmpMockService : public MockService { public: explicit TmpMockService(void) { - EXPECT_CALL(*this, registerUpdates()) + EXPECT_CALL(*this, enable) .Times(1); - ON_CALL(*this, registerUpdates()) - .WillByDefault([]() -> std::vector { - return { - { - "TmpMockService"_hs, - "TmpMockService", - [](MM::Engine&) {} - } - }; - }); + ON_CALL(*this, enable) + .WillByDefault([](MM::Engine&, std::vector& task_array) -> bool { + using MM::UpdateStrategies::TaskInfo; - EXPECT_CALL(*this, enable(_)) - .Times(1); - ON_CALL(*this, enable(_)) - .WillByDefault(Return(true)); + task_array.push_back( + TaskInfo{"TmpMockService"} + //.precede("PreviousTask") + .fn([](MM::Engine& engine) { (void)engine; }) + ); + + return true; + }); EXPECT_CALL(*this, disable(_)) .Times(1); diff --git a/framework/filesystem/src/mm/services/filesystem.cpp b/framework/filesystem/src/mm/services/filesystem.cpp index dfc04b3..71125d2 100644 --- a/framework/filesystem/src/mm/services/filesystem.cpp +++ b/framework/filesystem/src/mm/services/filesystem.cpp @@ -22,7 +22,7 @@ namespace MM::Services { -bool FilesystemService::enable(Engine&) { +bool FilesystemService::enable(Engine&, std::vector&) { if (PHYSFS_isInit()) { LOG_ERROR("physfs already initialized!!"); return false; diff --git a/framework/filesystem/src/mm/services/filesystem.hpp b/framework/filesystem/src/mm/services/filesystem.hpp index 16b7c7f..f53ffc6 100644 --- a/framework/filesystem/src/mm/services/filesystem.hpp +++ b/framework/filesystem/src/mm/services/filesystem.hpp @@ -1,5 +1,7 @@ #pragma once +#include "mm/services/service.hpp" +#include "mm/update_strategies/update_strategy.hpp" #include #include @@ -20,7 +22,7 @@ class FilesystemService : public Service { public: - bool enable(Engine&) override; + bool enable(Engine&, std::vector&) override; void disable(Engine&) override; const char* name(void) override { return "Filesystem"; } diff --git a/framework/imgui/src/mm/services/engine_tools.cpp b/framework/imgui/src/mm/services/engine_tools.cpp index bfff92c..08b5805 100644 --- a/framework/imgui/src/mm/services/engine_tools.cpp +++ b/framework/imgui/src/mm/services/engine_tools.cpp @@ -1,12 +1,10 @@ #include "./engine_tools.hpp" -#include "mm/update_strategies/update_strategy.hpp" #include #include -#include -#include +#include #include @@ -17,10 +15,13 @@ namespace MM::Services { using UpdateStrategies::update_key_t; template -static void renderUpdateStratGraph(const std::unordered_map>& g, std::set& a, NColFn&& node_color_fn, LColFn&& line_color_fn, TTFn&& tooltip_fn) { - //auto& g = us_default->getGraph(UpdateStrategies::update_phase_t::MAIN); - //auto& a = us_default->getActiveSet(UpdateStrategies::update_phase_t::MAIN); - +static void renderUpdateStratGraph( + const std::unordered_map>& g, + std::set& a, + NColFn&& node_color_fn, + LColFn&& line_color_fn, + TTFn&& tooltip_fn +) { using UpdateStrategies::update_key_t; std::set work_queue{a.begin(), a.end()}; @@ -156,7 +157,7 @@ static void renderUpdateStratGraph(const std::unordered_map& task_array) { auto& menu_bar = engine.getService(); // use underscore hack to make it last @@ -179,6 +180,13 @@ bool ImGuiEngineTools::enable(Engine& engine) { ImGui::MenuItem("UpdateStrategy", NULL, &_show_update_stategy); }; + // add task + task_array.push_back( + UpdateStrategies::TaskInfo{"ImGuiEngineTools::render"} + .fn([this](Engine& e){ renderImGui(e); }) + .succeed("ImGuiMenuBar::render") + ); + return true; } @@ -191,22 +199,6 @@ void ImGuiEngineTools::disable(Engine& engine) { menu_bar.menu_tree["Engine"].erase("UpdateStrategy"); } -std::vector ImGuiEngineTools::registerUpdates(void) { -using namespace entt::literals; - return { - { - "ImGuiEngineTools::render"_hs, - "ImGuiEngineTools::render", - [this](Engine& e){ renderImGui(e); }, - UpdateStrategies::update_phase_t::MAIN, - true, - { - "ImGuiMenuBar::render"_hs - } - } - }; -} - void ImGuiEngineTools::renderImGui(Engine& engine) { if (_show_about) { renderAbout(engine); @@ -250,7 +242,7 @@ void ImGuiEngineTools::renderServices(Engine& engine) { ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Text("%d", it.first); + ImGui::Text("%u", it.first); ImGui::TableNextColumn(); ImGui::Text("%s", it.second->second->name()); @@ -284,10 +276,99 @@ void ImGuiEngineTools::renderUpdateStrategy(Engine& engine) { auto us_name = us.name(); ImGui::Text("UpdateStrategy: '%s'", us_name); - ImGui::Separator(); - auto* us_default = dynamic_cast(&us); - if (us_default) { + // TODO: tabs? dropdown(combo)? + static const char* const phase_str[4] = { + "All", + "Pre", + "Main", + "Post", + }; + static int curr_phase = 2; + + ImGui::Combo("Phase", &curr_phase, phase_str, 4); + + if (ImGui::BeginTabBar("tabs")) { + if (curr_phase != 0 && ImGui::BeginTabItem("Graph")) { + // BRUHHH this is needs to be cached + std::unordered_map> graph; + std::unordered_map task_lut; + std::set nodes; + + // build lut + us.forEachTask([&graph, &nodes, &task_lut](UpdateStrategies::TaskInfo& task) -> bool { + if (task._phase != UpdateStrategies::update_phase_t(curr_phase-1)) { + return true; // skip, not our phase + } + + graph[task._key] = task._dependencies; + task_lut[task._key] = &task; + nodes.emplace(task._key); + + return true; + }); + + // also do dependents // ugh, 2*N + us.forEachTask([&graph](UpdateStrategies::TaskInfo& task) -> bool { + if (task._phase != UpdateStrategies::update_phase_t(curr_phase-1)) { + return true; // skip, not our phase + } + + for (const auto it : task._dependents) { + graph[it].emplace(task._key); + } + + return true; + }); + + // TODO: make sense of the colloring + renderUpdateStratGraph(graph, nodes, + [](const update_key_t key) -> ImVec4 { + return {0.9f, 1.f, 0.9f, 1.f}; + }, + [](const update_key_t from, const update_key_t to) -> ImVec4 { + return {0.9f, 1.f, 0.9f, 1.f}; + }, + [&task_lut](update_key_t key) { + ImGui::SetTooltip("%s\n[%u]", task_lut.at(key)->_name.c_str(), key); + } + ); + + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem("List")) { + if (ImGui::BeginTable("table", curr_phase == 0 ? 3 : 2)) { + us.forEachTask([](UpdateStrategies::TaskInfo& task) -> bool { + if ( + curr_phase == 0 || + task._phase == UpdateStrategies::update_phase_t(curr_phase-1) + ) { + + ImGui::TableNextRow(); + + ImGui::TableNextColumn(); + ImGui::Text("%u", task._key); + + if (curr_phase == 0) { + ImGui::TableNextColumn(); + ImGui::Text("%s", phase_str[task._phase + 1]); + } + + ImGui::TableNextColumn(); + ImGui::Text("%s", task._name.c_str()); + } + + return true; + }); + ImGui::EndTable(); + } + ImGui::EndTabItem(); + } + + ImGui::EndTabBar(); + } +#if 0 auto& g = us_default->getGraph(UpdateStrategies::update_phase_t::MAIN); auto& a = us_default->getActiveSet(UpdateStrategies::update_phase_t::MAIN); std::set nodes; @@ -305,7 +386,7 @@ void ImGuiEngineTools::renderUpdateStrategy(Engine& engine) { ImGui::Text("%u", it); ImGui::TableNextColumn(); - ImGui::Text("%s", us_default->_tasks[it].name.c_str()); + ImGui::Text("%s", us_default->_tasks.at(it)._name.c_str()); } ImGui::EndTable(); } @@ -329,7 +410,7 @@ void ImGuiEngineTools::renderUpdateStrategy(Engine& engine) { } }, [us_default](update_key_t key) { - ImGui::SetTooltip("'%s'\n[%u]", us_default->_tasks[key].name.c_str(), key); + ImGui::SetTooltip("'%s'\n[%u]", us_default->_tasks.at(key)._name.c_str(), key); }); ImGui::EndTabItem(); } @@ -337,6 +418,7 @@ void ImGuiEngineTools::renderUpdateStrategy(Engine& engine) { ImGui::EndTabBar(); } } +#endif } ImGui::End(); } diff --git a/framework/imgui/src/mm/services/engine_tools.hpp b/framework/imgui/src/mm/services/engine_tools.hpp index e549b2e..0b16cf7 100644 --- a/framework/imgui/src/mm/services/engine_tools.hpp +++ b/framework/imgui/src/mm/services/engine_tools.hpp @@ -8,11 +8,9 @@ namespace MM::Services { public: const char* name(void) override { return "ImGuiEngineTools"; } - bool enable(Engine& engine) override; + bool enable(Engine& engine, std::vector& task_array) override; void disable(Engine& engine) override; - std::vector registerUpdates(void) override; - private: bool _show_about = false; bool _show_services = false; diff --git a/framework/imgui/src/mm/services/imgui_menu_bar.cpp b/framework/imgui/src/mm/services/imgui_menu_bar.cpp index db926bd..8b8d6b4 100644 --- a/framework/imgui/src/mm/services/imgui_menu_bar.cpp +++ b/framework/imgui/src/mm/services/imgui_menu_bar.cpp @@ -1,4 +1,5 @@ #include "./imgui_menu_bar.hpp" +#include "mm/services/service.hpp" #include #include @@ -17,7 +18,7 @@ namespace MM::Services { - bool ImGuiMenuBar::enable(Engine& engine) { + bool ImGuiMenuBar::enable(Engine& engine, std::vector& task_array) { MM::Logger::initSectionLogger("ImGuiMenuBar"); auto* sdl_ss = engine.tryService(); @@ -32,6 +33,12 @@ namespace MM::Services { LOG_WARN("no SDLService, skipping toggle hotkey"); } + // add task + task_array.push_back( + UpdateStrategies::TaskInfo{"ImGuiMenuBar::render"} + .fn([this](Engine& e){ renderImGui(e); }) + ); + return true; } @@ -43,17 +50,6 @@ namespace MM::Services { } } - std::vector ImGuiMenuBar::registerUpdates(void) { - using namespace entt::literals; - return { - { - "ImGuiMenuBar::render"_hs, - "ImGuiMenuBar::render", - [this](Engine& e){ renderImGui(e); } - } - }; - } - void ImGuiMenuBar::renderImGui(Engine& engine) { if (show_menu_bar && ImGui::BeginMainMenuBar()) { @@ -80,7 +76,8 @@ namespace MM::Services { } - ImGui::Text("| %.1fFPS", ImGui::GetIO().Framerate); + ImGui::Separator(); + ImGui::Text("%.1fFPS", ImGui::GetIO().Framerate); ImGui::EndMainMenuBar(); } } diff --git a/framework/imgui/src/mm/services/imgui_menu_bar.hpp b/framework/imgui/src/mm/services/imgui_menu_bar.hpp index e0efa61..1dc3eda 100644 --- a/framework/imgui/src/mm/services/imgui_menu_bar.hpp +++ b/framework/imgui/src/mm/services/imgui_menu_bar.hpp @@ -12,11 +12,9 @@ namespace MM::Services { public: const char* name(void) override { return "ImGuiMenuBar"; } - bool enable(Engine& engine) override; + bool enable(Engine& engine, std::vector& task_array) override; void disable(Engine& engine) override; - std::vector registerUpdates(void) override; - public: bool show_menu_bar = true; diff --git a/framework/imgui/src/mm/services/imgui_s.cpp b/framework/imgui/src/mm/services/imgui_s.cpp index dbdff82..0fbd5a4 100644 --- a/framework/imgui/src/mm/services/imgui_s.cpp +++ b/framework/imgui/src/mm/services/imgui_s.cpp @@ -1,4 +1,6 @@ #include "./imgui_s.hpp" +#include "mm/services/service.hpp" +#include "mm/update_strategies/update_strategy.hpp" #include #include @@ -25,7 +27,7 @@ namespace MM::Services { -bool ImGuiService::enable(Engine& engine) { +bool ImGuiService::enable(Engine& engine, std::vector& task_array) { IMGUI_CHECKVERSION(); ImGui::CreateContext(); @@ -69,6 +71,14 @@ bool ImGuiService::enable(Engine& engine) { [this](const SDL_Event& e) { return handle_sdl_event(e); } ); + // add task + task_array.push_back( + UpdateStrategies::TaskInfo{"ImGuiService::new_frame"} + .phase(UpdateStrategies::update_phase_t::PRE) + .fn([this](Engine& e) { this->imgui_new_frame(e); }) + .succeed("SDLService::events") + ); + return true; } @@ -85,20 +95,6 @@ void ImGuiService::disable(Engine& engine) { ImGui::DestroyContext(); } -std::vector ImGuiService::registerUpdates(void) { - using namespace entt::literals; - return { - { - "ImGuiService::new_frame"_hs, - "ImGuiService::new_frame", - [this](Engine& e) { this->imgui_new_frame(e); }, - UpdateStrategies::update_phase_t::PRE, - true, - {"SDLService::events"_hs} - } - }; -} - void ImGuiService::imgui_new_frame(Engine& engine) { ZoneScopedN("MM::Services::ImGuiService::imgui_new_frame"); diff --git a/framework/imgui/src/mm/services/imgui_s.hpp b/framework/imgui/src/mm/services/imgui_s.hpp index 49df490..5a1c98a 100644 --- a/framework/imgui/src/mm/services/imgui_s.hpp +++ b/framework/imgui/src/mm/services/imgui_s.hpp @@ -14,13 +14,11 @@ namespace MM::Services { // new frame needs to start AFTER the events have been processed (and obv bf rendt) public: - bool enable(Engine& engine) override; + bool enable(Engine& engine, std::vector& task_array) override; void disable(Engine& engine) override; const char* name(void) override { return "ImGuiService"; } - std::vector registerUpdates(void) override; - private: void imgui_new_frame(Engine& engine); diff --git a/framework/imgui/src/mm/services/scene_tools.cpp b/framework/imgui/src/mm/services/scene_tools.cpp index 6f0b7d0..a20e278 100644 --- a/framework/imgui/src/mm/services/scene_tools.cpp +++ b/framework/imgui/src/mm/services/scene_tools.cpp @@ -7,6 +7,7 @@ #include #include "./imgui_menu_bar.hpp" #include "mm/components/time_delta.hpp" +#include "mm/services/service.hpp" #include @@ -36,7 +37,7 @@ namespace MM::Services { - bool ImGuiSceneToolsService::enable(Engine& engine) { + bool ImGuiSceneToolsService::enable(Engine& engine, std::vector& task_array) { if (!engine.tryService()) { LOGIGS("error: no SceneServiceInterface"); return false; @@ -82,6 +83,13 @@ namespace MM::Services { ImGui::MenuItem("TimeDelta Context", NULL, &_show_time_delta_ctx, td_ptr); }; + // add task + task_array.push_back( + UpdateStrategies::TaskInfo{"ImGuiSceneToolsService::render"} + .fn([this](Engine& e){ renderImGui(e); }) + .succeed("ImGuiMenuBar::render") + ); + return true; } @@ -94,22 +102,6 @@ namespace MM::Services { menu_bar.menu_tree["Scene"].erase("TimeCtx"); } - std::vector ImGuiSceneToolsService::registerUpdates(void) { - using namespace entt::literals; - return { - { - "ImGuiSceneToolsService::render"_hs, - "ImGuiSceneToolsService::render", - [this](Engine& e){ renderImGui(e); }, - UpdateStrategies::update_phase_t::MAIN, - true, - { - "ImGuiMenuBar::render"_hs - } - } - }; - } - void ImGuiSceneToolsService::renderImGui(Engine& engine) { auto& scene = engine.tryService()->getScene(); diff --git a/framework/imgui/src/mm/services/scene_tools.hpp b/framework/imgui/src/mm/services/scene_tools.hpp index f9a0edd..0a22f26 100644 --- a/framework/imgui/src/mm/services/scene_tools.hpp +++ b/framework/imgui/src/mm/services/scene_tools.hpp @@ -1,5 +1,6 @@ #pragma once +#include "mm/services/service.hpp" #define MM_IEEE_ENTITY_WIDGET ::MM::ImGuiWidgets::Entity // evil #define MM_IEEE_ASSERT(x) #include @@ -11,13 +12,11 @@ namespace MM::Services { class ImGuiSceneToolsService : public Service { public: - bool enable(Engine& engine) override; + bool enable(Engine& engine, std::vector& task_array) override; void disable(Engine& engine) override; const char* name(void) override { return "ImGuiSceneToolsService"; } - std::vector registerUpdates(void) override; - private: bool _show_scene_metrics = false; bool _show_entity_editor = false; diff --git a/framework/imgui/src/mm/services/sound_tools.cpp b/framework/imgui/src/mm/services/sound_tools.cpp index dc099d7..7e6dfd8 100644 --- a/framework/imgui/src/mm/services/sound_tools.cpp +++ b/framework/imgui/src/mm/services/sound_tools.cpp @@ -1,5 +1,5 @@ #include "./sound_tools.hpp" -#include "mm/imgui/sound_info.hpp" +#include #include #include @@ -13,7 +13,7 @@ namespace MM::Services { - bool ImGuiSoundTools::enable(Engine& engine) { + bool ImGuiSoundTools::enable(Engine& engine, std::vector& task_array) { auto& menu_bar = engine.getService(); //menu_bar.menu_tree["Engine"]["Stop Engine"] = [](Engine& e) { @@ -35,6 +35,13 @@ namespace MM::Services { ImGui::MenuItem("Info", NULL, &_show_info); }; + // add task + task_array.push_back( + UpdateStrategies::TaskInfo{"ImGuiSoundTools::render"} + .fn([this](Engine& e){ renderImGui(e); }) + .succeed("ImGuiMenuBar::render") + ); + return true; } @@ -45,22 +52,6 @@ namespace MM::Services { menu_bar.menu_tree["Sound"].erase("Info"); } - std::vector ImGuiSoundTools::registerUpdates(void) { - using namespace entt::literals; - return { - { - "ImGuiSoundTools::render"_hs, - "ImGuiSoundTools::render", - [this](Engine& e){ renderImGui(e); }, - UpdateStrategies::update_phase_t::MAIN, - true, - { - "ImGuiMenuBar::render"_hs - } - } - }; - } - void ImGuiSoundTools::renderImGui(Engine& engine) { if (_show_info) { MM::ImGuiSoundInfo(engine, &_show_info); diff --git a/framework/imgui/src/mm/services/sound_tools.hpp b/framework/imgui/src/mm/services/sound_tools.hpp index 204bed7..f158332 100644 --- a/framework/imgui/src/mm/services/sound_tools.hpp +++ b/framework/imgui/src/mm/services/sound_tools.hpp @@ -1,6 +1,7 @@ #pragma once #include "./imgui_menu_bar.hpp" +#include "mm/services/service.hpp" namespace MM::Services { @@ -8,11 +9,9 @@ namespace MM::Services { public: const char* name(void) override { return "ImGuiSoundTools"; } - bool enable(Engine& engine) override; + bool enable(Engine& engine, std::vector& task_array) override; void disable(Engine& engine) override; - std::vector registerUpdates(void) override; - private: bool _show_info = false; diff --git a/framework/imgui/test/scene_tools_test.cpp b/framework/imgui/test/scene_tools_test.cpp index 862a798..259de0c 100644 --- a/framework/imgui/test/scene_tools_test.cpp +++ b/framework/imgui/test/scene_tools_test.cpp @@ -47,7 +47,7 @@ TEST(imgui_scene_tools, it) { ASSERT_TRUE(engine.enableService()); engine.addService(); - engine.getUpdateStrategy().depend("ImGuiSceneToolsService::render"_hs, "SimpleSceneService::scene_tick"_hs); + //engine.getUpdateStrategy().depend("ImGuiSceneToolsService::render"_hs, "SimpleSceneService::scene_tick"_hs); auto& rs = engine.addService(); ASSERT_TRUE(engine.enableService()); diff --git a/framework/imgui/test/sound_test.cpp b/framework/imgui/test/sound_test.cpp index 21159f3..3e029d6 100644 --- a/framework/imgui/test/sound_test.cpp +++ b/framework/imgui/test/sound_test.cpp @@ -1,3 +1,4 @@ +#include "mm/services/service.hpp" #include #include @@ -45,7 +46,7 @@ class ImGuiSpeechy : public MM::Services::Service { public: const char* name(void) override { return "TestWindow"; } - bool enable(MM::Engine& engine) override { + bool enable(MM::Engine& engine, std::vector& task_array) override { auto& sound = engine.getService().engine; speech.setText("Test text. 1. 2. 3."); @@ -55,21 +56,16 @@ class ImGuiSpeechy : public MM::Services::Service { sound.setGlobalFilter(1, &echo); sound.setGlobalFilter(2, &freeverb); + task_array.push_back( + MM::UpdateStrategies::TaskInfo{"testwindow"} + .fn([this](MM::Engine& engine) { renderImGui(engine); }) + ); + return true; } void disable(MM::Engine&) override {} - std::vector registerUpdates(void) override { - return {{ - "testwindow"_hs, - "testwindow", - [this](MM::Engine& engine) { - renderImGui(engine); - } - }}; - } - void renderImGui(MM::Engine& engine) { auto& sound = *engine.tryService(); diff --git a/framework/imgui/test/text_edit_test.cpp b/framework/imgui/test/text_edit_test.cpp index eb5ec7e..03360bd 100644 --- a/framework/imgui/test/text_edit_test.cpp +++ b/framework/imgui/test/text_edit_test.cpp @@ -1,3 +1,4 @@ +#include "mm/services/service.hpp" #include #include @@ -32,16 +33,16 @@ class TemplateUpdateMainService : public MM::Services::Service { explicit TemplateUpdateMainService(std::function fn) : _fn(fn) {} const char* name(void) override { return "TemplateUpdateMainService"; } - bool enable(MM::Engine&) override { return true; } - void disable(MM::Engine&) override {} - std::vector registerUpdates(void) override { - return {{ - "TemplateUpdateMainService::fn"_hs, - "TemplateUpdateMainService::fn", - _fn - }}; + bool enable(MM::Engine&, std::vector& task_array) override { + task_array.push_back( + MM::UpdateStrategies::TaskInfo{"TemplateUpdateMainService::fn"} + .fn(_fn) + ); + return true; } + + void disable(MM::Engine&) override {} }; TEST(imgui_text_edit, it) { diff --git a/framework/imgui/test/widget_test.cpp b/framework/imgui/test/widget_test.cpp index 2aebf35..0ff2a48 100644 --- a/framework/imgui/test/widget_test.cpp +++ b/framework/imgui/test/widget_test.cpp @@ -1,5 +1,4 @@ -#include "mm/imgui/widgets/scalar_range.hpp" -#include "mm/scalar_range2.hpp" +#include "mm/services/service.hpp" #include #include @@ -17,6 +16,7 @@ #include #include +#include const char* argv0; @@ -44,14 +44,11 @@ TEST(imgui_widgets, basic) { class TestWindow : public MM::Services::Service { public: const char* name(void) override { return "TestWindow"; } - bool enable(MM::Engine&) override { return true; } - void disable(MM::Engine&) override {} - std::vector registerUpdates(void) override { - return {{ - "testwindow"_hs, - "testwindow", - [](MM::Engine&) { + bool enable(MM::Engine&, std::vector& task_array) override { + task_array.push_back( + MM::UpdateStrategies::TaskInfo{"testwindow"} + .fn([](MM::Engine&) { if (ImGui::Begin("test window")) { static float knob_test = 0.f; @@ -63,9 +60,12 @@ TEST(imgui_widgets, basic) { MM::ImGuiWidgets::DragScalarRange2("range", range); } ImGui::End(); - } - }}; + }) + ); + return true; } + + void disable(MM::Engine&) override {} }; engine.addService(); diff --git a/framework/input/src/mm/services/input_service.cpp b/framework/input/src/mm/services/input_service.cpp index 01fa27f..bf337ff 100644 --- a/framework/input/src/mm/services/input_service.cpp +++ b/framework/input/src/mm/services/input_service.cpp @@ -77,7 +77,7 @@ InputService::InputService(void) { InputService::~InputService(void) { } -bool InputService::enable(Engine& engine) { +bool InputService::enable(Engine& engine, std::vector& task_array) { auto* sdl_ss = engine.tryService(); if (!sdl_ss) { LOG_ERROR("InputService requires SDLService in engine!"); @@ -90,6 +90,24 @@ bool InputService::enable(Engine& engine) { return false; } + // add task + task_array.push_back( + UpdateStrategies::TaskInfo{"InputService::update"} + .fn([this](MM::Engine&) { + for (size_t i = 0; i < 4; i++) { + if (!_player_active[i]) + continue; + + auto& p = _player[i]; + if (p.is_controller) { + } else { + updateKPlayerDirs(p); + } + } + } + ) + ); + return true; } @@ -105,28 +123,6 @@ void InputService::disable(Engine& engine) { } } -std::vector InputService::registerUpdates(void) { - using namespace entt::literals; - return { - { - "InputService::update"_hs, - "InputService::update", - [this](MM::Engine&) { - for (size_t i = 0; i < 4; i++) { - if (!_player_active[i]) - continue; - - auto& p = _player[i]; - if (p.is_controller) { - } else { - updateKPlayerDirs(p); - } - } - } - } - }; -} - bool InputService::handleSDL_Event(const SDL_Event& e, MM::Engine& engine) { ZoneScopedN("MM::InputService::handleSDL_Event"); switch (e.type) { diff --git a/framework/input/src/mm/services/input_service.hpp b/framework/input/src/mm/services/input_service.hpp index 2c326ba..40db405 100644 --- a/framework/input/src/mm/services/input_service.hpp +++ b/framework/input/src/mm/services/input_service.hpp @@ -1,7 +1,6 @@ #pragma once -#include - +#include "mm/services/service.hpp" #include #include @@ -108,14 +107,11 @@ namespace MM::Services { SDLService::EventHandlerHandle _event_handle = nullptr; public: - bool enable(Engine& engine) override; + bool enable(Engine& engine, std::vector& task_array) override; void disable(Engine& engine) override; const char* name(void) override { return "InputService"; } - // you will likely want to make the scene depend on this - std::vector registerUpdates(void) override; - public: // returns true if event was relevant bool handleSDL_Event(const SDL_Event& e, MM::Engine& engine); diff --git a/framework/input/test/input_visualizer.cpp b/framework/input/test/input_visualizer.cpp index 1e88218..12c7a72 100644 --- a/framework/input/test/input_visualizer.cpp +++ b/framework/input/test/input_visualizer.cpp @@ -1,4 +1,6 @@ +#include "mm/services/service.hpp" #include + #include #include #include @@ -11,7 +13,6 @@ #include - class InputVisualizer : public MM::Services::Service { private: MM::Input::PlayerID _player_id; @@ -20,7 +21,7 @@ class InputVisualizer : public MM::Services::Service { public: const char* name(void) override { return "InputVisualizer"; } - bool enable(MM::Engine& engine) override { + bool enable(MM::Engine& engine, std::vector& task_array) override { _player_id = UINT16_MAX; auto* sdl_ss = engine.tryService(); @@ -40,27 +41,18 @@ class InputVisualizer : public MM::Services::Service { } } + task_array.push_back( + MM::UpdateStrategies::TaskInfo{"InputVisualizer::render"} + .fn([this](MM::Engine& e){ renderImGui(e); }) + .succeed("InputService::update") + ); + return true; } void disable(MM::Engine&) override { } - std::vector registerUpdates(void) override { - using namespace entt::literals; - return { - { - "InputVisualizer::render"_hs, - "InputVisualizer::render", - [this](MM::Engine& e){ this->renderImGui(e); }, - MM::UpdateStrategies::update_phase_t::MAIN, - true, - { "InputService::update"_hs } - } - }; - } - - private: void renderImGui(MM::Engine& engine) { ImGui::Begin("InputVisualizer", NULL, ImGuiWindowFlags_AlwaysAutoResize); diff --git a/framework/opengl_renderer/src/mm/services/opengl_renderer.cpp b/framework/opengl_renderer/src/mm/services/opengl_renderer.cpp index 484c710..f838000 100644 --- a/framework/opengl_renderer/src/mm/services/opengl_renderer.cpp +++ b/framework/opengl_renderer/src/mm/services/opengl_renderer.cpp @@ -43,7 +43,7 @@ OpenGLRenderer::OpenGLRenderer(void) { OpenGLRenderer::~OpenGLRenderer(void) { } -bool OpenGLRenderer::enable(Engine& engine) { +bool OpenGLRenderer::enable(Engine& engine, std::vector& task_array) { if (!engine.tryService()) { LOG_ERROR("OpenGLRenderer requires SDLService"); return false; @@ -126,6 +126,14 @@ bool OpenGLRenderer::enable(Engine& engine) { } } + { // add task + task_array.push_back( + UpdateStrategies::TaskInfo{"OpenGLRenderer::render"} + .phase(UpdateStrategies::update_phase_t::POST) + .fn([this](Engine& e){ this->render(e); }) + ); + } + return true; } @@ -138,17 +146,6 @@ void OpenGLRenderer::disable(Engine&) { MM::ResourceManager::ref().clear(); } -std::vector OpenGLRenderer::registerUpdates(void) { - return { - { - "OpenGLRenderer::render"_hs, - "OpenGLRenderer::render", - [this](Engine& e){ this->render(e); }, - UpdateStrategies::update_phase_t::POST - } - }; -} - void OpenGLRenderer::render(Engine& engine) { ZoneScopedN("MM::Services::OpenGLRenderer::render"); diff --git a/framework/opengl_renderer/src/mm/services/opengl_renderer.hpp b/framework/opengl_renderer/src/mm/services/opengl_renderer.hpp index e7aa297..fd34744 100644 --- a/framework/opengl_renderer/src/mm/services/opengl_renderer.hpp +++ b/framework/opengl_renderer/src/mm/services/opengl_renderer.hpp @@ -31,14 +31,11 @@ namespace MM::Services { SDLService::EventHandlerHandle _sdl_event_handle = nullptr; public: - bool enable(Engine& engine) override; + bool enable(Engine& engine, std::vector& task_array) override; void disable(Engine& engine) override; const char* name(void) override { return "OpenGLRendererService"; } - std::vector registerUpdates(void) override; - - private: void render(Engine& engine); }; diff --git a/framework/opengl_renderer/src/mm/services/opengl_renderer_tools.cpp b/framework/opengl_renderer/src/mm/services/opengl_renderer_tools.cpp index 684d068..5c34a03 100644 --- a/framework/opengl_renderer/src/mm/services/opengl_renderer_tools.cpp +++ b/framework/opengl_renderer/src/mm/services/opengl_renderer_tools.cpp @@ -10,7 +10,7 @@ namespace MM::Services { -bool ImGuiOpenGLRendererTools::enable(Engine& engine) { +bool ImGuiOpenGLRendererTools::enable(Engine& engine, std::vector& task_array) { auto& menu_bar = engine.getService(); menu_bar.menu_tree["OpenGL"]["RenderTasks"] = [this](Engine&) { @@ -21,6 +21,13 @@ bool ImGuiOpenGLRendererTools::enable(Engine& engine) { ImGui::MenuItem("Texture Cache (legacy)", NULL, &_show_texture_cache_legacy); }; + // add task + task_array.push_back( + UpdateStrategies::TaskInfo{"ImGuiOpenGLRendererTools::render"} + .fn([this](Engine& e) { renderImGui(e); }) + .succeed("ImGuiMenuBar::render") + ); + return true; } @@ -31,22 +38,6 @@ void ImGuiOpenGLRendererTools::disable(Engine& engine) { menu_bar.menu_tree["OpenGL"].erase("TextureCacheLegacy"); } -std::vector ImGuiOpenGLRendererTools::registerUpdates(void) { - using namespace entt::literals; - return { - { - "ImGuiOpenGLRendererTools::render"_hs, - "ImGuiOpenGLRendererTools::render", - [this](Engine& e) { renderImGui(e); }, - UpdateStrategies::update_phase_t::MAIN, - true, - { - "ImGuiMenuBar::render"_hs - } - } - }; -} - void ImGuiOpenGLRendererTools::renderImGui(Engine& engine) { if (_show_render_tasks) { renderRenderTasks(engine); diff --git a/framework/opengl_renderer/src/mm/services/opengl_renderer_tools.hpp b/framework/opengl_renderer/src/mm/services/opengl_renderer_tools.hpp index de5b34f..c1ee82a 100644 --- a/framework/opengl_renderer/src/mm/services/opengl_renderer_tools.hpp +++ b/framework/opengl_renderer/src/mm/services/opengl_renderer_tools.hpp @@ -8,11 +8,9 @@ namespace MM::Services { public: const char* name(void) override { return "ImGuiOpenGLRendererTools"; } - bool enable(Engine& engine) override; + bool enable(Engine& engine, std::vector& task_array) override; void disable(Engine& engine) override; - std::vector registerUpdates(void) override; - private: bool _show_render_tasks = false; bool _show_texture_cache_legacy = false; diff --git a/framework/opengl_renderer/test/imgui_render_task_test.cpp b/framework/opengl_renderer/test/imgui_render_task_test.cpp index 4fa0799..74170d7 100644 --- a/framework/opengl_renderer/test/imgui_render_task_test.cpp +++ b/framework/opengl_renderer/test/imgui_render_task_test.cpp @@ -30,17 +30,16 @@ TEST(imgui_render_task, demowindow) { class ImGuiDemoWindowService : public MM::Services::Service { public: const char* name(void) override { return "ImGuiDemoWindowService"; } - bool enable(MM::Engine&) override { return true; } - void disable(MM::Engine&) override {} - std::vector registerUpdates(void) override { - return {{ - "ImGuiDemoWindow"_hs, - "ImGuiDemoWindow", - [](MM::Engine&) { ImGui::ShowDemoWindow(); } - }}; + bool enable(MM::Engine&, std::vector& task_array) override { + task_array.push_back( + MM::UpdateStrategies::TaskInfo{"ImGuiDemoWindow"} + .fn([](MM::Engine&) { ImGui::ShowDemoWindow(); }) + ); + return true; } + void disable(MM::Engine&) override {} }; engine.addService(); ASSERT_TRUE(engine.enableService()); diff --git a/framework/organizer_scene/src/mm/services/organizer_scene.cpp b/framework/organizer_scene/src/mm/services/organizer_scene.cpp index cb6e67a..5d9886f 100644 --- a/framework/organizer_scene/src/mm/services/organizer_scene.cpp +++ b/framework/organizer_scene/src/mm/services/organizer_scene.cpp @@ -36,7 +36,25 @@ static std::ostream& operator<<(std::ostream& out, const std::vector& task_array) { + // add tasks + task_array.push_back( + UpdateStrategies::TaskInfo{"OrganizerSceneService::scene_update"} + .fn([this](Engine& e) { sceneUpdate(e); }) + ); + task_array.push_back( + UpdateStrategies::TaskInfo{"OrganizerSceneService::scene_tick"} + .fn([this](Engine& e) { sceneFixedUpdate(e); }) + + // bc it renders imgui, but this is not "hard" + .succeed("OrganizerSceneService::scene_update") + ); + task_array.push_back( + UpdateStrategies::TaskInfo{"OrganizerSceneService::scene_changer"} + .fn([this](Engine& e) { changeSceneFixedUpdate(e); }) + .succeed("OrganizerSceneService::scene_tick") + ); + // default scene if (!_scene) { _scene = std::make_unique(); @@ -52,38 +70,6 @@ bool OrganizerSceneService::enable(Engine& engine) { void OrganizerSceneService::disable(Engine&) { } -std::vector OrganizerSceneService::registerUpdates(void) { - using namespace entt::literals; - return { - { - "OrganizerSceneService::scene_update"_hs, - "OrganizerSceneService::scene_update", - [this](Engine& e) { sceneUpdate(e); }, - // depends on imgui - }, - { - "OrganizerSceneService::scene_tick"_hs, - "OrganizerSceneService::scene_tick", - [this](Engine& e) { sceneFixedUpdate(e); }, - UpdateStrategies::update_phase_t::MAIN, - true, - { - "OrganizerSceneService::scene_update"_hs, // bc it renders imgui, but this is not "hard" - } - }, - { - "OrganizerSceneService::scene_changer"_hs, - "OrganizerSceneService::scene_changer", - [this](Engine& e) { changeSceneFixedUpdate(e); }, - UpdateStrategies::update_phase_t::MAIN, - true, - { - "OrganizerSceneService::scene_tick"_hs, - } - }, - }; -} - void OrganizerSceneService::sceneFixedUpdate(Engine&) { ZoneScoped; diff --git a/framework/organizer_scene/src/mm/services/organizer_scene.hpp b/framework/organizer_scene/src/mm/services/organizer_scene.hpp index 004fd64..f54a211 100644 --- a/framework/organizer_scene/src/mm/services/organizer_scene.hpp +++ b/framework/organizer_scene/src/mm/services/organizer_scene.hpp @@ -1,5 +1,6 @@ #pragma once +#include "mm/services/service.hpp" #include #include @@ -28,11 +29,9 @@ namespace MM::Services { const char* name(void) override { return "OrganizerSceneService"; } - bool enable(Engine& engine) override; + bool enable(Engine& engine, std::vector& task_array) override; void disable(Engine& engine) override; - std::vector registerUpdates(void) override; - public: // scene interface Scene& getScene(void) override { return *_scene; } diff --git a/framework/screen_director/src/mm/services/screen_director.cpp b/framework/screen_director/src/mm/services/screen_director.cpp index db105b3..0bb0d65 100644 --- a/framework/screen_director/src/mm/services/screen_director.cpp +++ b/framework/screen_director/src/mm/services/screen_director.cpp @@ -1,4 +1,6 @@ #include "./screen_director.hpp" +#include "mm/services/service.hpp" +#include "mm/update_strategies/update_strategy.hpp" #include @@ -8,7 +10,14 @@ namespace MM::Services { -bool ScreenDirector::enable(MM::Engine& engine) { +bool ScreenDirector::enable(MM::Engine& engine, std::vector& task_array) { + // add task + task_array.push_back( + UpdateStrategies::TaskInfo{"ScreenDirector::update"} + .fn([this](Engine& e) { update(e); }) + .phase(UpdateStrategies::update_phase_t::POST) + ); + // start initial screen if (!queued_screen_id.empty()) { auto next_screen_id = queued_screen_id; @@ -25,18 +34,6 @@ bool ScreenDirector::enable(MM::Engine& engine) { void ScreenDirector::disable(MM::Engine&) { } -std::vector ScreenDirector::registerUpdates(void) { - using namespace entt::literals; - return { - { - "ScreenDirector::update"_hs, - "ScreenDirector::update", - [this](Engine& engine) { update(engine); }, - UpdateStrategies::update_phase_t::POST - } - }; -} - void ScreenDirector::update(MM::Engine& engine) { if (curr_screen_id != queued_screen_id) { engine.getUpdateStrategy().addDeferred([this](MM::Engine& e) { diff --git a/framework/screen_director/src/mm/services/screen_director.hpp b/framework/screen_director/src/mm/services/screen_director.hpp index b31b106..f6c52e0 100644 --- a/framework/screen_director/src/mm/services/screen_director.hpp +++ b/framework/screen_director/src/mm/services/screen_director.hpp @@ -12,11 +12,9 @@ class ScreenDirector : public Service { const char* name(void) override { return "ScreenDirector"; } // enable switches to queued_screen_index - bool enable(MM::Engine&) override; + bool enable(MM::Engine&, std::vector& task_array) override; void disable(MM::Engine&) override; - std::vector registerUpdates(void) override; - public: struct Screen { // lists of services relevant for this screen, disable and enable are called when its changed to diff --git a/framework/screen_director/test/sd_test.cpp b/framework/screen_director/test/sd_test.cpp index 6c7b280..f14f704 100644 --- a/framework/screen_director/test/sd_test.cpp +++ b/framework/screen_director/test/sd_test.cpp @@ -7,7 +7,7 @@ class TestService1 : public MM::Services::Service { public: const char* name(void) override { return "TestService1"; } - bool enable(MM::Engine&) override { return true; } + bool enable(MM::Engine&, std::vector&) override { return true; } void disable(MM::Engine&) override {} }; @@ -15,7 +15,7 @@ class TestService2 : public MM::Services::Service { public: const char* name(void) override { return "TestService2"; } - bool enable(MM::Engine&) override { return true; } + bool enable(MM::Engine&, std::vector&) override { return true; } void disable(MM::Engine&) override {} }; @@ -23,7 +23,7 @@ class TestServiceInterface : public MM::Services::Service { public: const char* name(void) override { return "TestServiceInterface"; } - bool enable(MM::Engine&) override { return true; } + bool enable(MM::Engine&, std::vector&) override { return true; } void disable(MM::Engine&) override {} public: @@ -34,7 +34,7 @@ class TestServiceInterfaceImpl1 : public TestServiceInterface { public: const char* name(void) override { return "TestServiceInterfaceImpl1"; } - bool enable(MM::Engine&) override { return true; } + bool enable(MM::Engine&, std::vector&) override { return true; } void disable(MM::Engine&) override {} public: @@ -47,7 +47,7 @@ class TestServiceInterfaceImpl2 : public TestServiceInterface { public: const char* name(void) override { return "TestServiceInterfaceImpl2"; } - bool enable(MM::Engine&) override { return true; } + bool enable(MM::Engine&, std::vector&) override { return true; } void disable(MM::Engine&) override {} public: diff --git a/framework/sdl_service/src/mm/services/sdl_service.cpp b/framework/sdl_service/src/mm/services/sdl_service.cpp index 6062e03..3a4d696 100644 --- a/framework/sdl_service/src/mm/services/sdl_service.cpp +++ b/framework/sdl_service/src/mm/services/sdl_service.cpp @@ -1,4 +1,6 @@ #include "./sdl_service.hpp" +#include "mm/services/service.hpp" +#include "mm/update_strategies/update_strategy.hpp" #include @@ -70,19 +72,14 @@ SDLService::~SDLService(void) { SDL_Quit(); } -std::vector SDLService::registerUpdates(void) { - using namespace entt::literals; - return { - { - "SDLService::events"_hs, - "SDLService::events", - [this](Engine& e) { this->processEvents(e); }, - UpdateStrategies::update_phase_t::PRE - } - }; -} +bool SDLService::enable(Engine&, std::vector& task_array) { + // add task + task_array.push_back( + UpdateStrategies::TaskInfo{"SDLService::events"} + .phase(UpdateStrategies::update_phase_t::PRE) + .fn([this](Engine& e) { this->processEvents(e); }) + ); -bool SDLService::enable(Engine&) { bool succ = true; return succ; } diff --git a/framework/sdl_service/src/mm/services/sdl_service.hpp b/framework/sdl_service/src/mm/services/sdl_service.hpp index 6c80268..cd3b71d 100644 --- a/framework/sdl_service/src/mm/services/sdl_service.hpp +++ b/framework/sdl_service/src/mm/services/sdl_service.hpp @@ -27,9 +27,7 @@ namespace MM::Services { ~SDLService(void); public: - std::vector registerUpdates(void) override; - - bool enable(Engine& engine) override; + bool enable(Engine& engine, std::vector& task_array) override; void disable(Engine& engine) override; // destroys windows and ass contexts const char* name(void) override { return "SDLService"; } diff --git a/framework/simple_scene/src/mm/services/simple_scene.cpp b/framework/simple_scene/src/mm/services/simple_scene.cpp index 64af80b..5009ace 100644 --- a/framework/simple_scene/src/mm/services/simple_scene.cpp +++ b/framework/simple_scene/src/mm/services/simple_scene.cpp @@ -1,4 +1,5 @@ #include "./simple_scene.hpp" +#include "mm/services/service.hpp" #include @@ -12,7 +13,18 @@ namespace MM::Services { -bool SimpleSceneService::enable(Engine& engine) { +bool SimpleSceneService::enable(Engine& engine, std::vector& task_array) { + // add tasks + task_array.push_back( + UpdateStrategies::TaskInfo{"SimpleSceneService::scene_tick"} + .fn([this](Engine& e) { sceneFixedUpdate(e); }) + ); + task_array.push_back( + UpdateStrategies::TaskInfo{"SimpleSceneService::scene_change"} + .succeed("SimpleSceneService::scene_tick") + .fn([this](Engine& e) { changeSceneFixedUpdate(e); }) + ); + // default scene if (!_scene) { _scene = std::make_unique(); @@ -27,29 +39,6 @@ bool SimpleSceneService::enable(Engine& engine) { void SimpleSceneService::disable(Engine&) { } -std::vector SimpleSceneService::registerUpdates(void) { - using namespace entt::literals; - return { - { - "SimpleSceneService::scene_tick"_hs, - "SimpleSceneService::scene_tick", - [this](Engine& e) { this->sceneFixedUpdate(e); }, - UpdateStrategies::update_phase_t::MAIN, - true, - {} // no dependencies" - }, - { - "SimpleSceneService::scene_change"_hs, - "SimpleSceneService::scene_change", - [this](Engine& e) { this->changeSceneFixedUpdate(e); }, - UpdateStrategies::update_phase_t::MAIN, - true, - //{"SimpleSceneService::scene_update"_hs} // first update, than change???? - {"SimpleSceneService::scene_tick"_hs} - } - }; -} - void SimpleSceneService::sceneFixedUpdate(Engine&) { ZoneScoped; diff --git a/framework/simple_scene/src/mm/services/simple_scene.hpp b/framework/simple_scene/src/mm/services/simple_scene.hpp index d84984b..063fcb3 100644 --- a/framework/simple_scene/src/mm/services/simple_scene.hpp +++ b/framework/simple_scene/src/mm/services/simple_scene.hpp @@ -1,5 +1,6 @@ #pragma once +#include "mm/services/service.hpp" #include #include @@ -26,11 +27,9 @@ namespace MM::Services { const char* name(void) override { return "SimpleSceneService"; } - bool enable(Engine& engine) override; + bool enable(Engine& engine, std::vector& task_array) override; void disable(Engine& engine) override; - std::vector registerUpdates(void) override; - private: void sceneFixedUpdate(Engine& engine); void changeSceneFixedUpdate(Engine& engine); diff --git a/framework/simple_sdl_renderer/src/mm/services/simple_sdl_renderer.cpp b/framework/simple_sdl_renderer/src/mm/services/simple_sdl_renderer.cpp index b775b33..f0cf943 100644 --- a/framework/simple_sdl_renderer/src/mm/services/simple_sdl_renderer.cpp +++ b/framework/simple_sdl_renderer/src/mm/services/simple_sdl_renderer.cpp @@ -20,7 +20,7 @@ SimpleSDLRendererService::SimpleSDLRendererService(void) { SimpleSDLRendererService::~SimpleSDLRendererService(void) { } -bool SimpleSDLRendererService::enable(Engine& engine) { +bool SimpleSDLRendererService::enable(Engine& engine, std::vector& task_array) { auto* sdl_ss = engine.tryService(); if (!sdl_ss) { LOG_ERROR("SimpleSDLRendererService requires SDLService in engine!"); @@ -46,6 +46,13 @@ bool SimpleSDLRendererService::enable(Engine& engine) { targets["display"].reset(renderer, 800, 600); + // add tasks + task_array.push_back( + UpdateStrategies::TaskInfo{"SimpleSDLRendererService::render"} + .phase(UpdateStrategies::update_phase_t::POST) + .fn([this](Engine& e){ this->render(e); }) + ); + return true; } @@ -57,18 +64,6 @@ void SimpleSDLRendererService::disable(Engine&) { SDL_DestroyRenderer(renderer); } -std::vector SimpleSDLRendererService::registerUpdates(void) { - using namespace entt::literals; - return { - { - "SimpleSDLRendererService::render"_hs, - "SimpleSDLRendererService::render", - [this](Engine& e){ this->render(e); }, - UpdateStrategies::update_phase_t::POST - } - }; -} - void SimpleSDLRendererService::render(Engine& engine) { targets["display"].clear(renderer, {40, 40, 40, 255}); diff --git a/framework/simple_sdl_renderer/src/mm/services/simple_sdl_renderer.hpp b/framework/simple_sdl_renderer/src/mm/services/simple_sdl_renderer.hpp index 2c1aa64..8b3b125 100644 --- a/framework/simple_sdl_renderer/src/mm/services/simple_sdl_renderer.hpp +++ b/framework/simple_sdl_renderer/src/mm/services/simple_sdl_renderer.hpp @@ -1,5 +1,6 @@ #pragma once +#include "mm/services/service.hpp" #include #include @@ -23,14 +24,11 @@ namespace MM::Services { public: - bool enable(Engine& engine) override; + bool enable(Engine& engine, std::vector& task_array) override; void disable(Engine& engine) override; const char* name(void) override { return "SimpleSDLServiceSystem"; }; - std::vector registerUpdates(void) override; - - private: void render(Engine& engine); }; diff --git a/framework/sound/src/mm/services/sound_service.cpp b/framework/sound/src/mm/services/sound_service.cpp index 915b4c9..2a6787c 100644 --- a/framework/sound/src/mm/services/sound_service.cpp +++ b/framework/sound/src/mm/services/sound_service.cpp @@ -19,7 +19,7 @@ SoundService::SoundService(void) : engine() { SoundService::~SoundService(void) { } -bool SoundService::enable(Engine&) { +bool SoundService::enable(Engine&, std::vector&) { unsigned int flags = SoLoud::Soloud::CLIP_ROUNDOFF; auto r = engine.init(flags); if (r != 0) { diff --git a/framework/sound/src/mm/services/sound_service.hpp b/framework/sound/src/mm/services/sound_service.hpp index d7008f6..8e61d64 100644 --- a/framework/sound/src/mm/services/sound_service.hpp +++ b/framework/sound/src/mm/services/sound_service.hpp @@ -11,7 +11,7 @@ namespace MM::Services { SoLoud::Soloud engine; public: - bool enable(Engine&) override; + bool enable(Engine&, std::vector&) override; void disable(Engine&) override; const char* name(void) override { return "SoundService"; }