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];
148 FuncCtor* func_ctor{};
150 FuncMove* func_move_ctor{};
152 FuncCopy* func_copy_ctor{};
154 FuncDtor* func_dtor{};
156 FuncCopy* func_copy{};
158 FuncMove* func_move{};
160 FuncSwap* func_swap{};
164 mutable FuncCreateSparseStore* func_create_sparse_store{};
166 FuncSave* func_save{};
168 FuncLoad* func_load{};
170 RuntimeTypeKind typeKind = RuntimeTypeKind::Struct;
172 Entity semantic = EntityBad;
175 RuntimeJsonEncoding jsonEncoding = RuntimeJsonEncoding::Default;
178 Entity underlyingType = EntityBad;
180 Entity elementType = EntityBad;
182 uint32_t elementCount = 0;
184 Entity opaqueAsType = EntityBad;
186 const RuntimeSequenceAdapter* sequenceAdapter =
nullptr;
188 const RuntimeOpaqueAdapter* opaqueAdapter =
nullptr;
193 #if GAIA_ENABLE_ADD_DEL_HOOKS
195 FuncOnAdd* func_add{};
197 FuncOnDel* func_del{};
199 #if GAIA_ENABLE_SET_HOOKS
201 FuncOnSet* func_set{};
210 const ComponentCache* m_ownerCache =
nullptr;
212 SymbolTable* m_symbols =
nullptr;
214 SymbolTable* m_ownedSymbols =
nullptr;
216 cnt::darray<RuntimeFieldDesc> m_fields;
218 cnt::darray<RuntimeConstantDesc> m_constants;
223 GAIA_NODISCARD uint32_t soa_capacity(uint32_t capacity)
const noexcept {
224 return entity.kind() == EntityKind::EK_Uni ? 1U : capacity;
234 void move_soa_element(
235 void* pDst,
const void* pSrc, uint32_t idxDst, uint32_t idxSrc, uint32_t capDst,
236 uint32_t capSrc)
const noexcept {
237 capDst = soa_capacity(capDst);
238 capSrc = soa_capacity(capSrc);
239 const std::span<const uint8_t> fieldSizes{soaSizes, comp.soa()};
240 GAIA_FOR(comp.soa()) {
241 auto* pD = mem::data_view_policy_soa_erased::set(pDst, comp.alig(), fieldSizes, i, idxDst, capDst);
242 const auto* pS = mem::data_view_policy_soa_erased::get(pSrc, comp.alig(), fieldSizes, i, idxSrc, capSrc);
243 memmove(pD, pS, soaSizes[i]);
254 void swap_soa_elements(
255 void* pLeft,
void* pRight, uint32_t idxLeft, uint32_t idxRight, uint32_t capLeft,
256 uint32_t capRight)
const noexcept {
257 capLeft = soa_capacity(capLeft);
258 capRight = soa_capacity(capRight);
259 const std::span<const uint8_t> fieldSizes{soaSizes, comp.soa()};
260 GAIA_FOR(comp.soa()) {
261 auto* pL = mem::data_view_policy_soa_erased::set(pLeft, comp.alig(), fieldSizes, i, idxLeft, capLeft);
262 auto* pR = mem::data_view_policy_soa_erased::set(pRight, comp.alig(), fieldSizes, i, idxRight, capRight);
263 GAIA_FOR_(soaSizes[i], j) {
264 const auto value = pL[j];
271 ComponentCacheItem() =
default;
272 ~ComponentCacheItem() =
default;
276 ComponentCacheItem(
const ComponentCacheItem&) =
delete;
278 ComponentCacheItem(ComponentCacheItem&&) =
delete;
280 ComponentCacheItem& operator=(
const ComponentCacheItem&) =
delete;
282 ComponentCacheItem& operator=(ComponentCacheItem&&) =
delete;
286 GAIA_NODISCARD util::str_view symbol_name() const noexcept {
287 return m_symbols !=
nullptr ? m_symbols->view(name) : util::str_view{};
298 ctor_move(
void* pDst,
void* pSrc, uint32_t idxDst, uint32_t idxSrc, uint32_t sizeDst, uint32_t sizeSrc)
const {
299 GAIA_ASSERT(pSrc !=
nullptr && pDst !=
nullptr);
300 GAIA_ASSERT(pSrc != pDst || idxSrc != idxDst);
301 if (func_move_ctor !=
nullptr) {
302 func_move_ctor(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
306 if (comp.soa() != 0) {
307 move_soa_element(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
310 if (comp.size() == 0)
313 auto* pD = (uint8_t*)pDst + ((uintptr_t)comp.size() * idxDst);
314 auto* pS = (uint8_t*)pSrc + ((uintptr_t)comp.size() * idxSrc);
315 memmove((
void*)pD, (
const void*)pS, comp.size());
326 void* pDst,
const void* pSrc, uint32_t idxDst, uint32_t idxSrc, uint32_t sizeDst, uint32_t sizeSrc)
const {
327 GAIA_ASSERT(pSrc !=
nullptr && pDst !=
nullptr);
328 GAIA_ASSERT(pSrc != pDst || idxSrc != idxDst);
329 if (func_copy_ctor !=
nullptr) {
330 func_copy_ctor(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
334 if (comp.soa() != 0) {
335 move_soa_element(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
338 if (comp.size() == 0)
341 auto* pD = (uint8_t*)pDst + ((uintptr_t)comp.size() * idxDst);
342 auto* pS = (
const uint8_t*)pSrc + ((uintptr_t)comp.size() * idxSrc);
343 memcpy((
void*)pD, (
const void*)pS, comp.size());
348 void dtor(
void* pSrc)
const {
349 if (func_dtor !=
nullptr)
361 copy(
void* pDst,
const void* pSrc, uint32_t idxDst, uint32_t idxSrc, uint32_t sizeDst, uint32_t sizeSrc)
const {
362 GAIA_ASSERT(pSrc !=
nullptr && pDst !=
nullptr);
363 GAIA_ASSERT(pSrc != pDst || idxSrc != idxDst);
364 if (func_copy !=
nullptr) {
365 func_copy(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
369 if (comp.soa() != 0) {
370 move_soa_element(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
373 if (comp.size() == 0)
376 auto* pD = (uint8_t*)pDst + ((uintptr_t)comp.size() * idxDst);
377 auto* pS = (
const uint8_t*)pSrc + ((uintptr_t)comp.size() * idxSrc);
378 memcpy((
void*)pD, (
const void*)pS, comp.size());
388 void move(
void* pDst,
void* pSrc, uint32_t idxDst, uint32_t idxSrc, uint32_t sizeDst, uint32_t sizeSrc)
const {
389 GAIA_ASSERT(pSrc !=
nullptr && pDst !=
nullptr);
390 GAIA_ASSERT(pSrc != pDst || idxSrc != idxDst);
391 if (func_move !=
nullptr) {
392 func_move(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
396 if (comp.soa() != 0) {
397 move_soa_element(pDst, pSrc, idxDst, idxSrc, sizeDst, sizeSrc);
400 if (comp.size() == 0)
403 auto* pD = (uint8_t*)pDst + ((uintptr_t)comp.size() * idxDst);
404 auto* pS = (uint8_t*)pSrc + ((uintptr_t)comp.size() * idxSrc);
405 memmove((
void*)pD, (
const void*)pS, comp.size());
416 swap(
void* pLeft,
void* pRight, uint32_t idxLeft, uint32_t idxRight, uint32_t sizeDst, uint32_t sizeSrc)
const {
417 GAIA_ASSERT(pLeft !=
nullptr && pRight !=
nullptr);
418 if (func_swap !=
nullptr) {
419 func_swap(pLeft, pRight, idxLeft, idxRight, sizeDst, sizeSrc);
423 if (comp.soa() != 0) {
424 swap_soa_elements(pLeft, pRight, idxLeft, idxRight, sizeDst, sizeSrc);
427 if (comp.size() == 0)
430 auto* l = (uint8_t*)pLeft + ((uintptr_t)comp.size() * idxLeft);
431 auto* r = (uint8_t*)pRight + ((uintptr_t)comp.size() * idxRight);
432 GAIA_FOR(comp.size()) {
433 const auto tmp = l[i];
443 bool cmp(
const void* pLeft,
const void* pRight)
const {
444 GAIA_ASSERT(pLeft != pRight);
445 if (func_cmp !=
nullptr)
446 return func_cmp(pLeft, pRight);
448 if (comp.soa() != 0 || comp.size() == 0)
451 return memcmp(pLeft, pRight, comp.size()) == 0;
460 void save(ser::serializer& serializer,
const void* pSrc, uint32_t from, uint32_t to, uint32_t cap)
const {
461 GAIA_ASSERT(serializer.valid() && pSrc !=
nullptr && from < to && to <= cap);
462 if (func_save !=
nullptr) {
463 func_save(serializer, pSrc, from, to, cap);
467 if (comp.soa() != 0 || comp.size() == 0)
470 const auto* pBase = (
const uint8_t*)pSrc;
471 GAIA_FOR2(from, to) {
472 const auto* p = pBase + ((uintptr_t)comp.size() * i);
473 serializer.save_raw((
const void*)p, comp.size(), ser::serialization_type_id::trivial_wrapper);
483 void load(ser::serializer& serializer,
void* pDst, uint32_t from, uint32_t to, uint32_t cap)
const {
484 GAIA_ASSERT(serializer.valid() && pDst !=
nullptr && from < to && to <= cap);
485 if (func_load !=
nullptr) {
486 func_load(serializer, pDst, from, to, cap);
490 if (comp.soa() != 0 || comp.size() == 0)
493 auto* pBase = (uint8_t*)pDst;
494 GAIA_FOR2(from, to) {
495 auto* p = pBase + ((uintptr_t)comp.size() * i);
496 serializer.load_raw((
void*)p, comp.size(), ser::serialization_type_id::trivial_wrapper);
501 GAIA_NODISCARD
bool has_fields()
const {
502 return !m_fields.empty();
509 template <
typename StringType>
510 GAIA_NODISCARD
static uint32_t field_element_count(
const RuntimeFieldMeta<StringType>& field)
noexcept {
511 return field.count == 0 ? 1U : field.count;
517 GAIA_NODISCARD
static uint32_t primitive_type_size(Entity type)
noexcept {
518 ser::serialization_type_id
id = ser::serialization_type_id::ignore;
519 if (!runtime_primitive_serialization_type(type,
id))
521 return ser::serialization_type_size(
id, 0);
527 GAIA_NODISCARD
const RuntimeFieldDesc* field(uint32_t index)
const noexcept {
528 return index < m_fields.size() ? &m_fields[index] :
nullptr;
534 GAIA_NODISCARD
const RuntimeFieldDesc* field(util::str_view fieldName)
const noexcept {
535 if (fieldName.empty() || fieldName.size() >= MaxNameLength)
538 for (
const auto& field: m_fields) {
539 if (field_name(field) == fieldName)
548 GAIA_NODISCARD util::str_view field_name(
const RuntimeFieldDesc& field)
const noexcept {
549 return m_symbols !=
nullptr ? m_symbols->view(field.name) : util::str_view{};
555 GAIA_NODISCARD util::str_view field_unit(
const RuntimeFieldDesc& field)
const noexcept {
556 return m_symbols !=
nullptr ? m_symbols->view(field.unit) : util::str_view{};
560 GAIA_NODISCARD uint32_t field_count() const noexcept {
561 return (uint32_t)m_fields.size();
565 GAIA_NODISCARD
const ComponentCache* owner_cache() const noexcept {
570 GAIA_NODISCARD Entity primitive_type() const noexcept {
571 if (typeKind == RuntimeTypeKind::Primitive)
573 if (typeKind == RuntimeTypeKind::Enum || typeKind == RuntimeTypeKind::Bitmask)
574 return underlyingType;
579 GAIA_NODISCARD Entity element_type() const noexcept {
580 return typeKind == RuntimeTypeKind::Array || typeKind == RuntimeTypeKind::Vector ? elementType : EntityBad;
584 GAIA_NODISCARD uint32_t element_count() const noexcept {
585 return typeKind == RuntimeTypeKind::Array ? elementCount : 0;
589 GAIA_NODISCARD Entity opaque_as_type() const noexcept {
590 return typeKind == RuntimeTypeKind::Opaque ? opaqueAsType : EntityBad;
594 GAIA_NODISCARD
const RuntimeSequenceAdapter* sequence_adapter() const noexcept {
595 return typeKind == RuntimeTypeKind::Vector ? sequenceAdapter :
nullptr;
599 GAIA_NODISCARD
const RuntimeOpaqueAdapter* opaque_adapter() const noexcept {
600 return typeKind == RuntimeTypeKind::Opaque ? opaqueAdapter :
nullptr;
604 GAIA_NODISCARD
bool has_custom_serializer() const noexcept {
605 return func_save !=
nullptr;
609 GAIA_NODISCARD
bool has_custom_deserializer() const noexcept {
610 return func_load !=
nullptr;
616 GAIA_NODISCARD
const RuntimeConstantDesc* constant(uint32_t index)
const noexcept {
617 return index < m_constants.size() ? &m_constants[index] :
nullptr;
623 GAIA_NODISCARD
const RuntimeConstantDesc* constant(util::str_view constantName)
const noexcept {
624 if (constantName.empty() || constantName.size() >= MaxNameLength)
627 for (
const auto& constant: m_constants) {
628 if (constant_name(constant) == constantName)
637 GAIA_NODISCARD util::str_view constant_name(
const RuntimeConstantDesc& constant)
const noexcept {
638 return m_symbols !=
nullptr ? m_symbols->view(constant.name) : util::str_view{};
644 GAIA_NODISCARD
const RuntimeConstantDesc* constant_by_value(int64_t value)
const noexcept {
645 for (
const auto& constant: m_constants) {
646 if (constant.value == value)
653 GAIA_NODISCARD uint32_t constant_count() const noexcept {
654 return (uint32_t)m_constants.size();
664 const Hooks& hooks()
const {
674 GAIA_NODISCARD uint32_t calc_new_mem_offset(uint32_t addr,
size_t cnt)
const noexcept {
675 if (comp.soa() == 0) {
676 addr = (uint32_t)mem::detail::get_aligned_byte_offset(addr, comp.alig(), comp.size(), cnt);
678 GAIA_FOR(comp.soa()) {
679 addr = (uint32_t)mem::detail::get_aligned_byte_offset(addr, comp.alig(), soaSizes[i], cnt);
684 addr += comp.soa() * 12;
694 template <
typename T>
695 GAIA_NODISCARD
static uint32_t init_type_name(
char (&nameTmp)[MaxNameLength]) {
696 auto ct_name = detail::ComponentDesc<T>::name();
705 auto nameTmpLen = (uint32_t)ct_name.size();
706 GAIA_ASSERT(nameTmpLen < MaxNameLength);
707 memcpy((
void*)nameTmp, (
const void*)ct_name.data(), nameTmpLen);
708 nameTmp[ct_name.size()] = 0;
710 auto strip_prefix = [&](
const char* prefix, uint32_t prefixLen) {
711 if (nameTmpLen <= prefixLen || strncmp(nameTmp, prefix, prefixLen) != 0)
714 memmove(nameTmp, nameTmp + prefixLen, nameTmpLen - prefixLen + 1);
715 nameTmpLen -= prefixLen;
718 strip_prefix(
"const ", 6);
720 const uint32_t NSubstrings = 3;
721 const char* to_remove[NSubstrings] = {
"class ",
"struct ",
"enum "};
722 const uint32_t to_remove_len[NSubstrings] = {6, 7, 5};
723 GAIA_FOR(NSubstrings) {
724 strip_prefix(to_remove[i], to_remove_len[i]);
727 while (nameTmpLen > 0) {
728 const auto ch = nameTmp[nameTmpLen - 1];
729 if (ch !=
' ' && ch !=
'&' && ch !=
'*')
732 nameTmp[--nameTmpLen] = 0;
735 if (nameTmpLen > 6 && strncmp(nameTmp + nameTmpLen - 6,
" const", 6) == 0) {
737 nameTmp[nameTmpLen] = 0;
742 GAIA_FOR(NSubstrings) {
743 const auto* str = to_remove[i];
744 const auto len = to_remove_len[i];
747 while ((pos = strstr(pos, str)) !=
nullptr) {
748 const bool isBoundary = pos == nameTmp || pos[-1] ==
'<' || pos[-1] ==
',' || pos[-1] ==
' ';
754 const auto tailMaxLen = (size_t)(MaxNameLength - (uint32_t)(pos + len - nameTmp));
755 memmove(pos, pos + len, GAIA_STRLEN(pos + len, tailMaxLen) + 1);
766 GAIA_NODISCARD
bool copy_runtime_field(
const RuntimeFieldInit& desc) {
767 if (m_symbols ==
nullptr || desc.name.empty() || desc.name.size() >= MaxNameLength ||
768 desc.unit.size() >= RuntimeFieldDesc::MaxUnitLength)
771 RuntimeFieldDesc field{};
772 field.name = m_symbols->intern(desc.name);
773 field.type = desc.type;
774 field.offset = desc.offset;
775 field.count = desc.count;
776 field.semantic = desc.semantic;
778 field.jsonEncoding = desc.jsonEncoding;
780 field.flags = desc.flags;
781 field.unit = m_symbols->intern(desc.unit);
782 field.minimum = desc.minimum;
783 field.maximum = desc.maximum;
784 field.step = desc.step;
785 m_fields.push_back(field);
792 GAIA_NODISCARD
bool copy_runtime_constant(
const RuntimeConstantInit& desc) {
793 if (m_symbols ==
nullptr || desc.name.empty() || desc.name.size() >= MaxNameLength)
796 RuntimeConstantDesc constant{};
797 constant.name = m_symbols->intern(desc.name);
798 constant.value = desc.value;
799 m_constants.push_back(constant);
803 template <
typename T>
804 GAIA_NODISCARD
static ComponentCacheItem*
805 create_typed(Entity entity, SymbolTable& symbols,
const RuntimeTypeDesc* pRuntimeType) {
806 static_assert(core::is_raw_v<T>);
808 constexpr auto componentSize = detail::ComponentDesc<T>::size();
810 componentSize < Component::MaxComponentSizeInBytes,
811 "Trying to register a component larger than the maximum allowed component size! In the future this "
812 "restriction won't apply to components not stored inside archetype chunks.");
814 char nameTmp[MaxNameLength];
815 const auto nameTmpLen = init_type_name<T>(nameTmp);
817 uint8_t soaSizes[meta::StructToTupleMaxTypes]{};
818 RuntimeFieldInit fields[meta::StructToTupleMaxTypes]{};
819 auto desc = detail::ComponentDesc<T>::make(
820 util::str_view(nameTmp, nameTmpLen), std::span<uint8_t, meta::StructToTupleMaxTypes>{soaSizes});
821 if (pRuntimeType !=
nullptr) {
822 desc.runtimeType = *pRuntimeType;
824#if GAIA_ECS_AUTO_COMPONENT_FIELDS
826 desc.runtimeType.fields = fields;
827 desc.runtimeType.fieldCount =
828 detail::ComponentDesc<T>::auto_fields(std::span<RuntimeFieldInit, meta::StructToTupleMaxTypes>{fields});
831 return create(entity, symbols, desc);
839 template <
typename T>
840 GAIA_NODISCARD
static ComponentCacheItem* create(Entity entity) {
841 auto* symbols =
new SymbolTable();
842 auto* item = create<T>(entity, *symbols);
843 item->m_ownedSymbols = symbols;
852 template <
typename T>
853 GAIA_NODISCARD
static ComponentCacheItem* create(Entity entity, SymbolTable& symbols) {
854 return create_typed<T>(entity, symbols,
nullptr);
863 template <
typename T>
864 GAIA_NODISCARD
static ComponentCacheItem* create(Entity entity,
const RuntimeTypeDesc& runtimeType) {
865 auto* symbols =
new SymbolTable();
866 auto* item = create<T>(entity, *symbols, runtimeType);
867 item->m_ownedSymbols = symbols;
877 template <
typename T>
878 GAIA_NODISCARD
static ComponentCacheItem*
879 create(Entity entity, SymbolTable& symbols,
const RuntimeTypeDesc& runtimeType) {
880 return create_typed<T>(entity, symbols, &runtimeType);
887 GAIA_NODISCARD
static ComponentCacheItem*
888 create(Entity entity, SymbolTable& symbols,
const ecs::ComponentDesc& desc) {
889 GAIA_ASSERT(!desc.name.empty());
890 GAIA_ASSERT(desc.name.size() < MaxNameLength);
891 GAIA_ASSERT(desc.size < Component::MaxComponentSizeInBytes);
892 GAIA_ASSERT((desc.size == 0 && desc.alig == 0) || (desc.alig > 0 && desc.alig < Component::MaxAlignment));
893 GAIA_ASSERT(desc.alig == 0 || (desc.alig & (desc.alig - 1)) == 0);
894 GAIA_ASSERT(desc.soa <= meta::StructToTupleMaxTypes);
895 GAIA_ASSERT(desc.soa == 0 || desc.pSoaSizes !=
nullptr);
896#if GAIA_ASSERT_ENABLED
898 uint32_t soaSize = 0;
900 GAIA_ASSERT(desc.pSoaSizes[i] != 0);
901 soaSize += desc.pSoaSizes[i];
903 GAIA_ASSERT(soaSize <= desc.size);
907 auto* cci =
new ComponentCacheItem();
908 cci->m_symbols = &symbols;
909 cci->entity = entity;
910 cci->comp = Component(entity.id(), desc.soa, desc.size, desc.alig, desc.storageType);
911 cci->hashLookup = desc.hashLookup.hash != 0
913 : ComponentLookupHash{core::calculate_hash64(desc.name.data(), desc.name.size())};
916 GAIA_FOR(desc.soa) cci->soaSizes[i] = desc.pSoaSizes[i];
919 cci->name = symbols.intern(desc.name);
920 GAIA_ASSERT(cci->name.valid());
922 cci->func_ctor = desc.funcCtor;
923 cci->func_move_ctor = desc.funcMoveCtor;
924 cci->func_copy_ctor = desc.funcCopyCtor;
925 cci->func_dtor = desc.funcDtor;
926 cci->func_copy = desc.funcCopy;
927 cci->func_move = desc.funcMove;
928 cci->func_swap = desc.funcSwap;
929 cci->func_cmp = desc.funcCmp;
930 cci->func_save = desc.funcSave;
931 cci->func_load = desc.funcLoad;
933 const auto& runtimeType = desc.runtimeType;
934 cci->typeKind = runtimeType.typeKind;
935 cci->semantic = runtimeType.semantic;
937 cci->jsonEncoding = runtimeType.jsonEncoding;
939 cci->underlyingType = runtimeType.underlyingType;
940 cci->elementType = runtimeType.elementType;
941 cci->elementCount = runtimeType.elementCount;
942 cci->opaqueAsType = runtimeType.opaqueAsType;
943 cci->sequenceAdapter = runtimeType.sequenceAdapter;
944 cci->opaqueAdapter = runtimeType.opaqueAdapter;
946 if (runtimeType.fieldCount > 0) {
947 GAIA_FOR(runtimeType.fieldCount) {
948 const bool copied = cci->copy_runtime_field(runtimeType.fields[i]);
953 if (runtimeType.constantCount > 0) {
954 GAIA_FOR(runtimeType.constantCount) {
955 const bool copied = cci->copy_runtime_constant(runtimeType.constants[i]);
968 GAIA_NODISCARD
static ComponentCacheItem* create(Entity entity,
const ecs::ComponentDesc& desc) {
969 auto* symbols =
new SymbolTable();
970 auto* item = create(entity, *symbols, desc);
971 item->m_ownedSymbols = symbols;
977 static void destroy(ComponentCacheItem* pItem) {
978 if (pItem ==
nullptr)
981 auto* ownedSymbols = pItem->m_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