#pragma once #include "./engine_fwd.hpp" #include #include #include #include #include #include #include #include #include #include #include namespace MM { // fwd namespace Services { class ImGuiEngineTools; } class Engine { friend Services::ImGuiEngineTools; private: //using service_family = entt::family; public: //using service_family_type = service_family::family_type; protected: std::unique_ptr _update_strategy; public: UpdateStrategies::UpdateStrategy& getUpdateStrategy(void) { return *_update_strategy; } private: volatile bool _is_running = false; 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; // ? std::unordered_map< entt::id_type, std::shared_ptr >> > _services; public: template constexpr static auto type(void) { //return entt::type_id.hash(); return entt::type_hash::value(); } template T& addService(Args&& ... args) { assert(!tryService()); auto& ss_entry = _services[type()] = std::make_shared>>( std::make_pair>( false, std::make_unique(std::forward(args)...) ) ); _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(); } template [[nodiscard]] T* tryService(void) const { if (_services.count(type())) { return static_cast(_services.at(type()).get()->second.get()); } return nullptr; } template [[deprecated("use tryService() instead")]] [[nodiscard]] T* tryGetService(void) const { return tryService(); } template [[nodiscard]] T& getService(void) const { T* tmp = tryService(); assert(tmp); return *tmp; } bool enableService(entt::id_type s_t); void disableService(entt::id_type s_t); template bool enableService(void) { return enableService(type()); } template void disableService(void) { disableService(type()); } // provide T as I implementation // T needs to be an added Service bool provide(entt::id_type I, entt::id_type T); // provide T as I implementation // T needs to be an added Service template bool provide(void) { static_assert(std::is_base_of_v, "T is not derived from I!"); static_assert(!std::is_same_v, "I and T are the same, makes no sense!"); return provide(type(), type()); } // TODO: reimplement??? //template //void removeProvider(void) { //if (auto it = _implementation_provider.find(service_family::type); it != _implementation_provider.end()) { //_implementation_provider.erase(it); //} //} }; } // MM