2020-09-29 13:47:50 +02:00
|
|
|
#pragma once
|
|
|
|
|
2020-12-12 16:55:27 +01:00
|
|
|
#include "./engine_fwd.hpp"
|
|
|
|
|
2021-04-29 13:44:00 +02:00
|
|
|
#include <entt/core/type_info.hpp>
|
2020-09-29 13:47:50 +02:00
|
|
|
|
|
|
|
#include <functional>
|
|
|
|
#include <memory>
|
|
|
|
#include <type_traits>
|
|
|
|
#include <unordered_map>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
|
|
|
#include <string>
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
#include <mm/services/service.hpp>
|
2020-12-12 16:55:27 +01:00
|
|
|
#include <mm/update_strategies/update_strategy.hpp>
|
2020-09-29 13:47:50 +02:00
|
|
|
|
|
|
|
namespace MM {
|
|
|
|
|
2021-01-11 17:45:51 +01:00
|
|
|
// fwd
|
|
|
|
namespace Services {
|
|
|
|
class ImGuiEngineTools;
|
|
|
|
}
|
|
|
|
|
2020-09-29 13:47:50 +02:00
|
|
|
class Engine {
|
2021-01-11 17:45:51 +01:00
|
|
|
friend Services::ImGuiEngineTools;
|
|
|
|
|
2020-09-29 13:47:50 +02:00
|
|
|
public:
|
2021-04-28 19:38:25 +02:00
|
|
|
using service_id_type = entt::id_type; // alias, for future proof
|
2020-09-29 13:47:50 +02:00
|
|
|
|
2021-04-28 19:38:25 +02:00
|
|
|
// UpdateStrategy
|
2020-12-12 16:55:27 +01:00
|
|
|
protected:
|
|
|
|
std::unique_ptr<UpdateStrategies::UpdateStrategy> _update_strategy;
|
2020-09-29 13:47:50 +02:00
|
|
|
|
2020-12-12 16:55:27 +01:00
|
|
|
public:
|
|
|
|
UpdateStrategies::UpdateStrategy& getUpdateStrategy(void) { return *_update_strategy; }
|
2020-09-29 13:47:50 +02:00
|
|
|
|
2021-04-28 19:38:25 +02:00
|
|
|
// state
|
2020-09-29 13:47:50 +02:00
|
|
|
private:
|
2020-12-12 16:55:27 +01:00
|
|
|
volatile bool _is_running = false;
|
2021-04-28 19:38:25 +02:00
|
|
|
// ... just realisied: i never needed a getter ...
|
|
|
|
|
|
|
|
std::vector<entt::id_type> _service_add_order; // ?
|
|
|
|
std::vector<entt::id_type> _service_enable_order; // ?
|
|
|
|
|
|
|
|
std::unordered_map<
|
|
|
|
entt::id_type,
|
|
|
|
std::shared_ptr<std::pair<
|
|
|
|
bool,
|
|
|
|
std::unique_ptr<Services::Service>
|
|
|
|
>>
|
|
|
|
> _services;
|
|
|
|
|
2020-09-29 13:47:50 +02:00
|
|
|
|
2021-04-28 19:38:25 +02:00
|
|
|
// private state helper
|
2020-09-29 13:47:50 +02:00
|
|
|
private:
|
2020-12-12 16:55:27 +01:00
|
|
|
void setup(void);
|
2020-09-29 13:47:50 +02:00
|
|
|
|
2021-04-28 19:38:25 +02:00
|
|
|
// ctr dtr ...
|
2020-12-12 16:55:27 +01:00
|
|
|
public:
|
|
|
|
Engine(void);
|
2021-04-28 19:38:25 +02:00
|
|
|
~Engine(void);
|
2020-12-12 16:55:27 +01:00
|
|
|
|
|
|
|
explicit Engine(std::unique_ptr<UpdateStrategies::UpdateStrategy> us) {
|
|
|
|
setup();
|
|
|
|
_update_strategy = std::move(us);
|
|
|
|
}
|
2020-09-29 13:47:50 +02:00
|
|
|
|
2021-04-28 19:38:25 +02:00
|
|
|
// called from destructor or explicitly (if eg "global", u need dis)
|
2020-09-29 13:47:50 +02:00
|
|
|
void cleanup(void);
|
|
|
|
|
|
|
|
void update(void);
|
|
|
|
|
2020-12-12 16:55:27 +01:00
|
|
|
void run(void); // calls update() until stopped
|
2020-09-29 13:47:50 +02:00
|
|
|
void stop(void);
|
|
|
|
|
|
|
|
public:
|
|
|
|
template<typename T>
|
2021-04-29 13:44:00 +02:00
|
|
|
constexpr static auto type(void) {
|
|
|
|
//return entt::type_id<T>.hash();
|
|
|
|
return entt::type_hash<T>::value();
|
2020-09-29 13:47:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, typename... Args>
|
|
|
|
T& addService(Args&& ... args) {
|
|
|
|
assert(!tryService<T>());
|
|
|
|
|
2021-04-29 13:44:00 +02:00
|
|
|
auto& ss_entry = _services[type<T>()] =
|
2020-09-29 13:47:50 +02:00
|
|
|
std::make_shared<std::pair<bool, std::unique_ptr<Services::Service>>>(
|
|
|
|
std::make_pair<bool, std::unique_ptr<Services::Service>>(
|
|
|
|
false,
|
|
|
|
std::make_unique<T>(std::forward<Args>(args)...)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2021-04-29 13:44:00 +02:00
|
|
|
_service_add_order.emplace_back(type<T>());
|
2020-09-29 13:47:50 +02:00
|
|
|
|
|
|
|
return (T&)*ss_entry.get()->second.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
[[nodiscard]] T* tryService(void) const {
|
2021-04-29 13:44:00 +02:00
|
|
|
if (_services.count(type<T>())) {
|
|
|
|
return static_cast<T*>(_services.at(type<T>()).get()->second.get());
|
2020-09-29 13:47:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
[[deprecated("use tryService() instead")]]
|
|
|
|
[[nodiscard]] T* tryGetService(void) const {
|
|
|
|
return tryService<T>();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
[[nodiscard]] T& getService(void) const {
|
|
|
|
T* tmp = tryService<T>();
|
|
|
|
assert(tmp);
|
|
|
|
return *tmp;
|
|
|
|
}
|
|
|
|
|
2021-04-29 13:44:00 +02:00
|
|
|
bool enableService(entt::id_type s_t);
|
|
|
|
void disableService(entt::id_type s_t);
|
2020-09-29 13:47:50 +02:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
bool enableService(void) {
|
2021-04-29 13:44:00 +02:00
|
|
|
return enableService(type<T>());
|
2020-09-29 13:47:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
void disableService(void) {
|
2021-04-29 13:44:00 +02:00
|
|
|
disableService(type<T>());
|
2020-09-29 13:47:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// provide T as I implementation
|
|
|
|
// T needs to be an added Service
|
2021-04-29 13:44:00 +02:00
|
|
|
bool provide(entt::id_type I, entt::id_type T);
|
2020-09-29 13:47:50 +02:00
|
|
|
|
|
|
|
// provide T as I implementation
|
|
|
|
// T needs to be an added Service
|
|
|
|
template<typename I, typename T>
|
|
|
|
bool provide(void) {
|
|
|
|
static_assert(std::is_base_of_v<I, T>, "T is not derived from I!");
|
|
|
|
static_assert(!std::is_same_v<I, T>, "I and T are the same, makes no sense!");
|
|
|
|
|
2021-04-29 13:44:00 +02:00
|
|
|
return provide(type<I>(), type<T>());
|
2020-09-29 13:47:50 +02:00
|
|
|
}
|
|
|
|
|
2021-04-28 19:38:25 +02:00
|
|
|
// TODO: remove service
|
2020-09-29 13:47:50 +02:00
|
|
|
//void removeProvider(void) {
|
|
|
|
};
|
|
|
|
|
|
|
|
} // MM
|
|
|
|
|