Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
id.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cstdint>
5#include <type_traits>
6
7#include "gaia/cnt/sparse_storage.h"
8#include "gaia/core/hashing_policy.h"
9#include "gaia/core/utility.h"
10#include "gaia/ecs/id_fwd.h"
11#include "gaia/ser/ser_common.h"
12
13namespace gaia {
14 namespace ecs {
15#define GAIA_ID(type) GAIA_ID_##type
16
17 using Identifier = uint64_t;
18 inline constexpr Identifier IdentifierBad = (Identifier)-1;
19 inline constexpr Identifier EntityCompMask = IdentifierBad << 1;
20 inline constexpr IdentifierId IdentifierIdBad = (IdentifierId)-1;
21
22 enum class DataStorageType : uint32_t {
24 Table,
26 Sparse,
29 DontFragment,
30
32 Count = 2
33 };
34
37#define GAIA_STORAGE(storage_name) static constexpr auto gaia_Data_Storage = ::gaia::ecs::DataStorageType::storage_name
38
39 // ------------------------------------------------------------------------------------
40 // Component
41 // ------------------------------------------------------------------------------------
42
45 struct GAIA_API Component final {
47 static constexpr uint32_t IdMask = IdentifierIdBad;
49 static constexpr uint32_t MaxComponentSize_Bits = 13;
51 static constexpr uint32_t MaxComponentSizeInBytes = (1 << MaxComponentSize_Bits) - 1;
53 static constexpr uint32_t MaxAlignment_Bits = MaxComponentSize_Bits;
55 static constexpr uint32_t MaxAlignment = MaxComponentSizeInBytes;
56
58 struct InternalData {
60 uint32_t id;
62 IdentifierData size : MaxComponentSize_Bits;
64 IdentifierData alig : MaxAlignment_Bits;
66 IdentifierData storage : 1;
68 IdentifierData soa : meta::StructToTupleMaxTypes_Bits;
70 IdentifierData unused : 1;
71 };
72 static_assert(sizeof(InternalData) == sizeof(Identifier));
73
74 union {
78 Identifier val;
79 };
80
81 Component() noexcept = default;
82
83 Component(uint32_t id, uint32_t soa, uint32_t size, uint32_t alig, DataStorageType storage) noexcept {
84 data.id = id;
85 data.soa = soa;
86 data.size = size;
87 data.alig = alig;
88 data.storage = (IdentifierData)storage;
89 data.unused = 0;
90 }
91
94 GAIA_NODISCARD constexpr auto id() const noexcept {
95 return (uint32_t)data.id;
96 }
97
100 GAIA_NODISCARD constexpr auto soa() const noexcept {
101 return (uint32_t)data.soa;
102 }
103
106 GAIA_NODISCARD constexpr auto size() const noexcept {
107 return (uint32_t)data.size;
108 }
109
112 GAIA_NODISCARD constexpr auto alig() const noexcept {
113 return (uint32_t)data.alig;
114 }
115
118 GAIA_NODISCARD constexpr DataStorageType storage_type() const noexcept {
119 return (DataStorageType)data.storage;
120 }
121
124 GAIA_NODISCARD constexpr auto value() const noexcept {
125 return val;
126 }
127
128 GAIA_NODISCARD constexpr bool operator==(Component other) const noexcept {
129 return value() == other.value();
130 }
131
132 GAIA_NODISCARD constexpr bool operator!=(Component other) const noexcept {
133 return value() != other.value();
134 }
135
136 GAIA_NODISCARD constexpr bool operator<(Component other) const noexcept {
137 return id() < other.id();
138 }
139
143 template <typename Serializer>
144 void save(Serializer& s) const;
145
149 template <typename Serializer>
150 void load(Serializer& s);
151 };
152
153 //----------------------------------------------------------------------
154 // Id type deduction
155 //----------------------------------------------------------------------
156
158 namespace detail {
159 template <typename T>
160 struct ExtractComponentType {
162 using Type = core::raw_t<T>;
164 using TypeFull = Type;
166 using TypeOriginal = T;
167 };
168
169 template <typename T>
170 struct component_type {
171 using type = ExtractComponentType<T>;
172 };
173 } // namespace detail
175
176 template <typename T>
177 using component_type_t = typename detail::component_type<T>::type;
178
179 //----------------------------------------------------------------------
180 // Pair helpers
181 //----------------------------------------------------------------------
182
184 namespace detail {
185 struct pair_base {};
186 } // namespace detail
188
196 template <typename Rel, typename Tgt>
197 class pair: public detail::pair_base {
198 using rel_comp_type = component_type_t<Rel>;
199 using tgt_comp_type = component_type_t<Tgt>;
200
201 public:
203 using rel = typename rel_comp_type::TypeFull;
205 using tgt = typename tgt_comp_type::TypeFull;
207 using rel_type = typename rel_comp_type::Type;
209 using tgt_type = typename tgt_comp_type::Type;
211 using rel_original = typename rel_comp_type::TypeOriginal;
213 using tgt_original = typename tgt_comp_type::TypeOriginal;
215 using type = std::conditional_t<!std::is_empty_v<rel_type> || std::is_empty_v<tgt_type>, rel, tgt>;
216 };
217
219 template <typename T>
220 struct is_pair {
222 static constexpr bool value = std::is_base_of<detail::pair_base, core::raw_t<T>>::value;
223 };
224
225 // ------------------------------------------------------------------------------------
226 // Entity
227 // ------------------------------------------------------------------------------------
228
231 struct GAIA_API Entity final {
233 static constexpr uint32_t IdMask = IdentifierIdBad;
234
238 EntityId id;
239
241 // Bits in this section need to be 1:1 with EntityContainer data.
242 // Note, the order of these bits is important because entities
243 // are sorted by their "val" member and many behaviors rely on this.
245
247 IdentifierData gen : 28;
249 IdentifierData ent : 1;
251 IdentifierData pair : 1;
253 IdentifierData reserved : 1;
255 IdentifierData tmp : 1;
256
258 };
259 static_assert(sizeof(InternalData) == sizeof(Identifier));
260
261 union {
265 Identifier val;
266 };
267
268 constexpr Entity() noexcept: val(IdentifierBad) {}
269
273 template <typename T, typename = std::enable_if_t<std::is_same_v<T, Identifier>>>
274 constexpr Entity(T value) noexcept: val(value) {}
275
277 Entity(EntityId id, IdentifierData gen) noexcept {
278 val = 0;
279 data.id = id;
280 data.gen = gen;
281 }
282
283 Entity(EntityId id, IdentifierData gen, bool isEntity, bool isPair) noexcept {
284 val = 0;
285 data.id = id;
286 data.gen = gen;
287 data.ent = isEntity;
288 data.pair = isPair;
289 data.reserved = 0;
290 data.tmp = 0;
291 }
292
295 GAIA_NODISCARD constexpr auto id() const noexcept {
296 return (uint32_t)data.id;
297 }
298
301 GAIA_NODISCARD constexpr auto gen() const noexcept {
302 return (uint32_t)data.gen;
303 }
304
307 GAIA_NODISCARD constexpr bool entity() const noexcept {
308 return data.ent != 0;
309 }
310
313 GAIA_NODISCARD constexpr bool pair() const noexcept {
314 return data.pair != 0;
315 }
316
319 GAIA_NODISCARD constexpr bool comp() const noexcept {
320 return (data.pair | data.ent) == 0;
321 }
322
325 GAIA_NODISCARD constexpr auto value() const noexcept {
326 return val;
327 }
328
329 GAIA_NODISCARD constexpr bool operator==(Entity other) const noexcept {
330 return value() == other.value();
331 }
332
333 GAIA_NODISCARD constexpr bool operator!=(Entity other) const noexcept {
334 return value() != other.value();
335 }
336
337 GAIA_NODISCARD constexpr bool operator<(Entity other) const noexcept {
338 return value() < other.value();
339 }
340 GAIA_NODISCARD constexpr bool operator<=(Entity other) const noexcept {
341 return value() <= other.value();
342 }
343
344 GAIA_NODISCARD constexpr bool operator>(Entity other) const noexcept {
345 return value() > other.value();
346 }
347 GAIA_NODISCARD constexpr bool operator>=(Entity other) const noexcept {
348 return value() >= other.value();
349 }
350
354 template <typename Serializer>
355 void save(Serializer& s) const;
356
360 template <typename Serializer>
361 void load(Serializer& s);
362 };
363
364 inline static const Entity EntityBad = Entity(IdentifierBad);
365
373 GAIA_NODISCARD constexpr bool operator()(Entity lhs, Entity rhs) const noexcept {
374 return lhs.id() < rhs.id();
375 }
376 };
377
379 namespace detail {
380 struct EntityLoadRemapState {
381 uint32_t savedLastCoreComponentId = 0;
382 uint32_t currLastCoreComponentId = 0;
383 bool remapComponentIds = false;
384 bool active = false;
385 };
386
387 // NOTE: Entity::load() only receives a serializer, not World state.
388 // Therefore the load-time core-id remap currently uses scoped ambient context.
389 // thread_local keeps concurrent world loads on different threads independent.
390 // Tradeoff: this is less explicit than carrying the remap state on the serializer.
391 inline thread_local EntityLoadRemapState g_entityLoadRemapState{};
392
393 struct EntityLoadRemapGuard {
394 EntityLoadRemapState prev;
395
396 EntityLoadRemapGuard(
397 uint32_t savedLastCoreComponentId, uint32_t currLastCoreComponentId, bool remapComponentIds) noexcept:
398 prev(g_entityLoadRemapState) {
399 g_entityLoadRemapState.savedLastCoreComponentId = savedLastCoreComponentId;
400 g_entityLoadRemapState.currLastCoreComponentId = currLastCoreComponentId;
401 g_entityLoadRemapState.remapComponentIds = remapComponentIds;
402 g_entityLoadRemapState.active = true;
403 }
404
405 ~EntityLoadRemapGuard() {
406 g_entityLoadRemapState = prev;
407 }
408
409 EntityLoadRemapGuard(const EntityLoadRemapGuard&) = delete;
410 EntityLoadRemapGuard& operator=(const EntityLoadRemapGuard&) = delete;
411 EntityLoadRemapGuard(EntityLoadRemapGuard&&) = delete;
412 EntityLoadRemapGuard& operator=(EntityLoadRemapGuard&&) = delete;
413 };
414
415 GAIA_NODISCARD inline uint32_t remap_loaded_entity_id(
416 uint32_t id, uint32_t savedLastCoreComponentId, uint32_t currLastCoreComponentId) noexcept {
417 if (id == Entity::IdMask || //
418 id <= savedLastCoreComponentId || //
419 currLastCoreComponentId <= savedLastCoreComponentId //
420 )
421 return id;
422
423 return id + (currLastCoreComponentId - savedLastCoreComponentId);
424 }
425
426 GAIA_NODISCARD inline uint32_t remap_loaded_entity_id(uint32_t id) noexcept {
427 const auto& state = g_entityLoadRemapState;
428 if (!state.active)
429 return id;
430
431 return remap_loaded_entity_id(id, state.savedLastCoreComponentId, state.currLastCoreComponentId);
432 }
433
434 GAIA_NODISCARD inline Entity
435 remap_loaded_entity(Entity entity, uint32_t savedLastCoreComponentId, uint32_t currLastCoreComponentId) noexcept {
436 if (entity == EntityBad)
437 return entity;
438
439 if (!entity.pair()) {
440 return Entity(
441 (EntityId)remap_loaded_entity_id(entity.id(), savedLastCoreComponentId, currLastCoreComponentId),
442 entity.gen(), entity.entity(), false);
443 }
444
445 return Entity(
446 (EntityId)remap_loaded_entity_id(entity.id(), savedLastCoreComponentId, currLastCoreComponentId),
447 (IdentifierData)remap_loaded_entity_id(entity.gen(), savedLastCoreComponentId, currLastCoreComponentId),
448 false, true);
449 }
450
451 GAIA_NODISCARD inline Entity remap_loaded_entity(Entity entity) noexcept {
452 const auto& state = g_entityLoadRemapState;
453 if (!state.active)
454 return entity;
455
456 return remap_loaded_entity(entity, state.savedLastCoreComponentId, state.currLastCoreComponentId);
457 }
458 } // namespace detail
460
461 template <typename Serializer>
462 inline void Entity::save(Serializer& s) const {
463 s.save(val);
464 }
465
466 template <typename Serializer>
467 inline void Entity::load(Serializer& s) {
468 s.load(val);
469 data.reserved = 0;
470 *this = detail::remap_loaded_entity(*this);
471 }
472
473 template <typename Serializer>
474 inline void Component::save(Serializer& s) const {
475 s.save(val);
476 }
477
478 template <typename Serializer>
479 inline void Component::load(Serializer& s) {
480 s.load(val);
481 if (detail::g_entityLoadRemapState.active && detail::g_entityLoadRemapState.remapComponentIds)
482 data.id = detail::remap_loaded_entity_id(data.id);
483 }
484
486 struct GAIA_API EntityLookupKey {
489
490 private:
492 Entity m_entity;
494 LookupHash m_hash;
495
496 static LookupHash calc(Entity entity) {
497 return {core::calculate_hash64(entity.value())};
498 }
499
500 public:
502 static constexpr bool IsDirectHashKey = true;
503
504 EntityLookupKey() = default;
505 explicit EntityLookupKey(Entity entity): m_entity(entity), m_hash(calc(entity)) {}
506 ~EntityLookupKey() = default;
507
508 EntityLookupKey(const EntityLookupKey&) = default;
509 EntityLookupKey(EntityLookupKey&&) noexcept = default;
510 EntityLookupKey& operator=(const EntityLookupKey&) = default;
511 EntityLookupKey& operator=(EntityLookupKey&&) noexcept = default;
512
515 Entity entity() const {
516 return m_entity;
517 }
518
521 size_t hash() const {
522 return (size_t)m_hash.hash;
523 }
524
525 bool operator==(const EntityLookupKey& other) const {
526 if GAIA_LIKELY (m_hash != other.m_hash)
527 return false;
528
529 return m_entity == other.m_entity;
530 }
531
532 bool operator!=(const EntityLookupKey& other) const {
533 return !operator==(other);
534 }
535 };
536
537 inline static const EntityLookupKey EntityBadLookupKey = EntityLookupKey(EntityBad);
538
540 struct GAIA_API EntityDesc {
542 const char* name{};
544 uint32_t name_len{};
546 const char* alias{};
548 uint32_t alias_len{};
549 };
550
551 //----------------------------------------------------------------------
552 // Pair
553 //----------------------------------------------------------------------
554
558 template <>
559 class pair<Entity, Entity>: public detail::pair_base {
560 Entity m_first;
561 Entity m_second;
562
563 public:
564 pair(Entity a, Entity b) noexcept: m_first(a), m_second(b) {}
565
566 operator Entity() const noexcept {
567 return Entity(
568 m_first.id(), m_second.id(), false,
569 // Always true for pairs
570 true);
571 }
572
575 Entity first() const noexcept {
576 return m_first;
577 }
578
581 Entity second() const noexcept {
582 return m_second;
583 }
584
585 bool operator==(const pair& other) const {
586 return m_first == other.m_first && m_second == other.m_second;
587 }
588 bool operator!=(const pair& other) const {
589 return !operator==(other);
590 }
591 };
592
593 using Pair = pair<Entity, Entity>;
594
595 //----------------------------------------------------------------------
596 // Core components
597 //----------------------------------------------------------------------
598
600 namespace detail {
601 template <typename T, typename U = void>
602 struct actual_type {
603 using type = typename component_type<T>::type;
604 };
605
606 template <typename T>
607 struct actual_type<T, std::enable_if_t<is_pair<T>::value>> {
608 using storage_type = typename T::type;
609 using type = typename component_type<storage_type>::type;
610 };
611 } // namespace detail
613
614 template <typename T>
615 using actual_type_t = typename detail::actual_type<T>::type;
616
617 //----------------------------------------------------------------------
618 // Core components
619 //----------------------------------------------------------------------
620
621 // Core component. The entity it is attached to is ignored by queries
622 struct GAIA_API Core_ {};
623 // struct EntityDesc;
624 // struct Component;
625 struct GAIA_API OnDelete_ {};
626 struct GAIA_API OnDeleteTarget_ {};
627 struct GAIA_API Remove_ {};
628 struct GAIA_API Delete_ {};
629 struct GAIA_API Error_ {};
634 struct GAIA_API Requires_ {};
635 struct GAIA_API CantCombine_ {};
636 struct GAIA_API Exclusive_ {};
637 struct GAIA_API DontFragment_ {};
638 struct GAIA_API Sparse_ {};
639 struct GAIA_API Acyclic_ {};
640 struct GAIA_API All_ {};
641 struct GAIA_API ChildOf_ {};
642 struct GAIA_API Parent_ {};
643 struct GAIA_API Is_ {};
644 struct GAIA_API Prefab_ {};
645 struct GAIA_API OnInstantiate_ {};
646 struct GAIA_API Override_ {};
647 struct GAIA_API Inherit_ {};
648 struct GAIA_API DontInherit_ {};
649 struct GAIA_API Traversable_ {};
650 struct GAIA_API System_;
651 struct GAIA_API DependsOn_ {};
652 struct GAIA_API Observer_;
653
654 // Query variables
655 struct GAIA_API _Var0 {};
656 struct GAIA_API _Var1 {};
657 struct GAIA_API _Var2 {};
658 struct GAIA_API _Var3 {};
659 struct GAIA_API _Var4 {};
660 struct GAIA_API _Var5 {};
661 struct GAIA_API _Var6 {};
662 struct GAIA_API _Var7 {};
663
664 //----------------------------------------------------------------------
665 // Core component entities
666 //----------------------------------------------------------------------
667
668 // Core component. The entity it is attached to is ignored by queries
669 inline Entity Core = Entity(0, 0, false, false);
670 inline Entity GAIA_ID(EntityDesc) = Entity(1, 0, false, false);
671 inline Entity GAIA_ID(Component) = Entity(2, 0, false, false);
672 // Cleanup rules
673 inline Entity OnDelete = Entity(3, 0, false, false);
674 inline Entity OnDeleteTarget = Entity(4, 0, false, false);
675 inline Entity Remove = Entity(5, 0, false, false);
676 inline Entity Delete = Entity(6, 0, false, false);
677 inline Entity Error = Entity(7, 0, false, false);
678 // Entity dependencies
681 inline Entity Requires = Entity(8, 0, false, false);
682 inline Entity CantCombine = Entity(9, 0, false, false);
683 inline Entity Exclusive = Entity(10, 0, false, false);
684 // Entity storage
685 inline Entity DontFragment = Entity(11, 0, false, false);
686 inline Entity Sparse = Entity(12, 0, false, false);
687 // Graph properties
688 inline Entity Acyclic = Entity(13, 0, false, false);
689 inline Entity Traversable = Entity(14, 0, false, false);
690 // Wildcard query entity
691 inline Entity All = Entity(15, 0, false, false);
694 inline Entity ChildOf = Entity(16, 0, false, false);
697 inline Entity Parent = Entity(17, 0, false, false);
698 // Alias for a base entity/inheritance
699 inline Entity Is = Entity(18, 0, false, false);
700 // Template entity excluded from queries by default unless explicitly requested.
701 inline Entity Prefab = Entity(19, 0, false, false);
702 // Prefab instantiation policy relation and values.
703 inline Entity OnInstantiate = Entity(20, 0, false, false);
704 inline Entity Override = Entity(21, 0, false, false);
705 inline Entity Inherit = Entity(22, 0, false, false);
706 inline Entity DontInherit = Entity(23, 0, false, false);
707 // Systems
708 inline Entity System = Entity(24, 0, false, false);
709 inline Entity DependsOn = Entity(25, 0, false, false);
710 // Observers
711 inline Entity Observer = Entity(26, 0, false, false);
712 // Query variables
713 inline Entity Var0 = Entity(27, 0, false, false);
714 inline Entity Var1 = Entity(28, 0, false, false);
715 inline Entity Var2 = Entity(29, 0, false, false);
716 inline Entity Var3 = Entity(30, 0, false, false);
717 inline Entity Var4 = Entity(31, 0, false, false);
718 inline Entity Var5 = Entity(32, 0, false, false);
719 inline Entity Var6 = Entity(33, 0, false, false);
720 inline Entity Var7 = Entity(34, 0, false, false);
721 // Runtime primitive type entities. Supported entity ids are aligned with ser::serialization_type_id:
722 // runtime_primitive_type_entity(t).id() == RuntimePrimitiveTypeBaseId + (uint32_t)t.
723 inline constexpr uint32_t RuntimePrimitiveTypeBaseId = 34;
724
725 GAIA_NODISCARD inline bool is_runtime_primitive_serialization_type_id(uint32_t typeId) noexcept {
726 return typeId >= (uint32_t)ser::serialization_type_id::s8 && typeId <= (uint32_t)ser::serialization_type_id::f64;
727 }
728
729 GAIA_NODISCARD inline Entity runtime_primitive_type_entity(ser::serialization_type_id type) noexcept {
730 const auto typeId = (uint32_t)type;
731 if (!is_runtime_primitive_serialization_type_id(typeId))
732 return EntityBad;
733 return Entity((EntityId)(RuntimePrimitiveTypeBaseId + typeId), 0, false, false);
734 }
735
736 GAIA_NODISCARD inline bool
737 runtime_primitive_serialization_type(Entity type, ser::serialization_type_id& out) noexcept {
738 if (type.pair())
739 return false;
740
741 const auto typeId = type.id() - RuntimePrimitiveTypeBaseId;
742 if (!is_runtime_primitive_serialization_type_id(typeId))
743 return false;
744
745 out = (ser::serialization_type_id)typeId;
746 return true;
747 }
748
749 inline Entity S8 = runtime_primitive_type_entity(ser::serialization_type_id::s8);
750 inline Entity U8 = runtime_primitive_type_entity(ser::serialization_type_id::u8);
751 inline Entity S16 = runtime_primitive_type_entity(ser::serialization_type_id::s16);
752 inline Entity U16 = runtime_primitive_type_entity(ser::serialization_type_id::u16);
753 inline Entity S32 = runtime_primitive_type_entity(ser::serialization_type_id::s32);
754 inline Entity U32 = runtime_primitive_type_entity(ser::serialization_type_id::u32);
755 inline Entity S64 = runtime_primitive_type_entity(ser::serialization_type_id::s64);
756 inline Entity U64 = runtime_primitive_type_entity(ser::serialization_type_id::u64);
757 inline Entity Bool = runtime_primitive_type_entity(ser::serialization_type_id::b);
758 inline Entity Char8 = runtime_primitive_type_entity(ser::serialization_type_id::c8);
759 inline Entity Char16 = runtime_primitive_type_entity(ser::serialization_type_id::c16);
760 inline Entity Char32 = runtime_primitive_type_entity(ser::serialization_type_id::c32);
761 inline Entity F8 = runtime_primitive_type_entity(ser::serialization_type_id::f8);
762 inline Entity F16 = runtime_primitive_type_entity(ser::serialization_type_id::f16);
763 inline Entity F32 = runtime_primitive_type_entity(ser::serialization_type_id::f32);
764 inline Entity F64 = runtime_primitive_type_entity(ser::serialization_type_id::f64);
765 inline static constexpr uint32_t MaxVarCnt = 8;
766
767 // Core component ids are append-only.
768 // Existing core ids must remain stable; new core components may only be added
769 // after LastCoreComponent.
770 //
771 // Because of that, old snapshots stay loadable without bumping the serializer
772 // version: any serialized entity id greater than the saved last core id is
773 // remapped by the current core-id delta during load.
774 //
775 // Reordering or removing core components is not supported by this compatibility path.
776 // Always has to match the last internal entity.
777 inline Entity GAIA_ID(LastCoreComponent) = F64;
778
779 //----------------------------------------------------------------------
780 // Helper functions
781 //----------------------------------------------------------------------
782
783 GAIA_NODISCARD inline bool is_wildcard(EntityId entityId) {
784 return entityId == All.id();
785 }
786
787 GAIA_NODISCARD inline bool is_wildcard(Entity entity) {
788 return entity.pair() && (is_wildcard(entity.id()) || is_wildcard(entity.gen()));
789 }
790
791 GAIA_NODISCARD inline bool is_wildcard(Pair pair) {
792 return pair.first() == All || pair.second() == All;
793 }
794
795 GAIA_NODISCARD inline bool is_variable(EntityId entityId) {
796 return entityId <= Var7.id() && entityId >= Var0.id();
797 }
798
799 GAIA_NODISCARD inline bool is_variable(Entity entity) {
800 return entity.id() <= Var7.id() && entity.id() >= Var0.id();
801 }
802
803 GAIA_NODISCARD inline bool is_variable(Pair pair) {
804 return is_variable(pair.first()) || is_variable(pair.second());
805 }
806
807 //----------------------------------------------------------------------
808 // Entity id enumeration
809 //----------------------------------------------------------------------
810
812 enum class EntityIdStorage : uint8_t {
814 None = 0x00,
816 Archetype = 0x01,
818 DontFragment = 0x02,
820 Relation = 0x04,
822 All = 0x07
823 };
824
829 GAIA_NODISCARD constexpr EntityIdStorage operator|(EntityIdStorage lhs, EntityIdStorage rhs) {
830 return (EntityIdStorage)((uint8_t)lhs | (uint8_t)rhs);
831 }
832
837 GAIA_NODISCARD constexpr bool entity_id_storage_has(EntityIdStorage value, EntityIdStorage bit) {
838 return (((uint8_t)value) & ((uint8_t)bit)) != 0;
839 }
840
842 enum class EntityIdKind : uint8_t {
844 None = 0x00,
846 Component = 0x01,
848 Pair = 0x02,
850 All = 0x03
851 };
852
857 GAIA_NODISCARD constexpr EntityIdKind operator|(EntityIdKind lhs, EntityIdKind rhs) {
858 return (EntityIdKind)((uint8_t)lhs | (uint8_t)rhs);
859 }
860
865 GAIA_NODISCARD constexpr bool entity_id_kind_has(EntityIdKind value, EntityIdKind bit) {
866 return (((uint8_t)value) & ((uint8_t)bit)) != 0;
867 }
868
871 enum class QueryMatchKind : uint8_t {
873 Semantic,
875 In,
877 Direct
878 };
879
891 storage = select_storage(storage, EntityIdStorage::Archetype);
892 return *this;
893 }
894
898 storage = select_storage(storage, EntityIdStorage::DontFragment);
899 return *this;
900 }
901
905 storage = select_storage(storage, EntityIdStorage::Relation);
906 return *this;
907 }
908
912 kind = select_kind(kind, EntityIdKind::Component);
913 return *this;
914 }
915
919 kind = select_kind(kind, EntityIdKind::Pair);
920 return *this;
921 }
922
926 matchKind = QueryMatchKind::Direct;
927 return *this;
928 }
929
936 matchKind = QueryMatchKind::In;
937 return *this;
938 }
939
940 private:
941 friend class World;
942
943 EntityIdStorage storage = EntityIdStorage::All;
944 EntityIdKind kind = EntityIdKind::All;
945 QueryMatchKind matchKind = QueryMatchKind::Direct;
946
951 GAIA_NODISCARD static constexpr EntityIdStorage select_storage(EntityIdStorage current, EntityIdStorage bit) {
952 return current == EntityIdStorage::All ? bit : (current | bit);
953 }
954
959 GAIA_NODISCARD static constexpr EntityIdKind select_kind(EntityIdKind current, EntityIdKind bit) {
960 return current == EntityIdKind::All ? bit : (current | bit);
961 }
962 };
963
964 } // namespace ecs
965
966 namespace cnt {
968 template <>
969 struct to_sparse_id<ecs::Entity> {
973 static sparse_id get(const ecs::Entity& item) noexcept {
974 // Cut off the flags
975 return item.id();
976 }
977 };
978 } // namespace cnt
979} // namespace gaia
Owns entities, components, archetypes, queries, observers, and systems.
Definition world.h:80
Entity first() const noexcept
First entity of the pair.
Definition id.h:575
Entity second() const noexcept
Second entity of the pair.
Definition id.h:581
Wrapper for two types forming a relationship pair. Depending on what types are used to form a pair it...
Definition id.h:197
typename rel_comp_type::TypeFull rel
Full relation type.
Definition id.h:203
typename tgt_comp_type::TypeOriginal tgt_original
Original target template type.
Definition id.h:213
typename tgt_comp_type::TypeFull tgt
Full target type.
Definition id.h:205
std::conditional_t<!std::is_empty_v< rel_type >||std::is_empty_v< tgt_type >, rel, tgt > type
Storage type for the pair value.
Definition id.h:215
typename rel_comp_type::TypeOriginal rel_original
Original relation template type.
Definition id.h:211
typename rel_comp_type::Type rel_type
Raw relation type.
Definition id.h:207
typename tgt_comp_type::Type tgt_type
Raw target type.
Definition id.h:209
void load(Reader &reader, T &data)
Read data using Reader at compile-time.
Definition ser_ct.h:112
void save(Writer &writer, const T &data)
Write data using Writer at compile-time.
Definition ser_ct.h:101
T hash
Precomputed hash value.
Definition hashing_policy.h:51
Definition id.h:639
Definition id.h:640
Definition id.h:635
Definition id.h:641
Bit-packed storage layout of a component id.
Definition id.h:58
IdentifierData soa
Component is SoA.
Definition id.h:68
IdentifierData alig
Component alignment.
Definition id.h:64
IdentifierData size
Component size.
Definition id.h:62
uint32_t id
Component entity index.
Definition id.h:60
IdentifierData storage
Component storage kind. 0 = table, 1 = sparse.
Definition id.h:66
IdentifierData unused
Unused part.
Definition id.h:70
Identifier of a registered component type. Packs the component id, size, alignment,...
Definition id.h:45
GAIA_NODISCARD constexpr auto value() const noexcept
Raw identifier value.
Definition id.h:124
void save(Serializer &s) const
Serializes the component id.
Definition id.h:474
Identifier val
Raw 64-bit value.
Definition id.h:78
void load(Serializer &s)
Deserializes the component id.
Definition id.h:479
GAIA_NODISCARD constexpr auto alig() const noexcept
Component alignment in bytes.
Definition id.h:112
GAIA_NODISCARD constexpr auto id() const noexcept
Component id.
Definition id.h:94
GAIA_NODISCARD constexpr auto size() const noexcept
Component size in bytes.
Definition id.h:106
GAIA_NODISCARD constexpr DataStorageType storage_type() const noexcept
Storage mode of the component.
Definition id.h:118
GAIA_NODISCARD constexpr auto soa() const noexcept
Whether the component uses SoA storage.
Definition id.h:100
InternalData data
Structured view of the packed value.
Definition id.h:76
Definition id.h:622
Definition id.h:628
Definition id.h:651
Definition id.h:637
Definition id.h:648
Component used to describe the entity name.
Definition id.h:540
Options for World::ids / World::ids_if. Defaults visit the complete direct type: every storage source...
Definition id.h:887
EntityIdOptions & in()
Allows direct and inherited matches. After the direct type, appends OnInstantiate(Inherit) ids from I...
Definition id.h:935
EntityIdOptions & pairs()
Selects relationship pair ids.
Definition id.h:918
EntityIdOptions & archetype()
Selects archetype-resident ids.
Definition id.h:890
EntityIdOptions & components()
Selects non-pair ids.
Definition id.h:911
EntityIdOptions & direct()
Restricts visitation to ids stored on the entity.
Definition id.h:925
EntityIdOptions & dont_fragment()
Selects DontFragment component membership.
Definition id.h:897
EntityIdOptions & relation()
Selects exclusive non-fragmenting pairs.
Definition id.h:904
Hashmap lookup structure used for Entity.
Definition id.h:486
size_t hash() const
Hash of the entity value.
Definition id.h:521
Bit-packed storage layout of an entity identifier.
Definition id.h:236
IdentifierData reserved
Reserved for future use. Always 0.
Definition id.h:253
EntityId id
Index in the entity array.
Definition id.h:238
IdentifierData tmp
0-real entity, 1-temporary entity
Definition id.h:255
IdentifierData gen
Generation index. Incremented every time an entity is deleted.
Definition id.h:247
IdentifierData pair
0-ordinary, 1-pair
Definition id.h:251
IdentifierData ent
0-component, 1-entity
Definition id.h:249
Identifier of an entity or component instance in the world. Packs the entity index,...
Definition id.h:231
void load(Serializer &s)
Deserializes the entity id, remapping it to the current world.
Definition id.h:467
GAIA_NODISCARD constexpr auto gen() const noexcept
Generation index of the entity.
Definition id.h:301
GAIA_NODISCARD constexpr auto value() const noexcept
Raw identifier value.
Definition id.h:325
GAIA_NODISCARD constexpr bool comp() const noexcept
Whether this id refers to a component.
Definition id.h:319
void save(Serializer &s) const
Serializes the entity id.
Definition id.h:462
InternalData data
Structured view of the packed value.
Definition id.h:263
static constexpr uint32_t IdMask
Bit mask covering all valid entity indices.
Definition id.h:233
GAIA_NODISCARD constexpr bool pair() const noexcept
Whether this id refers to a relationship pair.
Definition id.h:313
Identifier val
Raw 64-bit value.
Definition id.h:265
GAIA_NODISCARD constexpr auto id() const noexcept
Entity index in the entity array.
Definition id.h:295
Entity(EntityId id, IdentifierData gen) noexcept
Special constructor for cnt::ilist.
Definition id.h:277
constexpr Entity(T value) noexcept
We need the entity to be braces-constructible and at the same type prevent it from getting constructe...
Definition id.h:274
GAIA_NODISCARD constexpr bool entity() const noexcept
Whether this id refers to an entity.
Definition id.h:307
Definition id.h:629
Definition id.h:636
Definition id.h:647
Definition id.h:643
Definition observer.h:242
Definition id.h:626
Definition id.h:625
Definition id.h:645
Definition id.h:646
Definition id.h:642
Definition id.h:644
Definition id.h:627
Marks an id as required. Used directly on a non-pair id, it prevents removing that id from its owners...
Definition id.h:634
Orders entities by id only, ignoring the generation and the other packed bits. Sorts that need this o...
Definition id.h:369
GAIA_NODISCARD constexpr bool operator()(Entity lhs, Entity rhs) const noexcept
Definition id.h:373
Definition id.h:638
Definition system.inl:695
Definition id.h:649
Definition id.h:655
Definition id.h:656
Definition id.h:657
Definition id.h:658
Definition id.h:659
Definition id.h:660
Definition id.h:661
Definition id.h:662
Detects whether a type is a relationship pair.
Definition id.h:220
static constexpr bool value
True when the type derives from the pair base.
Definition id.h:222