From 13a86a76c82b0328d772fbc8391bd6e72b28f6f6 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sat, 3 Feb 2024 15:22:33 +0300 Subject: [PATCH] Add ecs::dispatcher - an event-based ECS system launcher --- libs/ecs/include/psemek/ecs/dispatcher.hpp | 93 ++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 libs/ecs/include/psemek/ecs/dispatcher.hpp diff --git a/libs/ecs/include/psemek/ecs/dispatcher.hpp b/libs/ecs/include/psemek/ecs/dispatcher.hpp new file mode 100644 index 00000000..c2b351f9 --- /dev/null +++ b/libs/ecs/include/psemek/ecs/dispatcher.hpp @@ -0,0 +1,93 @@ +#pragma once + +#include +#include +#include + +#include + +namespace psemek::ecs +{ + + struct dispatcher + { + dispatcher() = default; + + dispatcher(ecs::container & container) + : container_(&container) + {} + + explicit operator bool() const + { + return container_ != nullptr; + } + + ecs::container & container() + { + return *container_; + } + + template + void handler(Handler handler) + { + handlers_[Event::uuid()].push_back([handler = std::move(handler), this](void const * event_ptr){ + auto const & event = *reinterpret_cast(event_ptr); + + if constexpr (std::invocable) + { + handler(event, *container_); + } + else + { + handler(event); + } + }); + } + + template + void system(System system) + { + handlers_[Event::uuid()].push_back([system = std::move(system), this, cache = container_->cache()](void const * event_ptr){ + auto const & event = *reinterpret_cast(event_ptr); + + if constexpr (std::invocable) + { + container_->apply([&](ecs::container & container, ecs::handle handle, Components & ... components){ + system(event, container, handle, components...); + }); + } + else if constexpr (std::invocable) + { + container_->apply([&](ecs::container & container, Components & ... components){ + system(event, container, components...); + }); + } + else if constexpr (std::invocable) + { + container_->apply([&](ecs::handle handle, Components & ... components){ + system(event, handle, components...); + }); + } + else + { + container_->apply([&](Components & ... components){ + system(event, components...); + }); + } + }); + } + + template + void dispatch(Event const & event) + { + for (auto & handler : handlers_[event.uuid()]) + handler(&event); + } + + private: + ecs::container * container_; + + util::hash_map>> handlers_; + }; + +}