Gaia-ECS v0.9.3
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
28 Count = 2
29 };
30
31 // ------------------------------------------------------------------------------------
32 // Component
33 // ------------------------------------------------------------------------------------
34
35 struct GAIA_API Component final {
36 static constexpr uint32_t IdMask = IdentifierIdBad;
37 static constexpr uint32_t MaxComponentSize_Bits = 13;
38 static constexpr uint32_t MaxComponentSizeInBytes = (1 << MaxComponentSize_Bits) - 1;
39 static constexpr uint32_t MaxAlignment_Bits = MaxComponentSize_Bits;
40 static constexpr uint32_t MaxAlignment = MaxComponentSizeInBytes;
41
42 struct InternalData {
44 uint32_t id;
46 IdentifierData size : MaxComponentSize_Bits;
48 IdentifierData alig : MaxAlignment_Bits;
50 IdentifierData storage : 1;
52 IdentifierData soa : meta::StructToTupleMaxTypes_Bits;
54 IdentifierData unused : 1;
55 };
56 static_assert(sizeof(InternalData) == sizeof(Identifier));
57
58 union {
59 InternalData data;
60 Identifier val;
61 };
62
63 Component() noexcept = default;
64
65 Component(uint32_t id, uint32_t soa, uint32_t size, uint32_t alig, DataStorageType storage) noexcept {
66 data.id = id;
67 data.soa = soa;
68 data.size = size;
69 data.alig = alig;
70 data.storage = (IdentifierData)storage;
71 data.unused = 0;
72 }
73
74 GAIA_NODISCARD constexpr auto id() const noexcept {
75 return (uint32_t)data.id;
76 }
77
78 GAIA_NODISCARD constexpr auto soa() const noexcept {
79 return (uint32_t)data.soa;
80 }
81
82 GAIA_NODISCARD constexpr auto size() const noexcept {
83 return (uint32_t)data.size;
84 }
85
86 GAIA_NODISCARD constexpr auto alig() const noexcept {
87 return (uint32_t)data.alig;
88 }
89
90 GAIA_NODISCARD constexpr DataStorageType storage_type() const noexcept {
91 return (DataStorageType)data.storage;
92 }
93
94 GAIA_NODISCARD constexpr auto value() const noexcept {
95 return val;
96 }
97
98 GAIA_NODISCARD constexpr bool operator==(Component other) const noexcept {
99 return value() == other.value();
100 }
101
102 GAIA_NODISCARD constexpr bool operator!=(Component other) const noexcept {
103 return value() != other.value();
104 }
105
106 GAIA_NODISCARD constexpr bool operator<(Component other) const noexcept {
107 return id() < other.id();
108 }
109
110 template <typename Serializer>
111 void save(Serializer& s) const;
112
113 template <typename Serializer>
114 void load(Serializer& s);
115 };
116
117 //----------------------------------------------------------------------
118 // Entity kind
119 //----------------------------------------------------------------------
120
121 enum EntityKind : uint8_t {
122 // Generic entity, one per entity
123 EK_Gen = 0,
124 // Unique entity, one per chunk
125 EK_Uni
126 };
127
128 inline constexpr const char* EntityKindString[] = {"Gen", "Uni"};
129
130 //----------------------------------------------------------------------
131 // Id type deduction
132 //----------------------------------------------------------------------
133
134 template <typename T>
135 struct uni {
136 static_assert(core::is_raw_v<T>);
137 static_assert(
138 std::is_trivial_v<T> ||
139 // For non-trivial T the comparison operator must be implemented because
140 // defragmentation needs it to figure out if entities can be moved around.
142 "Non-trivial Uni component must implement operator==");
143
145 static constexpr EntityKind Kind = EntityKind::EK_Uni;
146
148 using TType = T;
152 using TTypeOriginal = T;
153 };
154
155 namespace detail {
156 template <typename, typename = void>
157 struct has_entity_kind: std::false_type {};
158 template <typename T>
159 struct has_entity_kind<T, std::void_t<decltype(T::Kind)>>: std::true_type {};
160
161 template <typename T>
164 static constexpr EntityKind Kind = EntityKind::EK_Gen;
165
167 using Type = core::raw_t<T>;
169 using TypeFull = Type;
171 using TypeOriginal = T;
172 };
173
174 template <typename T>
177 static constexpr EntityKind Kind = T::Kind;
178
180 using Type = typename T::TType;
182 using TypeFull = std::conditional_t<Kind == EntityKind::EK_Gen, Type, uni<Type>>;
184 using TypeOriginal = typename T::TTypeOriginal;
185 };
186
187 template <typename, typename = void>
188 struct is_gen_component: std::true_type {};
189 template <typename T>
190 struct is_gen_component<T, std::void_t<decltype(T::Kind)>>: std::bool_constant<T::Kind == EntityKind::EK_Gen> {};
191
192 template <typename T, typename = void>
195 };
196 template <typename T>
197 struct component_type<T, std::void_t<decltype(T::Kind)>> {
199 };
200 } // namespace detail
201
202 template <typename T>
203 using component_type_t = typename detail::component_type<T>::type;
204
205 template <typename T>
206 inline constexpr EntityKind entity_kind_v = component_type_t<T>::Kind;
207
208 //----------------------------------------------------------------------
209 // Pair helpers
210 //----------------------------------------------------------------------
211
212 namespace detail {
213 struct pair_base {};
214 } // namespace detail
215
223 template <typename Rel, typename Tgt>
224 class pair: public detail::pair_base {
225 using rel_comp_type = component_type_t<Rel>;
226 using tgt_comp_type = component_type_t<Tgt>;
227
228 public:
229 using rel = typename rel_comp_type::TypeFull;
230 using tgt = typename tgt_comp_type::TypeFull;
231 using rel_type = typename rel_comp_type::Type;
232 using tgt_type = typename tgt_comp_type::Type;
233 using rel_original = typename rel_comp_type::TypeOriginal;
234 using tgt_original = typename tgt_comp_type::TypeOriginal;
235 using type = std::conditional_t<!std::is_empty_v<rel_type> || std::is_empty_v<tgt_type>, rel, tgt>;
236 };
237
238 template <typename T>
239 struct is_pair {
240 static constexpr bool value = std::is_base_of<detail::pair_base, core::raw_t<T>>::value;
241 };
242
243 // ------------------------------------------------------------------------------------
244 // Entity
245 // ------------------------------------------------------------------------------------
246
247 struct GAIA_API Entity final {
248 static constexpr uint32_t IdMask = IdentifierIdBad;
249
252 EntityId id;
253
255 // Bits in this section need to be 1:1 with EntityContainer data.
256 // Note, the order of these bits is important because entities
257 // are sorted by their "val" member and many behaviors rely on this.
259
261 IdentifierData gen : 28;
263 IdentifierData ent : 1;
265 IdentifierData pair : 1;
267 IdentifierData kind : 1;
269 IdentifierData tmp : 1;
270
272 };
273 static_assert(sizeof(InternalData) == sizeof(Identifier));
274
275 union {
276 InternalData data;
277 Identifier val;
278 };
279
280 constexpr Entity() noexcept: val(IdentifierBad) {};
281
285 template <typename T, typename = std::enable_if_t<std::is_same_v<T, Identifier>>>
286 constexpr Entity(T value) noexcept: val(value) {}
287
289 Entity(EntityId id, IdentifierData gen) noexcept {
290 val = 0;
291 data.id = id;
292 data.gen = gen;
293 }
294
295 Entity(EntityId id, IdentifierData gen, bool isEntity, bool isPair, EntityKind kind) noexcept {
296 data.id = id;
297 data.gen = gen;
298 data.ent = isEntity;
299 data.pair = isPair;
300 data.kind = kind;
301 data.tmp = 0;
302 }
303
304 GAIA_NODISCARD constexpr auto id() const noexcept {
305 return (uint32_t)data.id;
306 }
307
308 GAIA_NODISCARD constexpr auto gen() const noexcept {
309 return (uint32_t)data.gen;
310 }
311
312 GAIA_NODISCARD constexpr bool entity() const noexcept {
313 return data.ent != 0;
314 }
315
316 GAIA_NODISCARD constexpr bool pair() const noexcept {
317 return data.pair != 0;
318 }
319
320 GAIA_NODISCARD constexpr bool comp() const noexcept {
321 return (data.pair | data.ent) == 0;
322 }
323
324 GAIA_NODISCARD constexpr auto kind() const noexcept {
325 return (EntityKind)data.kind;
326 }
327
328 GAIA_NODISCARD constexpr auto value() const noexcept {
329 return val;
330 }
331
332 GAIA_NODISCARD constexpr bool operator==(Entity other) const noexcept {
333 return value() == other.value();
334 }
335
336 GAIA_NODISCARD constexpr bool operator!=(Entity other) const noexcept {
337 return value() != other.value();
338 }
339
340 GAIA_NODISCARD constexpr bool operator<(Entity other) const noexcept {
341 return value() < other.value();
342 }
343 GAIA_NODISCARD constexpr bool operator<=(Entity other) const noexcept {
344 return value() <= other.value();
345 }
346
347 GAIA_NODISCARD constexpr bool operator>(Entity other) const noexcept {
348 return value() > other.value();
349 }
350 GAIA_NODISCARD constexpr bool operator>=(Entity other) const noexcept {
351 return value() >= other.value();
352 }
353
354 template <typename Serializer>
355 void save(Serializer& s) const;
356
357 template <typename Serializer>
358 void load(Serializer& s);
359 };
360
361 inline static const Entity EntityBad = Entity(IdentifierBad);
362
363 namespace detail {
365 uint32_t savedLastCoreComponentId = 0;
366 uint32_t currLastCoreComponentId = 0;
367 bool remapComponentIds = false;
368 bool active = false;
369 };
370
371 // NOTE: Entity::load() only receives a serializer, not World state.
372 // Therefore the load-time core-id remap currently uses scoped ambient context.
373 // thread_local keeps concurrent world loads on different threads independent.
374 // Tradeoff: this is less explicit than carrying the remap state on the serializer.
375 inline thread_local EntityLoadRemapState g_entityLoadRemapState{};
376
379
381 uint32_t savedLastCoreComponentId, uint32_t currLastCoreComponentId, bool remapComponentIds) noexcept:
382 prev(g_entityLoadRemapState) {
383 g_entityLoadRemapState.savedLastCoreComponentId = savedLastCoreComponentId;
384 g_entityLoadRemapState.currLastCoreComponentId = currLastCoreComponentId;
385 g_entityLoadRemapState.remapComponentIds = remapComponentIds;
386 g_entityLoadRemapState.active = true;
387 }
388
390 g_entityLoadRemapState = prev;
391 }
392
394 EntityLoadRemapGuard& operator=(const EntityLoadRemapGuard&) = delete;
396 EntityLoadRemapGuard& operator=(EntityLoadRemapGuard&&) = delete;
397 };
398
399 GAIA_NODISCARD inline uint32_t remap_loaded_entity_id(
400 uint32_t id, uint32_t savedLastCoreComponentId, uint32_t currLastCoreComponentId) noexcept {
401 if (id == Entity::IdMask || //
402 id <= savedLastCoreComponentId || //
403 currLastCoreComponentId <= savedLastCoreComponentId //
404 )
405 return id;
406
407 return id + (currLastCoreComponentId - savedLastCoreComponentId);
408 }
409
410 GAIA_NODISCARD inline uint32_t remap_loaded_entity_id(uint32_t id) noexcept {
411 const auto& state = g_entityLoadRemapState;
412 if (!state.active)
413 return id;
414
415 return remap_loaded_entity_id(id, state.savedLastCoreComponentId, state.currLastCoreComponentId);
416 }
417
418 GAIA_NODISCARD inline Entity
419 remap_loaded_entity(Entity entity, uint32_t savedLastCoreComponentId, uint32_t currLastCoreComponentId) noexcept {
420 if (entity == EntityBad)
421 return entity;
422
423 if (!entity.pair()) {
424 return Entity(
425 (EntityId)remap_loaded_entity_id(entity.id(), savedLastCoreComponentId, currLastCoreComponentId),
426 entity.gen(), entity.entity(), false, entity.kind());
427 }
428
429 return Entity(
430 (EntityId)remap_loaded_entity_id(entity.id(), savedLastCoreComponentId, currLastCoreComponentId),
431 (IdentifierData)remap_loaded_entity_id(entity.gen(), savedLastCoreComponentId, currLastCoreComponentId),
432 entity.entity(), true, entity.kind());
433 }
434
435 GAIA_NODISCARD inline Entity remap_loaded_entity(Entity entity) noexcept {
436 const auto& state = g_entityLoadRemapState;
437 if (!state.active)
438 return entity;
439
440 return remap_loaded_entity(entity, state.savedLastCoreComponentId, state.currLastCoreComponentId);
441 }
442 } // namespace detail
443
444 template <typename Serializer>
445 inline void Entity::save(Serializer& s) const {
446 s.save(val);
447 }
448
449 template <typename Serializer>
450 inline void Entity::load(Serializer& s) {
451 s.load(val);
452 *this = detail::remap_loaded_entity(*this);
453 }
454
455 template <typename Serializer>
456 inline void Component::save(Serializer& s) const {
457 s.save(val);
458 }
459
460 template <typename Serializer>
461 inline void Component::load(Serializer& s) {
462 s.load(val);
463 if (detail::g_entityLoadRemapState.active && detail::g_entityLoadRemapState.remapComponentIds)
464 data.id = detail::remap_loaded_entity_id(data.id);
465 }
466
468 struct GAIA_API EntityLookupKey {
470
471 private:
473 Entity m_entity;
475 LookupHash m_hash;
476
477 static LookupHash calc(Entity entity) {
478 return {core::calculate_hash64(entity.value())};
479 }
480
481 public:
482 static constexpr bool IsDirectHashKey = true;
483
484 EntityLookupKey() = default;
485 explicit EntityLookupKey(Entity entity): m_entity(entity), m_hash(calc(entity)) {}
486 ~EntityLookupKey() = default;
487
488 EntityLookupKey(const EntityLookupKey&) = default;
489 EntityLookupKey(EntityLookupKey&&) noexcept = default;
490 EntityLookupKey& operator=(const EntityLookupKey&) = default;
491 EntityLookupKey& operator=(EntityLookupKey&&) noexcept = default;
492
493 Entity entity() const {
494 return m_entity;
495 }
496
497 size_t hash() const {
498 return (size_t)m_hash.hash;
499 }
500
501 bool operator==(const EntityLookupKey& other) const {
502 if GAIA_LIKELY (m_hash != other.m_hash)
503 return false;
504
505 return m_entity == other.m_entity;
506 }
507
508 bool operator!=(const EntityLookupKey& other) const {
509 return !operator==(other);
510 }
511 };
512
513 inline static const EntityLookupKey EntityBadLookupKey = EntityLookupKey(EntityBad);
514
516 struct GAIA_API EntityDesc {
517 const char* name{};
518 uint32_t name_len{};
519 const char* alias{};
520 uint32_t alias_len{};
521 };
522
523 //----------------------------------------------------------------------
524 // Pair
525 //----------------------------------------------------------------------
526
528 template <>
530 Entity m_first;
531 Entity m_second;
532
533 public:
534 pair(Entity a, Entity b) noexcept: m_first(a), m_second(b) {}
535
536 operator Entity() const noexcept {
537 return Entity(
538 m_first.id(), m_second.id(),
539 // Pairs have no way of telling gen and uni entities apart.
540 // Therefore, for first, we use the entity bit as Gen/Uni...
541 (bool)m_first.kind(),
542 // Always true for pairs
543 true,
544 // ... and for second, we use the kind bit.
545 m_second.kind());
546 }
547
548 Entity first() const noexcept {
549 return m_first;
550 }
551
552 Entity second() const noexcept {
553 return m_second;
554 }
555
556 bool operator==(const pair& other) const {
557 return m_first == other.m_first && m_second == other.m_second;
558 }
559 bool operator!=(const pair& other) const {
560 return !operator==(other);
561 }
562 };
563
565
566 //----------------------------------------------------------------------
567 // Core components
568 //----------------------------------------------------------------------
569
570 namespace detail {
571 template <typename T, typename U = void>
572 struct actual_type {
573 using type = typename component_type<T>::type;
574 };
575
576 template <typename T>
577 struct actual_type<T, std::enable_if_t<is_pair<T>::value>> {
578 using storage_type = typename T::type;
579 using type = typename component_type<storage_type>::type;
580 };
581 } // namespace detail
582
583 template <typename T>
584 using actual_type_t = typename detail::actual_type<T>::type;
585
586 //----------------------------------------------------------------------
587 // Core components
588 //----------------------------------------------------------------------
589
590 // Core component. The entity it is attached to is ignored by queries
591 struct GAIA_API Core_ {};
592 // struct EntityDesc;
593 // struct Component;
594 struct GAIA_API OnDelete_ {};
595 struct GAIA_API OnDeleteTarget_ {};
596 struct GAIA_API Remove_ {};
597 struct GAIA_API Delete_ {};
598 struct GAIA_API Error_ {};
599 struct GAIA_API Requires_ {};
600 struct GAIA_API CantCombine_ {};
601 struct GAIA_API Exclusive_ {};
602 struct GAIA_API DontFragment_ {};
603 struct GAIA_API Sparse_ {};
604 struct GAIA_API Acyclic_ {};
605 struct GAIA_API All_ {};
606 struct GAIA_API ChildOf_ {};
607 struct GAIA_API Parent_ {};
608 struct GAIA_API Is_ {};
609 struct GAIA_API Prefab_ {};
610 struct GAIA_API OnInstantiate_ {};
611 struct GAIA_API Override_ {};
612 struct GAIA_API Inherit_ {};
613 struct GAIA_API DontInherit_ {};
614 struct GAIA_API Traversable_ {};
615 struct GAIA_API System_;
616 struct GAIA_API DependsOn_ {};
617 struct GAIA_API Observer_;
618
619 // Query variables
620 struct GAIA_API _Var0 {};
621 struct GAIA_API _Var1 {};
622 struct GAIA_API _Var2 {};
623 struct GAIA_API _Var3 {};
624 struct GAIA_API _Var4 {};
625 struct GAIA_API _Var5 {};
626 struct GAIA_API _Var6 {};
627 struct GAIA_API _Var7 {};
628
629 //----------------------------------------------------------------------
630 // Core component entities
631 //----------------------------------------------------------------------
632
633 // Core component. The entity it is attached to is ignored by queries
634 inline Entity Core = Entity(0, 0, false, false, EntityKind::EK_Gen);
635 inline Entity GAIA_ID(EntityDesc) = Entity(1, 0, false, false, EntityKind::EK_Gen);
636 inline Entity GAIA_ID(Component) = Entity(2, 0, false, false, EntityKind::EK_Gen);
637 // Cleanup rules
638 inline Entity OnDelete = Entity(3, 0, false, false, EntityKind::EK_Gen);
639 inline Entity OnDeleteTarget = Entity(4, 0, false, false, EntityKind::EK_Gen);
640 inline Entity Remove = Entity(5, 0, false, false, EntityKind::EK_Gen);
641 inline Entity Delete = Entity(6, 0, false, false, EntityKind::EK_Gen);
642 inline Entity Error = Entity(7, 0, false, false, EntityKind::EK_Gen);
643 // Entity dependencies
644 inline Entity Requires = Entity(8, 0, false, false, EntityKind::EK_Gen);
645 inline Entity CantCombine = Entity(9, 0, false, false, EntityKind::EK_Gen);
646 inline Entity Exclusive = Entity(10, 0, false, false, EntityKind::EK_Gen);
647 // Entity storage
648 inline Entity DontFragment = Entity(11, 0, false, false, EntityKind::EK_Gen);
649 inline Entity Sparse = Entity(12, 0, false, false, EntityKind::EK_Gen);
650 // Graph properties
651 inline Entity Acyclic = Entity(13, 0, false, false, EntityKind::EK_Gen);
652 inline Entity Traversable = Entity(14, 0, false, false, EntityKind::EK_Gen);
653 // Wildcard query entity
654 inline Entity All = Entity(15, 0, false, false, EntityKind::EK_Gen);
655 // Entity representing a physical hierarchy.
656 // When the relationship target is deleted all children are deleted as well.
657 inline Entity ChildOf = Entity(16, 0, false, false, EntityKind::EK_Gen);
658 // Entity representing a logical/non-fragmenting hierarchy.
659 inline Entity Parent = Entity(17, 0, false, false, EntityKind::EK_Gen);
660 // Alias for a base entity/inheritance
661 inline Entity Is = Entity(18, 0, false, false, EntityKind::EK_Gen);
662 // Template entity excluded from queries by default unless explicitly requested.
663 inline Entity Prefab = Entity(19, 0, false, false, EntityKind::EK_Gen);
664 // Prefab instantiation policy relation and values.
665 inline Entity OnInstantiate = Entity(20, 0, false, false, EntityKind::EK_Gen);
666 inline Entity Override = Entity(21, 0, false, false, EntityKind::EK_Gen);
667 inline Entity Inherit = Entity(22, 0, false, false, EntityKind::EK_Gen);
668 inline Entity DontInherit = Entity(23, 0, false, false, EntityKind::EK_Gen);
669 // Systems
670 inline Entity System = Entity(24, 0, false, false, EntityKind::EK_Gen);
671 inline Entity DependsOn = Entity(25, 0, false, false, EntityKind::EK_Gen);
672 // Observers
673 inline Entity Observer = Entity(26, 0, false, false, EntityKind::EK_Gen);
674 // Query variables
675 inline Entity Var0 = Entity(27, 0, false, false, EntityKind::EK_Gen);
676 inline Entity Var1 = Entity(28, 0, false, false, EntityKind::EK_Gen);
677 inline Entity Var2 = Entity(29, 0, false, false, EntityKind::EK_Gen);
678 inline Entity Var3 = Entity(30, 0, false, false, EntityKind::EK_Gen);
679 inline Entity Var4 = Entity(31, 0, false, false, EntityKind::EK_Gen);
680 inline Entity Var5 = Entity(32, 0, false, false, EntityKind::EK_Gen);
681 inline Entity Var6 = Entity(33, 0, false, false, EntityKind::EK_Gen);
682 inline Entity Var7 = Entity(34, 0, false, false, EntityKind::EK_Gen);
683 // Runtime primitive type entities. Supported entity ids are aligned with ser::serialization_type_id:
684 // runtime_primitive_type_entity(t).id() == RuntimePrimitiveTypeBaseId + (uint32_t)t.
685 inline constexpr uint32_t RuntimePrimitiveTypeBaseId = 34;
686
687 GAIA_NODISCARD inline bool is_runtime_primitive_serialization_type_id(uint32_t typeId) noexcept {
688 return typeId >= (uint32_t)ser::serialization_type_id::s8 && typeId <= (uint32_t)ser::serialization_type_id::f64;
689 }
690
691 GAIA_NODISCARD inline Entity runtime_primitive_type_entity(ser::serialization_type_id type) noexcept {
692 const auto typeId = (uint32_t)type;
693 if (!is_runtime_primitive_serialization_type_id(typeId))
694 return EntityBad;
695 return Entity((EntityId)(RuntimePrimitiveTypeBaseId + typeId), 0, false, false, EntityKind::EK_Gen);
696 }
697
698 GAIA_NODISCARD inline bool
699 runtime_primitive_serialization_type(Entity type, ser::serialization_type_id& out) noexcept {
700 if (type.pair())
701 return false;
702
703 const auto typeId = type.id() - RuntimePrimitiveTypeBaseId;
704 if (!is_runtime_primitive_serialization_type_id(typeId))
705 return false;
706
707 out = (ser::serialization_type_id)typeId;
708 return true;
709 }
710
711 inline Entity S8 = runtime_primitive_type_entity(ser::serialization_type_id::s8);
712 inline Entity U8 = runtime_primitive_type_entity(ser::serialization_type_id::u8);
713 inline Entity S16 = runtime_primitive_type_entity(ser::serialization_type_id::s16);
714 inline Entity U16 = runtime_primitive_type_entity(ser::serialization_type_id::u16);
715 inline Entity S32 = runtime_primitive_type_entity(ser::serialization_type_id::s32);
716 inline Entity U32 = runtime_primitive_type_entity(ser::serialization_type_id::u32);
717 inline Entity S64 = runtime_primitive_type_entity(ser::serialization_type_id::s64);
718 inline Entity U64 = runtime_primitive_type_entity(ser::serialization_type_id::u64);
719 inline Entity Bool = runtime_primitive_type_entity(ser::serialization_type_id::b);
720 inline Entity Char8 = runtime_primitive_type_entity(ser::serialization_type_id::c8);
721 inline Entity Char16 = runtime_primitive_type_entity(ser::serialization_type_id::c16);
722 inline Entity Char32 = runtime_primitive_type_entity(ser::serialization_type_id::c32);
723 inline Entity WChar = runtime_primitive_type_entity(ser::serialization_type_id::cw);
724 inline Entity F8 = runtime_primitive_type_entity(ser::serialization_type_id::f8);
725 inline Entity F16 = runtime_primitive_type_entity(ser::serialization_type_id::f16);
726 inline Entity F32 = runtime_primitive_type_entity(ser::serialization_type_id::f32);
727 inline Entity F64 = runtime_primitive_type_entity(ser::serialization_type_id::f64);
728 inline static constexpr uint32_t MaxVarCnt = 8;
729
730 // Core component ids are append-only.
731 // Existing core ids must remain stable; new core components may only be added
732 // after LastCoreComponent.
733 //
734 // Because of that, old snapshots stay loadable without bumping the serializer
735 // version: any serialized entity id greater than the saved last core id is
736 // remapped by the current core-id delta during load.
737 //
738 // Reordering or removing core components is not supported by this compatibility path.
739 // Always has to match the last internal entity.
740 inline Entity GAIA_ID(LastCoreComponent) = F64;
741
742 //----------------------------------------------------------------------
743 // Helper functions
744 //----------------------------------------------------------------------
745
746 GAIA_NODISCARD inline bool is_wildcard(EntityId entityId) {
747 return entityId == All.id();
748 }
749
750 GAIA_NODISCARD inline bool is_wildcard(Entity entity) {
751 return entity.pair() && (is_wildcard(entity.id()) || is_wildcard(entity.gen()));
752 }
753
754 GAIA_NODISCARD inline bool is_wildcard(Pair pair) {
755 return pair.first() == All || pair.second() == All;
756 }
757
758 GAIA_NODISCARD inline bool is_variable(EntityId entityId) {
759 return entityId <= Var7.id() && entityId >= Var0.id();
760 }
761
762 GAIA_NODISCARD inline bool is_variable(Entity entity) {
763 return entity.id() <= Var7.id() && entity.id() >= Var0.id();
764 }
765
766 GAIA_NODISCARD inline bool is_variable(Pair pair) {
767 return is_variable(pair.first()) || is_variable(pair.second());
768 }
769
770 } // namespace ecs
771
772 namespace cnt {
773 template <>
774 struct to_sparse_id<ecs::Entity> {
775 static sparse_id get(const ecs::Entity& item) noexcept {
776 // Cut off the flags
777 return item.id();
778 }
779 };
780 } // namespace cnt
781} // namespace gaia
Array with variable size of elements of type.
Definition darray_impl.h:25
Wrapper for two Entities forming a relationship pair.
Definition id.h:529
Wrapper for two types forming a relationship pair. Depending on what types are used to form a pair it...
Definition id.h:224
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Definition sparse_storage.h:31
Detects whether T supports a free operator==.
Definition utility.h:766
Detects whether T defines operator== as a member function.
Definition utility.h:758
Definition id.h:604
Definition id.h:605
Definition id.h:600
Definition id.h:606
IdentifierData soa
Component is SoA.
Definition id.h:52
IdentifierData alig
Component alignment.
Definition id.h:48
IdentifierData size
Component size.
Definition id.h:46
uint32_t id
Component entity index.
Definition id.h:44
IdentifierData storage
Component storage kind. 0 = table, 1 = sparse.
Definition id.h:50
IdentifierData unused
Unused part.
Definition id.h:54
Definition id.h:35
Definition id.h:591
Definition id.h:597
Definition id.h:616
Definition id.h:602
Definition id.h:613
Component used to describe the entity name.
Definition id.h:516
Hashmap lookup structure used for Entity.
Definition id.h:468
EntityId id
Index in the entity array.
Definition id.h:252
IdentifierData tmp
0-real entity, 1-temporary entity
Definition id.h:269
IdentifierData kind
0-EntityKind::CT_Gen, 1-EntityKind::CT_Uni
Definition id.h:267
IdentifierData gen
Generation index. Incremented every time an entity is deleted.
Definition id.h:261
IdentifierData pair
0-ordinary, 1-pair
Definition id.h:265
IdentifierData ent
0-component, 1-entity
Definition id.h:263
Definition id.h:247
Entity(EntityId id, IdentifierData gen) noexcept
Special constructor for cnt::ilist.
Definition id.h:289
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:286
Definition id.h:598
Definition id.h:601
Definition id.h:612
Definition id.h:608
Definition observer.h:237
Definition id.h:595
Definition id.h:594
Definition id.h:610
Definition id.h:611
Definition id.h:607
Definition id.h:609
Definition id.h:596
Definition id.h:599
Definition id.h:603
Definition id.h:614
Definition id.h:620
Definition id.h:621
Definition id.h:622
Definition id.h:623
Definition id.h:624
Definition id.h:625
Definition id.h:626
Definition id.h:627
Type TypeFull
Same as Type.
Definition id.h:169
T TypeOriginal
Original template type.
Definition id.h:171
core::raw_t< T > Type
Raw type with no additional sugar.
Definition id.h:167
static constexpr EntityKind Kind
Component kind.
Definition id.h:164
static constexpr EntityKind Kind
Component kind.
Definition id.h:177
std::conditional_t< Kind==EntityKind::EK_Gen, Type, uni< Type > > TypeFull
T or uni<T> depending on entity kind specified.
Definition id.h:182
typename T::TType Type
Raw type with no additional sugar.
Definition id.h:180
typename T::TTypeOriginal TypeOriginal
Original template type.
Definition id.h:184
Definition id.h:213
Definition id.h:239
Definition id.h:135
static constexpr EntityKind Kind
Component kind.
Definition id.h:145
T TTypeOriginal
Original template type.
Definition id.h:152
T TType
Raw type with no additional sugar.
Definition id.h:148