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,
27
29 Count = 2
30 };
31
34#define GAIA_STORAGE(storage_name) static constexpr auto gaia_Data_Storage = ::gaia::ecs::DataStorageType::storage_name
35
36 // ------------------------------------------------------------------------------------
37 // Component
38 // ------------------------------------------------------------------------------------
39
42 struct GAIA_API Component final {
44 static constexpr uint32_t IdMask = IdentifierIdBad;
46 static constexpr uint32_t MaxComponentSize_Bits = 13;
48 static constexpr uint32_t MaxComponentSizeInBytes = (1 << MaxComponentSize_Bits) - 1;
50 static constexpr uint32_t MaxAlignment_Bits = MaxComponentSize_Bits;
52 static constexpr uint32_t MaxAlignment = MaxComponentSizeInBytes;
53
55 struct InternalData {
57 uint32_t id;
59 IdentifierData size : MaxComponentSize_Bits;
61 IdentifierData alig : MaxAlignment_Bits;
63 IdentifierData storage : 1;
65 IdentifierData soa : meta::StructToTupleMaxTypes_Bits;
67 IdentifierData unused : 1;
68 };
69 static_assert(sizeof(InternalData) == sizeof(Identifier));
70
71 union {
75 Identifier val;
76 };
77
78 Component() noexcept = default;
79
80 Component(uint32_t id, uint32_t soa, uint32_t size, uint32_t alig, DataStorageType storage) noexcept {
81 data.id = id;
82 data.soa = soa;
83 data.size = size;
84 data.alig = alig;
85 data.storage = (IdentifierData)storage;
86 data.unused = 0;
87 }
88
91 GAIA_NODISCARD constexpr auto id() const noexcept {
92 return (uint32_t)data.id;
93 }
94
97 GAIA_NODISCARD constexpr auto soa() const noexcept {
98 return (uint32_t)data.soa;
99 }
100
103 GAIA_NODISCARD constexpr auto size() const noexcept {
104 return (uint32_t)data.size;
105 }
106
109 GAIA_NODISCARD constexpr auto alig() const noexcept {
110 return (uint32_t)data.alig;
111 }
112
115 GAIA_NODISCARD constexpr DataStorageType storage_type() const noexcept {
116 return (DataStorageType)data.storage;
117 }
118
121 GAIA_NODISCARD constexpr auto value() const noexcept {
122 return val;
123 }
124
125 GAIA_NODISCARD constexpr bool operator==(Component other) const noexcept {
126 return value() == other.value();
127 }
128
129 GAIA_NODISCARD constexpr bool operator!=(Component other) const noexcept {
130 return value() != other.value();
131 }
132
133 GAIA_NODISCARD constexpr bool operator<(Component other) const noexcept {
134 return id() < other.id();
135 }
136
140 template <typename Serializer>
141 void save(Serializer& s) const;
142
146 template <typename Serializer>
147 void load(Serializer& s);
148 };
149
150 //----------------------------------------------------------------------
151 // Entity kind
152 //----------------------------------------------------------------------
153
154 enum EntityKind : uint8_t {
156 EK_Gen = 0,
158 EK_Uni
159 };
160
161 inline constexpr const char* EntityKindString[] = {"Gen", "Uni"};
162
163 //----------------------------------------------------------------------
164 // Id type deduction
165 //----------------------------------------------------------------------
166
168 template <typename T>
169 struct uni {
170 static_assert(core::is_raw_v<T>);
171 static_assert(
172 std::is_trivial_v<T> ||
173 // For non-trivial T the comparison operator must be implemented because
174 // defragmentation needs it to figure out if entities can be moved around.
176 "Non-trivial Uni component must implement operator==");
177
179 static constexpr EntityKind Kind = EntityKind::EK_Uni;
180
182 using TType = T;
186 using TTypeOriginal = T;
187 };
188
190 namespace detail {
191 template <typename, typename = void>
192 struct has_entity_kind: std::false_type {};
193 template <typename T>
194 struct has_entity_kind<T, std::void_t<decltype(T::Kind)>>: std::true_type {};
195
196 template <typename T>
197 struct ExtractComponentType_NoEntityKind {
199 static constexpr EntityKind Kind = EntityKind::EK_Gen;
200
202 using Type = core::raw_t<T>;
204 using TypeFull = Type;
206 using TypeOriginal = T;
207 };
208
209 template <typename T>
210 struct ExtractComponentType_WithEntityKind {
212 static constexpr EntityKind Kind = T::Kind;
213
215 using Type = typename T::TType;
217 using TypeFull = std::conditional_t<Kind == EntityKind::EK_Gen, Type, uni<Type>>;
219 using TypeOriginal = typename T::TTypeOriginal;
220 };
221
222 template <typename, typename = void>
223 struct is_gen_component: std::true_type {};
224 template <typename T>
225 struct is_gen_component<T, std::void_t<decltype(T::Kind)>>: std::bool_constant<T::Kind == EntityKind::EK_Gen> {};
226
227 template <typename T, typename = void>
228 struct component_type {
229 using type = typename detail::ExtractComponentType_NoEntityKind<T>;
230 };
231 template <typename T>
232 struct component_type<T, std::void_t<decltype(T::Kind)>> {
233 using type = typename detail::ExtractComponentType_WithEntityKind<T>;
234 };
235 } // namespace detail
237
238 template <typename T>
239 using component_type_t = typename detail::component_type<T>::type;
240
241 template <typename T>
242 inline constexpr EntityKind entity_kind_v = component_type_t<T>::Kind;
243
244 //----------------------------------------------------------------------
245 // Pair helpers
246 //----------------------------------------------------------------------
247
249 namespace detail {
250 struct pair_base {};
251 } // namespace detail
253
261 template <typename Rel, typename Tgt>
262 class pair: public detail::pair_base {
263 using rel_comp_type = component_type_t<Rel>;
264 using tgt_comp_type = component_type_t<Tgt>;
265
266 public:
268 using rel = typename rel_comp_type::TypeFull;
270 using tgt = typename tgt_comp_type::TypeFull;
272 using rel_type = typename rel_comp_type::Type;
274 using tgt_type = typename tgt_comp_type::Type;
276 using rel_original = typename rel_comp_type::TypeOriginal;
278 using tgt_original = typename tgt_comp_type::TypeOriginal;
280 using type = std::conditional_t<!std::is_empty_v<rel_type> || std::is_empty_v<tgt_type>, rel, tgt>;
281 };
282
284 template <typename T>
285 struct is_pair {
287 static constexpr bool value = std::is_base_of<detail::pair_base, core::raw_t<T>>::value;
288 };
289
290 // ------------------------------------------------------------------------------------
291 // Entity
292 // ------------------------------------------------------------------------------------
293
296 struct GAIA_API Entity final {
298 static constexpr uint32_t IdMask = IdentifierIdBad;
299
303 EntityId id;
304
306 // Bits in this section need to be 1:1 with EntityContainer data.
307 // Note, the order of these bits is important because entities
308 // are sorted by their "val" member and many behaviors rely on this.
310
312 IdentifierData gen : 28;
314 IdentifierData ent : 1;
316 IdentifierData pair : 1;
318 IdentifierData kind : 1;
320 IdentifierData tmp : 1;
321
323 };
324 static_assert(sizeof(InternalData) == sizeof(Identifier));
325
326 union {
330 Identifier val;
331 };
332
333 constexpr Entity() noexcept: val(IdentifierBad) {};
334
338 template <typename T, typename = std::enable_if_t<std::is_same_v<T, Identifier>>>
339 constexpr Entity(T value) noexcept: val(value) {}
340
342 Entity(EntityId id, IdentifierData gen) noexcept {
343 val = 0;
344 data.id = id;
345 data.gen = gen;
346 }
347
348 Entity(EntityId id, IdentifierData gen, bool isEntity, bool isPair, EntityKind kind) noexcept {
349 data.id = id;
350 data.gen = gen;
351 data.ent = isEntity;
352 data.pair = isPair;
353 data.kind = kind;
354 data.tmp = 0;
355 }
356
359 GAIA_NODISCARD constexpr auto id() const noexcept {
360 return (uint32_t)data.id;
361 }
362
365 GAIA_NODISCARD constexpr auto gen() const noexcept {
366 return (uint32_t)data.gen;
367 }
368
371 GAIA_NODISCARD constexpr bool entity() const noexcept {
372 return data.ent != 0;
373 }
374
377 GAIA_NODISCARD constexpr bool pair() const noexcept {
378 return data.pair != 0;
379 }
380
383 GAIA_NODISCARD constexpr bool comp() const noexcept {
384 return (data.pair | data.ent) == 0;
385 }
386
389 GAIA_NODISCARD constexpr auto kind() const noexcept {
390 return (EntityKind)data.kind;
391 }
392
395 GAIA_NODISCARD constexpr auto value() const noexcept {
396 return val;
397 }
398
399 GAIA_NODISCARD constexpr bool operator==(Entity other) const noexcept {
400 return value() == other.value();
401 }
402
403 GAIA_NODISCARD constexpr bool operator!=(Entity other) const noexcept {
404 return value() != other.value();
405 }
406
407 GAIA_NODISCARD constexpr bool operator<(Entity other) const noexcept {
408 return value() < other.value();
409 }
410 GAIA_NODISCARD constexpr bool operator<=(Entity other) const noexcept {
411 return value() <= other.value();
412 }
413
414 GAIA_NODISCARD constexpr bool operator>(Entity other) const noexcept {
415 return value() > other.value();
416 }
417 GAIA_NODISCARD constexpr bool operator>=(Entity other) const noexcept {
418 return value() >= other.value();
419 }
420
424 template <typename Serializer>
425 void save(Serializer& s) const;
426
430 template <typename Serializer>
431 void load(Serializer& s);
432 };
433
434 inline static const Entity EntityBad = Entity(IdentifierBad);
435
437 namespace detail {
438 struct EntityLoadRemapState {
439 uint32_t savedLastCoreComponentId = 0;
440 uint32_t currLastCoreComponentId = 0;
441 bool remapComponentIds = false;
442 bool active = false;
443 };
444
445 // NOTE: Entity::load() only receives a serializer, not World state.
446 // Therefore the load-time core-id remap currently uses scoped ambient context.
447 // thread_local keeps concurrent world loads on different threads independent.
448 // Tradeoff: this is less explicit than carrying the remap state on the serializer.
449 inline thread_local EntityLoadRemapState g_entityLoadRemapState{};
450
451 struct EntityLoadRemapGuard {
452 EntityLoadRemapState prev;
453
454 EntityLoadRemapGuard(
455 uint32_t savedLastCoreComponentId, uint32_t currLastCoreComponentId, bool remapComponentIds) noexcept:
456 prev(g_entityLoadRemapState) {
457 g_entityLoadRemapState.savedLastCoreComponentId = savedLastCoreComponentId;
458 g_entityLoadRemapState.currLastCoreComponentId = currLastCoreComponentId;
459 g_entityLoadRemapState.remapComponentIds = remapComponentIds;
460 g_entityLoadRemapState.active = true;
461 }
462
463 ~EntityLoadRemapGuard() {
464 g_entityLoadRemapState = prev;
465 }
466
467 EntityLoadRemapGuard(const EntityLoadRemapGuard&) = delete;
468 EntityLoadRemapGuard& operator=(const EntityLoadRemapGuard&) = delete;
469 EntityLoadRemapGuard(EntityLoadRemapGuard&&) = delete;
470 EntityLoadRemapGuard& operator=(EntityLoadRemapGuard&&) = delete;
471 };
472
473 GAIA_NODISCARD inline uint32_t remap_loaded_entity_id(
474 uint32_t id, uint32_t savedLastCoreComponentId, uint32_t currLastCoreComponentId) noexcept {
475 if (id == Entity::IdMask || //
476 id <= savedLastCoreComponentId || //
477 currLastCoreComponentId <= savedLastCoreComponentId //
478 )
479 return id;
480
481 return id + (currLastCoreComponentId - savedLastCoreComponentId);
482 }
483
484 GAIA_NODISCARD inline uint32_t remap_loaded_entity_id(uint32_t id) noexcept {
485 const auto& state = g_entityLoadRemapState;
486 if (!state.active)
487 return id;
488
489 return remap_loaded_entity_id(id, state.savedLastCoreComponentId, state.currLastCoreComponentId);
490 }
491
492 GAIA_NODISCARD inline Entity
493 remap_loaded_entity(Entity entity, uint32_t savedLastCoreComponentId, uint32_t currLastCoreComponentId) noexcept {
494 if (entity == EntityBad)
495 return entity;
496
497 if (!entity.pair()) {
498 return Entity(
499 (EntityId)remap_loaded_entity_id(entity.id(), savedLastCoreComponentId, currLastCoreComponentId),
500 entity.gen(), entity.entity(), false, entity.kind());
501 }
502
503 return Entity(
504 (EntityId)remap_loaded_entity_id(entity.id(), savedLastCoreComponentId, currLastCoreComponentId),
505 (IdentifierData)remap_loaded_entity_id(entity.gen(), savedLastCoreComponentId, currLastCoreComponentId),
506 entity.entity(), true, entity.kind());
507 }
508
509 GAIA_NODISCARD inline Entity remap_loaded_entity(Entity entity) noexcept {
510 const auto& state = g_entityLoadRemapState;
511 if (!state.active)
512 return entity;
513
514 return remap_loaded_entity(entity, state.savedLastCoreComponentId, state.currLastCoreComponentId);
515 }
516 } // namespace detail
518
519 template <typename Serializer>
520 inline void Entity::save(Serializer& s) const {
521 s.save(val);
522 }
523
524 template <typename Serializer>
525 inline void Entity::load(Serializer& s) {
526 s.load(val);
527 *this = detail::remap_loaded_entity(*this);
528 }
529
530 template <typename Serializer>
531 inline void Component::save(Serializer& s) const {
532 s.save(val);
533 }
534
535 template <typename Serializer>
536 inline void Component::load(Serializer& s) {
537 s.load(val);
538 if (detail::g_entityLoadRemapState.active && detail::g_entityLoadRemapState.remapComponentIds)
539 data.id = detail::remap_loaded_entity_id(data.id);
540 }
541
543 struct GAIA_API EntityLookupKey {
546
547 private:
549 Entity m_entity;
551 LookupHash m_hash;
552
553 static LookupHash calc(Entity entity) {
554 return {core::calculate_hash64(entity.value())};
555 }
556
557 public:
559 static constexpr bool IsDirectHashKey = true;
560
561 EntityLookupKey() = default;
562 explicit EntityLookupKey(Entity entity): m_entity(entity), m_hash(calc(entity)) {}
563 ~EntityLookupKey() = default;
564
565 EntityLookupKey(const EntityLookupKey&) = default;
566 EntityLookupKey(EntityLookupKey&&) noexcept = default;
567 EntityLookupKey& operator=(const EntityLookupKey&) = default;
568 EntityLookupKey& operator=(EntityLookupKey&&) noexcept = default;
569
572 Entity entity() const {
573 return m_entity;
574 }
575
578 size_t hash() const {
579 return (size_t)m_hash.hash;
580 }
581
582 bool operator==(const EntityLookupKey& other) const {
583 if GAIA_LIKELY (m_hash != other.m_hash)
584 return false;
585
586 return m_entity == other.m_entity;
587 }
588
589 bool operator!=(const EntityLookupKey& other) const {
590 return !operator==(other);
591 }
592 };
593
594 inline static const EntityLookupKey EntityBadLookupKey = EntityLookupKey(EntityBad);
595
597 struct GAIA_API EntityDesc {
599 const char* name{};
601 uint32_t name_len{};
603 const char* alias{};
605 uint32_t alias_len{};
606 };
607
608 //----------------------------------------------------------------------
609 // Pair
610 //----------------------------------------------------------------------
611
613 template <>
614 class pair<Entity, Entity>: public detail::pair_base {
615 Entity m_first;
616 Entity m_second;
617
618 public:
619 pair(Entity a, Entity b) noexcept: m_first(a), m_second(b) {}
620
621 operator Entity() const noexcept {
622 return Entity(
623 m_first.id(), m_second.id(),
624 // Pairs have no way of telling gen and uni entities apart.
625 // Therefore, for first, we use the entity bit as Gen/Uni...
626 (bool)m_first.kind(),
627 // Always true for pairs
628 true,
629 // ... and for second, we use the kind bit.
630 m_second.kind());
631 }
632
635 Entity first() const noexcept {
636 return m_first;
637 }
638
641 Entity second() const noexcept {
642 return m_second;
643 }
644
645 bool operator==(const pair& other) const {
646 return m_first == other.m_first && m_second == other.m_second;
647 }
648 bool operator!=(const pair& other) const {
649 return !operator==(other);
650 }
651 };
652
653 using Pair = pair<Entity, Entity>;
654
655 //----------------------------------------------------------------------
656 // Core components
657 //----------------------------------------------------------------------
658
660 namespace detail {
661 template <typename T, typename U = void>
662 struct actual_type {
663 using type = typename component_type<T>::type;
664 };
665
666 template <typename T>
667 struct actual_type<T, std::enable_if_t<is_pair<T>::value>> {
668 using storage_type = typename T::type;
669 using type = typename component_type<storage_type>::type;
670 };
671 } // namespace detail
673
674 template <typename T>
675 using actual_type_t = typename detail::actual_type<T>::type;
676
677 //----------------------------------------------------------------------
678 // Core components
679 //----------------------------------------------------------------------
680
681 // Core component. The entity it is attached to is ignored by queries
682 struct GAIA_API Core_ {};
683 // struct EntityDesc;
684 // struct Component;
685 struct GAIA_API OnDelete_ {};
686 struct GAIA_API OnDeleteTarget_ {};
687 struct GAIA_API Remove_ {};
688 struct GAIA_API Delete_ {};
689 struct GAIA_API Error_ {};
694 struct GAIA_API Requires_ {};
695 struct GAIA_API CantCombine_ {};
696 struct GAIA_API Exclusive_ {};
697 struct GAIA_API DontFragment_ {};
698 struct GAIA_API Sparse_ {};
699 struct GAIA_API Acyclic_ {};
700 struct GAIA_API All_ {};
701 struct GAIA_API ChildOf_ {};
702 struct GAIA_API Parent_ {};
703 struct GAIA_API Is_ {};
704 struct GAIA_API Prefab_ {};
705 struct GAIA_API OnInstantiate_ {};
706 struct GAIA_API Override_ {};
707 struct GAIA_API Inherit_ {};
708 struct GAIA_API DontInherit_ {};
709 struct GAIA_API Traversable_ {};
710 struct GAIA_API System_;
711 struct GAIA_API DependsOn_ {};
712 struct GAIA_API Observer_;
713
714 // Query variables
715 struct GAIA_API _Var0 {};
716 struct GAIA_API _Var1 {};
717 struct GAIA_API _Var2 {};
718 struct GAIA_API _Var3 {};
719 struct GAIA_API _Var4 {};
720 struct GAIA_API _Var5 {};
721 struct GAIA_API _Var6 {};
722 struct GAIA_API _Var7 {};
723
724 //----------------------------------------------------------------------
725 // Core component entities
726 //----------------------------------------------------------------------
727
728 // Core component. The entity it is attached to is ignored by queries
729 inline Entity Core = Entity(0, 0, false, false, EntityKind::EK_Gen);
730 inline Entity GAIA_ID(EntityDesc) = Entity(1, 0, false, false, EntityKind::EK_Gen);
731 inline Entity GAIA_ID(Component) = Entity(2, 0, false, false, EntityKind::EK_Gen);
732 // Cleanup rules
733 inline Entity OnDelete = Entity(3, 0, false, false, EntityKind::EK_Gen);
734 inline Entity OnDeleteTarget = Entity(4, 0, false, false, EntityKind::EK_Gen);
735 inline Entity Remove = Entity(5, 0, false, false, EntityKind::EK_Gen);
736 inline Entity Delete = Entity(6, 0, false, false, EntityKind::EK_Gen);
737 inline Entity Error = Entity(7, 0, false, false, EntityKind::EK_Gen);
738 // Entity dependencies
741 inline Entity Requires = Entity(8, 0, false, false, EntityKind::EK_Gen);
742 inline Entity CantCombine = Entity(9, 0, false, false, EntityKind::EK_Gen);
743 inline Entity Exclusive = Entity(10, 0, false, false, EntityKind::EK_Gen);
744 // Entity storage
745 inline Entity DontFragment = Entity(11, 0, false, false, EntityKind::EK_Gen);
746 inline Entity Sparse = Entity(12, 0, false, false, EntityKind::EK_Gen);
747 // Graph properties
748 inline Entity Acyclic = Entity(13, 0, false, false, EntityKind::EK_Gen);
749 inline Entity Traversable = Entity(14, 0, false, false, EntityKind::EK_Gen);
750 // Wildcard query entity
751 inline Entity All = Entity(15, 0, false, false, EntityKind::EK_Gen);
754 inline Entity ChildOf = Entity(16, 0, false, false, EntityKind::EK_Gen);
757 inline Entity Parent = Entity(17, 0, false, false, EntityKind::EK_Gen);
758 // Alias for a base entity/inheritance
759 inline Entity Is = Entity(18, 0, false, false, EntityKind::EK_Gen);
760 // Template entity excluded from queries by default unless explicitly requested.
761 inline Entity Prefab = Entity(19, 0, false, false, EntityKind::EK_Gen);
762 // Prefab instantiation policy relation and values.
763 inline Entity OnInstantiate = Entity(20, 0, false, false, EntityKind::EK_Gen);
764 inline Entity Override = Entity(21, 0, false, false, EntityKind::EK_Gen);
765 inline Entity Inherit = Entity(22, 0, false, false, EntityKind::EK_Gen);
766 inline Entity DontInherit = Entity(23, 0, false, false, EntityKind::EK_Gen);
767 // Systems
768 inline Entity System = Entity(24, 0, false, false, EntityKind::EK_Gen);
769 inline Entity DependsOn = Entity(25, 0, false, false, EntityKind::EK_Gen);
770 // Observers
771 inline Entity Observer = Entity(26, 0, false, false, EntityKind::EK_Gen);
772 // Query variables
773 inline Entity Var0 = Entity(27, 0, false, false, EntityKind::EK_Gen);
774 inline Entity Var1 = Entity(28, 0, false, false, EntityKind::EK_Gen);
775 inline Entity Var2 = Entity(29, 0, false, false, EntityKind::EK_Gen);
776 inline Entity Var3 = Entity(30, 0, false, false, EntityKind::EK_Gen);
777 inline Entity Var4 = Entity(31, 0, false, false, EntityKind::EK_Gen);
778 inline Entity Var5 = Entity(32, 0, false, false, EntityKind::EK_Gen);
779 inline Entity Var6 = Entity(33, 0, false, false, EntityKind::EK_Gen);
780 inline Entity Var7 = Entity(34, 0, false, false, EntityKind::EK_Gen);
781 // Runtime primitive type entities. Supported entity ids are aligned with ser::serialization_type_id:
782 // runtime_primitive_type_entity(t).id() == RuntimePrimitiveTypeBaseId + (uint32_t)t.
783 inline constexpr uint32_t RuntimePrimitiveTypeBaseId = 34;
784
785 GAIA_NODISCARD inline bool is_runtime_primitive_serialization_type_id(uint32_t typeId) noexcept {
786 return typeId >= (uint32_t)ser::serialization_type_id::s8 && typeId <= (uint32_t)ser::serialization_type_id::f64;
787 }
788
789 GAIA_NODISCARD inline Entity runtime_primitive_type_entity(ser::serialization_type_id type) noexcept {
790 const auto typeId = (uint32_t)type;
791 if (!is_runtime_primitive_serialization_type_id(typeId))
792 return EntityBad;
793 return Entity((EntityId)(RuntimePrimitiveTypeBaseId + typeId), 0, false, false, EntityKind::EK_Gen);
794 }
795
796 GAIA_NODISCARD inline bool
797 runtime_primitive_serialization_type(Entity type, ser::serialization_type_id& out) noexcept {
798 if (type.pair())
799 return false;
800
801 const auto typeId = type.id() - RuntimePrimitiveTypeBaseId;
802 if (!is_runtime_primitive_serialization_type_id(typeId))
803 return false;
804
805 out = (ser::serialization_type_id)typeId;
806 return true;
807 }
808
809 inline Entity S8 = runtime_primitive_type_entity(ser::serialization_type_id::s8);
810 inline Entity U8 = runtime_primitive_type_entity(ser::serialization_type_id::u8);
811 inline Entity S16 = runtime_primitive_type_entity(ser::serialization_type_id::s16);
812 inline Entity U16 = runtime_primitive_type_entity(ser::serialization_type_id::u16);
813 inline Entity S32 = runtime_primitive_type_entity(ser::serialization_type_id::s32);
814 inline Entity U32 = runtime_primitive_type_entity(ser::serialization_type_id::u32);
815 inline Entity S64 = runtime_primitive_type_entity(ser::serialization_type_id::s64);
816 inline Entity U64 = runtime_primitive_type_entity(ser::serialization_type_id::u64);
817 inline Entity Bool = runtime_primitive_type_entity(ser::serialization_type_id::b);
818 inline Entity Char8 = runtime_primitive_type_entity(ser::serialization_type_id::c8);
819 inline Entity Char16 = runtime_primitive_type_entity(ser::serialization_type_id::c16);
820 inline Entity Char32 = runtime_primitive_type_entity(ser::serialization_type_id::c32);
821 inline Entity F8 = runtime_primitive_type_entity(ser::serialization_type_id::f8);
822 inline Entity F16 = runtime_primitive_type_entity(ser::serialization_type_id::f16);
823 inline Entity F32 = runtime_primitive_type_entity(ser::serialization_type_id::f32);
824 inline Entity F64 = runtime_primitive_type_entity(ser::serialization_type_id::f64);
825 inline static constexpr uint32_t MaxVarCnt = 8;
826
827 // Core component ids are append-only.
828 // Existing core ids must remain stable; new core components may only be added
829 // after LastCoreComponent.
830 //
831 // Because of that, old snapshots stay loadable without bumping the serializer
832 // version: any serialized entity id greater than the saved last core id is
833 // remapped by the current core-id delta during load.
834 //
835 // Reordering or removing core components is not supported by this compatibility path.
836 // Always has to match the last internal entity.
837 inline Entity GAIA_ID(LastCoreComponent) = F64;
838
839 //----------------------------------------------------------------------
840 // Helper functions
841 //----------------------------------------------------------------------
842
843 GAIA_NODISCARD inline bool is_wildcard(EntityId entityId) {
844 return entityId == All.id();
845 }
846
847 GAIA_NODISCARD inline bool is_wildcard(Entity entity) {
848 return entity.pair() && (is_wildcard(entity.id()) || is_wildcard(entity.gen()));
849 }
850
851 GAIA_NODISCARD inline bool is_wildcard(Pair pair) {
852 return pair.first() == All || pair.second() == All;
853 }
854
855 GAIA_NODISCARD inline bool is_variable(EntityId entityId) {
856 return entityId <= Var7.id() && entityId >= Var0.id();
857 }
858
859 GAIA_NODISCARD inline bool is_variable(Entity entity) {
860 return entity.id() <= Var7.id() && entity.id() >= Var0.id();
861 }
862
863 GAIA_NODISCARD inline bool is_variable(Pair pair) {
864 return is_variable(pair.first()) || is_variable(pair.second());
865 }
866
867 } // namespace ecs
868
869 namespace cnt {
871 template <>
872 struct to_sparse_id<ecs::Entity> {
876 static sparse_id get(const ecs::Entity& item) noexcept {
877 // Cut off the flags
878 return item.id();
879 }
880 };
881 } // namespace cnt
882} // namespace gaia
Array with variable size of elements of type.
Definition darray_impl.h:27
Entity first() const noexcept
First entity of the pair.
Definition id.h:635
Entity second() const noexcept
Second entity of the pair.
Definition id.h:641
Wrapper for two types forming a relationship pair. Depending on what types are used to form a pair it...
Definition id.h:262
typename rel_comp_type::TypeFull rel
Full relation type, either the relation or a uni wrapper.
Definition id.h:268
typename tgt_comp_type::TypeOriginal tgt_original
Original target template type.
Definition id.h:278
typename tgt_comp_type::TypeFull tgt
Full target type, either the target or a uni wrapper.
Definition id.h:270
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:280
typename rel_comp_type::TypeOriginal rel_original
Original relation template type.
Definition id.h:276
typename rel_comp_type::Type rel_type
Raw relation type.
Definition id.h:272
typename tgt_comp_type::Type tgt_type
Raw target type.
Definition id.h:274
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
static sparse_id get(const ecs::Entity &item) noexcept
Returns the entity index as a sparse id.
Definition id.h:876
Converts an item to the sparse identifier used by sparse_storage.
Definition sparse_storage.h:49
T hash
Precomputed hash value.
Definition hashing_policy.h:51
Detects whether T supports a free operator==.
Definition utility.h:776
Detects whether T defines operator== as a member function.
Definition utility.h:768
Definition id.h:699
Definition id.h:700
Definition id.h:695
Definition id.h:701
Bit-packed storage layout of a component id.
Definition id.h:55
IdentifierData soa
Component is SoA.
Definition id.h:65
IdentifierData alig
Component alignment.
Definition id.h:61
IdentifierData size
Component size.
Definition id.h:59
uint32_t id
Component entity index.
Definition id.h:57
IdentifierData storage
Component storage kind. 0 = table, 1 = sparse.
Definition id.h:63
IdentifierData unused
Unused part.
Definition id.h:67
Identifier of a registered component type. Packs the component id, size, alignment,...
Definition id.h:42
GAIA_NODISCARD constexpr auto value() const noexcept
Raw identifier value.
Definition id.h:121
void save(Serializer &s) const
Serializes the component id.
Definition id.h:531
Identifier val
Raw 64-bit value.
Definition id.h:75
void load(Serializer &s)
Deserializes the component id.
Definition id.h:536
GAIA_NODISCARD constexpr auto alig() const noexcept
Component alignment in bytes.
Definition id.h:109
GAIA_NODISCARD constexpr auto id() const noexcept
Component id.
Definition id.h:91
GAIA_NODISCARD constexpr auto size() const noexcept
Component size in bytes.
Definition id.h:103
GAIA_NODISCARD constexpr DataStorageType storage_type() const noexcept
Storage mode of the component.
Definition id.h:115
GAIA_NODISCARD constexpr auto soa() const noexcept
Whether the component uses SoA storage.
Definition id.h:97
InternalData data
Structured view of the packed value.
Definition id.h:73
Definition id.h:682
Definition id.h:688
Definition id.h:711
Definition id.h:697
Definition id.h:708
Component used to describe the entity name.
Definition id.h:597
Hashmap lookup structure used for Entity.
Definition id.h:543
size_t hash() const
Hash of the entity value.
Definition id.h:578
Bit-packed storage layout of an entity identifier.
Definition id.h:301
EntityId id
Index in the entity array.
Definition id.h:303
IdentifierData tmp
0-real entity, 1-temporary entity
Definition id.h:320
IdentifierData kind
0-EntityKind::CT_Gen, 1-EntityKind::CT_Uni
Definition id.h:318
IdentifierData gen
Generation index. Incremented every time an entity is deleted.
Definition id.h:312
IdentifierData pair
0-ordinary, 1-pair
Definition id.h:316
IdentifierData ent
0-component, 1-entity
Definition id.h:314
Identifier of an entity or component instance in the world. Packs the entity index,...
Definition id.h:296
void load(Serializer &s)
Deserializes the entity id, remapping it to the current world.
Definition id.h:525
GAIA_NODISCARD constexpr auto gen() const noexcept
Generation index of the entity.
Definition id.h:365
GAIA_NODISCARD constexpr auto value() const noexcept
Raw identifier value.
Definition id.h:395
GAIA_NODISCARD constexpr bool comp() const noexcept
Whether this id refers to a component.
Definition id.h:383
void save(Serializer &s) const
Serializes the entity id.
Definition id.h:520
InternalData data
Structured view of the packed value.
Definition id.h:328
static constexpr uint32_t IdMask
Bit mask covering all valid entity indices.
Definition id.h:298
GAIA_NODISCARD constexpr bool pair() const noexcept
Whether this id refers to a relationship pair.
Definition id.h:377
GAIA_NODISCARD constexpr auto kind() const noexcept
Entity kind of this id.
Definition id.h:389
Identifier val
Raw 64-bit value.
Definition id.h:330
GAIA_NODISCARD constexpr auto id() const noexcept
Entity index in the entity array.
Definition id.h:359
Entity(EntityId id, IdentifierData gen) noexcept
Special constructor for cnt::ilist.
Definition id.h:342
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:339
GAIA_NODISCARD constexpr bool entity() const noexcept
Whether this id refers to an entity.
Definition id.h:371
Definition id.h:689
Definition id.h:696
Definition id.h:707
Definition id.h:703
Definition observer.h:237
Definition id.h:686
Definition id.h:685
Definition id.h:705
Definition id.h:706
Definition id.h:702
Definition id.h:704
Definition id.h:687
Marks an id as required. Used directly on a non-pair id, it prevents removing that id from its owners...
Definition id.h:694
Definition id.h:698
Definition system.inl:676
Definition id.h:709
Definition id.h:715
Definition id.h:716
Definition id.h:717
Definition id.h:718
Definition id.h:719
Definition id.h:720
Definition id.h:721
Definition id.h:722
Detects whether a type is a relationship pair.
Definition id.h:285
static constexpr bool value
True when the type derives from the pair base.
Definition id.h:287
Wraps a type as a unique entity kind with one value per chunk.
Definition id.h:169
static constexpr EntityKind Kind
Component kind.
Definition id.h:179
T TTypeOriginal
Original template type.
Definition id.h:186
T TType
Raw type with no additional sugar.
Definition id.h:182