2#include "gaia/config/config.h"
4#include "gaia/cnt/darray_ext.h"
5#include "gaia/cnt/map.h"
6#include "gaia/cnt/set.h"
7#include "gaia/ecs/id.h"
12 using PairLookupMap = cnt::map<EntityLookupKey, cnt::set<EntityLookupKey>>;
16 PairLookupMap m_relToTgt;
18 PairLookupMap m_tgtToRel;
30 GAIA_NODISCARD
const cnt::set<EntityLookupKey>* targets(Entity relation)
const {
31 const auto it = m_relToTgt.find(EntityLookupKey(relation));
32 if (it == m_relToTgt.end())
41 GAIA_NODISCARD
const cnt::set<EntityLookupKey>* relations(Entity target)
const {
42 const auto it = m_tgtToRel.find(EntityLookupKey(target));
43 if (it == m_tgtToRel.end())
51 GAIA_NODISCARD
auto relation_begin()
const {
52 return m_relToTgt.begin();
57 GAIA_NODISCARD
auto relation_end()
const {
58 return m_relToTgt.end();
64 void add_pair(Entity relation, Entity target) {
65 const auto relKey = EntityLookupKey(relation);
66 const auto tgtKey = EntityLookupKey(target);
67 const auto allKey = EntityLookupKey(All);
69 auto& relTargets = m_relToTgt[relKey];
70 const bool relHadTargets = !relTargets.empty();
71 relTargets.insert(tgtKey);
73 auto& tgtRelations = m_tgtToRel[tgtKey];
74 const bool tgtHadRelations = !tgtRelations.empty();
75 tgtRelations.insert(relKey);
78 m_relToTgt[allKey].insert(tgtKey);
80 m_tgtToRel[allKey].insert(relKey);
88 static bool del_bucket_entry(PairLookupMap& map, EntityLookupKey source, EntityLookupKey remove) {
89 auto itTargets = map.find(source);
90 if (itTargets == map.end())
93 auto& targets = itTargets->second;
94 targets.erase(remove);
95 return targets.empty();
102 static void collect_bucket_entries(
103 const PairLookupMap& map, EntityLookupKey source, cnt::darray_ext<EntityLookupKey, 64>& out) {
104 const auto it = map.find(source);
108 for (
auto entry: it->second)
109 out.push_back(entry);
115 void del_pair(Entity relation, Entity target) {
116 const auto relKey = EntityLookupKey(relation);
117 const auto tgtKey = EntityLookupKey(target);
118 const auto allKey = EntityLookupKey(All);
120 const bool relEmpty = del_bucket_entry(m_relToTgt, relKey, tgtKey);
121 const bool tgtEmpty = del_bucket_entry(m_tgtToRel, tgtKey, relKey);
123 (void)del_bucket_entry(m_relToTgt, allKey, tgtKey);
125 (void)del_bucket_entry(m_tgtToRel, allKey, relKey);
130 void del_entity_pairs(Entity entity) {
131 const auto key = EntityLookupKey(entity);
133 cnt::darray_ext<EntityLookupKey, 64> targets;
134 cnt::darray_ext<EntityLookupKey, 64> relations;
135 collect_bucket_entries(m_relToTgt, key, targets);
136 collect_bucket_entries(m_tgtToRel, key, relations);
138 for (
auto target: targets)
139 del_pair(entity, target.entity());
140 for (
auto relation: relations)
141 del_pair(relation.entity(), entity);
143 m_relToTgt.erase(key);
144 m_tgtToRel.erase(key);