Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
archetype_graph.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cstdint>
5
6#include "gaia/cnt/map.h"
7#include "gaia/ecs/api.h"
8#include "gaia/ecs/archetype_common.h"
9#include "gaia/ecs/component.h"
10#include "gaia/ecs/id.h"
11#include "gaia/util/logging.h"
12
14namespace gaia {
15 namespace ecs {
16 class World;
17
18 using ArchetypeGraphEdge = ArchetypeIdHashPair;
19
20 class ArchetypeGraph {
21 using EdgeMap = cnt::map<EntityLookupKey, ArchetypeGraphEdge>;
22
24 EdgeMap m_edgesAdd;
26 EdgeMap m_edgesDel;
27
28 private:
29 void add_edge(EdgeMap& edges, Entity entity, ArchetypeId archetypeId, ArchetypeIdHash hash) {
30#if GAIA_ASSERT_ENABLED
31 const auto ret =
32#endif
33 edges.try_emplace(EntityLookupKey(entity), ArchetypeGraphEdge{archetypeId, hash});
34#if GAIA_ASSERT_ENABLED
35 // If the result already exists make sure the new one is the same
36 if (!ret.second) {
37 const auto it = edges.find(EntityLookupKey(entity));
38 GAIA_ASSERT(it != edges.end());
39 GAIA_ASSERT(it->second.id == archetypeId);
40 GAIA_ASSERT(it->second.hash == hash);
41 }
42#endif
43 }
44
45 void del_edge(EdgeMap& edges, Entity entity) {
46 edges.erase(EntityLookupKey(entity));
47 }
48
49 GAIA_NODISCARD ArchetypeGraphEdge find_edge(const EdgeMap& edges, Entity entity) const {
50 const auto it = edges.find(EntityLookupKey(entity));
51 return it != edges.end() ? it->second : ArchetypeIdHashPairBad;
52 }
53
54 public:
59 void add_edge_right(Entity entity, ArchetypeId archetypeId, ArchetypeIdHash hash) {
60 add_edge(m_edgesAdd, entity, archetypeId, hash);
61 }
62
67 void add_edge_left(Entity entity, ArchetypeId archetypeId, ArchetypeIdHash hash) {
68 add_edge(m_edgesDel, entity, archetypeId, hash);
69 }
70
73 void del_edge_right(Entity entity) {
74 del_edge(m_edgesAdd, entity);
75 }
76
79 void del_edge_left(Entity entity) {
80 del_edge(m_edgesDel, entity);
81 }
82
86 GAIA_NODISCARD ArchetypeGraphEdge find_edge_right(Entity entity) const {
87 return find_edge(m_edgesAdd, entity);
88 }
89
93 GAIA_NODISCARD ArchetypeGraphEdge find_edge_left(Entity entity) const {
94 return find_edge(m_edgesDel, entity);
95 }
96
97 GAIA_NODISCARD auto& right_edges() {
98 return m_edgesAdd;
99 }
100
101 GAIA_NODISCARD const auto& right_edges() const {
102 return m_edgesAdd;
103 }
104
105 GAIA_NODISCARD auto& left_edges() {
106 return m_edgesDel;
107 }
108
109 GAIA_NODISCARD const auto& left_edges() const {
110 return m_edgesDel;
111 }
112
113 void diag(const World& world) const {
114 auto diagEdge = [&](const auto& edges) {
115 for (const auto& edge: edges) {
116 const auto entity = edge.first.entity();
117 if (entity.pair()) {
118 const auto name0 = entity_name(world, entity.id());
119 const auto name1 = entity_name(world, entity.gen());
120 GAIA_LOG_N(
121 " pair [%u:%u], %.*s -> %.*s, aid:%u",
122 //
123 entity.id(), entity.gen(), (int)name0.size(), name0.empty() ? "" : name0.data(), (int)name1.size(),
124 name1.empty() ? "" : name1.data(), edge.second.id);
125 } else {
126 const auto name = entity_name(world, entity);
127 GAIA_LOG_N(
128 " ent [%u:%u], %.*s [%s], aid:%u",
129 //
130 entity.id(), entity.gen(), (int)name.size(), name.empty() ? "" : name.data(),
131 EntityKindString[entity.kind()], edge.second.id);
132 }
133 }
134 };
135
136 // Add edges (movement towards the leafs)
137 if (!m_edgesAdd.empty()) {
138 GAIA_LOG_N(" Add edges - count:%u", (uint32_t)m_edgesAdd.size());
139 diagEdge(m_edgesAdd);
140 }
141
142 // Delete edges (movement towards the root)
143 if (!m_edgesDel.empty()) {
144 GAIA_LOG_N(" Del edges - count:%u", (uint32_t)m_edgesDel.size());
145 diagEdge(m_edgesDel);
146 }
147 }
148 };
149 } // namespace ecs
150} // namespace gaia