CoriEngine
Loading...
Searching...
No Matches
Hierarchy.cpp
Go to the documentation of this file.
1#include "Hierarchy.hpp"
2
3namespace Cori {
4 namespace World {
5 namespace Systems {
7 m_Owner.GetRegistry().on_destroy<Components::Entity::Hierarchy>().connect<&Hierarchy::OnHierarchyComponentDestroyed>(this);
8 return true;
9 }
10
11 std::expected<void, Core::CoriError<>> Hierarchy::SetParent(Entity subject, Entity parent) {
12 UnlinkFromParent(subject);
13
14 if (parent.IsValid()) {
15 return LinkToParent(subject, parent);
16 }
17 return {};
18 }
19
20 std::expected<void, Core::CoriError<>> Hierarchy::LinkToParent(Entity subject, Entity parent) {
21 entt::registry* registry = subject.GetRawHandle().registry();
23 return std::unexpected(Core::CoriError("Linking 2 entities is only allowed when both of them have a name."));
24 }
25
26 auto& hierarchy = subject.GetOrAddComponent<Components::Entity::Hierarchy>();
27
28 hierarchy.m_Parent = parent.GetRawEntity();
29
31 const auto& name = subject.GetName();
32 if (cache.m_Children.contains(name)) {
33 return std::unexpected(Core::CoriError("A parent entity can't have 2 children with the same name."));
34 }
35 cache.m_Children.emplace(name, subject.GetRawHandle().entity());
36
37 auto& parentHierarchy = parent.GetOrAddComponent<Components::Entity::Hierarchy>();
38 const entt::entity firstChild = parentHierarchy.m_FirstChild;
39
40 if (registry->valid(firstChild)) {
41 registry->get<Components::Entity::Hierarchy>(firstChild).m_PreviousSibling = subject.GetRawHandle().entity();
42 hierarchy.m_NextSibling = firstChild;
43 }
44
45 parentHierarchy.m_FirstChild = subject.GetRawHandle().entity();
46 subject.UpdateInactivityFlagsRecursive(subject.GetRawHandle().entity(), parent.IsActiveGlobally());
47 return {};
48 }
49
51 entt::registry* registry = subject.GetRawHandle().registry();
53 return;
54 }
55 auto& hierarchy = subject.GetComponents<Components::Entity::Hierarchy>();
56 const entt::entity parent = hierarchy.m_Parent;
57 if (!registry->valid(parent)) {
58 return;
59 }
60
61 if (!registry->all_of<Components::Entity::ChildCache, Components::Entity::Hierarchy>(parent)) {
62 return;
63 }
64
65 auto& cache = registry->get<Components::Entity::ChildCache>(parent);
66 cache.m_Children.erase(std::string(subject.GetName()));
67
68 auto& parentHierarchy = registry->get<Components::Entity::Hierarchy>(parent);
69 const entt::entity previousSibling = parentHierarchy.m_PreviousSibling;
70 const entt::entity nextSibling = parentHierarchy.m_NextSibling;
71
72 if (parentHierarchy.m_FirstChild == subject.GetRawHandle().entity()) {
73 parentHierarchy.m_FirstChild = nextSibling;
74 } else {
75 if (registry->valid(previousSibling)) {
76 registry->get<Components::Entity::Hierarchy>(previousSibling).m_NextSibling = nextSibling;
77 }
78 }
79
80 if (registry->valid(nextSibling)) {
81 registry->get<Components::Entity::Hierarchy>(nextSibling).m_PreviousSibling = previousSibling;
82 }
83
84 hierarchy.m_Parent = entt::null;
85 hierarchy.m_NextSibling = entt::null;
86 hierarchy.m_PreviousSibling = entt::null;
87 subject.UpdateInactivityFlagsRecursive(subject.GetRawHandle().entity(), true);
88 }
89
90 std::expected<std::vector<Entity>, Core::CoriError<>> Hierarchy::GetSiblings(Entity subject) {
92 return std::unexpected(Core::CoriError("Entity doesn't have hierarchy component, and thus doesn't have any siblings."));
93 }
94 auto& hierarchy = subject.GetComponents<Components::Entity::Hierarchy>();
95 entt::registry* registry = subject.GetRawHandle().registry();
96 if (!registry->valid(hierarchy.m_Parent)) {
97 return std::unexpected(Core::CoriError("Entity doesn't have a parent, and thus doesn't have any siblings."));
98 }
99
100 const Entity parent = entt::handle{ *registry, hierarchy.m_Parent };
101 auto siblings = parent.GetChildren();
102 if (siblings) {
103 return siblings.value();
104 }
105
106 return std::unexpected(siblings.error());
107 }
108
109 std::expected<std::vector<Entity>, Core::CoriError<>> Hierarchy::GetChildren(Entity subject) {
110 std::vector<Entity> children;
111
113 return std::unexpected(Core::CoriError("Entity doesn't have any children."));
114 }
115
116 entt::registry* registry = subject.GetRawHandle().registry();
117 auto& childCache = subject.GetComponents<Components::Entity::ChildCache>();
118
119 for (const auto& child : childCache.m_Children | std::views::values) {
120 children.emplace_back(entt::handle{*registry, child});
121 }
122
123 return children;
124 }
125
126 std::expected<Entity, Core::CoriError<>> Hierarchy::GetParent(Entity subject) {
128 return std::unexpected(Core::CoriError("Entity doesn't have HierarchyComponent, and thus doesn't have a parent."));
129 }
130
131 auto& hierarchy = subject.GetComponents<Components::Entity::Hierarchy>();
132 if (hierarchy.m_Parent == entt::null) {
133 return std::unexpected(Core::CoriError("Entity doesn't have a parent."));
134 }
135
136 return Entity{ entt::handle{ *subject.GetRawHandle().registry(), hierarchy.m_Parent } };
137 }
138
139 std::expected<Entity, Core::CoriError<>> Hierarchy::FindChildByName(Entity subject, const char* name) {
141 return std::unexpected(Core::CoriError("Entity doesn't have any children."));
142 }
143
144 auto& cache = subject.GetComponents<Components::Entity::ChildCache>();
145
146 if (cache.m_Children.contains(name)) {
147 entt::entity child = cache.m_Children.find(name)->second;
148 return Entity{ { *subject.GetRawHandle().registry(), child } };
149 }
150 return std::unexpected(Core::CoriError("No children found with the specified name."));
151 }
152
153 std::expected<Entity, Core::CoriError<>> Hierarchy::FindChildByName(Entity subject, const std::string_view name) {
155 return std::unexpected(Core::CoriError("Entity doesn't have any children."));
156 }
157
158 auto& cache = subject.GetComponents<Components::Entity::ChildCache>();
159
160 if (cache.m_Children.contains(name)) {
161 entt::entity child = cache.m_Children.find(name)->second;
162 return Entity{ { *subject.GetRawHandle().registry(), child } };
163 }
164 return std::unexpected(Core::CoriError("No children found with the specified name."));
165 }
166
167 std::expected<Entity, Core::CoriError<>> Hierarchy::FindChildByName(Entity subject, const std::string& name) {
169 return std::unexpected(Core::CoriError("Entity doesn't have any children."));
170 }
171
172 auto& cache = subject.GetComponents<Components::Entity::ChildCache>();
173
174 if (cache.m_Children.contains(name)) {
175 entt::entity child = cache.m_Children.find(name)->second;
176 return Entity{ { *subject.GetRawHandle().registry(), child } };
177 }
178 return std::unexpected(Core::CoriError("No children found with the specified name."));
179 }
180
182 entt::registry* registry = subject.GetRawHandle().registry();
183 const auto& hierarchy = registry->get<Components::Entity::Hierarchy>(subject.GetRawEntity());
184 if (registry->all_of<Components::Entity::ChildCache>(subject.GetRawEntity())) {
185 auto& cache = registry->get<Components::Entity::ChildCache>(subject.GetRawEntity());
186 cache.m_Children.clear();
187 }
188 entt::entity currentChild = hierarchy.m_FirstChild;
189 while (registry->valid(currentChild)) {
190 const entt::entity nextChild = registry->get<Components::Entity::Hierarchy>(currentChild).m_NextSibling;
191 registry->destroy(currentChild);
192 currentChild = nextChild;
193 }
194 }
195
197 if (!subject.HasComponents<Components::Entity::Name>()) {
198 return;
199 }
200
201 CORI_CORE_DEBUG_TAGGED({ Logger::Tags::World::Self, Logger::Tags::World::Entity::Self }, "Printing full hierarchy tree of '{}'", subject.GetName());
203 entt::entity root = subject.GetRawEntity();
204 entt::entity currentParent = subject.GetComponents<Components::Entity::Hierarchy>().m_Parent;
205 while (subject.GetRawHandle().registry()->valid(currentParent)) {
206 root = currentParent;
207 currentParent = subject.GetRawHandle().registry()->get<Components::Entity::Hierarchy>(root).m_Parent;
208 }
209
210 Entity rootHandle{ entt::handle{ *subject.GetRawHandle().registry(), root } };
211
212 const std::string_view rootName = rootHandle.GetName();
213 CORI_CORE_DEBUG_TAGGED({ Logger::Tags::World::Self, Logger::Tags::World::Entity::Self }, "Hierarchy top level root/parent '{}'", rootName);
214
216 const auto children = rootHandle.GetChildren();
217 if (children) {
218 for (size_t i = 0; i < children.value().size(); ++i) {
219 const auto& child = children.value()[i];
220 const bool isLastChild = i == children.value().size() - 1;
221 DrawHierarchyRecursive(child, " ", isLastChild);
222 }
223 }
224 } else {
225 CORI_CORE_DEBUG_TAGGED({ Logger::Tags::World::Self, Logger::Tags::World::Entity::Self }, "Hierarchy top level root/parent '{}'", subject.GetName());
226
228 }
229
231 }
232
233 void Hierarchy::DrawHierarchyRecursive(const Entity& entity, const std::string& prefix, const bool isLast) {
234 CORI_CORE_TRACE_TAGGED({ Logger::Tags::World::Self, Logger::Tags::World::Entity::Self }, "{}{}{}", prefix, isLast ? "└─" : "├─", entity.GetName());
235
236 const std::string childPrefix = prefix + (isLast ? " " : "│ ");
237
238 const auto children = entity.GetChildren();
239 if (children) {
240 for (size_t i = 0; i < children.value().size(); ++i) {
241 const auto& child = children.value()[i];
242 const bool isLastChild = i == children.value().size() - 1;
243 DrawHierarchyRecursive(child, childPrefix, isLastChild);
244 }
245 }
246 }
247
248 void Hierarchy::OnHierarchyComponentDestroyed(entt::registry& registry, entt::entity entity) {
249 Entity e = entt::handle{ registry, entity };
250 e.DestroyChildren();
251 }
252 }
253 }
254}
#define CORI_CORE_DEBUG_TAGGED(...)
Definition Logger.hpp:1026
#define CORI_CORE_TRACE_TAGGED(...)
Definition Logger.hpp:1025
Custom error class mainly used in std::expected.
Definition Error.hpp:27
Entities are the essential part of WorldSystem.
Definition Entity.hpp:25
bool IsValid() const
Checks if the actual entity behind this handle is valid.
Definition Entity.hpp:161
bool IsActiveGlobally() const
Checks if the entity is active locally (doesn't have InactiveGloballyFlag), just a convenience functi...
Definition Entity.cpp:61
std::string_view GetName() const
Retrieves the name of the entity.
Definition Entity.cpp:114
entt::handle GetRawHandle() const
Gets a raw entt::handle if you need to interact with entt directly.
Definition Entity.hpp:287
std::expected< std::vector< Entity >, Core::CoriError<> > GetChildren() const
Creates and returns a vector containing all entity children (does not include grandchildren and so on...
Definition Entity.cpp:90
T & GetOrAddComponent(Args &&... args)
Retries or adds a component to the entity.
Definition Entity.hpp:112
void DestroyChildren()
Destroys all children (and they grandchildren) that the entity has.
Definition Entity.cpp:106
bool HasComponents() const
Checks if the entity has all the specified components.
Definition Entity.hpp:122
decltype(auto) GetComponents()
Retries the references to the requested components of the entity.
Definition Entity.hpp:74
entt::entity GetRawEntity() const
Gets a raw entt::entity if you need to interact with entt directly.
Definition Entity.hpp:280
void UpdateInactivityFlagsRecursive(entt::entity parent, bool parentIsActive)
Definition Entity.cpp:151
SceneHandle m_Owner
Definition System.hpp:38
static std::expected< std::vector< Entity >, Core::CoriError<> > GetSiblings(Entity subject)
Definition Hierarchy.cpp:90
static void DrawHierarchyRecursive(const Entity &entity, const std::string &prefix, const bool isLast)
static std::expected< void, Core::CoriError<> > LinkToParent(Entity subject, Entity parent)
Definition Hierarchy.cpp:20
static std::expected< Entity, Core::CoriError<> > GetParent(Entity subject)
static std::expected< Entity, Core::CoriError<> > FindChildByName(Entity subject, const char *name)
static std::expected< void, Core::CoriError<> > SetParent(Entity subject, Entity parent)
Definition Hierarchy.cpp:11
static void UnlinkFromParent(Entity subject)
Definition Hierarchy.cpp:50
static void DestroyChildren(Entity subject)
static std::expected< std::vector< Entity >, Core::CoriError<> > GetChildren(Entity subject)
static void PrintHierarchy(Entity subject)
Anything connected to WorldSystem (ECS) is in this namespace.
Global engine namespace.
static constexpr char Self[]
Definition Logger.hpp:127
static constexpr char Self[]
Definition Logger.hpp:119
Every Entity has a ChildCache component by default, it's essential for entity ChildCache system.
Every Entity has a hierarchy component by default, it's essential for entity hierarchy system.
Every Entity by default has a name component, it holds a non-unique entity name. Just holds the data,...