2#include "gaia/config/config.h"
7#include "gaia/ecs/component_cache.h"
8#include "gaia/ecs/component_cache_item.h"
9#include "gaia/ecs/id.h"
10#include "gaia/util/str.h"
19 void world_finish_write(World& world, Entity term, Entity entity);
23 enum ComponentRawViewFlags : uint32_t {
25 ComponentRawViewFlag_None = 0,
27 ComponentRawViewFlag_Valid = 1U << 0
40 const void*
data =
nullptr;
44 uint32_t
flags = ComponentRawViewFlag_None;
47 GAIA_NODISCARD
bool valid() const noexcept {
48 return (
flags & ComponentRawViewFlag_Valid) != 0;
52 sizeof(ComponentRawView) ==
sizeof(
void*) +
sizeof(uint32_t) * 2,
"ComponentRawView must not contain padding");
53 static_assert(
sizeof(ComponentRawView) <= 16,
"ComponentRawView must stay compact");
70 uint32_t
flags = ComponentRawViewFlag_None;
73 GAIA_NODISCARD
bool valid() const noexcept {
74 return (
flags & ComponentRawViewFlag_Valid) != 0;
78 sizeof(ComponentRawMutView) ==
sizeof(
void*) +
sizeof(uint32_t) * 2,
79 "ComponentRawMutView must not contain padding");
80 static_assert(
sizeof(ComponentRawMutView) <= 16,
"ComponentRawMutView must stay compact");
87 ComponentRawView world_get_raw(
const World& world, Entity entity, Entity component);
93 ComponentRawMutView world_mut_raw(World& world, Entity entity, Entity component);
101 ComponentRawView world_get_raw_field(
const World& world, Entity entity, Entity component, uint32_t fieldIdx);
108 ComponentRawMutView world_mut_raw_field(World& world, Entity entity, Entity component, uint32_t fieldIdx);
111 enum class CursorStatus : uint8_t {
126 template <
typename T>
129 CursorStatus
status = CursorStatus::Invalid;
134 GAIA_NODISCARD
bool ok() const noexcept {
135 return status == CursorStatus::Ok;
139 GAIA_NODISCARD
explicit operator bool() const noexcept {
148 CursorStatus
status = CursorStatus::Invalid;
151 GAIA_NODISCARD
bool ok() const noexcept {
152 return status == CursorStatus::Ok;
156 GAIA_NODISCARD
explicit operator bool() const noexcept {
162 GAIA_NODISCARD
inline bool operator==(CursorResult<void> result, CursorStatus status)
noexcept {
163 return result.status == status;
167 GAIA_NODISCARD
inline bool operator==(CursorStatus status, CursorResult<void> result)
noexcept {
168 return result.status == status;
172 GAIA_NODISCARD
inline bool operator!=(CursorResult<void> result, CursorStatus status)
noexcept {
173 return result.status != status;
177 GAIA_NODISCARD
inline bool operator!=(CursorStatus status, CursorResult<void> result)
noexcept {
178 return result.status != status;
203 cursor.m_components = &components;
204 cursor.m_stack[0].type = component;
206 cursor.m_stack[0].size = view.
size;
207 cursor.m_stack[0].elemSize = view.
size;
208 cursor.m_stack[0].elemCount = 1;
209 cursor.m_valid =
true;
226 cursor.m_world = &world;
227 cursor.m_components = &components;
228 cursor.m_entity = entity;
229 cursor.m_rootType = component;
230 cursor.m_stack[0].type = component;
232 cursor.m_stack[0].mutData = view.
data;
233 cursor.m_stack[0].size = view.
size;
234 cursor.m_stack[0].elemSize = view.
size;
235 cursor.m_stack[0].elemCount = 1;
236 cursor.m_stack[0].writable =
true;
237 cursor.m_valid =
true;
251 cursor.m_readWorld = &world;
252 cursor.m_components = &components;
253 cursor.m_entity = entity;
254 cursor.m_rootType = component;
255 cursor.m_stack[0].type = component;
256 cursor.m_stack[0].size =
size;
257 cursor.m_stack[0].elemSize =
size;
258 cursor.m_stack[0].elemCount = 1;
259 cursor.m_rootSoa =
true;
260 cursor.m_valid =
true;
273 auto cursor =
from_soa((
const World&)world, components, entity, component,
size);
274 cursor.m_world = &world;
275 cursor.m_stack[0].writable =
true;
280 GAIA_NODISCARD
bool valid() const noexcept {
285 GAIA_NODISCARD uint32_t
depth() const noexcept {
291 return m_valid ? m_stack[m_depth].type : EntityBad;
296 GAIA_NODISCARD RuntimeTypeKind
type_kind() const noexcept {
297 const auto* pItem = current_item();
298 return pItem !=
nullptr ? pItem->typeKind : RuntimeTypeKind::None;
304 const auto* pItem = current_item();
305 return pItem !=
nullptr ? pItem->opaque_as_type() : EntityBad;
311 const auto* pItem = current_item();
312 return pItem !=
nullptr ? pItem->element_type() : EntityBad;
317 GAIA_NODISCARD uint32_t
size() const noexcept {
318 return m_valid ? m_stack[m_depth].size : 0;
322 GAIA_NODISCARD
const void*
ptr() const noexcept {
323 return m_valid ? m_stack[m_depth].data :
nullptr;
327 GAIA_NODISCARD
void*
mut_ptr() const noexcept {
328 return m_valid ? m_stack[m_depth].mutData :
nullptr;
333 if (!m_valid || m_stack[m_depth].elemCount != 1)
335 const auto* pItem = current_item();
336 if (pItem ==
nullptr)
338 if (pItem->typeKind == RuntimeTypeKind::Opaque && pItem->opaque_adapter() !=
nullptr) {
339 const auto* pSemantic = opaque_semantic_item(*pItem);
340 return pSemantic !=
nullptr ? pSemantic->field_count() : 0;
342 return pItem->field_count();
350 result.
status = CursorStatus::Invalid;
354 const auto& current = m_stack[m_depth];
355 if (current.elemCount > 1) {
356 result.status = CursorStatus::Ok;
357 result.value = current.elemCount;
361 const auto* pType = current_item();
362 if (pType ==
nullptr) {
363 result.status = CursorStatus::TypeMismatch;
366 if (pType->typeKind == RuntimeTypeKind::Array) {
367 result.status = CursorStatus::Ok;
368 result.value = pType->element_count();
371 if (pType->typeKind == RuntimeTypeKind::Vector) {
372 const auto* adapter = pType->sequence_adapter();
373 if (adapter ==
nullptr || adapter->count ==
nullptr) {
374 result.status = CursorStatus::TypeMismatch;
379 if (!adapter->count(adapter->ctx, sequence, value)) {
380 result.status = CursorStatus::Invalid;
383 result.status = CursorStatus::Ok;
384 result.value = value;
387 result.status = CursorStatus::TypeMismatch;
395 if (!m_valid || m_stack[m_depth].elemCount != 1)
397 const auto* pItem = current_item();
398 if (pItem ==
nullptr)
401 if (pItem->typeKind == RuntimeTypeKind::Opaque)
402 return field_opaque(index);
405 return pField !=
nullptr ? descend(*pField, index) :
false;
412 if (!m_valid || m_stack[m_depth].elemCount != 1)
414 const auto* pItem = current_item();
415 if (pItem ==
nullptr)
418 if (pItem->typeKind == RuntimeTypeKind::Opaque)
419 return field_opaque(name);
422 if (pField ==
nullptr)
426 const auto fieldCount = pItem->field_count();
427 while (index < fieldCount && pItem->
field(index) != pField)
429 return index < fieldCount && descend(*pField, index);
435 bool elem(uint32_t index)
noexcept {
436 if (!m_valid || m_depth + 1 >=
MaxDepth)
439 const auto& current = m_stack[m_depth];
441 if (current.elemCount > 1) {
442 if (index >= current.elemCount || current.elemSize == 0)
444 if ((uint64_t)current.elemSize * ((uint64_t)index + 1) > current.size)
447 next.type = current.type;
448 next.size = current.elemSize;
449 next.elemSize = current.elemSize;
451 next.sequenceAdapter = current.sequenceAdapter;
452 next.sequenceDepth = current.sequenceDepth;
453 next.elementDepth = current.elementDepth;
454 next.elementToken = current.elementToken;
455 next.opaqueAdapter = current.opaqueAdapter;
456 next.opaqueDepth = current.opaqueDepth;
457 next.opaqueValueDepth = current.opaqueValueDepth;
458 next.opaqueToken = current.opaqueToken;
459 next.writable = current.writable;
460 if (current.data !=
nullptr)
461 next.data = (
const uint8_t*)current.data + (uint64_t)current.elemSize * index;
462 if (current.mutData !=
nullptr)
463 next.mutData = (uint8_t*)current.mutData + (uint64_t)current.elemSize * index;
465 const auto* pType = m_components !=
nullptr ? m_components->find(current.type) :
nullptr;
466 if (pType ==
nullptr)
469 if (pType->typeKind == RuntimeTypeKind::Vector) {
470 const auto* adapter = pType->sequence_adapter();
471 if (adapter ==
nullptr || adapter->count ==
nullptr || adapter->element ==
nullptr)
474 uint32_t elemCount = 0;
475 if (!adapter->count(adapter->ctx, sequence, elemCount) || index >= elemCount)
478 element.
type = pType->element_type();
479 if (!adapter->element(adapter->ctx, sequence, index, element))
481 if (element.type == EntityBad)
482 element.type = pType->element_type();
483 if (element.type == EntityBad || element.size == 0 || element.data ==
nullptr)
486 next.type = element.type;
487 next.
data = element.data;
488 next.mutData = element.mutData;
489 next.size = element.size;
490 next.elemSize = element.size;
492 next.sequenceAdapter = adapter;
493 next.sequenceDepth = m_depth;
494 next.elementDepth = m_depth + 1;
495 next.elementToken = element.token;
496 next.writable = current.writable && element.mutData !=
nullptr;
497 }
else if (pType->typeKind == RuntimeTypeKind::Array) {
499 const auto elemCount = pType->element_count();
500 const auto elementType = pType->element_type();
501 const auto* pElementType = m_components->find(elementType);
502 if (pElementType ==
nullptr || elemCount == 0 || index >= elemCount)
505 const auto elemSize = pElementType->comp.size();
508 if ((uint64_t)elemSize * ((uint64_t)index + 1) > current.size)
511 next.type = elementType;
512 next.size = elemSize;
513 next.elemSize = elemSize;
515 next.writable = current.writable;
516 if (current.data !=
nullptr)
517 next.data = (
const uint8_t*)current.data + (uint64_t)elemSize * index;
518 if (current.mutData !=
nullptr)
519 next.mutData = (uint8_t*)current.mutData + (uint64_t)elemSize * index;
525 m_stack[++m_depth] = next;
533 return {CursorStatus::Invalid};
534 const auto* pType = current_item();
535 if (pType ==
nullptr || pType->typeKind != RuntimeTypeKind::Vector)
536 return {CursorStatus::TypeMismatch};
537 const auto* adapter = pType->sequence_adapter();
538 if (adapter ==
nullptr || adapter->resize ==
nullptr)
539 return {CursorStatus::TypeMismatch};
540 if (!m_stack[m_depth].writable || m_world ==
nullptr || m_entity == EntityBad || m_rootType == EntityBad)
541 return {CursorStatus::ReadOnly};
543 m_stack[m_depth].type, m_stack[m_depth].data, m_stack[m_depth].mutData, m_stack[m_depth].size};
544 if (!adapter->resize(adapter->ctx, sequence,
count))
545 return {CursorStatus::OutOfRange};
546 world_finish_write(*m_world, m_rootType, m_entity);
547 return {CursorStatus::Ok};
553 if (!m_valid || m_depth == 0)
562 return read_primitive<bool>(Bool);
569 return write_primitive(Bool, value);
575 return read_primitive<char>(Char8);
582 return write_primitive(Char8, value);
599 const auto status = validate_primitive(Char8,
false,
false);
600 if (status != CursorStatus::Ok) {
601 result.status = status;
604 if (m_stack[m_depth].elemCount <= 1) {
605 result.status = CursorStatus::TypeMismatch;
608 if (dst ==
nullptr) {
609 result.status = CursorStatus::Invalid;
613 result.status = CursorStatus::OutOfRange;
618 result.status = CursorStatus::Ok;
619 result.value =
size();
628 const auto status = validate_primitive(Char8,
true,
false);
629 if (status != CursorStatus::Ok)
631 if (m_stack[m_depth].elemCount <= 1)
632 return {CursorStatus::TypeMismatch};
634 return {CursorStatus::OutOfRange};
635 if (len != 0 && src ==
nullptr)
636 return {CursorStatus::Invalid};
639 if (!commit_current_sequence_element())
640 return {CursorStatus::Invalid};
641 world_finish_write(*m_world, m_rootType, m_entity);
642 return {CursorStatus::Ok};
648 return read_primitive<char16_t>(Char16);
655 return write_primitive(Char16, value);
661 return read_primitive<char32_t>(Char32);
668 return write_primitive(Char32, value);
674 return read_primitive<int8_t>(S8);
680 return write_primitive(S8, value);
686 return read_primitive<uint8_t>(U8);
692 return write_primitive(U8, value);
698 return read_primitive<int16_t>(S16);
704 return write_primitive(S16, value);
710 return read_primitive<uint16_t>(U16);
716 return write_primitive(U16, value);
722 return read_primitive<int32_t>(S32);
728 return write_primitive(S32, value);
734 return read_primitive<uint32_t>(U32);
740 return write_primitive(U32, value);
746 return read_primitive<int64_t>(S64);
752 return write_primitive(S64, value);
758 return read_primitive<uint64_t>(U64);
764 return write_primitive(U64, value);
770 return read_primitive<float>(F32);
776 return write_primitive(F32, value);
782 return read_primitive<double>(F64);
788 return write_primitive(F64, value);
801 result.
status = CursorStatus::Invalid;
804 if (byteCount <
size()) {
805 result.status = CursorStatus::OutOfRange;
808 if (
size() != 0 && (data ==
nullptr ||
ptr() ==
nullptr)) {
809 result.status = CursorStatus::Invalid;
814 result.status = CursorStatus::Ok;
815 result.value =
size();
829 return set_raw(data, byteCount,
true);
837 return {CursorStatus::Invalid};
838 if (!m_stack[m_depth].writable || m_world ==
nullptr || m_entity == EntityBad || m_rootType == EntityBad)
839 return {CursorStatus::ReadOnly};
840 if (byteCount !=
size())
841 return {CursorStatus::OutOfRange};
843 return {CursorStatus::Ok};
844 if (data ==
nullptr ||
mut_ptr() ==
nullptr)
845 return {CursorStatus::Invalid};
847 memcpy(
mut_ptr(), data, byteCount);
849 if (!commit_current_sequence_element())
850 return {CursorStatus::Invalid};
851 world_finish_write(*m_world, m_rootType, m_entity);
853 return {CursorStatus::Ok};
857 Entity type = EntityBad;
858 const void* data =
nullptr;
859 void* mutData =
nullptr;
861 uint32_t elemSize = 0;
862 uint32_t elemCount = 1;
863 const RuntimeSequenceAdapter* sequenceAdapter =
nullptr;
864 uint32_t sequenceDepth = 0;
865 uint32_t elementDepth = 0;
866 void* elementToken =
nullptr;
867 const RuntimeOpaqueAdapter* opaqueAdapter =
nullptr;
868 uint32_t opaqueDepth = 0;
869 uint32_t opaqueValueDepth = 0;
870 void* opaqueToken =
nullptr;
871 bool writable =
false;
874 World* m_world =
nullptr;
876 const World* m_readWorld =
nullptr;
877 const ComponentCache* m_components =
nullptr;
879 Entity m_entity = EntityBad;
880 Entity m_rootType = EntityBad;
882 uint32_t m_depth = 0;
883 bool m_valid =
false;
885 bool m_rootSoa =
false;
887 GAIA_NODISCARD
const ComponentCacheItem* current_item() const noexcept {
888 if (!m_valid || m_components ==
nullptr)
890 const auto type = m_stack[m_depth].type;
891 return type.
pair() ? m_components->find_pair_payload(
type) : m_components->find(
type);
894 GAIA_NODISCARD
const ComponentCacheItem* opaque_semantic_item(
const ComponentCacheItem& item)
const noexcept {
895 if (m_components ==
nullptr || item.typeKind != RuntimeTypeKind::Opaque)
897 return m_components->find(item.opaque_as_type());
900 GAIA_NODISCARD
static RuntimeOpaqueScope make_opaque_scope(
const Scope& scope)
noexcept {
901 return {scope.type, scope.data, scope.mutData, scope.size};
904 GAIA_NODISCARD RuntimeOpaqueValue make_opaque_value(
const Scope& scope)
const noexcept {
905 return {scope.type, scope.data, scope.mutData, scope.size, scope.opaqueToken};
908 bool project_opaque_scope(
const ComponentCacheItem& item, Scope& out)
const noexcept {
909 const auto* adapter = item.opaque_adapter();
910 const auto* pSemantic = opaque_semantic_item(item);
911 if (adapter ==
nullptr || adapter->project ==
nullptr || pSemantic ==
nullptr)
913 RuntimeOpaqueScope opaque = make_opaque_scope(m_stack[m_depth]);
914 RuntimeOpaqueValue value{};
915 value.type = item.opaque_as_type();
916 if (!adapter->project(adapter->ctx, opaque, value))
918 if (value.type == EntityBad)
919 value.type = item.opaque_as_type();
920 if (value.type != item.opaque_as_type() || value.data ==
nullptr || value.size != pSemantic->comp.size())
924 out.type = value.type;
925 out.data = value.data;
926 out.mutData = value.mutData;
927 out.size = value.size;
928 out.elemSize = value.size;
930 out.opaqueAdapter = adapter;
931 out.opaqueDepth = m_depth;
932 out.opaqueValueDepth = m_depth + 1;
933 out.opaqueToken = value.token;
934 out.writable = m_stack[m_depth].writable && value.mutData !=
nullptr;
938 bool field_opaque(uint32_t index)
noexcept {
941 const auto* pItem = current_item();
942 if (pItem ==
nullptr)
945 if (!project_opaque_scope(*pItem, projected))
947 const auto* pSemantic = m_components->find(projected.type);
948 const auto* pField = pSemantic !=
nullptr ? pSemantic->field(index) :
nullptr;
949 if (pField ==
nullptr)
951 m_stack[++m_depth] = projected;
952 if (!descend(*pField)) {
959 bool field_opaque(util::str_view name)
noexcept {
962 const auto* pItem = current_item();
963 if (pItem ==
nullptr)
966 if (!project_opaque_scope(*pItem, projected))
968 const auto* pSemantic = m_components->find(projected.type);
969 const auto* pField = pSemantic !=
nullptr ? pSemantic->field(name) :
nullptr;
970 if (pField ==
nullptr)
972 m_stack[++m_depth] = projected;
973 if (!descend(*pField)) {
980 GAIA_NODISCARD
static RuntimeSequenceScope make_sequence_scope(
const Scope& scope)
noexcept {
981 return {scope.type, scope.data, scope.mutData, scope.size};
984 GAIA_NODISCARD RuntimeSequenceElement make_sequence_element(
const Scope& scope)
const noexcept {
985 return {scope.type, scope.data, scope.mutData, scope.size, scope.elementToken};
988 bool commit_current_sequence_element() noexcept {
989 const auto& current = m_stack[m_depth];
990 if (current.sequenceAdapter !=
nullptr && current.sequenceAdapter->commitElement !=
nullptr) {
993 RuntimeSequenceScope sequence = make_sequence_scope(m_stack[current.sequenceDepth]);
994 RuntimeSequenceElement element = make_sequence_element(m_stack[current.elementDepth]);
995 if (!current.sequenceAdapter->commitElement(current.sequenceAdapter->ctx, sequence, element))
999 if (current.opaqueAdapter !=
nullptr && current.opaqueAdapter->commit !=
nullptr) {
1000 if (current.opaqueDepth >=
MaxDepth || current.opaqueValueDepth >=
MaxDepth)
1002 RuntimeOpaqueScope opaque = make_opaque_scope(m_stack[current.opaqueDepth]);
1003 RuntimeOpaqueValue value = make_opaque_value(m_stack[current.opaqueValueDepth]);
1004 if (!current.opaqueAdapter->commit(current.opaqueAdapter->ctx, opaque, value))
1010 GAIA_NODISCARD CursorStatus
1011 validate_primitive(Entity expectedType,
bool requireWrite,
bool requireScalar)
const noexcept {
1013 return CursorStatus::Invalid;
1014 const auto& current = m_stack[m_depth];
1015 if (current.type != expectedType) {
1016 const auto* pCurrentType = m_components !=
nullptr ? m_components->find(current.type) :
nullptr;
1017 if (pCurrentType ==
nullptr || pCurrentType->primitive_type() != expectedType)
1018 return CursorStatus::TypeMismatch;
1020 if (requireScalar && current.elemCount != 1)
1021 return CursorStatus::TypeMismatch;
1022 if (current.size != current.elemSize * current.elemCount)
1023 return CursorStatus::OutOfRange;
1024 if (current.size == 0)
1025 return CursorStatus::TypeMismatch;
1026 if (
ptr() ==
nullptr)
1027 return CursorStatus::Invalid;
1029 if (!current.writable || m_world ==
nullptr || m_entity == EntityBad || m_rootType == EntityBad)
1030 return CursorStatus::ReadOnly;
1032 return CursorStatus::Invalid;
1034 return CursorStatus::Ok;
1037 template <
typename T>
1038 GAIA_NODISCARD CursorResult<T> read_primitive(Entity expectedType)
const noexcept {
1039 CursorResult<T> result{};
1040 const auto status = validate_primitive(expectedType,
false,
true);
1041 if (status != CursorStatus::Ok) {
1042 result.status = status;
1045 if (
size() !=
sizeof(T)) {
1046 result.status = CursorStatus::TypeMismatch;
1050 memcpy(&result.value,
ptr(),
sizeof(T));
1051 result.status = CursorStatus::Ok;
1055 template <
typename T>
1056 GAIA_NODISCARD CursorResult<void> write_primitive(Entity expectedType,
const T& value)
noexcept {
1057 const auto status = validate_primitive(expectedType,
true,
true);
1058 if (status != CursorStatus::Ok)
1060 if (
size() !=
sizeof(T))
1061 return {CursorStatus::TypeMismatch};
1063 memcpy(
mut_ptr(), &value,
sizeof(T));
1064 if (!commit_current_sequence_element())
1065 return {CursorStatus::Invalid};
1066 world_finish_write(*m_world, m_rootType, m_entity);
1067 return {CursorStatus::Ok};
1070 bool descend(
const RuntimeFieldDesc&
field, uint32_t fieldIdx = UINT32_MAX)
noexcept {
1071 if (!m_valid || m_components ==
nullptr || m_depth + 1 >=
MaxDepth)
1074 const auto* pType = m_components->find(
field.type);
1075 if (pType ==
nullptr)
1078 Entity scopeType =
field.type;
1079 uint32_t elemSize = pType->comp.size();
1080 uint32_t elemCount = ComponentCacheItem::field_element_count(
field);
1081 if (pType->typeKind == RuntimeTypeKind::Array) {
1082 if (
field.count != 0)
1084 const auto elementType = pType->element_type();
1085 const auto* pElementType = m_components->find(elementType);
1086 if (pElementType ==
nullptr || pType->element_count() == 0)
1088 scopeType = elementType;
1089 elemSize = pElementType->comp.size();
1090 elemCount = pType->element_count();
1092 const auto fieldSize64 = (uint64_t)elemSize * (uint64_t)elemCount;
1093 const auto end = (uint64_t)
field.offset + fieldSize64;
1094 if (fieldSize64 > UINT32_MAX || end > m_stack[m_depth].
size)
1098 next.type = scopeType;
1099 next.size = (uint32_t)fieldSize64;
1100 next.elemSize = elemSize;
1101 next.elemCount = elemCount;
1102 next.sequenceAdapter = m_stack[m_depth].sequenceAdapter;
1103 next.sequenceDepth = m_stack[m_depth].sequenceDepth;
1104 next.elementDepth = m_stack[m_depth].elementDepth;
1105 next.elementToken = m_stack[m_depth].elementToken;
1106 next.opaqueAdapter = m_stack[m_depth].opaqueAdapter;
1107 next.opaqueDepth = m_stack[m_depth].opaqueDepth;
1108 next.opaqueValueDepth = m_stack[m_depth].opaqueValueDepth;
1109 next.opaqueToken = m_stack[m_depth].opaqueToken;
1110 next.writable = m_stack[m_depth].writable;
1111 if (m_rootSoa && m_depth == 0) {
1112 if (fieldIdx == UINT32_MAX || m_readWorld ==
nullptr)
1115 if (m_world !=
nullptr) {
1116 const auto view = world_mut_raw_field(*m_world, m_entity, m_rootType, fieldIdx);
1117 if (!view.valid() || view.size != next.size)
1119 next.data = view.data;
1120 next.mutData = view.data;
1122 const auto view = world_get_raw_field(*m_readWorld, m_entity, m_rootType, fieldIdx);
1123 if (!view.valid() || view.size != next.size)
1125 next.data = view.data;
1128 if (m_stack[m_depth].data !=
nullptr)
1129 next.data = (
const uint8_t*)m_stack[m_depth].data +
field.offset;
1130 if (m_stack[m_depth].mutData !=
nullptr)
1131 next.mutData = (uint8_t*)m_stack[m_depth].mutData +
field.offset;
1134 m_stack[++m_depth] = next;
Owns entities, components, archetypes, queries, observers, and systems.
Definition world.h:80
Stack-only cursor over raw component bytes and runtime field metadata.
Definition component_cursor.h:186
static GAIA_NODISCARD ComponentCursor from_soa(World &world, const ComponentCache &components, Entity entity, Entity component, uint32_t size)
Creates a mutable cursor over a non-contiguous SoA component value.
Definition component_cursor.h:272
GAIA_NODISCARD CursorResult< double > f64() const noexcept
Reads the current cursor value as an f64.
Definition component_cursor.h:781
GAIA_NODISCARD RuntimeTypeKind type_kind() const noexcept
Returns the runtime type kind at the current cursor scope.
Definition component_cursor.h:296
GAIA_NODISCARD CursorResult< uint32_t > c8(char *dst, uint32_t cap) const noexcept
Reads the current fixed c8 buffer.
Definition component_cursor.h:597
GAIA_NODISCARD CursorResult< float > f32() const noexcept
Reads the current cursor value as an f32.
Definition component_cursor.h:769
bool field(uint32_t index)
Descends into the reflected field at index.
Definition component_cursor.h:394
GAIA_NODISCARD CursorResult< uint64_t > u64() const noexcept
Reads the current cursor value as a u64.
Definition component_cursor.h:757
GAIA_NODISCARD void * mut_ptr() const noexcept
Definition component_cursor.h:327
GAIA_NODISCARD CursorResult< uint32_t > u32() const noexcept
Reads the current cursor value as a u32.
Definition component_cursor.h:733
GAIA_NODISCARD CursorResult< char16_t > c16() const noexcept
Reads the current cursor value as a scalar c16.
Definition component_cursor.h:647
GAIA_NODISCARD CursorResult< void > f64(double value) noexcept
Writes value to the current cursor value as an f64.
Definition component_cursor.h:787
CursorResult< void > resize(uint32_t count) noexcept
Resizes the current adapted dynamic sequence scope.
Definition component_cursor.h:531
GAIA_NODISCARD CursorResult< void > c8(const char *src, uint32_t len) noexcept
Writes bytes to the current fixed c8 buffer.
Definition component_cursor.h:627
GAIA_NODISCARD CursorResult< int16_t > s16() const noexcept
Reads the current cursor value as an s16.
Definition component_cursor.h:697
GAIA_NODISCARD CursorResult< uint32_t > get_raw(void *data, uint32_t byteCount) const noexcept
Copies exact bytes from the current cursor position.
Definition component_cursor.h:798
static GAIA_NODISCARD ComponentCursor from_raw(const ComponentCache &components, Entity component, ComponentRawView view)
Creates a read-only cursor from a raw component view.
Definition component_cursor.h:198
GAIA_NODISCARD CursorResult< uint8_t > u8() const noexcept
Reads the current cursor value as a u8.
Definition component_cursor.h:685
GAIA_NODISCARD uint32_t field_count() const
Definition component_cursor.h:332
bool parent() noexcept
Moves back to the parent cursor scope.
Definition component_cursor.h:552
GAIA_NODISCARD CursorResult< int8_t > s8() const noexcept
Reads the current cursor value as an s8.
Definition component_cursor.h:673
GAIA_NODISCARD CursorResult< void > c8(char value) noexcept
Writes value to the current cursor value as a scalar c8.
Definition component_cursor.h:581
GAIA_NODISCARD uint32_t size() const noexcept
Returns the current payload or field size in bytes.
Definition component_cursor.h:317
GAIA_NODISCARD CursorResult< void > b(bool value) noexcept
Writes value to the current cursor value as a bool.
Definition component_cursor.h:568
GAIA_NODISCARD CursorResult< void > f32(float value) noexcept
Writes value to the current cursor value as an f32.
Definition component_cursor.h:775
GAIA_NODISCARD CursorResult< void > c32(char32_t value) noexcept
Writes value to the current cursor value as a scalar c32.
Definition component_cursor.h:667
GAIA_NODISCARD CursorResult< bool > b() const noexcept
Reads the current cursor value as a bool.
Definition component_cursor.h:561
GAIA_NODISCARD CursorResult< uint16_t > u16() const noexcept
Reads the current cursor value as a u16.
Definition component_cursor.h:709
GAIA_NODISCARD CursorResult< char > c8() const noexcept
Reads the current cursor value as a scalar c8.
Definition component_cursor.h:574
GAIA_NODISCARD CursorResult< int64_t > s64() const noexcept
Reads the current cursor value as an s64.
Definition component_cursor.h:745
GAIA_NODISCARD uint32_t depth() const noexcept
Definition component_cursor.h:285
GAIA_NODISCARD bool valid() const noexcept
Definition component_cursor.h:280
GAIA_NODISCARD CursorResult< void > u16(uint16_t value) noexcept
Writes value to the current cursor value as a u16.
Definition component_cursor.h:715
GAIA_NODISCARD CursorResult< void > c16(char16_t value) noexcept
Writes value to the current cursor value as a scalar c16.
Definition component_cursor.h:654
GAIA_NODISCARD CursorResult< void > s64(int64_t value) noexcept
Writes value to the current cursor value as an s64.
Definition component_cursor.h:751
GAIA_NODISCARD Entity type() const noexcept
Definition component_cursor.h:290
GAIA_NODISCARD CursorResult< char32_t > c32() const noexcept
Reads the current cursor value as a scalar c32.
Definition component_cursor.h:660
GAIA_NODISCARD CursorResult< void > u32(uint32_t value) noexcept
Writes value to the current cursor value as a u32.
Definition component_cursor.h:739
GAIA_NODISCARD CursorResult< void > u64(uint64_t value) noexcept
Writes value to the current cursor value as a u64.
Definition component_cursor.h:763
static GAIA_NODISCARD ComponentCursor from_soa(const World &world, const ComponentCache &components, Entity entity, Entity component, uint32_t size)
Creates a read-only cursor over a non-contiguous SoA component value.
Definition component_cursor.h:249
GAIA_NODISCARD const void * ptr() const noexcept
Definition component_cursor.h:322
GAIA_NODISCARD CursorResult< uint32_t > count() const noexcept
Returns the element count for the current fixed or adapted sequence scope.
Definition component_cursor.h:347
bool elem(uint32_t index) noexcept
Descends into element index of the current fixed inline or named array scope.
Definition component_cursor.h:435
GAIA_NODISCARD CursorResult< int32_t > s32() const noexcept
Reads the current cursor value as an s32.
Definition component_cursor.h:721
GAIA_NODISCARD Entity element_type() const noexcept
Returns the element type for the current sequence scope, or EntityBad otherwise.
Definition component_cursor.h:310
static constexpr uint32_t MaxDepth
Maximum nested field depth tracked by the cursor.
Definition component_cursor.h:188
static GAIA_NODISCARD ComponentCursor from_raw(World &world, const ComponentCache &components, Entity entity, Entity component, ComponentRawMutView view)
Creates a mutable cursor from a raw component view.
Definition component_cursor.h:220
GAIA_NODISCARD CursorResult< void > s8(int8_t value) noexcept
Writes value to the current cursor value as an s8.
Definition component_cursor.h:679
bool field(util::str_view name)
Descends into the reflected field named name.
Definition component_cursor.h:411
GAIA_NODISCARD CursorResult< void > u8(uint8_t value) noexcept
Writes value to the current cursor value as a u8.
Definition component_cursor.h:691
CursorResult< void > set_raw(const void *data, uint32_t byteCount) noexcept
Writes exact bytes to the current cursor position.
Definition component_cursor.h:828
GAIA_NODISCARD CursorResult< uint32_t > c8(char *dst, uint32_t cap) noexcept
Reads the current fixed c8 buffer.
Definition component_cursor.h:589
GAIA_NODISCARD Entity opaque_as_type() const noexcept
Returns the semantic runtime type exposed by the current opaque scope, or EntityBad otherwise.
Definition component_cursor.h:303
GAIA_NODISCARD CursorResult< void > s16(int16_t value) noexcept
Writes value to the current cursor value as an s16.
Definition component_cursor.h:703
GAIA_NODISCARD CursorResult< void > s32(int32_t value) noexcept
Writes value to the current cursor value as an s32.
Definition component_cursor.h:727
Non-owning mutable view over raw component bytes on an entity.
Definition component_cursor.h:64
void * data
Raw component payload bytes. Null for tags and invalid views.
Definition component_cursor.h:66
uint32_t flags
Bitmask of ComponentRawViewFlags values.
Definition component_cursor.h:70
uint32_t size
Payload size in bytes.
Definition component_cursor.h:68
GAIA_NODISCARD bool valid() const noexcept
Definition component_cursor.h:73
Non-owning read-only view over raw component bytes on an entity.
Definition component_cursor.h:38
uint32_t size
Payload size in bytes.
Definition component_cursor.h:42
uint32_t flags
Bitmask of ComponentRawViewFlags values.
Definition component_cursor.h:44
GAIA_NODISCARD bool valid() const noexcept
Definition component_cursor.h:47
const void * data
Raw component payload bytes. Null for tags and invalid views.
Definition component_cursor.h:40
GAIA_NODISCARD bool ok() const noexcept
Definition component_cursor.h:151
Result of reading or writing through a ComponentCursor.
Definition component_cursor.h:127
GAIA_NODISCARD bool ok() const noexcept
Definition component_cursor.h:134
T value
Value returned by a successful read operation.
Definition component_cursor.h:131
CursorStatus status
Operation status.
Definition component_cursor.h:129
Identifier of an entity or component instance in the world. Packs the entity index,...
Definition id.h:296
InternalData data
Structured view of the packed value.
Definition id.h:328
GAIA_NODISCARD constexpr bool pair() const noexcept
Whether this id refers to a relationship pair.
Definition id.h:377
Runtime sequence element returned by an adapter.
Definition component_desc.h:162
Entity type
Runtime type entity for the selected element value.
Definition component_desc.h:164
Runtime sequence adapter input scope. The byte layout is owned by the adapter.
Definition component_desc.h:150
Entity type
Runtime type entity for the selected sequence value.
Definition component_desc.h:152
Lightweight non-owning string view over a character sequence.
Definition str.h:13