Add ecs::dispatcher - an event-based ECS system launcher
This commit is contained in:
parent
5533826711
commit
13a86a76c8
1 changed files with 93 additions and 0 deletions
93
libs/ecs/include/psemek/ecs/dispatcher.hpp
Normal file
93
libs/ecs/include/psemek/ecs/dispatcher.hpp
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/ecs/container.hpp>
|
||||||
|
#include <psemek/util/hash_table.hpp>
|
||||||
|
#include <psemek/util/function.hpp>
|
||||||
|
|
||||||
|
#include <concepts>
|
||||||
|
|
||||||
|
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 <typename Event, typename Handler>
|
||||||
|
void handler(Handler handler)
|
||||||
|
{
|
||||||
|
handlers_[Event::uuid()].push_back([handler = std::move(handler), this](void const * event_ptr){
|
||||||
|
auto const & event = *reinterpret_cast<Event const *>(event_ptr);
|
||||||
|
|
||||||
|
if constexpr (std::invocable<Handler, Event const &, ecs::container &>)
|
||||||
|
{
|
||||||
|
handler(event, *container_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handler(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Event, typename ... Components, typename System>
|
||||||
|
void system(System system)
|
||||||
|
{
|
||||||
|
handlers_[Event::uuid()].push_back([system = std::move(system), this, cache = container_->cache<Components...>()](void const * event_ptr){
|
||||||
|
auto const & event = *reinterpret_cast<Event const *>(event_ptr);
|
||||||
|
|
||||||
|
if constexpr (std::invocable<System, Event const &, ecs::container &, handle, Components & ...>)
|
||||||
|
{
|
||||||
|
container_->apply<Components...>([&](ecs::container & container, ecs::handle handle, Components & ... components){
|
||||||
|
system(event, container, handle, components...);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if constexpr (std::invocable<System, Event const &, ecs::container &, Components & ...>)
|
||||||
|
{
|
||||||
|
container_->apply<Components...>([&](ecs::container & container, Components & ... components){
|
||||||
|
system(event, container, components...);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if constexpr (std::invocable<System, Event const &, handle, Components & ...>)
|
||||||
|
{
|
||||||
|
container_->apply<Components...>([&](ecs::handle handle, Components & ... components){
|
||||||
|
system(event, handle, components...);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
container_->apply<Components...>([&](Components & ... components){
|
||||||
|
system(event, components...);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Event>
|
||||||
|
void dispatch(Event const & event)
|
||||||
|
{
|
||||||
|
for (auto & handler : handlers_[event.uuid()])
|
||||||
|
handler(&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ecs::container * container_;
|
||||||
|
|
||||||
|
util::hash_map<util::uuid, std::vector<util::function<void(void const *)>>> handlers_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue