1 #ifndef NTA_ECS_H_INCLUDED
2 #define NTA_ECS_H_INCLUDED
4 #include <unordered_set>
5 #include <unordered_map>
8 #include "nta/Option.h"
9 #include "nta/IDFactory.h"
10 #include "nta/TypeMap.h"
11 #include "nta/SlotMap.h"
12 #include "nta/Event.h"
17 using Entity = utils::SlotMapKey<>;
18 using ComponentID = utils::SlotMapKey<>;
20 using ComponentList = utils::SlotMap<T>;
44 static const Record get() {
45 static_assert(std::is_base_of_v<nta::Component, T>,
46 "ComponentRegistry: Can only register types deriving from nta::Component");
55 list[e].map([&](T& cmpn) {
56 cmpn_gen.free(cmpn.get_id());
71 ret.num_components = [](
const utils::TypeMap& map) -> std::size_t {
90 using iterator = std::unordered_map<std::size_t, Record>::iterator;
91 using const_iterator = std::unordered_map<std::size_t, Record>::const_iterator;
93 std::unordered_map<std::size_t, Record> m_records;
99 void register_component() { m_records.insert(std::make_pair(
typeid(T).hash_code(), Record::get<T>())); }
102 utils::Option<Record> get_record()
const {
return operator[](
typeid(T).hash_code()); }
103 utils::Option<Record> operator[](std::size_t hash)
const {
104 auto rec = m_records.find(hash);
108 std::size_t size()
const {
return m_records.size(); }
110 iterator begin() {
return m_records.begin(); }
111 const_iterator begin()
const {
return m_records.cbegin(); }
112 const_iterator cbegin()
const {
return m_records.cbegin(); }
113 iterator end() {
return m_records.end(); }
114 const_iterator end()
const {
return m_records.cend(); }
115 const_iterator cend()
const {
return m_records.cend(); }
189 template<
typename T,
typename... Args>
191 template<
typename T,
typename... Args>
224 void for_each(std::function<
void(T&)> func)
const;
227 template<
typename T,
typename Event>
229 template<
typename T,
typename Event,
typename Event::enum_type e>
231 template<
typename T,
typename Event>
232 void enact_on(
const Event& event,
typename Event::enum_type e,
Entity entity)
const;
234 template<
typename T,
typename Event>
236 template<
typename T,
typename Event,
typename Event::enum_type e>
238 template<
typename T,
typename Event>
241 template<
typename T,
typename Event>
242 void enact_on_all(
const Event& event,
typename Event::enum_type e)
const;
243 template<
typename T,
typename Event,
typename Event::enum_type e>
249 template<
typename T,
typename... Args>
253 list.reserve(entity.idx+1);
255 if (!list.insert_emplace(entity, std::forward<Args>(args)...)) {
256 return utils::make_none<ComponentID>();
258 T& cmpn = list[entity].unwrap();
262 ComponentInfo info = { .type =
typeid(T).hash_code(), .owner = entity };
264 assert(
false &&
"This should never happen");
268 template<
typename T,
typename... Args>
271 return add_component<T>(e, std::forward<Args>(args)...);
276 auto maybe_cmpn = get_component<T>(entity);
288 return maybe_owner ? has_component<T>(maybe_owner.unwrap()) : false;
293 assert(
false &&
"Attempted to get a ComponentList for a non-registered type");
304 return get_owner(cmpn).map<T&>([&](
Entity e) {
return get_component<T>(e); });
308 auto& list = get_component_list<T>();
309 for (
auto& cmpn : list) {
313 template<
typename T,
typename Event>
315 get_component<T>(entity).map([&](T& cmpn) { event(cmpn); });
317 template<
typename T,
typename Event,
typename Event::enum_type e>
319 get_component<T>(entity).map([&](T& cmpn) {
event.enact<e>(cmpn); });
321 template<
typename T,
typename Event>
322 void ECS::enact_on(
const Event& event,
typename Event::enum_type e, Entity entity)
const {
323 get_component<T>(entity).map([&](T& cmpn) { event(e, cmpn); });
325 template<
typename T,
typename Event>
327 get_sibling<T>(cmpn).map([&](T& sib) { event(sib); });
329 template<
typename T,
typename Event,
typename Event::enum_type e>
331 get_sibling<T>(cmpn).map([&](T& sib) {
event.enact<e>(sib); });
333 template<
typename T,
typename Event>
334 void ECS::enact_on_sibling(
const Event& event,
typename Event::enum_type e, ComponentID cmpn)
const {
335 get_sibling<T>(cmpn).map([&](T& sib) { event(e, sib); });
337 template<
typename T,
typename Event>
339 for (
auto& cmpn : get_component_list<T>()) {
343 template<
typename T,
typename Event,
typename Event::enum_type e>
345 for (
auto& cmpn : get_component_list<T>()) {
346 event.enact<e>(cmpn);
351 #endif // NTA_ECS_H_INCLUDED