2#include "gaia/config/config.h"
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"
15#define GAIA_ID(type) GAIA_ID_##type
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;
22 enum class DataStorageType : uint32_t {
37#define GAIA_STORAGE(storage_name) static constexpr auto gaia_Data_Storage = ::gaia::ecs::DataStorageType::storage_name
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;
62 IdentifierData
size : MaxComponentSize_Bits;
64 IdentifierData
alig : MaxAlignment_Bits;
68 IdentifierData
soa : meta::StructToTupleMaxTypes_Bits;
72 static_assert(
sizeof(
InternalData) ==
sizeof(Identifier));
83 Component(uint32_t
id, uint32_t soa, uint32_t size, uint32_t alig, DataStorageType storage) noexcept {
88 data.storage = (IdentifierData)storage;
94 GAIA_NODISCARD
constexpr auto id() const noexcept {
95 return (uint32_t)data.id;
100 GAIA_NODISCARD
constexpr auto soa() const noexcept {
101 return (uint32_t)data.soa;
106 GAIA_NODISCARD
constexpr auto size() const noexcept {
107 return (uint32_t)data.size;
112 GAIA_NODISCARD
constexpr auto alig() const noexcept {
113 return (uint32_t)data.alig;
118 GAIA_NODISCARD
constexpr DataStorageType
storage_type() const noexcept {
119 return (DataStorageType)data.storage;
124 GAIA_NODISCARD
constexpr auto value() const noexcept {
128 GAIA_NODISCARD
constexpr bool operator==(
Component other)
const noexcept {
129 return value() == other.value();
132 GAIA_NODISCARD
constexpr bool operator!=(Component other)
const noexcept {
133 return value() != other.value();
136 GAIA_NODISCARD
constexpr bool operator<(Component other)
const noexcept {
137 return id() < other.id();
143 template <
typename Serializer>
144 void save(Serializer& s)
const;
149 template <
typename Serializer>
150 void load(Serializer& s);
159 template <
typename T>
160 struct ExtractComponentType {
162 using Type = core::raw_t<T>;
164 using TypeFull = Type;
166 using TypeOriginal = T;
169 template <
typename T>
170 struct component_type {
171 using type = ExtractComponentType<T>;
176 template <
typename T>
177 using component_type_t =
typename detail::component_type<T>::type;
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>;
203 using rel =
typename rel_comp_type::TypeFull;
205 using tgt =
typename tgt_comp_type::TypeFull;
215 using type = std::conditional_t<!std::is_empty_v<rel_type> || std::is_empty_v<tgt_type>,
rel,
tgt>;
219 template <
typename T>
222 static constexpr bool value = std::is_base_of<detail::pair_base, core::raw_t<T>>
::value;
233 static constexpr uint32_t IdMask = IdentifierIdBad;
259 static_assert(
sizeof(
InternalData) ==
sizeof(Identifier));
268 constexpr Entity() noexcept: val(IdentifierBad) {}
273 template <
typename T,
typename = std::enable_if_t<std::is_same_v<T, Identifier>>>
274 constexpr Entity(T value)
noexcept: val(value) {}
277 Entity(EntityId
id, IdentifierData gen)
noexcept {
283 Entity(EntityId
id, IdentifierData gen,
bool isEntity,
bool isPair)
noexcept {
295 GAIA_NODISCARD
constexpr auto id() const noexcept {
296 return (uint32_t)data.id;
301 GAIA_NODISCARD
constexpr auto gen() const noexcept {
302 return (uint32_t)data.gen;
307 GAIA_NODISCARD
constexpr bool entity() const noexcept {
308 return data.ent != 0;
313 GAIA_NODISCARD
constexpr bool pair() const noexcept {
314 return data.pair != 0;
319 GAIA_NODISCARD
constexpr bool comp() const noexcept {
320 return (data.pair | data.ent) == 0;
325 GAIA_NODISCARD
constexpr auto value() const noexcept {
329 GAIA_NODISCARD
constexpr bool operator==(
Entity other)
const noexcept {
330 return value() == other.value();
333 GAIA_NODISCARD
constexpr bool operator!=(Entity other)
const noexcept {
334 return value() != other.value();
337 GAIA_NODISCARD
constexpr bool operator<(Entity other)
const noexcept {
338 return value() < other.value();
340 GAIA_NODISCARD
constexpr bool operator<=(Entity other)
const noexcept {
341 return value() <= other.value();
344 GAIA_NODISCARD
constexpr bool operator>(Entity other)
const noexcept {
345 return value() > other.value();
347 GAIA_NODISCARD
constexpr bool operator>=(Entity other)
const noexcept {
348 return value() >= other.value();
354 template <
typename Serializer>
355 void save(Serializer& s)
const;
360 template <
typename Serializer>
361 void load(Serializer& s);
364 inline static const Entity EntityBad = Entity(IdentifierBad);
374 return lhs.id() < rhs.id();
380 struct EntityLoadRemapState {
381 uint32_t savedLastCoreComponentId = 0;
382 uint32_t currLastCoreComponentId = 0;
383 bool remapComponentIds =
false;
391 inline thread_local EntityLoadRemapState g_entityLoadRemapState{};
393 struct EntityLoadRemapGuard {
394 EntityLoadRemapState prev;
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;
405 ~EntityLoadRemapGuard() {
406 g_entityLoadRemapState = prev;
409 EntityLoadRemapGuard(
const EntityLoadRemapGuard&) =
delete;
410 EntityLoadRemapGuard& operator=(
const EntityLoadRemapGuard&) =
delete;
411 EntityLoadRemapGuard(EntityLoadRemapGuard&&) =
delete;
412 EntityLoadRemapGuard& operator=(EntityLoadRemapGuard&&) =
delete;
415 GAIA_NODISCARD
inline uint32_t remap_loaded_entity_id(
416 uint32_t
id, uint32_t savedLastCoreComponentId, uint32_t currLastCoreComponentId)
noexcept {
418 id <= savedLastCoreComponentId ||
419 currLastCoreComponentId <= savedLastCoreComponentId
423 return id + (currLastCoreComponentId - savedLastCoreComponentId);
426 GAIA_NODISCARD
inline uint32_t remap_loaded_entity_id(uint32_t
id)
noexcept {
427 const auto& state = g_entityLoadRemapState;
431 return remap_loaded_entity_id(
id, state.savedLastCoreComponentId, state.currLastCoreComponentId);
434 GAIA_NODISCARD
inline Entity
435 remap_loaded_entity(Entity entity, uint32_t savedLastCoreComponentId, uint32_t currLastCoreComponentId)
noexcept {
436 if (entity == EntityBad)
439 if (!entity.pair()) {
441 (EntityId)remap_loaded_entity_id(entity.id(), savedLastCoreComponentId, currLastCoreComponentId),
442 entity.gen(), entity.entity(),
false);
446 (EntityId)remap_loaded_entity_id(entity.id(), savedLastCoreComponentId, currLastCoreComponentId),
447 (IdentifierData)remap_loaded_entity_id(entity.gen(), savedLastCoreComponentId, currLastCoreComponentId),
451 GAIA_NODISCARD
inline Entity remap_loaded_entity(Entity entity)
noexcept {
452 const auto& state = g_entityLoadRemapState;
456 return remap_loaded_entity(entity, state.savedLastCoreComponentId, state.currLastCoreComponentId);
461 template <
typename Serializer>
466 template <
typename Serializer>
470 *
this = detail::remap_loaded_entity(*
this);
473 template <
typename Serializer>
478 template <
typename Serializer>
481 if (detail::g_entityLoadRemapState.active && detail::g_entityLoadRemapState.remapComponentIds)
497 return {core::calculate_hash64(entity.
value())};
502 static constexpr bool IsDirectHashKey =
true;
522 return (
size_t)m_hash.
hash;
526 if GAIA_LIKELY (m_hash != other.m_hash)
529 return m_entity == other.m_entity;
533 return !operator==(other);
537 inline static const EntityLookupKey EntityBadLookupKey = EntityLookupKey(EntityBad);
548 uint32_t alias_len{};
566 operator Entity()
const noexcept {
568 m_first.id(), m_second.
id(),
false,
585 bool operator==(
const pair& other)
const {
586 return m_first == other.m_first && m_second == other.m_second;
588 bool operator!=(
const pair& other)
const {
589 return !operator==(other);
593 using Pair = pair<Entity, Entity>;
601 template <
typename T,
typename U =
void>
603 using type =
typename component_type<T>::type;
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;
614 template <
typename T>
615 using actual_type_t =
typename detail::actual_type<T>::type;
674 inline Entity OnDeleteTarget =
Entity(4, 0,
false,
false);
685 inline Entity DontFragment =
Entity(11, 0,
false,
false);
689 inline Entity Traversable =
Entity(14, 0,
false,
false);
703 inline Entity OnInstantiate =
Entity(20, 0,
false,
false);
706 inline Entity DontInherit =
Entity(23, 0,
false,
false);
723 inline constexpr uint32_t RuntimePrimitiveTypeBaseId = 34;
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;
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))
733 return Entity((EntityId)(RuntimePrimitiveTypeBaseId + typeId), 0,
false,
false);
736 GAIA_NODISCARD
inline bool
737 runtime_primitive_serialization_type(Entity type, ser::serialization_type_id& out)
noexcept {
741 const auto typeId = type.id() - RuntimePrimitiveTypeBaseId;
742 if (!is_runtime_primitive_serialization_type_id(typeId))
745 out = (ser::serialization_type_id)typeId;
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;
777 inline Entity GAIA_ID(LastCoreComponent) = F64;
783 GAIA_NODISCARD
inline bool is_wildcard(EntityId entityId) {
784 return entityId == All.
id();
787 GAIA_NODISCARD
inline bool is_wildcard(Entity entity) {
788 return entity.pair() && (is_wildcard(entity.id()) || is_wildcard(entity.gen()));
791 GAIA_NODISCARD
inline bool is_wildcard(Pair pair) {
792 return pair.first() == All || pair.second() == All;
795 GAIA_NODISCARD
inline bool is_variable(EntityId entityId) {
796 return entityId <= Var7.
id() && entityId >= Var0.
id();
799 GAIA_NODISCARD
inline bool is_variable(Entity entity) {
800 return entity.id() <= Var7.
id() && entity.id() >= Var0.
id();
803 GAIA_NODISCARD
inline bool is_variable(Pair pair) {
804 return is_variable(pair.first()) || is_variable(pair.second());
812 enum class EntityIdStorage : uint8_t {
829 GAIA_NODISCARD
constexpr EntityIdStorage operator|(EntityIdStorage lhs, EntityIdStorage rhs) {
830 return (EntityIdStorage)((uint8_t)lhs | (uint8_t)rhs);
837 GAIA_NODISCARD
constexpr bool entity_id_storage_has(EntityIdStorage value, EntityIdStorage bit) {
838 return (((uint8_t)value) & ((uint8_t)bit)) != 0;
842 enum class EntityIdKind : uint8_t {
857 GAIA_NODISCARD
constexpr EntityIdKind operator|(EntityIdKind lhs, EntityIdKind rhs) {
858 return (EntityIdKind)((uint8_t)lhs | (uint8_t)rhs);
865 GAIA_NODISCARD
constexpr bool entity_id_kind_has(EntityIdKind value, EntityIdKind bit) {
866 return (((uint8_t)value) & ((uint8_t)bit)) != 0;
871 enum class QueryMatchKind : uint8_t {
891 storage = select_storage(storage, EntityIdStorage::Archetype);
898 storage = select_storage(storage, EntityIdStorage::DontFragment);
905 storage = select_storage(storage, EntityIdStorage::Relation);
912 kind = select_kind(kind, EntityIdKind::Component);
919 kind = select_kind(kind, EntityIdKind::Pair);
926 matchKind = QueryMatchKind::Direct;
936 matchKind = QueryMatchKind::In;
943 EntityIdStorage storage = EntityIdStorage::All;
944 EntityIdKind kind = EntityIdKind::All;
945 QueryMatchKind matchKind = QueryMatchKind::Direct;
951 GAIA_NODISCARD
static constexpr EntityIdStorage select_storage(EntityIdStorage current, EntityIdStorage bit) {
952 return current == EntityIdStorage::All ? bit : (current | bit);
959 GAIA_NODISCARD
static constexpr EntityIdKind select_kind(EntityIdKind current, EntityIdKind bit) {
960 return current == EntityIdKind::All ? bit : (current | bit);
969 struct to_sparse_id<ecs::Entity> {
973 static sparse_id get(
const ecs::Entity& item)
noexcept {
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
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
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 observer.h:242
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 system.inl:695
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