Add event-based behavior & processor registration in ECS

This commit is contained in:
Nikita Lisitsa 2022-08-16 14:36:35 +03:00
parent 2482a8c224
commit 4fae4bbbe4

View file

@ -2,6 +2,7 @@
#include <psemek/util/to_string.hpp>
#include <psemek/util/type_name.hpp>
#include <psemek/util/function.hpp>
#include <cstdint>
#include <typeindex>
@ -466,8 +467,22 @@ namespace psemek::util
template <typename Behavior, typename ... Args>
void apply(Behavior && behavior, species_handle species, Args const & ... args);
template <typename Event, typename Processor>
void register_processor(Processor && processor);
template <typename Event, typename Behavior>
void register_behavior(Behavior && behavior);
template <typename Event, typename Behavior>
void register_behavior(Behavior && behavior, species_handle species);
template <typename Event>
void event(Event const & event);
private:
std::vector<std::unique_ptr<ecs_detail::species_base>> species_;
std::unordered_map<std::type_index, std::vector<util::function<void(void const *)>>> event_subscribers_;
};
template <typename ... Components>
@ -573,6 +588,38 @@ namespace psemek::util
species_[species.value]->apply(behavior, args...);
}
template <typename Event, typename Processor>
void ecs::register_processor(Processor && processor)
{
event_subscribers_[typeid(Event)].push_back([this, processor = std::move(processor)](void const * event) mutable {
processor(*static_cast<Event const *>(event));
});
}
template <typename Event, typename Behavior>
void ecs::register_behavior(Behavior && behavior)
{
event_subscribers_[typeid(Event)].push_back([this, behavior = std::move(behavior)](void const * event) mutable {
apply(behavior, *static_cast<Event const *>(event));
});
}
template <typename Event, typename Behavior>
void ecs::register_behavior(Behavior && behavior, species_handle species)
{
event_subscribers_[typeid(Event)].push_back([this, species, behavior = std::move(behavior)](void const * event) mutable {
apply(behavior, species, *static_cast<Event const *>(event));
});
}
template <typename Event>
void ecs::event(Event const & event)
{
if (auto it = event_subscribers_.find(typeid(Event)); it != event_subscribers_.end())
for (auto const & b : it->second)
b(std::addressof(event));
}
}
namespace std