2#include "gaia/config/config.h"
8#include "gaia/ecs/api.h"
9#include "gaia/ecs/archetype.h"
10#include "gaia/ecs/chunk.h"
11#include "gaia/ecs/command_buffer_fwd.h"
12#include "gaia/ecs/component.h"
13#include "gaia/ecs/component_cache_item.h"
14#include "gaia/ecs/component_cursor.h"
15#include "gaia/ecs/id.h"
16#include "gaia/ecs/observer_event.h"
17#include "gaia/ecs/query_common.h"
18#include "gaia/mem/data_layout_policy.h"
29 const void* (*funcGet)(
const void*,
Entity) =
nullptr;
31 void* (*funcMut)(
void*,
Entity) =
nullptr;
41 void* world_typed_sparse_store_ptr(
World& world,
Entity component);
43 const T& world_typed_sparse_store_get(
const void* pStore,
Entity entity);
45 T& world_typed_sparse_store_mut(
void* pStore,
Entity entity);
47 bool world_typed_sparse_store_has(
const void* pStore,
Entity entity);
49 decltype(
auto) world_query_entity_arg_by_id_cached_const(
53 void world_init_query_entity_arg_by_id_chunk_stable_const(
55 const std::remove_cv_t<std::remove_reference_t<T>>*& pDataInherited);
57 const std::remove_cv_t<std::remove_reference_t<T>>*
59 bool world_term_uses_inherit_policy(
const World& world,
Entity term);
64 enum class Constraints : uint8_t {
78 Entity termId = EntityBad;
79 bool isEntity =
false;
80 bool usesSparseStorage =
false;
81 bool storageKnown =
false;
84 struct ChunkIterTypedOps {
86 static IterTermDesc term_desc(
const ChunkIterImpl& self);
88 static auto view_any(
const ChunkIterImpl& self);
90 static auto view_any(ChunkIterImpl& self, uint32_t termIdx);
92 static auto view(
const ChunkIterImpl& self);
94 static auto view(
const ChunkIterImpl& self, uint32_t termIdx);
96 static auto view_any_mut(ChunkIterImpl& self);
98 static auto view_mut(ChunkIterImpl& self);
100 static auto view_mut(ChunkIterImpl& self, uint32_t termIdx);
101 template <
typename T>
102 static auto view_any_mut(ChunkIterImpl& self, uint32_t termIdx);
103 template <
typename T>
104 static auto sview_any_mut(ChunkIterImpl& self);
105 template <
typename T>
106 static auto sview_mut(ChunkIterImpl& self);
107 template <
typename T>
108 static auto sview_mut(ChunkIterImpl& self, uint32_t termIdx);
109 template <
typename T>
110 static auto sview_any_mut(ChunkIterImpl& self, uint32_t termIdx);
114 const Archetype* pArchetype =
nullptr;
115 Chunk* pChunk =
nullptr;
122 struct RawTermViewGet {
123 const uint8_t* pData =
nullptr;
124 uint32_t elemSize = 0;
126 uint32_t flags = ComponentRawViewFlag_None;
128 GAIA_NODISCARD ComponentRawView operator[](
size_t idx)
const {
129 GAIA_ASSERT(idx < cnt);
130 if ((flags & ComponentRawViewFlag_Valid) == 0 || idx >= cnt)
133 return {
nullptr, 0, ComponentRawViewFlag_Valid};
135 return {pData + (uintptr_t)elemSize * idx, elemSize, ComponentRawViewFlag_Valid};
138 GAIA_NODISCARD
constexpr size_t size() const noexcept {
144 struct RawTermViewSet {
145 uint8_t* pData =
nullptr;
146 uint32_t elemSize = 0;
148 uint32_t flags = ComponentRawViewFlag_None;
150 GAIA_NODISCARD ComponentRawMutView operator[](
size_t idx)
const {
151 GAIA_ASSERT(idx < cnt);
152 if ((flags & ComponentRawViewFlag_Valid) == 0 || idx >= cnt)
155 return {
nullptr, 0, ComponentRawViewFlag_Valid};
157 return {pData + (uintptr_t)elemSize * idx, elemSize, ComponentRawViewFlag_Valid};
160 GAIA_NODISCARD
constexpr size_t size() const noexcept {
167 struct RawTermViewGetEntity {
168 const Entity* pEntities =
nullptr;
169 const World* pWorld =
nullptr;
170 Entity component = EntityBad;
172 RawSparseStoreOps sparse{};
174 GAIA_NODISCARD ComponentRawView operator[](
size_t idx)
const {
175 GAIA_ASSERT(idx < cnt);
176 if (pEntities ==
nullptr || pWorld ==
nullptr || component == EntityBad || idx >= cnt)
179 const auto entity = pEntities[idx];
180 if (sparse.pStore !=
nullptr) {
181 if (sparse.funcHas(sparse.pStore, entity))
182 return {sparse.funcGet(sparse.pStore, entity), sparse.elemSize, ComponentRawViewFlag_Valid};
185 return world_get_raw(*pWorld, entity, component);
188 GAIA_NODISCARD
constexpr size_t size() const noexcept {
195 struct RawTermViewSetEntity {
196 const Entity* pEntities =
nullptr;
197 World* pWorld =
nullptr;
198 Entity component = EntityBad;
200 RawSparseStoreOps sparse{};
202 GAIA_NODISCARD ComponentRawMutView operator[](
size_t idx)
const {
203 GAIA_ASSERT(idx < cnt);
204 if (pEntities ==
nullptr || pWorld ==
nullptr || component == EntityBad || idx >= cnt)
207 const auto entity = pEntities[idx];
208 if (sparse.pStore !=
nullptr)
210 sparse.funcMut(
const_cast<void*
>(sparse.pStore), entity), sparse.elemSize, ComponentRawViewFlag_Valid};
212 return world_mut_raw(*pWorld, entity, component);
215 GAIA_NODISCARD
constexpr size_t size() const noexcept {
222 template <
typename U>
223 struct EntityTermViewGetPointer {
224 const U* pData =
nullptr;
227 GAIA_NODISCARD
decltype(
auto)
operator[](
size_t idx)
const {
228 GAIA_ASSERT(idx < cnt);
232 GAIA_NODISCARD
constexpr size_t size() const noexcept {
236 GAIA_NODISCARD
const U* data() const noexcept {
243 template <
typename U>
244 struct EntityTermViewGetEntity {
245 const Entity* pEntities =
nullptr;
246 World* pWorld =
nullptr;
247 Entity
id = EntityBad;
249 mutable const Archetype* pLastArchetype =
nullptr;
250 mutable Entity cachedOwner = EntityBad;
251 mutable bool cachedDirect =
false;
253 GAIA_NODISCARD
decltype(
auto)
operator[](
size_t idx)
const {
254 GAIA_ASSERT(idx < cnt);
255 return world_query_entity_arg_by_id_cached_const<const U&>(
256 *pWorld, pEntities[idx],
id, pLastArchetype, cachedOwner, cachedDirect);
259 GAIA_NODISCARD
constexpr size_t size() const noexcept {
263 GAIA_NODISCARD
const U* data() const noexcept {
270 template <
typename U>
271 struct EntityTermViewSetPointer {
275 GAIA_NODISCARD
decltype(
auto)
operator[](
size_t idx) {
276 GAIA_ASSERT(idx < cnt);
280 GAIA_NODISCARD
decltype(
auto)
operator[](
size_t idx)
const {
281 GAIA_ASSERT(idx < cnt);
282 return static_cast<const U&
>(pData[idx]);
285 GAIA_NODISCARD
constexpr size_t size() const noexcept {
289 GAIA_NODISCARD U* data() noexcept {
293 GAIA_NODISCARD
const U* data() const noexcept {
300 template <
typename U,
bool WriteIm>
301 struct EntityTermViewSetEntity {
302 const Entity* pEntities =
nullptr;
303 World* pWorld =
nullptr;
304 Entity
id = EntityBad;
307 GAIA_NODISCARD
decltype(
auto)
operator[](
size_t idx) {
308 GAIA_ASSERT(idx < cnt);
309 if constexpr (WriteIm)
310 return world_query_entity_arg_by_id<U&>(*pWorld, pEntities[idx],
id);
312 return world_query_entity_arg_by_id_raw<U&>(*pWorld, pEntities[idx],
id);
315 GAIA_NODISCARD
decltype(
auto)
operator[](
size_t idx)
const {
316 GAIA_ASSERT(idx < cnt);
317 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx],
id);
320 GAIA_NODISCARD
constexpr size_t size() const noexcept {
324 GAIA_NODISCARD U* data() noexcept {
328 GAIA_NODISCARD
const U* data() const noexcept {
334 template <
typename U>
335 struct EntityTermViewGetSparse {
336 const Entity* pEntities =
nullptr;
337 World* pWorld =
nullptr;
338 const void* pStore =
nullptr;
339 Entity
id = EntityBad;
342 GAIA_NODISCARD
decltype(
auto)
operator[](
size_t idx)
const {
343 GAIA_ASSERT(idx < cnt);
344 const auto entity = pEntities[idx];
345 if (world_typed_sparse_store_has<U>(pStore, entity))
346 return world_typed_sparse_store_get<U>(pStore, entity);
347 return world_query_entity_arg_by_id<const U&>(*pWorld, entity,
id);
350 GAIA_NODISCARD
constexpr size_t size() const noexcept {
354 GAIA_NODISCARD
const U* data() const noexcept {
360 template <
typename U>
361 struct EntityTermViewSetSparse {
362 const Entity* pEntities =
nullptr;
363 World* pWorld =
nullptr;
364 void* pStore =
nullptr;
365 Entity
id = EntityBad;
368 GAIA_NODISCARD
decltype(
auto)
operator[](
size_t idx) {
369 GAIA_ASSERT(idx < cnt);
370 const auto entity = pEntities[idx];
371 if (world_typed_sparse_store_has<U>(pStore, entity))
372 return world_typed_sparse_store_mut<U>(pStore, entity);
373 return world_query_entity_arg_by_id_raw<U&>(*pWorld, entity,
id);
376 GAIA_NODISCARD
decltype(
auto)
operator[](
size_t idx)
const {
377 GAIA_ASSERT(idx < cnt);
378 const auto entity = pEntities[idx];
379 if (world_typed_sparse_store_has<U>(pStore, entity))
380 return world_typed_sparse_store_get<U>(pStore, entity);
381 return world_query_entity_arg_by_id<const U&>(*pWorld, entity,
id);
384 GAIA_NODISCARD
constexpr size_t size() const noexcept {
388 GAIA_NODISCARD U* data() noexcept {
392 GAIA_NODISCARD
const U* data() const noexcept {
399 template <
typename U>
400 struct EntityTermViewGet {
401 const U* pData =
nullptr;
402 const Entity* pEntities =
nullptr;
403 World* pWorld =
nullptr;
404 Entity
id = EntityBad;
406 const U* pDataInherited =
nullptr;
407 mutable const Archetype* pLastArchetype =
nullptr;
408 mutable Entity cachedOwner = EntityBad;
409 mutable bool cachedDirect =
false;
411 static EntityTermViewGet pointer(
const U* pData, uint32_t cnt) {
412 return {pData,
nullptr,
nullptr, EntityBad, cnt,
nullptr,
nullptr, EntityBad,
false};
415 static EntityTermViewGet entity(
const Entity* pEntities, World* pWorld, Entity
id, uint32_t cnt) {
416 return {
nullptr, pEntities, pWorld, id, cnt,
nullptr,
nullptr, EntityBad,
false};
419 static EntityTermViewGet inherited(
const U* pDataInherited, uint32_t cnt) {
420 return {
nullptr,
nullptr,
nullptr, EntityBad, cnt, pDataInherited,
nullptr, EntityBad,
false};
423 static EntityTermViewGet entity_chunk_stable(
424 const Entity* pEntities,
const Chunk* pChunk, World* pWorld, Entity
id, uint16_t rowBase, uint32_t cnt) {
425 uint32_t compIdx = BadIndex;
426 const U* pDataInherited =
nullptr;
428 world_init_query_entity_arg_by_id_chunk_stable_const<U>(
429 *pWorld, *pChunk, pEntities,
id, direct, compIdx, pDataInherited);
430 const U* pData =
nullptr;
432 pData =
reinterpret_cast<const U*
>(pChunk->comp_ptr(compIdx, rowBase));
434 return {pData,
nullptr, pWorld, id, cnt, pDataInherited,
nullptr, EntityBad,
false};
437 GAIA_NODISCARD
decltype(
auto)
operator[](
size_t idx)
const {
438 GAIA_ASSERT(idx < cnt);
439 if (pData !=
nullptr)
441 if (pDataInherited !=
nullptr) {
442 GAIA_ASSERT(pDataInherited !=
nullptr);
443 return *pDataInherited;
446 return world_query_entity_arg_by_id_cached_const<const U&>(
447 *pWorld, pEntities[idx],
id, pLastArchetype, cachedOwner, cachedDirect);
450 GAIA_NODISCARD
constexpr size_t size() const noexcept {
454 GAIA_NODISCARD
const U* data() const noexcept {
461 template <
typename U>
462 struct EntityTermViewSet {
464 const Entity* pEntities =
nullptr;
465 World* pWorld =
nullptr;
466 Entity
id = EntityBad;
470 static EntityTermViewSet pointer(U* pData, uint32_t cnt) {
471 return {pData,
nullptr,
nullptr, EntityBad, cnt,
true};
474 static EntityTermViewSet
475 entity(
const Entity* pEntities, World* pWorld, Entity
id, uint32_t cnt,
bool writeIm =
true) {
476 return {
nullptr, pEntities, pWorld, id, cnt, writeIm};
479 GAIA_NODISCARD
decltype(
auto)
operator[](
size_t idx) {
480 GAIA_ASSERT(idx < cnt);
481 if (pData !=
nullptr)
485 return EntityTermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}[idx];
486 return EntityTermViewSetEntity<U, false>{pEntities, pWorld, id, cnt}[idx];
489 GAIA_NODISCARD
decltype(
auto)
operator[](
size_t idx)
const {
490 GAIA_ASSERT(idx < cnt);
491 if (pData !=
nullptr)
492 return static_cast<const U&
>(pData[idx]);
494 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx],
id);
497 GAIA_NODISCARD
constexpr size_t size() const noexcept {
501 GAIA_NODISCARD U* data() noexcept {
505 GAIA_NODISCARD
const U* data() const noexcept {
512 template <
typename U>
513 struct SoATermRowWriteProxyPointer {
514 using raw_view_policy = mem::data_view_policy_soa<U::gaia_Data_Layout, U>;
516 uint8_t* pData =
nullptr;
517 uint32_t dataSize = 0;
520 GAIA_NODISCARD
operator U()
const {
521 return raw_view_policy::get(std::span<const uint8_t>{pData, dataSize}, idx);
524 SoATermRowWriteProxyPointer& operator=(
const U& value) {
525 raw_view_policy::set(std::span<uint8_t>{pData, dataSize}, idx) = value;
532 template <
typename U,
bool WriteIm>
533 struct SoATermRowWriteProxyEntity {
534 const Entity* pEntities =
nullptr;
535 World* pWorld =
nullptr;
536 Entity
id = EntityBad;
539 GAIA_NODISCARD
operator U()
const {
540 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx],
id);
543 SoATermRowWriteProxyEntity& operator=(
const U& value) {
544 if constexpr (WriteIm)
545 world_query_entity_arg_by_id<U&>(*pWorld, pEntities[idx],
id) = value;
547 world_query_entity_arg_by_id_raw<U&>(*pWorld, pEntities[idx],
id) = value;
554 template <
typename U,
size_t Item>
555 struct SoATermFieldReadProxyPointer {
556 using view_policy = mem::data_view_policy_soa_get<U::gaia_Data_Layout, U>;
557 using value_type =
typename view_policy::template data_view_policy_idx_info<Item>::const_value_type;
559 const value_type* pData =
nullptr;
562 GAIA_NODISCARD value_type operator[](
size_t idx)
const {
563 GAIA_ASSERT(idx < cnt);
567 GAIA_NODISCARD
constexpr size_t size() const noexcept {
574 template <
typename U,
size_t Item>
575 struct SoATermFieldReadProxyEntity {
576 using view_policy = mem::data_view_policy_soa_get<U::gaia_Data_Layout, U>;
577 using value_type =
typename view_policy::template data_view_policy_idx_info<Item>::const_value_type;
579 const Entity* pEntities =
nullptr;
580 World* pWorld =
nullptr;
581 Entity
id = EntityBad;
584 GAIA_NODISCARD value_type operator[](
size_t idx)
const {
585 GAIA_ASSERT(idx < cnt);
586 const U value = world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx],
id);
587 return std::get<Item>(meta::struct_to_tuple(value));
590 GAIA_NODISCARD
constexpr size_t size() const noexcept {
597 template <
typename U,
size_t Item>
598 struct SoATermFieldWriteProxyPointer {
599 using view_policy = mem::data_view_policy_soa_set<U::gaia_Data_Layout, U>;
600 using value_type =
typename view_policy::template data_view_policy_idx_info<Item>::value_type;
602 value_type* pData =
nullptr;
605 GAIA_NODISCARD value_type& operator[](
size_t idx) {
606 GAIA_ASSERT(idx < cnt);
610 GAIA_NODISCARD
const value_type& operator[](
size_t idx)
const {
611 GAIA_ASSERT(idx < cnt);
615 GAIA_NODISCARD
constexpr size_t size() const noexcept {
622 template <
typename U,
size_t Item,
bool WriteIm>
623 struct SoATermFieldWriteProxyEntity {
624 using view_policy = mem::data_view_policy_soa_set<U::gaia_Data_Layout, U>;
625 using value_type =
typename view_policy::template data_view_policy_idx_info<Item>::value_type;
628 struct ElementProxy {
629 const Entity* pEntities =
nullptr;
630 World* pWorld =
nullptr;
631 Entity
id = EntityBad;
634 GAIA_NODISCARD
operator value_type()
const {
635 const U value = world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx],
id);
636 return std::get<Item>(meta::struct_to_tuple(value));
639 ElementProxy& operator=(
const value_type& value) {
640 auto data = world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx],
id);
641 auto tuple = meta::struct_to_tuple(data);
642 std::get<Item>(tuple) = value;
643 if constexpr (WriteIm)
644 world_query_entity_arg_by_id<U&>(*pWorld, pEntities[idx],
id) = meta::tuple_to_struct<U>(GAIA_MOV(tuple));
646 world_query_entity_arg_by_id_raw<U&>(*pWorld, pEntities[idx],
id) =
647 meta::tuple_to_struct<U>(GAIA_MOV(tuple));
651 template <
typename V>
652 ElementProxy& operator+=(V&& value) {
653 const value_type current =
operator value_type();
654 return operator=(current + GAIA_FWD(value));
657 template <
typename V>
658 ElementProxy& operator-=(V&& value) {
659 const value_type current =
operator value_type();
660 return operator=(current - GAIA_FWD(value));
663 template <
typename V>
664 ElementProxy& operator*=(V&& value) {
665 const value_type current =
operator value_type();
666 return operator=(current * GAIA_FWD(value));
669 template <
typename V>
670 ElementProxy& operator/=(V&& value) {
671 const value_type current =
operator value_type();
672 return operator=(current / GAIA_FWD(value));
676 const Entity* pEntities =
nullptr;
677 World* pWorld =
nullptr;
678 Entity
id = EntityBad;
681 GAIA_NODISCARD ElementProxy operator[](
size_t idx)
const {
682 GAIA_ASSERT(idx < cnt);
683 return ElementProxy{pEntities, pWorld, id, (uint32_t)idx};
686 GAIA_NODISCARD
constexpr size_t size() const noexcept {
693 template <
typename U>
694 struct SoATermViewGetPointer {
695 using raw_view_policy = mem::data_view_policy_soa<U::gaia_Data_Layout, U>;
696 using read_view_policy = mem::data_view_policy_soa_get<U::gaia_Data_Layout, U>;
698 const uint8_t* pData =
nullptr;
699 uint32_t dataSize = 0;
700 uint32_t idxBase = 0;
703 GAIA_NODISCARD U operator[](
size_t idx)
const {
704 GAIA_ASSERT(idx < cnt);
705 return raw_view_policy::get(std::span<const uint8_t>{pData, dataSize}, idxBase + idx);
708 template <
size_t Item>
709 GAIA_NODISCARD
auto get()
const {
710 const auto field = read_view_policy{std::span<const uint8_t>{pData, dataSize}}.template get<Item>();
711 return SoATermFieldReadProxyPointer<U, Item>{field.data() + idxBase, cnt};
714 GAIA_NODISCARD
constexpr size_t size() const noexcept {
721 template <
typename U>
722 struct SoATermViewGetEntity {
723 const Entity* pEntities =
nullptr;
724 World* pWorld =
nullptr;
725 Entity
id = EntityBad;
728 GAIA_NODISCARD U operator[](
size_t idx)
const {
729 GAIA_ASSERT(idx < cnt);
730 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx],
id);
733 template <
size_t Item>
734 GAIA_NODISCARD
auto get()
const {
735 return SoATermFieldReadProxyEntity<U, Item>{pEntities, pWorld, id, cnt};
738 GAIA_NODISCARD
constexpr size_t size() const noexcept {
745 template <
typename U>
746 struct SoATermViewSetPointer {
747 using raw_view_policy = mem::data_view_policy_soa<U::gaia_Data_Layout, U>;
748 using read_view_policy = mem::data_view_policy_soa_get<U::gaia_Data_Layout, U>;
749 using write_view_policy = mem::data_view_policy_soa_set<U::gaia_Data_Layout, U>;
751 uint8_t* pData =
nullptr;
752 uint32_t dataSize = 0;
753 uint32_t idxBase = 0;
756 GAIA_NODISCARD
auto operator[](
size_t idx) {
757 GAIA_ASSERT(idx < cnt);
758 return SoATermRowWriteProxyPointer<U>{pData, dataSize, idxBase + (uint32_t)idx};
761 GAIA_NODISCARD U operator[](
size_t idx)
const {
762 GAIA_ASSERT(idx < cnt);
763 return raw_view_policy::get(std::span<const uint8_t>{pData, dataSize}, idxBase + idx);
766 template <
size_t Item>
767 GAIA_NODISCARD
auto get()
const {
768 const auto field = read_view_policy{std::span<const uint8_t>{pData, dataSize}}.template get<Item>();
769 return SoATermFieldReadProxyPointer<U, Item>{field.data() + idxBase, cnt};
772 template <
size_t Item>
773 GAIA_NODISCARD
auto set() {
774 auto field = write_view_policy{std::span<uint8_t>{pData, dataSize}}.template set<Item>();
775 return SoATermFieldWriteProxyPointer<U, Item>{field.data() + idxBase, cnt};
778 GAIA_NODISCARD
constexpr size_t size() const noexcept {
785 template <
typename U,
bool WriteIm>
786 struct SoATermViewSetEntity {
787 const Entity* pEntities =
nullptr;
788 World* pWorld =
nullptr;
789 Entity
id = EntityBad;
792 GAIA_NODISCARD
auto operator[](
size_t idx) {
793 GAIA_ASSERT(idx < cnt);
794 return SoATermRowWriteProxyEntity<U, WriteIm>{pEntities, pWorld, id, (uint32_t)idx};
797 GAIA_NODISCARD U operator[](
size_t idx)
const {
798 GAIA_ASSERT(idx < cnt);
799 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx],
id);
802 template <
size_t Item>
803 GAIA_NODISCARD
auto get()
const {
804 return SoATermFieldReadProxyEntity<U, Item>{pEntities, pWorld, id, cnt};
807 template <
size_t Item>
808 GAIA_NODISCARD
auto set() {
809 return SoATermFieldWriteProxyEntity<U, Item, WriteIm>{pEntities, pWorld, id, cnt};
812 GAIA_NODISCARD
constexpr size_t size() const noexcept {
819 template <
typename U>
820 struct SoATermRowWriteProxy {
821 uint8_t* pData =
nullptr;
822 uint32_t dataSize = 0;
823 const Entity* pEntities =
nullptr;
824 World* pWorld =
nullptr;
825 Entity
id = EntityBad;
829 GAIA_NODISCARD
operator U()
const {
830 if (pData !=
nullptr)
831 return (U)SoATermRowWriteProxyPointer<U>{pData, dataSize, idx};
834 return (U)SoATermRowWriteProxyEntity<U, true>{pEntities, pWorld, id, idx};
835 return (U)SoATermRowWriteProxyEntity<U, false>{pEntities, pWorld, id, idx};
838 SoATermRowWriteProxy& operator=(
const U& value) {
839 if (pData !=
nullptr) {
840 SoATermRowWriteProxyPointer<U>{pData, dataSize, idx} = value;
842 SoATermRowWriteProxyEntity<U, true>{pEntities, pWorld, id, idx} = value;
844 SoATermRowWriteProxyEntity<U, false>{pEntities, pWorld, id, idx} = value;
851 template <
typename U,
size_t Item>
852 struct SoATermFieldReadProxy {
853 using value_type =
typename SoATermFieldReadProxyPointer<U, Item>::value_type;
855 const value_type* pData =
nullptr;
856 const Entity* pEntities =
nullptr;
857 World* pWorld =
nullptr;
858 Entity
id = EntityBad;
861 GAIA_NODISCARD value_type operator[](
size_t idx)
const {
862 GAIA_ASSERT(idx < cnt);
863 if (pData !=
nullptr)
864 return SoATermFieldReadProxyPointer<U, Item>{pData, cnt}[idx];
866 return SoATermFieldReadProxyEntity<U, Item>{pEntities, pWorld, id, cnt}[idx];
869 GAIA_NODISCARD
constexpr size_t size() const noexcept {
876 template <
typename U,
size_t Item>
877 struct SoATermFieldWriteProxy {
878 using value_type =
typename SoATermFieldWriteProxyPointer<U, Item>::value_type;
880 value_type* pData =
nullptr;
881 const Entity* pEntities =
nullptr;
882 World* pWorld =
nullptr;
883 Entity
id = EntityBad;
889 struct ElementProxy {
890 value_type* pData =
nullptr;
891 const Entity* pEntities =
nullptr;
892 World* pWorld =
nullptr;
893 Entity
id = EntityBad;
897 GAIA_NODISCARD
operator value_type()
const {
898 if (pData !=
nullptr)
899 return SoATermFieldWriteProxyPointer<U, Item>{pData, idx + 1}[idx];
902 return SoATermFieldWriteProxyEntity<U, Item, true>{pEntities, pWorld, id, idx + 1}[idx];
903 return SoATermFieldWriteProxyEntity<U, Item, false>{pEntities, pWorld, id, idx + 1}[idx];
906 ElementProxy& operator=(
const value_type& value) {
907 if (pData !=
nullptr) {
908 SoATermFieldWriteProxyPointer<U, Item>{pData, idx + 1}[idx] = value;
913 SoATermFieldWriteProxyEntity<U, Item, true>{pEntities, pWorld, id, idx + 1}[idx] = value;
915 SoATermFieldWriteProxyEntity<U, Item, false>{pEntities, pWorld, id, idx + 1}[idx] = value;
919 template <
typename V>
920 ElementProxy& operator+=(V&& value) {
921 const value_type current =
operator value_type();
922 return operator=(current + GAIA_FWD(value));
925 template <
typename V>
926 ElementProxy& operator-=(V&& value) {
927 const value_type current =
operator value_type();
928 return operator=(current - GAIA_FWD(value));
931 template <
typename V>
932 ElementProxy& operator*=(V&& value) {
933 const value_type current =
operator value_type();
934 return operator=(current * GAIA_FWD(value));
937 template <
typename V>
938 ElementProxy& operator/=(V&& value) {
939 const value_type current =
operator value_type();
940 return operator=(current / GAIA_FWD(value));
944 GAIA_NODISCARD ElementProxy operator[](
size_t idx)
const {
945 GAIA_ASSERT(idx < cnt);
946 return ElementProxy{pData, pEntities, pWorld, id, (uint32_t)idx, writeIm};
949 GAIA_NODISCARD
constexpr size_t size() const noexcept {
956 template <
typename U>
957 struct SoATermViewGet {
958 const uint8_t* pData =
nullptr;
959 uint32_t dataSize = 0;
960 const Entity* pEntities =
nullptr;
961 World* pWorld =
nullptr;
962 Entity
id = EntityBad;
963 uint32_t idxBase = 0;
966 GAIA_NODISCARD U operator[](
size_t idx)
const {
967 GAIA_ASSERT(idx < cnt);
968 if (pData !=
nullptr)
969 return SoATermViewGetPointer<U>{pData, dataSize, idxBase, cnt}[idx];
971 return SoATermViewGetEntity<U>{pEntities, pWorld, id, cnt}[idx];
974 template <
size_t Item>
975 GAIA_NODISCARD
auto get()
const {
976 if (pData !=
nullptr) {
977 const auto field = SoATermViewGetPointer<U>{pData, dataSize, idxBase, cnt}.template get<Item>();
978 return SoATermFieldReadProxy<U, Item>{field.pData,
nullptr, pWorld, id, cnt};
981 const auto field = SoATermViewGetEntity<U>{pEntities, pWorld, id, cnt}.template get<Item>();
982 return SoATermFieldReadProxy<U, Item>{
nullptr, field.pEntities, field.pWorld, field.id, field.cnt};
985 GAIA_NODISCARD
constexpr size_t size() const noexcept {
992 template <
typename U>
993 struct SoATermViewSet {
994 uint8_t* pData =
nullptr;
995 uint32_t dataSize = 0;
996 const Entity* pEntities =
nullptr;
997 World* pWorld =
nullptr;
998 Entity
id = EntityBad;
999 uint32_t idxBase = 0;
1001 bool writeIm =
true;
1003 GAIA_NODISCARD
auto operator[](
size_t idx) {
1004 GAIA_ASSERT(idx < cnt);
1005 return SoATermRowWriteProxy<U>{pData, dataSize, pEntities, pWorld, id, idxBase + (uint32_t)idx, writeIm};
1008 GAIA_NODISCARD U operator[](
size_t idx)
const {
1009 GAIA_ASSERT(idx < cnt);
1010 if (pData !=
nullptr)
1011 return SoATermViewSetPointer<U>{pData, dataSize, idxBase, cnt}[idx];
1013 return SoATermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}[idx];
1016 template <
size_t Item>
1017 GAIA_NODISCARD
auto get()
const {
1018 if (pData !=
nullptr) {
1019 const auto field = SoATermViewSetPointer<U>{pData, dataSize, idxBase, cnt}.template get<Item>();
1020 return SoATermFieldReadProxy<U, Item>{field.pData,
nullptr, pWorld, id, cnt};
1023 const auto field = SoATermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}.template get<Item>();
1024 return SoATermFieldReadProxy<U, Item>{
nullptr, field.pEntities, field.pWorld, field.id, field.cnt};
1027 template <
size_t Item>
1028 GAIA_NODISCARD
auto set() {
1029 if (pData !=
nullptr) {
1030 auto field = SoATermViewSetPointer<U>{pData, dataSize, idxBase, cnt}.template set<Item>();
1031 return SoATermFieldWriteProxy<U, Item>{field.pData,
nullptr, pWorld, id, cnt};
1035 const auto field = SoATermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}.template set<Item>();
1036 return SoATermFieldWriteProxy<U, Item>{
nullptr, field.pEntities, field.pWorld, field.id, field.cnt,
true};
1039 const auto field = SoATermViewSetEntity<U, false>{pEntities, pWorld, id, cnt}.template set<Item>();
1040 return SoATermFieldWriteProxy<U, Item>{
nullptr, field.pEntities, field.pWorld, field.id, field.cnt,
false};
1043 GAIA_NODISCARD
constexpr size_t size() const noexcept {
1048 class ChunkIterImpl {
1049 friend struct ChunkIterTypedOps;
1052 using CompIndicesBitView = core::bit_view<ChunkHeader::MAX_COMPONENTS_BITS>;
1055 const World* m_pWorld =
nullptr;
1057 const Archetype* m_pArchetype =
nullptr;
1059 Chunk* m_pChunk =
nullptr;
1061 const uint8_t* m_pCompIndices =
nullptr;
1062#if GAIA_ASSERT_ENABLED
1064 const QueryCtx::Data* m_pQueryAccess =
nullptr;
1067 InheritedTermDataView m_inheritedData;
1069 const Entity* m_pTermIdMapping =
nullptr;
1071 bool m_writeIm =
true;
1073 Constraints m_constraints = Constraints::EnabledOnly;
1074#if GAIA_OBSERVERS_ENABLED
1076 ObserverEvent m_observerEvent = ObserverEvent::None;
1079 uint8_t m_touchedCompIndices[ChunkHeader::MAX_COMPONENTS];
1080 uint8_t m_touchedCompCnt = 0;
1082 Entity m_touchedTerms[ChunkHeader::MAX_COMPONENTS];
1083 uint8_t m_touchedTermCnt = 0;
1085 Entity m_entitySnapshot[ChunkHeader::MAX_CHUNK_ENTITIES];
1086 bool m_entitySnapshotValid =
false;
1092 GroupId m_groupId = 0;
1094 void* m_pCtx =
nullptr;
1097 ChunkIterImpl() =
default;
1098 ~ChunkIterImpl() =
default;
1099 ChunkIterImpl(ChunkIterImpl&&) noexcept = default;
1100 ChunkIterImpl& operator=(ChunkIterImpl&&) noexcept = default;
1101 ChunkIterImpl(const ChunkIterImpl&) = delete;
1102 ChunkIterImpl& operator=(const ChunkIterImpl&) = delete;
1104 void set_world(const World* pWorld) {
1105 GAIA_ASSERT(pWorld !=
nullptr);
1109 GAIA_NODISCARD World* world() {
1110 GAIA_ASSERT(m_pWorld !=
nullptr);
1111 return const_cast<World*
>(m_pWorld);
1114 GAIA_NODISCARD
const World* world()
const {
1115 GAIA_ASSERT(m_pWorld !=
nullptr);
1119 void set_archetype(
const Archetype* pArchetype) {
1120 GAIA_ASSERT(pArchetype !=
nullptr);
1121 m_pArchetype = pArchetype;
1129 GAIA_NODISCARD
const Archetype* archetype()
const {
1130 GAIA_ASSERT(m_pArchetype !=
nullptr);
1131 return m_pArchetype;
1134 void set_chunk(Chunk* pChunk) {
1135 GAIA_ASSERT(pChunk !=
nullptr);
1137 m_entitySnapshotValid =
false;
1138 m_from = start_index(m_pChunk, m_constraints);
1139 m_to = end_index(m_pChunk, m_constraints);
1142 void set_chunk(Chunk* pChunk, uint16_t from, uint16_t to) {
1143 if (from == 0 && to == 0) {
1148 GAIA_ASSERT(pChunk !=
nullptr);
1150 m_entitySnapshotValid =
false;
1155 GAIA_NODISCARD
const Chunk* chunk()
const {
1156 GAIA_ASSERT(m_pChunk !=
nullptr);
1160 void set_comp_indices(
const uint8_t* pCompIndices) {
1161 m_pCompIndices = pCompIndices;
1164#if GAIA_ASSERT_ENABLED
1167 void set_query_access(
const QueryCtx::Data* pQueryAccess) {
1168 m_pQueryAccess = pQueryAccess;
1174 void assert_term_access(uint32_t termIdx, Entity fallbackId = EntityBad)
const {
1175 if (m_pQueryAccess ==
nullptr)
1177 GAIA_ASSERT(termIdx < m_pQueryAccess->idsCnt &&
"Query field index out of range");
1178 if (!m_pQueryAccess->has_match_terms())
1181 GAIA_FOR(m_pQueryAccess->idsCnt) {
1182 if (m_pQueryAccess->terms[i].fieldIndex == termIdx) {
1184 m_pQueryAccess->terms[i].access != QueryAccess::Match &&
1185 "Presence-only terms have no payload access");
1189 if (fallbackId != EntityBad)
1190 assert_term_access(fallbackId);
1198 GAIA_NODISCARD
static bool
1199 allows_term_access(
const QueryCtx::Data& data, Entity component,
bool selfSourceOnly =
true) {
1200 if (!data.has_match_terms())
1203 bool matchOnly =
false;
1204 GAIA_FOR(data.idsCnt) {
1205 const auto& term = data.terms[i];
1206 if (term.op == QueryOpKind::Not || (selfSourceOnly && !query_term_maps_to_current_archetype(term)))
1209 const bool matches =
1210 term.id == component ||
1211 (term.id.pair() && component.pair() && (is_wildcard(term.id.id()) || term.id.id() == component.id()) &&
1212 (is_wildcard(term.id.gen()) || term.id.gen() == component.gen()));
1215 if (term.access != QueryAccess::Match)
1224 void assert_term_access(Entity component)
const {
1226 (m_pQueryAccess ==
nullptr || allows_term_access(*m_pQueryAccess, component)) &&
1227 "Presence-only terms have no payload access");
1231 void set_inherited_data(InheritedTermDataView inheritedData) {
1232 m_inheritedData = inheritedData;
1235 void set_term_ids(
const Entity* pTermIds) {
1236 m_pTermIdMapping = pTermIds;
1239 GAIA_NODISCARD
const uint8_t* comp_indices()
const {
1240 return m_pCompIndices;
1243 GAIA_NODISCARD InheritedTermDataView inherited_data()
const {
1244 return m_inheritedData;
1247 GAIA_NODISCARD
const Entity* term_ids()
const {
1248 return m_pTermIdMapping;
1251 void set_write_im(
bool value) {
1253 clear_touched_writes();
1256 void set_constraints(Constraints constraints) {
1257 m_constraints = constraints;
1258 if (m_pChunk !=
nullptr) {
1259 m_from = start_index(m_pChunk, m_constraints);
1260 m_to = end_index(m_pChunk, m_constraints);
1261 m_entitySnapshotValid =
false;
1269 void init_query_state(
const World* pWorld, Constraints constraints,
bool writeIm) {
1271 m_constraints = constraints;
1272 m_writeIm = writeIm;
1273 clear_touched_writes();
1282 void set_query_chunk(
1283 const Archetype* pArchetype,
const uint8_t* pCompIndices, Chunk* pChunk, uint16_t from, uint16_t to) {
1284 GAIA_ASSERT(pArchetype !=
nullptr);
1285 GAIA_ASSERT(pChunk !=
nullptr);
1286 if (m_pArchetype != pArchetype)
1287 m_pArchetype = pArchetype;
1288 if (m_pCompIndices != pCompIndices)
1289 m_pCompIndices = pCompIndices;
1291 m_entitySnapshotValid =
false;
1296 GAIA_NODISCARD
bool write_im()
const {
1300 GAIA_NODISCARD Constraints constraints()
const {
1301 return m_constraints;
1304 void clear_touched_writes() {
1305 m_touchedCompCnt = 0;
1306 m_touchedTermCnt = 0;
1309 GAIA_NODISCARD
const Entity* entity_snapshot() {
1310 if (!m_entitySnapshotValid) {
1311 const auto cnt = size();
1312 GAIA_ASSERT(cnt <= ChunkHeader::MAX_CHUNK_ENTITIES);
1314 const auto entities = m_pChunk->entity_view();
1316 m_entitySnapshot[i] = entities[from() + i];
1319 m_entitySnapshotValid =
true;
1322 return m_entitySnapshot;
1325 GAIA_NODISCARD
auto touched_comp_indices()
const {
1326 return std::span<const uint8_t>{m_touchedCompIndices, m_touchedCompCnt};
1329 GAIA_NODISCARD
auto touched_terms()
const {
1330 return std::span<const Entity>{m_touchedTerms, m_touchedTermCnt};
1333 GAIA_NODISCARD
auto entity_rows() {
1334 if (m_entitySnapshotValid)
1335 return std::span<const Entity>{m_entitySnapshot, size()};
1337 return std::span<const Entity>{m_pChunk->entity_view().data() + from(), size()};
1340 template <
typename U>
1341 GAIA_NODISCARD
auto entity_view_set(Entity termId,
bool writeIm) {
1342#if GAIA_ASSERT_ENABLED
1343 assert_term_access(termId);
1345 return EntityTermViewSet<U>::entity(entity_snapshot(), world(), termId, size(), writeIm);
1349 template <
typename U>
1350 GAIA_NODISCARD
static auto entity_view_set_empty(
bool writeIm) {
1351 return EntityTermViewSet<U>::entity(
nullptr,
nullptr, EntityBad, 0, writeIm);
1354 template <
typename U>
1355 GAIA_NODISCARD
auto entity_soa_view_set(Entity termId,
bool writeIm) {
1356#if GAIA_ASSERT_ENABLED
1357 assert_term_access(termId);
1359 return SoATermViewSet<U>{
nullptr, 0, entity_snapshot(), world(), termId, 0, size(), writeIm};
1363 template <
typename U>
1364 GAIA_NODISCARD
static auto entity_soa_view_set_empty(
bool writeIm) {
1365 return SoATermViewSet<U>{
nullptr, 0,
nullptr,
nullptr, EntityBad, 0, 0, writeIm};
1368 void set_group_id(GroupId groupId) {
1369 m_groupId = groupId;
1372 GAIA_NODISCARD GroupId group_id()
const {
1384 void ctx(
void* pCtx) {
1390 GAIA_NODISCARD
void* ctx()
const {
1395 GAIA_NODISCARD CommandBufferST& cmd_buffer_st()
const {
1396 auto* pWorld =
const_cast<World*
>(m_pWorld);
1397 return cmd_buffer_st_get(*pWorld);
1400 GAIA_NODISCARD CommandBufferMT& cmd_buffer_mt()
const {
1401 auto* pWorld =
const_cast<World*
>(m_pWorld);
1402 return cmd_buffer_mt_get(*pWorld);
1405 GAIA_NODISCARD IterTermDesc resolved_term_desc(uint32_t termIdx, IterTermDesc desc)
const {
1406 if (m_pTermIdMapping !=
nullptr) {
1407 const auto mappedTermId = m_pTermIdMapping[termIdx];
1408 if (mappedTermId != EntityBad)
1409 desc.termId = mappedTermId;
1412 if (!desc.storageKnown && !desc.isEntity && desc.termId != EntityBad)
1413 desc.usesSparseStorage = world_component_uses_sparse_storage(*world(), desc.termId);
1418 void touch_comp_idx(uint8_t compIdx) {
1419 GAIA_ASSERT(compIdx != 0xFF);
1420 GAIA_FOR(m_touchedCompCnt) {
1421 if (m_touchedCompIndices[i] == compIdx)
1425 GAIA_ASSERT(m_touchedCompCnt < ChunkHeader::MAX_COMPONENTS);
1426 m_touchedCompIndices[m_touchedCompCnt++] = compIdx;
1429 GAIA_NODISCARD
bool touch_term(Entity term) {
1430 GAIA_ASSERT(term != EntityBad);
1431 GAIA_FOR(m_touchedTermCnt) {
1432 if (m_touchedTerms[i] == term)
1436 if (m_touchedTermCnt >= ChunkHeader::MAX_COMPONENTS)
1439 m_touchedTerms[m_touchedTermCnt++] = term;
1443 GAIA_NODISCARD
bool touch_term_desc(
const IterTermDesc& desc) {
1446 if (desc.usesSparseStorage)
1447 return touch_term(desc.termId);
1448 touch_comp_idx((uint8_t)m_pChunk->comp_idx(desc.termId));
1455 GAIA_NODISCARD
bool touch_raw_component(Entity component) {
1456 if (!world_component_uses_sparse_storage(*world(), component)) {
1457 const auto compIdx = core::get_index(m_pChunk->ids_view(), component);
1458 if (compIdx != BadIndex) {
1459 touch_comp_idx((uint8_t)compIdx);
1464 return touch_term(component);
1470 GAIA_NODISCARD
bool owns_raw_component(Entity component) {
1471#if GAIA_ASSERT_ENABLED
1472 assert_term_access(component);
1474 const auto* pEntities = entity_snapshot();
1476 if (!world_mut_raw(*world(), pEntities[i], component).valid())
1483 GAIA_NODISCARD RawTermViewGet raw_term_view(uint32_t termIdx)
const {
1484#if GAIA_ASSERT_ENABLED
1485 assert_term_access(termIdx);
1487 if (m_pCompIndices ==
nullptr || m_pChunk ==
nullptr)
1490 const auto compIdx = m_pCompIndices[termIdx];
1491 if (compIdx == 0xFF)
1494 const auto recs = m_pChunk->comp_rec_view();
1495 if (compIdx >= recs.size())
1498 const auto& rec = recs[compIdx];
1499 if (rec.comp.soa() != 0)
1502 const auto elemSize = rec.comp.size();
1503 const auto row = (uint32_t)from();
1504 const auto* pData = elemSize != 0 ? m_pChunk->comp_ptr(compIdx, row) :
nullptr;
1505 return {pData, elemSize, size(), ComponentRawViewFlag_Valid};
1515 GAIA_NODISCARD
bool raw_term_field_info(
1516 uint32_t termIdx, uint32_t fieldIdx, uint8_t& compIdx,
const ComponentCacheItem*& pItem)
const {
1517#if GAIA_ASSERT_ENABLED
1518 assert_term_access(termIdx);
1520 if (m_pCompIndices ==
nullptr || m_pChunk ==
nullptr || size() == 0)
1523 compIdx = m_pCompIndices[termIdx];
1524 if (compIdx == 0xFF)
1527 const auto recs = m_pChunk->comp_rec_view();
1528 if (compIdx >= recs.size())
1531 const auto& rec = recs[compIdx];
1533 return pItem !=
nullptr && rec.comp.storage_type() == DataStorageType::Table && rec.comp.soa() != 0 &&
1534 fieldIdx < rec.comp.soa() && pItem->soaSizes[fieldIdx] != 0;
1541 GAIA_NODISCARD RawTermViewGet raw_term_field_view(uint32_t termIdx, uint32_t fieldIdx)
const {
1543 const ComponentCacheItem* pItem;
1544 if (!raw_term_field_info(termIdx, fieldIdx, compIdx, pItem))
1547 const auto recs = m_pChunk->comp_rec_view();
1548 const auto& rec = recs[compIdx];
1549 const std::span<const uint8_t> fieldSizes{pItem->soaSizes, rec.comp.soa()};
1550 const auto* pData = mem::data_view_policy_soa_erased::get(
1551 m_pChunk->comp_ptr(compIdx), rec.comp.alig(), fieldSizes, fieldIdx, from(), m_pChunk->capacity());
1552 return {pData, pItem->soaSizes[fieldIdx], size(), ComponentRawViewFlag_Valid};
1560 GAIA_NODISCARD RawTermViewSet raw_term_field_view_mut(uint32_t termIdx, uint32_t fieldIdx,
bool trackWrite) {
1562 const ComponentCacheItem* pItem;
1563 if (!raw_term_field_info(termIdx, fieldIdx, compIdx, pItem))
1567 touch_comp_idx(compIdx);
1569 m_pChunk->update_world_version(compIdx);
1572 const auto recs = m_pChunk->comp_rec_view();
1573 const auto& rec = recs[compIdx];
1574 const std::span<const uint8_t> fieldSizes{pItem->soaSizes, rec.comp.soa()};
1575 auto* pData = mem::data_view_policy_soa_erased::set(
1576 m_pChunk->comp_ptr_mut(compIdx), rec.comp.alig(), fieldSizes, fieldIdx, from(), m_pChunk->capacity());
1577 return {pData, pItem->soaSizes[fieldIdx], size(), ComponentRawViewFlag_Valid};
1580 GAIA_NODISCARD RawTermViewSet raw_term_view_mut(uint32_t termIdx,
bool trackWrite) {
1581#if GAIA_ASSERT_ENABLED
1582 assert_term_access(termIdx);
1584 if (m_pCompIndices ==
nullptr || m_pChunk ==
nullptr)
1587 const auto compIdx = m_pCompIndices[termIdx];
1588 if (compIdx == 0xFF)
1591 const auto recs = m_pChunk->comp_rec_view();
1592 if (compIdx >= recs.size())
1595 const auto& rec = recs[compIdx];
1596 if (rec.comp.soa() != 0)
1600 touch_comp_idx(compIdx);
1602 m_pChunk->update_world_version(compIdx);
1605 const auto elemSize = rec.comp.size();
1606 const auto row = (uint32_t)from();
1607 auto* pData = elemSize != 0 ? m_pChunk->comp_ptr_mut(compIdx, row) :
nullptr;
1608 return {pData, elemSize, size(), ComponentRawViewFlag_Valid};
1615 GAIA_NODISCARD RawTermViewSetEntity raw_term_view_any_mut(Entity component,
bool trackWrite) {
1616#if GAIA_ASSERT_ENABLED
1617 assert_term_access(component);
1619 if (component == EntityBad || m_pChunk ==
nullptr || size() == 0)
1622 const auto* pEntities = entity_snapshot();
1623 RawSparseStoreOps sparse{};
1624 if (world_bind_raw_sparse_store(*world(), component, sparse)) {
1626 if (!sparse.funcHas(sparse.pStore, pEntities[i]))
1629 }
else if (!owns_raw_component(component))
1631 if (trackWrite && !touch_raw_component(component))
1634 return {pEntities, world(), component, size(), sparse};
1640 GAIA_NODISCARD RawTermViewGet view_raw(uint32_t termIdx)
const {
1641 return raw_term_view(termIdx);
1651 GAIA_NODISCARD RawTermViewGet view_raw_field(uint32_t termIdx, uint32_t fieldIdx)
const {
1652 return raw_term_field_view(termIdx, fieldIdx);
1662 GAIA_NODISCARD RawTermViewSet view_raw_field_mut(uint32_t termIdx, uint32_t fieldIdx) {
1663 return raw_term_field_view_mut(termIdx, fieldIdx,
true);
1673 GAIA_NODISCARD RawTermViewSet sview_raw_field_mut(uint32_t termIdx, uint32_t fieldIdx) {
1674 return raw_term_field_view_mut(termIdx, fieldIdx,
false);
1681 GAIA_NODISCARD RawTermViewSet view_raw_mut(uint32_t termIdx) {
1682 return raw_term_view_mut(termIdx,
true);
1689 GAIA_NODISCARD RawTermViewSet sview_raw_mut(uint32_t termIdx) {
1690 return raw_term_view_mut(termIdx,
false);
1698 GAIA_NODISCARD RawTermViewGetEntity view_raw_any(Entity component)
const {
1699#if GAIA_ASSERT_ENABLED
1700 assert_term_access(component);
1702 if (component == EntityBad || m_pChunk ==
nullptr || size() == 0)
1705 const auto* pEntities = m_pChunk->entity_view().data() + from();
1706 RawSparseStoreOps sparse{};
1707 if (!world_bind_raw_sparse_store(*world(), component, sparse) &&
1708 !world_get_raw(*world(), pEntities[0], component).valid())
1711 return {pEntities, world(), component, size(), sparse};
1720 GAIA_NODISCARD RawTermViewSetEntity view_raw_any_mut(Entity component) {
1721 return raw_term_view_any_mut(component,
true);
1729 GAIA_NODISCARD RawTermViewSetEntity sview_raw_any_mut(Entity component) {
1730 return raw_term_view_any_mut(component,
false);
1735 void modify_raw(uint32_t termIdx) {
1736#if GAIA_ASSERT_ENABLED
1737 assert_term_access(termIdx);
1739 if (m_pCompIndices ==
nullptr || m_pChunk ==
nullptr)
1742 const auto compIdx = m_pCompIndices[termIdx];
1743 if (compIdx == 0xFF || compIdx >= m_pChunk->comp_rec_view().size())
1746 const auto recs = m_pChunk->comp_rec_view();
1747 const auto& rec = recs[compIdx];
1748 if (rec.comp.soa() != 0) {
1749 uint8_t fieldCompIdx;
1750 const ComponentCacheItem* pItem;
1751 if (!raw_term_field_info(termIdx, 0, fieldCompIdx, pItem))
1755 touch_comp_idx(compIdx);
1763 GAIA_NODISCARD
bool modify_raw(Entity component) {
1764#if GAIA_ASSERT_ENABLED
1765 assert_term_access(component);
1767 if (component == EntityBad || m_pChunk ==
nullptr || size() == 0 || !owns_raw_component(component))
1770 return touch_raw_component(component);
1779 template <
typename T>
1780 GAIA_NODISCARD
auto view_any()
const {
1781 return ChunkIterTypedOps::template view_any<T>(*
this);
1791 template <
typename T>
1792 GAIA_NODISCARD
auto view_any(uint32_t termIdx) {
1793 return ChunkIterTypedOps::template view_any<T>(*
this, termIdx);
1803 template <
typename T>
1804 GAIA_NODISCARD
auto view()
const {
1805 return ChunkIterTypedOps::template view<T>(*
this);
1815 template <
typename T>
1816 GAIA_NODISCARD
auto view(uint32_t termIdx)
const {
1817 return ChunkIterTypedOps::template view<T>(*
this, termIdx);
1826 template <
typename T>
1827 GAIA_NODISCARD
auto view_any_mut() {
1828 return ChunkIterTypedOps::template view_any_mut<T>(*
this);
1836 template <
typename T>
1837 GAIA_NODISCARD
auto view_mut() {
1838 return ChunkIterTypedOps::template view_mut<T>(*
this);
1848 template <
typename T>
1849 GAIA_NODISCARD
auto view_mut(uint32_t termIdx) {
1850 return ChunkIterTypedOps::template view_mut<T>(*
this, termIdx);
1860 template <
typename T>
1861 GAIA_NODISCARD
auto view_any_mut(uint32_t termIdx) {
1862 return ChunkIterTypedOps::template view_any_mut<T>(*
this, termIdx);
1872 template <
typename T>
1873 GAIA_NODISCARD
auto sview_any_mut() {
1874 return ChunkIterTypedOps::template sview_any_mut<T>(*
this);
1882 template <
typename T>
1883 GAIA_NODISCARD
auto sview_mut() {
1884 return ChunkIterTypedOps::template sview_mut<T>(*
this);
1894 template <
typename T>
1895 GAIA_NODISCARD
auto sview_mut(uint32_t termIdx) {
1896 return ChunkIterTypedOps::template sview_mut<T>(*
this, termIdx);
1907 template <
typename T>
1908 GAIA_NODISCARD
auto sview_any_mut(uint32_t termIdx) {
1909 return ChunkIterTypedOps::template sview_any_mut<T>(*
this, termIdx);
1915 template <
typename T,
bool TriggerHooks>
1917#if GAIA_ASSERT_ENABLED
1918 assert_term_access(ChunkIterTypedOps::template term_desc<T>(*this).termId);
1920 m_pChunk->template modify<T, TriggerHooks>();
1929 template <
typename T>
1930 GAIA_NODISCARD
auto view_auto() {
1931 using UOriginal =
typename actual_type_t<T>::TypeOriginal;
1932 if constexpr (core::is_mut_v<UOriginal>)
1933 return view_mut<T>();
1944 template <
typename T>
1945 GAIA_NODISCARD
auto view_auto_any() {
1946 using UOriginal =
typename actual_type_t<T>::TypeOriginal;
1947 if constexpr (core::is_mut_v<UOriginal>)
1948 return view_any_mut<T>();
1950 return view_any<T>();
1960 template <
typename T>
1961 GAIA_NODISCARD
auto sview_auto_any() {
1962 using UOriginal =
typename actual_type_t<T>::TypeOriginal;
1963 if constexpr (core::is_mut_v<UOriginal>)
1964 return sview_any_mut<T>();
1966 return view_any<T>();
1976 template <
typename T>
1977 GAIA_NODISCARD
auto sview_auto() {
1978 using UOriginal =
typename actual_type_t<T>::TypeOriginal;
1979 if constexpr (core::is_mut_v<UOriginal>)
1980 return sview_mut<T>();
1987 GAIA_NODISCARD
bool enabled(uint32_t index)
const {
1988 const auto row = (uint16_t)(from() + index);
1989 return m_pChunk->enabled(row);
1995 GAIA_NODISCARD
bool has(Entity entity)
const {
1996 return m_pChunk->has(entity);
2002 GAIA_NODISCARD
bool has(Pair pair)
const {
2003 return m_pChunk->has((Entity)pair);
2009 template <
typename T>
2010 GAIA_NODISCARD
bool has()
const {
2011 return m_pChunk->template has<T>();
2014 GAIA_NODISCARD
static uint16_t start_index(Chunk* pChunk, Constraints constraints)
noexcept {
2015 if (constraints == Constraints::EnabledOnly)
2016 return pChunk->size_disabled();
2020 GAIA_NODISCARD
static uint16_t end_index(Chunk* pChunk, Constraints constraints)
noexcept {
2021 if (constraints == Constraints::DisabledOnly)
2022 return pChunk->size_disabled();
2023 return pChunk->size();
2026 GAIA_NODISCARD
static uint16_t size(Chunk* pChunk, Constraints constraints)
noexcept {
2027 if (constraints == Constraints::EnabledOnly)
2028 return pChunk->size_enabled();
2029 if (constraints == Constraints::DisabledOnly)
2030 return pChunk->size_disabled();
2031 return pChunk->size();
2035 GAIA_NODISCARD uint16_t size() const noexcept {
2036 return (uint16_t)(to() - from());
2040 GAIA_NODISCARD uint16_t row_begin() const noexcept {
2045 GAIA_NODISCARD uint16_t row_end() const noexcept {
2052 template <
typename T>
2053 uint32_t acc_index(uint32_t idx)
const noexcept {
2054 using U =
typename actual_type_t<T>::Type;
2055 if constexpr (mem::is_soa_layout_v<U>)
2056 return idx + from();
2063 GAIA_NODISCARD uint16_t from() const noexcept {
2068 GAIA_NODISCARD uint16_t to() const noexcept {
2077 class GAIA_API
Iter:
public detail::ChunkIterImpl {
2080 static constexpr Constraints ConstraintMode = Constraints::EnabledOnly;
2082 using detail::ChunkIterImpl::size;
2085 set_constraints(ConstraintMode);
2088#if GAIA_OBSERVERS_ENABLED
2092 void event(ObserverEvent value)
noexcept {
2093 m_observerEvent = value;
2101 GAIA_NODISCARD ObserverEvent event() const noexcept {
2102 return m_observerEvent;
2110 return detail::ChunkIterImpl::start_index(pChunk, ConstraintMode);
2117 return detail::ChunkIterImpl::end_index(pChunk, ConstraintMode);
2123 GAIA_NODISCARD
static uint16_t
size(
Chunk* pChunk)
noexcept {
2124 return detail::ChunkIterImpl::size(pChunk, ConstraintMode);
2130 return m_pChunk->size_enabled();
2137 return m_pChunk->size_disabled();
2169 void set_range(uint16_t from, uint16_t cnt) {
2170 GAIA_ASSERT(from < m_pChunk->size());
2171 GAIA_ASSERT(from + cnt <= m_pChunk->size());
2179 GAIA_ASSERT(pWorld !=
nullptr);
2186 GAIA_ASSERT(m_pWorld !=
nullptr);
2187 return const_cast<World*
>(m_pWorld);
2193 GAIA_ASSERT(m_pWorld !=
nullptr);
2200 GAIA_ASSERT(pArchetype !=
nullptr);
2201 m_pArchetype = pArchetype;
2212 GAIA_ASSERT(m_pArchetype !=
nullptr);
2213 return m_pArchetype;
2219 GAIA_ASSERT(pChunk !=
nullptr);
2226 GAIA_ASSERT(m_pChunk !=
nullptr);
2233 auto* pWorld =
const_cast<World*
>(m_pWorld);
2234 return cmd_buffer_st_get(*pWorld);
2240 auto* pWorld =
const_cast<World*
>(m_pWorld);
2241 return cmd_buffer_mt_get(*pWorld);
2248 template <
typename T>
2250 return m_pChunk->template view<T>(from(), to());
2257 template <
typename T>
2259 return m_pChunk->template view_mut<T>(from(), to());
2267 template <
typename T>
2269 return m_pChunk->template sview_mut<T>(from(), to());
2275 template <
typename T,
bool TriggerHooks>
2277 m_pChunk->template modify<T, TriggerHooks>();
2285 template <
typename T>
2287 return m_pChunk->template view_auto<T>(from(), to());
2296 template <
typename T>
2298 return m_pChunk->template sview_auto<T>(from(), to());
2304 GAIA_NODISCARD
bool enabled(uint32_t index)
const {
2305 const auto row = (uint16_t)(from() + index);
2306 return m_pChunk->
enabled(row);
2313 return m_pChunk->
has(entity);
2326 template <
typename T>
2327 GAIA_NODISCARD
bool has()
const {
2328 return m_pChunk->template has<T>();
2333 GAIA_NODISCARD uint16_t
size() const noexcept {
2339 GAIA_NODISCARD uint16_t from() const noexcept {
2344 GAIA_NODISCARD uint16_t to() const noexcept {
2345 return m_from + m_cnt;
2351#include "gaia/ecs/chunk_iterator_typed.inl"
Fixed-shape group of chunks storing entities that share the same component layout....
Definition archetype.h:97
Fixed-capacity archetype storage unit holding entities and their component columns.
Definition chunk.h:36
bool enabled(uint16_t row) const
Checks if the entity is enabled.
Definition chunk.h:1371
GAIA_NODISCARD bool has(Entity entity) const
Checks if a component/entity entity is present in the chunk.
Definition chunk.h:1450
Iterator used when copying entities.
Definition chunk_iterator.h:2142
uint16_t m_from
Row of the first entity we iterate from.
Definition chunk_iterator.h:2154
GAIA_NODISCARD CommandBufferST & cmd_buffer_st() const
Returns the world's single-threaded command buffer.
Definition chunk_iterator.h:2232
GAIA_NODISCARD auto view() const
Returns a read-only entity or component view.
Definition chunk_iterator.h:2249
void set_world(const World *pWorld)
Associates the iterator with its owning world.
Definition chunk_iterator.h:2178
GAIA_NODISCARD const Chunk * chunk() const
Returns the associated source chunk.
Definition chunk_iterator.h:2225
GAIA_NODISCARD CommandBufferMT & cmd_buffer_mt() const
Returns the world's multi-threaded command buffer.
Definition chunk_iterator.h:2239
GAIA_NODISCARD auto sview_auto()
Returns either a mutable or immutable entity/component view based on the requested type....
Definition chunk_iterator.h:2297
GAIA_NODISCARD auto sview_mut()
Returns a mutable component view. Doesn't update the world version when the access is acquired.
Definition chunk_iterator.h:2268
GAIA_NODISCARD World * world()
Returns mutable access to the associated world.
Definition chunk_iterator.h:2185
void set_archetype(const Archetype *pArchetype)
Associates the iterator with the source archetype.
Definition chunk_iterator.h:2199
GAIA_NODISCARD bool has() const
Checks if component T is present in the chunk.
Definition chunk_iterator.h:2327
GAIA_NODISCARD auto view_mut()
Returns a mutable entity or component view.
Definition chunk_iterator.h:2258
GAIA_NODISCARD bool has(Pair pair) const
Checks if relationship pair pair is present in the chunk.
Definition chunk_iterator.h:2319
uint16_t m_cnt
The number of entities accessible via the iterator.
Definition chunk_iterator.h:2156
GAIA_NODISCARD auto view_auto()
Returns either a mutable or immutable entity/component view based on the requested type....
Definition chunk_iterator.h:2286
GAIA_NODISCARD bool has(Entity entity) const
Checks if entity entity is present in the chunk.
Definition chunk_iterator.h:2312
void modify()
Marks the component T as modified. Best used with sview to manually trigger an update at user's whim....
Definition chunk_iterator.h:2276
GAIA_NODISCARD const Archetype * archetype() const
Returns the associated source archetype.
Definition chunk_iterator.h:2211
GAIA_NODISCARD const World * world() const
Returns read-only access to the associated world.
Definition chunk_iterator.h:2192
void set_chunk(Chunk *pChunk)
Associates the iterator with a source chunk.
Definition chunk_iterator.h:2218
GAIA_NODISCARD uint16_t size() const noexcept
Returns the number of entities accessible via the iterator.
Definition chunk_iterator.h:2333
GAIA_NODISCARD bool enabled(uint32_t index) const
Checks if the entity at the current iterator index is enabled.
Definition chunk_iterator.h:2304
Iterator for iterating entity subsets selected by Constraints. Disabled entities always precede enabl...
Definition chunk_iterator.h:2077
static GAIA_NODISCARD uint16_t size(Chunk *pChunk) noexcept
Returns the number of enabled rows in a chunk.
Definition chunk_iterator.h:2123
static GAIA_NODISCARD uint16_t end_index(Chunk *pChunk) noexcept
Returns the end of the enabled row range in a chunk.
Definition chunk_iterator.h:2116
GAIA_NODISCARD uint16_t size_disabled() const noexcept
Returns the number of disabled entities accessible via the iterator. Can be read also as "the index o...
Definition chunk_iterator.h:2136
GAIA_NODISCARD uint16_t size_enabled() const noexcept
Returns the number of enabled entities accessible via the iterator.
Definition chunk_iterator.h:2129
static GAIA_NODISCARD uint16_t start_index(Chunk *pChunk) noexcept
Returns the first enabled row in a chunk.
Definition chunk_iterator.h:2109
Owns entities, components, archetypes, queries, observers, and systems.
Definition world.h:80
Buffer for deferred execution of some operations on entities.
Definition command_buffer.h:56
Wrapper for two Entities forming a relationship pair. Conversion to Entity stores only id() of each e...
Definition id.h:559
Wrapper for two types forming a relationship pair. Depending on what types are used to form a pair it...
Definition id.h:197
Provides packed access to fixed-width unsigned values stored in a byte span.
Definition bit_utils.h:13
Identifier of an entity or component instance in the world. Packs the entity index,...
Definition id.h:231
Prebound operations for one runtime sparse component store.
Definition chunk_iterator.h:25
uint32_t elemSize
Size of one stored component value in bytes.
Definition chunk_iterator.h:35
bool(* funcHas)(const void *, Entity)
Tests whether an entity has a value in the store.
Definition chunk_iterator.h:33
const void * pStore
Type-erased sparse store instance.
Definition chunk_iterator.h:27