Skip to main content

EntityManager.ixx File

Central manager for entity lifecycle and component storage. More...

Included Headers

#include <memory> #include <vector> #include <cstddef> #include <helios.ecs.concepts.Traits> #include <helios.ecs.ComponentOpsRegistry> #include <helios.ecs.types> #include <helios.ecs.EntityRegistry> #include <helios.ecs.SparseSet>

Namespaces Index

namespacehelios
namespaceecs

Classes Index

classEntityManager<THandle, TEntityRegistry, TCapacity>

Manages entities and their associated components. More...

Description

Central manager for entity lifecycle and component storage.

File Listing

The file content with the documentation metadata removed is:

1
5module;
6
7#include <memory>
8#include <vector>
9#include <cstddef>
10
11export module helios.ecs.EntityManager;
12
13import helios.ecs.SparseSet;
14import helios.ecs.EntityRegistry;
15import helios.ecs.ComponentOpsRegistry;
16
17import helios.ecs.types;
18
19import helios.ecs.concepts.Traits;
20
21
22using namespace helios::ecs::types;
23using namespace helios::ecs::concepts;
24export namespace helios::ecs {
25
68 template<
69 typename THandle,
70 typename TEntityRegistry,
71 size_t TCapacity
72 >
74
75
76 public:
77
78 using EntityRegistry_type = TEntityRegistry;
79 using Handle_type = THandle;
80 using StrongId_type = Handle_type::StrongId_type;
83
87 EntityManager(const EntityManager&) = delete;
89
90 EntityManager(EntityManager&&) noexcept = default;
91 EntityManager& operator=(EntityManager&&) noexcept = default;
92
102 explicit EntityManager(const size_t capacity = TCapacity)
103 : registry_(EntityRegistry_type{capacity}), capacity_(capacity)
104 {}
105
116 explicit EntityManager(
117 EntityRegistry_type& registry,
118 const size_t capacity = TCapacity)
119 : registry_(registry), capacity_(capacity)
120 {}
121
131 [[nodiscard]] Handle_type create(StrongId_type strongId = StrongId_type{}) {
132 return registry_.create(strongId);
133 }
134
142 [[nodiscard]] bool isValid(const Handle_type handle) const noexcept {
143 return registry_.isValid(handle);
144 }
145
153 [[nodiscard]] bool isValid(const EntityId entityId) const noexcept {
154 return registry_.isValid(handle(entityId));
155 }
156
168 [[nodiscard]] bool destroy(const Handle_type handle) {
169
170 if (!registry_.isValid(handle)) {
171 return false;
172 }
173
174 for (size_t i = 0; i < components_.size(); i++) {
175
176 if (!components_[i]) {
177 continue;
178 }
179 const auto typeId = ComponentTypeId_type{i};
180 if (void* rawCmp = raw(handle, typeId)) {
181 if (const auto& ops = ComponentOpsRegistry_type::ops(typeId); ops.onRemove) {
182 ops.onRemove(rawCmp);
183 }
184 }
185
186 components_[i]->remove(handle.entityId);
187 }
188
189 registry_.destroy(handle);
190
191 return true;
192 }
193
204 template<typename T>
205 [[nodiscard]] T* get(const Handle_type handle) const {
206 if (!has<T>(handle)) {
207 return nullptr;
208 }
209
210 const auto entityId = handle.entityId;
211 const auto typeId = ComponentTypeId_type::template id<T>().value();
212
213 auto* sparseSet = static_cast<SparseSet<T>*>(components_[typeId].get());
214
215 return sparseSet->get(entityId);
216 }
217
225 template<typename T>
226 [[nodiscard]] SparseSet<T>* getSparseSet() {
227
228 const auto typeId = ComponentTypeId_type::template id<T>().value();
229
230 if (typeId >= components_.size()) {
231 return nullptr;
232 }
233
234 return static_cast<SparseSet<T>*>(components_[typeId].get());
235 }
236
244 template<typename T>
245 [[nodiscard]] const SparseSet<T>* getSparseSet() const {
246
247 const auto typeId = ComponentTypeId_type::template id<T>().value();
248
249 if (typeId >= components_.size()) {
250 return nullptr;
251 }
252
253 return static_cast<SparseSet<T>*>(components_[typeId].get());
254 }
255
266 template<typename T>
267 [[nodiscard]] bool has(const Handle_type handle) const {
268 if (!registry_.isValid(handle)) {
269 return false;
270 }
271
272 const auto typeId = ComponentTypeId_type::template id<T>().value();
273
274 if (typeId < components_.size() && components_[typeId]) {
275 return components_[typeId]->contains(handle.entityId);
276 }
277
278 return false;
279 }
280
289 [[nodiscard]] bool has(const Handle_type handle,
290 const ComponentTypeId_type typeId) const {
291 if (!registry_.isValid(handle)) {
292 return false;
293 }
294
295 const auto tvalue = typeId.value();
296
297 if (tvalue < components_.size() && components_[tvalue]) {
298 return components_[tvalue]->contains(handle.entityId);
299 }
300
301 return false;
302 }
303
312 void enable(const Handle_type handle, const ComponentTypeId_type typeId) const {
313 enable(handle, typeId, true);
314 }
315
324 void disable(const Handle_type handle, const ComponentTypeId_type typeId) const {
325 enable(handle, typeId, false);
326 }
327
335 void enable(const Handle_type handle, const ComponentTypeId_type typeId, const bool enable) const {
336
337 if (!has(handle, typeId)) {
338 return;
339 }
340
341 void* rawCmp = raw(handle, typeId);
342 if (!rawCmp) {
343 return;
344 }
345 const auto& ops = ComponentOpsRegistry_type::ops(typeId);
346
347 if (enable && ops.enable) {
348 ops.enable(rawCmp);
349 } else if (!enable && ops.disable) {
350 ops.disable(rawCmp);
351 }
352 }
353
371 template<typename T, typename... Args>
372 T* emplace(const Handle_type handle, Args&& ...args) {
373
374 if (!registry_.isValid(handle)) {
375 return nullptr;
376 }
377
378 const auto entityId = handle.entityId;
379
380 const auto typeId = ComponentTypeId_type::template id<T>().value();
381
382 if (typeId >= components_.size()) {
383 components_.resize(typeId + 1);
384 }
385
386 if (!components_[typeId]) {
387 components_[typeId] = std::make_unique<SparseSet<T>>(capacity_);
388 }
389
390 auto* sparseSet = static_cast<SparseSet<T>*>(components_[typeId].get());
391
392 if (sparseSet->contains(entityId)) {
393 return nullptr;
394 }
395
396 return sparseSet->emplace(entityId, std::forward<Args>(args)...);
397 }
398
411 template<typename T, typename... Args>
412 T* emplaceOrGet(const Handle_type handle, Args&& ...args) {
413
414 if (!registry_.isValid(handle)) {
415 return nullptr;
416 }
417
418 auto* raw = emplace<T>(handle, std::forward<Args>(args)...);
419
420 if (!raw) {
421 return get<T>(handle);
422 }
423
424 return raw;
425 }
426
444 template<typename T>
445 bool remove(const Handle_type& handle) {
446
447 if (!has<T>(handle)) {
448 return false;
449 }
450
451 const auto typeId = ComponentTypeId_type::template id<T>();
452 void* rawCmp = raw(handle, typeId);
453 if (!rawCmp) {
454 return false;
455 }
456 const auto& ops = ComponentOpsRegistry_type::ops(typeId);
457
458 if (ops.onRemove && !ops.onRemove(rawCmp)) {
459 return false;
460 }
461
462 return components_[typeId.value()]->remove(handle.entityId);
463 }
464
470 template<typename TFunc>
471 void forEachComponentTypeId(const Handle_type handle, TFunc&& func) const {
472 if (!registry_.isValid(handle)) {
473 return;
474 }
475
476 for (size_t i = 0; i < components_.size(); i++) {
477 if (components_[i] && components_[i]->contains(handle.entityId)) {
478 std::forward<TFunc>(func)(ComponentTypeId_type{i});
479 }
480 }
481 }
482
493 void clone(const Handle_type source, const Handle_type target) {
494
495 if (!registry_.isValid(source)) {
496 return;
497 }
498
500 [&](const ComponentTypeId_type typeId) {
501 if (!has(target, typeId)) {
502
503 const auto& ops = ComponentOpsRegistry_type::ops(typeId);
504 const void* sourceCmp = raw(source, typeId);
505
506 if (sourceCmp && ops.clone) {
507 ops.clone(this, sourceCmp, &target);
508 }
509 }
510 }
511 );
512
513 }
514
523 [[nodiscard]] void* raw(const Handle_type handle, const ComponentTypeId_type typeId ) const {
524 if (!has(handle, typeId)) {
525 return nullptr;
526 }
527
528 return components_[typeId.value()]->raw(handle.entityId);
529 }
530
538 [[nodiscard]] Handle_type handle(const EntityId entityId) const {
539 return Handle_type{entityId, registry_.version(entityId), registry_.strongId(entityId)};
540 }
541
542 private:
548 std::vector<std::unique_ptr<SparseSetBase>> components_;
549
553 EntityRegistry_type registry_;
554
558 const size_t capacity_;
559
560 };
561
562
563}

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.9.8.