2#include "gaia/config/config.h"
8#include "gaia/cnt/darray.h"
9#include "gaia/cnt/map.h"
10#include "gaia/core/hashing_string.h"
11#include "gaia/ecs/component.h"
12#include "gaia/ecs/component_desc.h"
13#include "gaia/ecs/id.h"
14#include "gaia/mem/mem_alloc.h"
15#include "gaia/mem/mem_utils.h"
16#include "gaia/mem/smallblock_allocator.h"
17#include "gaia/ser/ser_common.h"
18#include "gaia/ser/ser_rt.h"
19#include "gaia/util/str.h"
27 struct ComponentRecord;
30 class SymbolTable final {
31 using Key = core::StringLookupKey<256>;
33 cnt::darray<Key> m_values;
34 cnt::map<Key, SymbolId> m_ids;
37 SymbolTable() =
default;
38 SymbolTable(
const SymbolTable&) =
delete;
39 SymbolTable(SymbolTable&&) =
delete;
40 SymbolTable& operator=(
const SymbolTable&) =
delete;
41 SymbolTable& operator=(SymbolTable&&) =
delete;
50 GAIA_NODISCARD SymbolId intern(util::str_view value) {
54 const Key lookup(value.data(), value.size(), 0);
55 const auto it = m_ids.find(lookup);
56 if (it != m_ids.end())
59 auto* data = mem::AllocHelper::alloc<char>(value.size() + 1);
60 memcpy(data, value.data(), value.size());
61 data[value.size()] = 0;
62 const Key owned(data, value.size(), 1);
63 const SymbolId
id{(uint32_t)m_values.size()};
64 m_values.push_back(owned);
65 m_ids.emplace(owned,
id);
72 GAIA_NODISCARD util::str_view view(SymbolId
id)
const noexcept {
73 if (!
id.valid() ||
id.value >= m_values.size())
75 const auto& value = m_values[
id.value];
76 return {value.str(), value.len()};
82 for (
const auto& value: m_values) {
83 if (value.str() !=
nullptr && value.owned())
84 mem::AllocHelper::free((
void*)value.str());
95 struct GAIA_API ComponentCacheItem final {
96 GAIA_USE_SMALLBLOCK(ComponentCacheItem)
97 friend class ComponentCache;
100 static constexpr uint32_t MaxNameLength = 256;
103 using SymbolLookupKey = core::StringLookupKey<512>;
106 using FuncCtor = void(
void*, uint32_t);
108 using FuncDtor = void(
void*, uint32_t);
110 using FuncFrom = void(
void*,
void*, uint32_t, uint32_t, uint32_t, uint32_t);
112 using FuncCopy = void(
void*,
const void*, uint32_t, uint32_t, uint32_t, uint32_t);
114 using FuncMove = void(
void*,
void*, uint32_t, uint32_t, uint32_t, uint32_t);
116 using FuncSwap = void(
void*,
void*, uint32_t, uint32_t, uint32_t, uint32_t);
118 using FuncCmp = bool(
const void*,
const void*);
120 using FuncCreateSparseStore = void(World&, Entity);
123 using FuncSave = void(ser::serializer&,
const void*, uint32_t, uint32_t, uint32_t);
125 using FuncLoad = void(ser::serializer&,
void*, uint32_t, uint32_t, uint32_t);
128 using FuncOnAdd = void(
const World& world,
const ComponentCacheItem&, Entity);
130 using FuncOnDel = void(
const World& world,
const ComponentCacheItem&, Entity);
132 using FuncOnSet = void(
const World& world,
const ComponentRecord&, Chunk& chunk);
139 ComponentLookupHash hashLookup;
141 uint8_t soaSizes[meta::StructToTupleMaxTypes];
146 SymbolId description;
150 FuncCtor* func_ctor{};
152 FuncMove* func_move_ctor{};
154 FuncCopy* func_copy_ctor{};
156 FuncDtor* func_dtor{};
158 FuncCopy* func_copy{};
160 FuncMove* func_move{};
162 FuncSwap* func_swap{};
166 mutable FuncCreateSparseStore* func_create_sparse_store{};
168 FuncSave* func_save{};
170 FuncLoad* func_load{};
172 RuntimeTypeKind typeKind = RuntimeTypeKind::Struct;
174 Entity semantic = EntityBad;
177 RuntimeJsonEncoding jsonEncoding = RuntimeJsonEncoding::Default;
180 Entity underlyingType = EntityBad;
182 Entity elementType = EntityBad;
184 uint32_t elementCount = 0;
186 Entity opaqueAsType = EntityBad;
188 const RuntimeSequenceAdapter* sequenceAdapter =
nullptr;
190 const RuntimeOpaqueAdapter* opaqueAdapter =
nullptr;
195 #if GAIA_ENABLE_ADD_DEL_HOOKS
197 FuncOnAdd* func_add{};
199 FuncOnDel* func_del{};
201 #if GAIA_ENABLE_SET_HOOKS
203 FuncOnSet* func_set{};
213 bool* m_pHooksAccessed =
nullptr;
216 const ComponentCache* m_ownerCache =
nullptr;
218 SymbolTable* m_symbols =
nullptr;
220 SymbolTable* m_ownedSymbols =
nullptr;
222 cnt::darray<RuntimeFieldDesc> m_fields;
224 cnt::darray<RuntimeConstantDesc> m_constants;
233 void move_soa_element(
234 void* pDst,
const void* pSrc, uint32_t idxDst, uint32_t idxSrc, uint32_t capDst,
235 uint32_t capSrc)
const noexcept {
236 const std::span<const uint8_t> fieldSizes{soaSizes, comp.soa()};
237 GAIA_FOR(comp.soa()) {
238 auto* pD = mem::data_view_policy_soa_erased::set(pDst, comp.alig(), fieldSizes, i, idxDst, capDst);
239 const auto* pS = mem::data_view_policy_soa_erased::get(pSrc, comp.alig(), fieldSizes, i, idxSrc, capSrc);
240 memmove(pD, pS, soaSizes[i]);
251 void swap_soa_elements(
252 void* pLeft,
void* pRight, uint32_t idxLeft, uint32_t idxRight, uint32_t capLeft,
253 uint32_t capRight)
const noexcept {
254 const std::span<const uint8_t> fieldSizes{soaSizes, comp.soa()};
255 GAIA_FOR(comp.soa()) {
256 auto* pL = mem::data_view_policy_soa_erased::set(pLeft, comp.alig(), fieldSizes, i, idxLeft, capLeft);
257 auto* pR = mem::data_view_policy_soa_erased::set(pRight, comp.alig(), fieldSizes, i, idxRight, capRight);
258 GAIA_FOR_(soaSizes[i], j) {
259 const auto value = pL[j];
266 ComponentCacheItem() =
default;
267 ~ComponentCacheItem() =
default;
271 ComponentCacheItem(
const ComponentCacheItem&) =
delete;
273 ComponentCacheItem(ComponentCacheItem&&) =
delete;
275 ComponentCacheItem& operator=(
const ComponentCacheItem&) =
delete;
277 ComponentCacheItem& operator=(ComponentCacheItem&&) =
delete;
281 GAIA_NODISCARD util::str_view symbol_name() const noexcept {
282 return m_symbols !=
nullptr ? m_symbols->view(name) : util::str_view{};
293 ctor_move(
void* pDst,
void* pSrc, uint32_t idxDst, uint32_t idxSrc, uint32_t sizeDst, uint32_t sizeSrc)
const {
294 GAIA_ASSERT(pSrc !=
nullptr && pDst !=
nullptr);
295 GAIA_ASSERT(pSrc != pDst || idxSrc != idxDst);
296 if (func_move_ctor !=
nullptr) {
297 func_move_ctor(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
301 if (comp.soa() != 0) {
302 move_soa_element(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
305 if (comp.size() == 0)
308 auto* pD = (uint8_t*)pDst + ((uintptr_t)comp.size() * idxDst);
309 auto* pS = (uint8_t*)pSrc + ((uintptr_t)comp.size() * idxSrc);
310 memmove((
void*)pD, (
const void*)pS, comp.size());
321 void* pDst,
const void* pSrc, uint32_t idxDst, uint32_t idxSrc, uint32_t sizeDst, uint32_t sizeSrc)
const {
322 GAIA_ASSERT(pSrc !=
nullptr && pDst !=
nullptr);
323 GAIA_ASSERT(pSrc != pDst || idxSrc != idxDst);
324 if (func_copy_ctor !=
nullptr) {
325 func_copy_ctor(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
329 if (comp.soa() != 0) {
330 move_soa_element(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
333 if (comp.size() == 0)
336 auto* pD = (uint8_t*)pDst + ((uintptr_t)comp.size() * idxDst);
337 auto* pS = (
const uint8_t*)pSrc + ((uintptr_t)comp.size() * idxSrc);
338 memcpy((
void*)pD, (
const void*)pS, comp.size());
343 void dtor(
void* pSrc)
const {
344 if (func_dtor !=
nullptr)
356 copy(
void* pDst,
const void* pSrc, uint32_t idxDst, uint32_t idxSrc, uint32_t sizeDst, uint32_t sizeSrc)
const {
357 GAIA_ASSERT(pSrc !=
nullptr && pDst !=
nullptr);
358 GAIA_ASSERT(pSrc != pDst || idxSrc != idxDst);
359 if (func_copy !=
nullptr) {
360 func_copy(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
364 if (comp.soa() != 0) {
365 move_soa_element(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
368 if (comp.size() == 0)
371 auto* pD = (uint8_t*)pDst + ((uintptr_t)comp.size() * idxDst);
372 auto* pS = (
const uint8_t*)pSrc + ((uintptr_t)comp.size() * idxSrc);
373 memcpy((
void*)pD, (
const void*)pS, comp.size());
383 void move(
void* pDst,
void* pSrc, uint32_t idxDst, uint32_t idxSrc, uint32_t sizeDst, uint32_t sizeSrc)
const {
384 GAIA_ASSERT(pSrc !=
nullptr && pDst !=
nullptr);
385 GAIA_ASSERT(pSrc != pDst || idxSrc != idxDst);
386 if (func_move !=
nullptr) {
387 func_move(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
391 if (comp.soa() != 0) {
392 move_soa_element(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
395 if (comp.size() == 0)
398 auto* pD = (uint8_t*)pDst + ((uintptr_t)comp.size() * idxDst);
399 auto* pS = (uint8_t*)pSrc + ((uintptr_t)comp.size() * idxSrc);
400 memmove((
void*)pD, (
const void*)pS, comp.size());
411 swap(
void* pLeft,
void* pRight, uint32_t idxLeft, uint32_t idxRight, uint32_t sizeDst, uint32_t sizeSrc)
const {
412 GAIA_ASSERT(pLeft !=
nullptr && pRight !=
nullptr);
413 if (func_swap !=
nullptr) {
414 func_swap(pLeft, pRight, idxLeft, idxRight, sizeDst, sizeSrc);
418 if (comp.soa() != 0) {
419 swap_soa_elements(pLeft, pRight, idxLeft, idxRight, sizeDst, sizeSrc);
422 if (comp.size() == 0)
425 auto* l = (uint8_t*)pLeft + ((uintptr_t)comp.size() * idxLeft);
426 auto* r = (uint8_t*)pRight + ((uintptr_t)comp.size() * idxRight);
427 GAIA_FOR(comp.size()) {
428 const auto tmp = l[i];
438 bool cmp(
const void* pLeft,
const void* pRight)
const {
439 GAIA_ASSERT(pLeft != pRight);
440 if (func_cmp !=
nullptr)
441 return func_cmp(pLeft, pRight);
443 if (comp.soa() != 0 || comp.size() == 0)
446 return memcmp(pLeft, pRight, comp.size()) == 0;
455 void save(ser::serializer& serializer,
const void* pSrc, uint32_t from, uint32_t to, uint32_t cap)
const {
456 GAIA_ASSERT(serializer.valid() && pSrc !=
nullptr && from < to && to <= cap);
457 if (func_save !=
nullptr) {
458 func_save(serializer, pSrc, from, to, cap);
462 if (comp.soa() != 0 || comp.size() == 0)
465 const auto* pBase = (
const uint8_t*)pSrc;
466 GAIA_FOR2(from, to) {
467 const auto* p = pBase + ((uintptr_t)comp.size() * i);
468 serializer.save_raw((
const void*)p, comp.size(), ser::serialization_type_id::trivial_wrapper);
478 void load(ser::serializer& serializer,
void* pDst, uint32_t from, uint32_t to, uint32_t cap)
const {
479 GAIA_ASSERT(serializer.valid() && pDst !=
nullptr && from < to && to <= cap);
480 if (func_load !=
nullptr) {
481 func_load(serializer, pDst, from, to, cap);
485 if (comp.soa() != 0 || comp.size() == 0)
488 auto* pBase = (uint8_t*)pDst;
489 GAIA_FOR2(from, to) {
490 auto* p = pBase + ((uintptr_t)comp.size() * i);
491 serializer.load_raw((
void*)p, comp.size(), ser::serialization_type_id::trivial_wrapper);
496 GAIA_NODISCARD
bool has_fields()
const {
497 return !m_fields.empty();
504 template <
typename StringType>
505 GAIA_NODISCARD
static uint32_t field_element_count(
const RuntimeFieldMeta<StringType>& field)
noexcept {
506 return field.count == 0 ? 1U : field.count;
512 GAIA_NODISCARD
static uint32_t primitive_type_size(Entity type)
noexcept {
513 ser::serialization_type_id
id = ser::serialization_type_id::ignore;
514 if (!runtime_primitive_serialization_type(type,
id))
516 return ser::serialization_type_size(
id, 0);
522 GAIA_NODISCARD
const RuntimeFieldDesc* field(uint32_t index)
const noexcept {
523 return index < m_fields.size() ? &m_fields[index] :
nullptr;
529 GAIA_NODISCARD
const RuntimeFieldDesc* field(util::str_view fieldName)
const noexcept {
530 if (fieldName.empty() || fieldName.size() >= MaxNameLength)
533 for (
const auto& field: m_fields) {
534 if (field_name(field) == fieldName)
543 GAIA_NODISCARD util::str_view field_name(
const RuntimeFieldDesc& field)
const noexcept {
544 return m_symbols !=
nullptr ? m_symbols->view(field.name) : util::str_view{};
550 GAIA_NODISCARD util::str_view field_unit(
const RuntimeFieldDesc& field)
const noexcept {
551 return m_symbols !=
nullptr ? m_symbols->view(field.unit) : util::str_view{};
557 GAIA_NODISCARD util::str_view field_description(
const RuntimeFieldDesc& field)
const noexcept {
558 return m_symbols !=
nullptr ? m_symbols->view(field.description) : util::str_view{};
563 GAIA_NODISCARD util::str_view type_description() const noexcept {
564 return m_symbols !=
nullptr ? m_symbols->view(description) : util::str_view{};
568 GAIA_NODISCARD uint32_t field_count() const noexcept {
569 return (uint32_t)m_fields.size();
573 GAIA_NODISCARD
const ComponentCache* owner_cache() const noexcept {
578 GAIA_NODISCARD Entity primitive_type() const noexcept {
579 if (typeKind == RuntimeTypeKind::Primitive)
581 if (typeKind == RuntimeTypeKind::Enum || typeKind == RuntimeTypeKind::Bitmask)
582 return underlyingType;
587 GAIA_NODISCARD Entity element_type() const noexcept {
588 return typeKind == RuntimeTypeKind::Array || typeKind == RuntimeTypeKind::Vector ? elementType : EntityBad;
592 GAIA_NODISCARD uint32_t element_count() const noexcept {
593 return typeKind == RuntimeTypeKind::Array ? elementCount : 0;
597 GAIA_NODISCARD Entity opaque_as_type() const noexcept {
598 return typeKind == RuntimeTypeKind::Opaque ? opaqueAsType : EntityBad;
602 GAIA_NODISCARD
const RuntimeSequenceAdapter* sequence_adapter() const noexcept {
603 return typeKind == RuntimeTypeKind::Vector ? sequenceAdapter :
nullptr;
607 GAIA_NODISCARD
const RuntimeOpaqueAdapter* opaque_adapter() const noexcept {
608 return typeKind == RuntimeTypeKind::Opaque ? opaqueAdapter :
nullptr;
612 GAIA_NODISCARD
bool has_custom_serializer() const noexcept {
613 return func_save !=
nullptr;
617 GAIA_NODISCARD
bool has_custom_deserializer() const noexcept {
618 return func_load !=
nullptr;
624 GAIA_NODISCARD
const RuntimeConstantDesc* constant(uint32_t index)
const noexcept {
625 return index < m_constants.size() ? &m_constants[index] :
nullptr;
631 GAIA_NODISCARD
const RuntimeConstantDesc* constant(util::str_view constantName)
const noexcept {
632 if (constantName.empty() || constantName.size() >= MaxNameLength)
635 for (
const auto& constant: m_constants) {
636 if (constant_name(constant) == constantName)
645 GAIA_NODISCARD util::str_view constant_name(
const RuntimeConstantDesc& constant)
const noexcept {
646 return m_symbols !=
nullptr ? m_symbols->view(constant.name) : util::str_view{};
652 GAIA_NODISCARD util::str_view constant_description(
const RuntimeConstantDesc& constant)
const noexcept {
653 return m_symbols !=
nullptr ? m_symbols->view(constant.description) : util::str_view{};
659 GAIA_NODISCARD
const RuntimeConstantDesc* constant_by_value(int64_t value)
const noexcept {
660 for (
const auto& constant: m_constants) {
661 if (constant.value == value)
668 GAIA_NODISCARD uint32_t constant_count() const noexcept {
669 return (uint32_t)m_constants.size();
675 if (m_pHooksAccessed !=
nullptr)
676 *m_pHooksAccessed =
true;
681 const Hooks& hooks()
const {
691 GAIA_NODISCARD uint32_t calc_new_mem_offset(uint32_t addr,
size_t cnt)
const noexcept {
692 if (comp.soa() == 0) {
693 addr = (uint32_t)mem::detail::get_aligned_byte_offset(addr, comp.alig(), comp.size(), cnt);
695 GAIA_FOR(comp.soa()) {
696 addr = (uint32_t)mem::detail::get_aligned_byte_offset(addr, comp.alig(), soaSizes[i], cnt);
701 addr += comp.soa() * 12;
711 template <
typename T>
712 GAIA_NODISCARD
static uint32_t init_type_name(
char (&nameTmp)[MaxNameLength]) {
713 auto ct_name = detail::ComponentDesc<T>::name();
722 auto nameTmpLen = (uint32_t)ct_name.size();
723 GAIA_ASSERT(nameTmpLen < MaxNameLength);
724 memcpy((
void*)nameTmp, (
const void*)ct_name.data(), nameTmpLen);
725 nameTmp[ct_name.size()] = 0;
727 auto strip_prefix = [&](
const char* prefix, uint32_t prefixLen) {
728 if (nameTmpLen <= prefixLen || memcmp(nameTmp, prefix, prefixLen) != 0)
731 memmove(nameTmp, nameTmp + prefixLen, nameTmpLen - prefixLen + 1);
732 nameTmpLen -= prefixLen;
735 strip_prefix(
"const ", 6);
737 const uint32_t NSubstrings = 3;
738 const char* to_remove[NSubstrings] = {
"class ",
"struct ",
"enum "};
739 const uint32_t to_remove_len[NSubstrings] = {6, 7, 5};
740 GAIA_FOR(NSubstrings) {
741 strip_prefix(to_remove[i], to_remove_len[i]);
744 while (nameTmpLen > 0) {
745 const auto ch = nameTmp[nameTmpLen - 1];
746 if (ch !=
' ' && ch !=
'&' && ch !=
'*')
749 nameTmp[--nameTmpLen] = 0;
752 if (nameTmpLen > 6 && strncmp(nameTmp + nameTmpLen - 6,
" const", 6) == 0) {
754 nameTmp[nameTmpLen] = 0;
759 GAIA_FOR(NSubstrings) {
760 const auto* str = to_remove[i];
761 const auto len = to_remove_len[i];
764 while ((pos = strstr(pos, str)) !=
nullptr) {
765 const bool isBoundary = pos == nameTmp || pos[-1] ==
'<' || pos[-1] ==
',' || pos[-1] ==
' ';
771 const auto tailMaxLen = (size_t)(MaxNameLength - (uint32_t)(pos + len - nameTmp));
772 memmove(pos, pos + len, GAIA_STRLEN(pos + len, tailMaxLen) + 1);
783 GAIA_NODISCARD
bool copy_runtime_field(
const RuntimeFieldInit& desc) {
784 if (m_symbols ==
nullptr || desc.name.empty() || desc.name.size() >= MaxNameLength ||
785 desc.unit.size() >= RuntimeFieldDesc::MaxUnitLength ||
786 desc.description.size() >= RuntimeDescriptionMaxLength)
789 RuntimeFieldDesc field{};
790 field.name = m_symbols->intern(desc.name);
791 field.type = desc.type;
792 field.offset = desc.offset;
793 field.count = desc.count;
794 field.semantic = desc.semantic;
796 field.jsonEncoding = desc.jsonEncoding;
798 field.flags = desc.flags;
799 field.unit = m_symbols->intern(desc.unit);
800 field.minimum = desc.minimum;
801 field.maximum = desc.maximum;
802 field.step = desc.step;
803 field.description = m_symbols->intern(desc.description);
804 m_fields.push_back(field);
811 GAIA_NODISCARD
bool copy_runtime_constant(
const RuntimeConstantInit& desc) {
812 if (m_symbols ==
nullptr || desc.name.empty() || desc.name.size() >= MaxNameLength ||
813 desc.description.size() >= RuntimeDescriptionMaxLength)
816 RuntimeConstantDesc constant{};
817 constant.name = m_symbols->intern(desc.name);
818 constant.value = desc.value;
819 constant.description = m_symbols->intern(desc.description);
820 m_constants.push_back(constant);
824 template <
typename T>
825 GAIA_NODISCARD
static ComponentCacheItem*
826 create_typed(Entity entity, SymbolTable& symbols,
const RuntimeTypeDesc* pRuntimeType) {
827 static_assert(core::is_raw_v<T>);
829 constexpr auto componentSize = detail::ComponentDesc<T>::size();
831 componentSize < Component::MaxComponentSizeInBytes,
832 "Trying to register a component larger than the maximum allowed component size! In the future this "
833 "restriction won't apply to components not stored inside archetype chunks.");
835 char nameTmp[MaxNameLength];
836 const auto nameTmpLen = init_type_name<T>(nameTmp);
838 uint8_t soaSizes[meta::StructToTupleMaxTypes]{};
839 auto desc = detail::ComponentDesc<T>::make(
840 util::str_view(nameTmp, nameTmpLen), std::span<uint8_t, meta::StructToTupleMaxTypes>{soaSizes});
841 if (pRuntimeType !=
nullptr) {
842 desc.runtimeType = *pRuntimeType;
844#if GAIA_ECS_AUTO_COMPONENT_FIELDS
846 RuntimeFieldInit fields[meta::StructToTupleMaxTypes]{};
847 desc.runtimeType.fields = fields;
848 desc.runtimeType.fieldCount =
849 detail::ComponentDesc<T>::auto_fields(std::span<RuntimeFieldInit, meta::StructToTupleMaxTypes>{fields});
852 return create(entity, symbols, desc);
860 template <
typename T>
861 GAIA_NODISCARD
static ComponentCacheItem* create(Entity entity) {
862 auto* symbols =
new SymbolTable();
863 auto* item = create<T>(entity, *symbols);
864 item->m_ownedSymbols = symbols;
873 template <
typename T>
874 GAIA_NODISCARD
static ComponentCacheItem* create(Entity entity, SymbolTable& symbols) {
875 return create_typed<T>(entity, symbols,
nullptr);
884 template <
typename T>
885 GAIA_NODISCARD
static ComponentCacheItem* create(Entity entity,
const RuntimeTypeDesc& runtimeType) {
886 auto* symbols =
new SymbolTable();
887 auto* item = create<T>(entity, *symbols, runtimeType);
888 item->m_ownedSymbols = symbols;
898 template <
typename T>
899 GAIA_NODISCARD
static ComponentCacheItem*
900 create(Entity entity, SymbolTable& symbols,
const RuntimeTypeDesc& runtimeType) {
901 return create_typed<T>(entity, symbols, &runtimeType);
908 GAIA_NODISCARD
static ComponentCacheItem*
909 create(Entity entity, SymbolTable& symbols,
const ecs::ComponentDesc& desc) {
910 GAIA_ASSERT(!desc.name.empty());
911 GAIA_ASSERT(desc.name.size() < MaxNameLength);
912 GAIA_ASSERT(desc.size < Component::MaxComponentSizeInBytes);
913 GAIA_ASSERT((desc.size == 0 && desc.alig == 0) || (desc.alig > 0 && desc.alig < Component::MaxAlignment));
914 GAIA_ASSERT(desc.alig == 0 || (desc.alig & (desc.alig - 1)) == 0);
915 GAIA_ASSERT(desc.soa <= meta::StructToTupleMaxTypes);
916 GAIA_ASSERT(desc.soa == 0 || desc.pSoaSizes !=
nullptr);
917#if GAIA_ASSERT_ENABLED
919 uint32_t soaSize = 0;
921 GAIA_ASSERT(desc.pSoaSizes[i] != 0);
922 soaSize += desc.pSoaSizes[i];
924 GAIA_ASSERT(soaSize <= desc.size);
928 auto* cci =
new ComponentCacheItem();
929 cci->m_symbols = &symbols;
930 cci->entity = entity;
931 cci->comp = Component(entity.id(), desc.soa, desc.size, desc.alig, desc.storageType);
932 cci->hashLookup = desc.hashLookup.hash != 0
934 : ComponentLookupHash{core::calculate_hash64(desc.name.data(), desc.name.size())};
937 GAIA_FOR(desc.soa) cci->soaSizes[i] = desc.pSoaSizes[i];
940 cci->name = symbols.intern(desc.name);
941 GAIA_ASSERT(cci->name.valid());
943 cci->func_ctor = desc.funcCtor;
944 cci->func_move_ctor = desc.funcMoveCtor;
945 cci->func_copy_ctor = desc.funcCopyCtor;
946 cci->func_dtor = desc.funcDtor;
947 cci->func_copy = desc.funcCopy;
948 cci->func_move = desc.funcMove;
949 cci->func_swap = desc.funcSwap;
950 cci->func_cmp = desc.funcCmp;
951 cci->func_save = desc.funcSave;
952 cci->func_load = desc.funcLoad;
954 const auto& runtimeType = desc.runtimeType;
955 GAIA_ASSERT(runtimeType.description.size() < RuntimeDescriptionMaxLength);
956 if (runtimeType.description.size() < RuntimeDescriptionMaxLength)
957 cci->description = symbols.intern(runtimeType.description);
958 cci->typeKind = runtimeType.typeKind;
959 cci->semantic = runtimeType.semantic;
961 cci->jsonEncoding = runtimeType.jsonEncoding;
963 cci->underlyingType = runtimeType.underlyingType;
964 cci->elementType = runtimeType.elementType;
965 cci->elementCount = runtimeType.elementCount;
966 cci->opaqueAsType = runtimeType.opaqueAsType;
967 cci->sequenceAdapter = runtimeType.sequenceAdapter;
968 cci->opaqueAdapter = runtimeType.opaqueAdapter;
970 if (runtimeType.fieldCount > 0) {
971 GAIA_FOR(runtimeType.fieldCount) {
972 [[maybe_unused]]
const bool copied = cci->copy_runtime_field(runtimeType.fields[i]);
977 if (runtimeType.constantCount > 0) {
978 GAIA_FOR(runtimeType.constantCount) {
979 [[maybe_unused]]
const bool copied = cci->copy_runtime_constant(runtimeType.constants[i]);
992 GAIA_NODISCARD
static ComponentCacheItem* create(Entity entity,
const ecs::ComponentDesc& desc) {
993 auto* symbols =
new SymbolTable();
994 auto* item = create(entity, *symbols, desc);
995 item->m_ownedSymbols = symbols;
1001 static void destroy(ComponentCacheItem* pItem) {
1002 if (pItem ==
nullptr)
1005 auto* ownedSymbols = pItem->m_ownedSymbols;
1007 delete ownedSymbols;
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