Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
chunk_iterator.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cinttypes>
5#include <cstdint>
6#include <type_traits>
7
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/query_common.h"
17#include "gaia/mem/data_layout_policy.h"
18
19namespace gaia {
20 namespace ecs {
21 class World;
22
26 const void* pStore = nullptr;
28 const void* (*funcGet)(const void*, Entity) = nullptr;
30 void* (*funcMut)(void*, Entity) = nullptr;
32 bool (*funcHas)(const void*, Entity) = nullptr;
34 uint32_t elemSize = 0;
35 };
36
37 bool world_bind_raw_sparse_store(const World& world, Entity component, RawSparseStoreOps& ops);
38 void world_notify_on_set_entity(World& world, Entity term, Entity entity);
39 template <typename T>
40 void* world_typed_sparse_store_ptr(World& world, Entity component);
41 template <typename T>
42 const T& world_typed_sparse_store_get(const void* pStore, Entity entity);
43 template <typename T>
44 T& world_typed_sparse_store_mut(void* pStore, Entity entity);
45 template <typename T>
46 bool world_typed_sparse_store_has(const void* pStore, Entity entity);
47 template <typename T>
48 decltype(auto) world_query_entity_arg_by_id_cached_const(
49 World& world, Entity entity, Entity id, const Archetype*& pLastArchetype, Entity& cachedOwner,
50 bool& cachedDirect);
51 template <typename T>
52 void world_init_query_entity_arg_by_id_chunk_stable_const(
53 World& world, const Chunk& chunk, const Entity* pEntities, Entity id, bool& direct, uint32_t& compIdx,
54 const std::remove_cv_t<std::remove_reference_t<T>>*& pDataInherited);
55 template <typename T>
56 const std::remove_cv_t<std::remove_reference_t<T>>*
57 world_query_inherited_arg_data_const(World& world, Entity owner, Entity id);
58 bool world_term_uses_inherit_policy(const World& world, Entity term);
59 template <typename T>
60 Entity world_query_arg_id(World& world);
61
63 enum class Constraints : uint8_t {
65 EnabledOnly,
67 DisabledOnly,
69 AcceptAll
70 };
71
73 namespace detail {
74 class ChunkIterImpl;
75
76 struct IterTermDesc {
77 Entity termId = EntityBad;
78 bool isEntity = false;
79 bool usesSparseStorage = false;
80 bool storageKnown = false;
81 };
82
83 struct ChunkIterTypedOps {
84 template <typename T>
85 static IterTermDesc term_desc(const ChunkIterImpl& self);
86 template <typename T>
87 static auto view_any(const ChunkIterImpl& self);
88 template <typename T>
89 static auto view_any(ChunkIterImpl& self, uint32_t termIdx);
90 template <typename T>
91 static auto view(const ChunkIterImpl& self);
92 template <typename T>
93 static auto view(const ChunkIterImpl& self, uint32_t termIdx);
94 template <typename T>
95 static auto view_any_mut(ChunkIterImpl& self);
96 template <typename T>
97 static auto view_mut(ChunkIterImpl& self);
98 template <typename T>
99 static auto view_mut(ChunkIterImpl& self, uint32_t termIdx);
100 template <typename T>
101 static auto view_any_mut(ChunkIterImpl& self, uint32_t termIdx);
102 template <typename T>
103 static auto sview_any_mut(ChunkIterImpl& self);
104 template <typename T>
105 static auto sview_mut(ChunkIterImpl& self);
106 template <typename T>
107 static auto sview_mut(ChunkIterImpl& self, uint32_t termIdx);
108 template <typename T>
109 static auto sview_any_mut(ChunkIterImpl& self, uint32_t termIdx);
110 };
111
112 struct BfsChunkRun {
113 const Archetype* pArchetype = nullptr;
114 Chunk* pChunk = nullptr;
115 uint16_t from = 0;
116 uint16_t to = 0;
117 uint32_t offset = 0;
118 };
119
121 struct RawTermViewGet {
122 const uint8_t* pData = nullptr;
123 uint32_t elemSize = 0;
124 uint32_t cnt = 0;
125 uint32_t flags = ComponentRawViewFlag_None;
126
127 GAIA_NODISCARD ComponentRawView operator[](size_t idx) const {
128 GAIA_ASSERT(idx < cnt);
129 if ((flags & ComponentRawViewFlag_Valid) == 0 || idx >= cnt)
130 return {};
131 if (elemSize == 0)
132 return {nullptr, 0, ComponentRawViewFlag_Valid};
133
134 return {pData + (uintptr_t)elemSize * idx, elemSize, ComponentRawViewFlag_Valid};
135 }
136
137 GAIA_NODISCARD constexpr size_t size() const noexcept {
138 return cnt;
139 }
140 };
141
143 struct RawTermViewSet {
144 uint8_t* pData = nullptr;
145 uint32_t elemSize = 0;
146 uint32_t cnt = 0;
147 uint32_t flags = ComponentRawViewFlag_None;
148
149 GAIA_NODISCARD ComponentRawMutView operator[](size_t idx) const {
150 GAIA_ASSERT(idx < cnt);
151 if ((flags & ComponentRawViewFlag_Valid) == 0 || idx >= cnt)
152 return {};
153 if (elemSize == 0)
154 return {nullptr, 0, ComponentRawViewFlag_Valid};
155
156 return {pData + (uintptr_t)elemSize * idx, elemSize, ComponentRawViewFlag_Valid};
157 }
158
159 GAIA_NODISCARD constexpr size_t size() const noexcept {
160 return cnt;
161 }
162 };
163
166 struct RawTermViewGetEntity {
167 const Entity* pEntities = nullptr;
168 const World* pWorld = nullptr;
169 Entity component = EntityBad;
170 uint32_t cnt = 0;
171 RawSparseStoreOps sparse{};
172
173 GAIA_NODISCARD ComponentRawView operator[](size_t idx) const {
174 GAIA_ASSERT(idx < cnt);
175 if (pEntities == nullptr || pWorld == nullptr || component == EntityBad || idx >= cnt)
176 return {};
177
178 const auto entity = pEntities[idx];
179 if (sparse.pStore != nullptr) {
180 if (sparse.funcHas(sparse.pStore, entity))
181 return {sparse.funcGet(sparse.pStore, entity), sparse.elemSize, ComponentRawViewFlag_Valid};
182 }
183
184 return world_get_raw(*pWorld, entity, component);
185 }
186
187 GAIA_NODISCARD constexpr size_t size() const noexcept {
188 return cnt;
189 }
190 };
191
194 struct RawTermViewSetEntity {
195 const Entity* pEntities = nullptr;
196 World* pWorld = nullptr;
197 Entity component = EntityBad;
198 uint32_t cnt = 0;
199 RawSparseStoreOps sparse{};
200
201 GAIA_NODISCARD ComponentRawMutView operator[](size_t idx) const {
202 GAIA_ASSERT(idx < cnt);
203 if (pEntities == nullptr || pWorld == nullptr || component == EntityBad || idx >= cnt)
204 return {};
205
206 const auto entity = pEntities[idx];
207 if (sparse.pStore != nullptr)
208 return {
209 sparse.funcMut(const_cast<void*>(sparse.pStore), entity), sparse.elemSize, ComponentRawViewFlag_Valid};
210
211 return world_mut_raw(*pWorld, entity, component);
212 }
213
214 GAIA_NODISCARD constexpr size_t size() const noexcept {
215 return cnt;
216 }
217 };
218
221 template <typename U>
222 struct EntityTermViewGetPointer {
223 const U* pData = nullptr;
224 uint32_t cnt = 0;
225
226 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
227 GAIA_ASSERT(idx < cnt);
228 return pData[idx];
229 }
230
231 GAIA_NODISCARD constexpr size_t size() const noexcept {
232 return cnt;
233 }
234
235 GAIA_NODISCARD const U* data() const noexcept {
236 return pData;
237 }
238 };
239
242 template <typename U>
243 struct EntityTermViewGetEntity {
244 const Entity* pEntities = nullptr;
245 World* pWorld = nullptr;
246 Entity id = EntityBad;
247 uint32_t cnt = 0;
248 mutable const Archetype* pLastArchetype = nullptr;
249 mutable Entity cachedOwner = EntityBad;
250 mutable bool cachedDirect = false;
251
252 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
253 GAIA_ASSERT(idx < cnt);
254 return world_query_entity_arg_by_id_cached_const<const U&>(
255 *pWorld, pEntities[idx], id, pLastArchetype, cachedOwner, cachedDirect);
256 }
257
258 GAIA_NODISCARD constexpr size_t size() const noexcept {
259 return cnt;
260 }
261
262 GAIA_NODISCARD const U* data() const noexcept {
263 return nullptr;
264 }
265 };
266
269 template <typename U>
270 struct EntityTermViewSetPointer {
271 U* pData = nullptr;
272 uint32_t cnt = 0;
273
274 GAIA_NODISCARD decltype(auto) operator[](size_t idx) {
275 GAIA_ASSERT(idx < cnt);
276 return pData[idx];
277 }
278
279 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
280 GAIA_ASSERT(idx < cnt);
281 return static_cast<const U&>(pData[idx]);
282 }
283
284 GAIA_NODISCARD constexpr size_t size() const noexcept {
285 return cnt;
286 }
287
288 GAIA_NODISCARD U* data() noexcept {
289 return pData;
290 }
291
292 GAIA_NODISCARD const U* data() const noexcept {
293 return pData;
294 }
295 };
296
299 template <typename U, bool WriteIm>
300 struct EntityTermViewSetEntity {
301 const Entity* pEntities = nullptr;
302 World* pWorld = nullptr;
303 Entity id = EntityBad;
304 uint32_t cnt = 0;
305
306 GAIA_NODISCARD decltype(auto) operator[](size_t idx) {
307 GAIA_ASSERT(idx < cnt);
308 if constexpr (WriteIm)
309 return world_query_entity_arg_by_id<U&>(*pWorld, pEntities[idx], id);
310 else
311 return world_query_entity_arg_by_id_raw<U&>(*pWorld, pEntities[idx], id);
312 }
313
314 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
315 GAIA_ASSERT(idx < cnt);
316 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
317 }
318
319 GAIA_NODISCARD constexpr size_t size() const noexcept {
320 return cnt;
321 }
322
323 GAIA_NODISCARD U* data() noexcept {
324 return nullptr;
325 }
326
327 GAIA_NODISCARD const U* data() const noexcept {
328 return nullptr;
329 }
330 };
331
333 template <typename U>
334 struct EntityTermViewGetSparse {
335 const Entity* pEntities = nullptr;
336 World* pWorld = nullptr;
337 const void* pStore = nullptr;
338 Entity id = EntityBad;
339 uint32_t cnt = 0;
340
341 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
342 GAIA_ASSERT(idx < cnt);
343 const auto entity = pEntities[idx];
344 if (world_typed_sparse_store_has<U>(pStore, entity))
345 return world_typed_sparse_store_get<U>(pStore, entity);
346 return world_query_entity_arg_by_id<const U&>(*pWorld, entity, id);
347 }
348
349 GAIA_NODISCARD constexpr size_t size() const noexcept {
350 return cnt;
351 }
352
353 GAIA_NODISCARD const U* data() const noexcept {
354 return nullptr;
355 }
356 };
357
359 template <typename U>
360 struct EntityTermViewSetSparse {
361 const Entity* pEntities = nullptr;
362 World* pWorld = nullptr;
363 void* pStore = nullptr;
364 Entity id = EntityBad;
365 uint32_t cnt = 0;
366
367 GAIA_NODISCARD decltype(auto) operator[](size_t idx) {
368 GAIA_ASSERT(idx < cnt);
369 const auto entity = pEntities[idx];
370 if (world_typed_sparse_store_has<U>(pStore, entity))
371 return world_typed_sparse_store_mut<U>(pStore, entity);
372 return world_query_entity_arg_by_id_raw<U&>(*pWorld, entity, id);
373 }
374
375 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
376 GAIA_ASSERT(idx < cnt);
377 const auto entity = pEntities[idx];
378 if (world_typed_sparse_store_has<U>(pStore, entity))
379 return world_typed_sparse_store_get<U>(pStore, entity);
380 return world_query_entity_arg_by_id<const U&>(*pWorld, entity, id);
381 }
382
383 GAIA_NODISCARD constexpr size_t size() const noexcept {
384 return cnt;
385 }
386
387 GAIA_NODISCARD U* data() noexcept {
388 return nullptr;
389 }
390
391 GAIA_NODISCARD const U* data() const noexcept {
392 return nullptr;
393 }
394 };
395
398 template <typename U>
399 struct EntityTermViewGet {
400 const U* pData = nullptr;
401 const Entity* pEntities = nullptr;
402 World* pWorld = nullptr;
403 Entity id = EntityBad;
404 uint32_t cnt = 0;
405 const U* pDataInherited = nullptr;
406 mutable const Archetype* pLastArchetype = nullptr;
407 mutable Entity cachedOwner = EntityBad;
408 mutable bool cachedDirect = false;
409
410 static EntityTermViewGet pointer(const U* pData, uint32_t cnt) {
411 return {pData, nullptr, nullptr, EntityBad, cnt, nullptr, nullptr, EntityBad, false};
412 }
413
414 static EntityTermViewGet entity(const Entity* pEntities, World* pWorld, Entity id, uint32_t cnt) {
415 return {nullptr, pEntities, pWorld, id, cnt, nullptr, nullptr, EntityBad, false};
416 }
417
418 static EntityTermViewGet inherited(const U* pDataInherited, uint32_t cnt) {
419 return {nullptr, nullptr, nullptr, EntityBad, cnt, pDataInherited, nullptr, EntityBad, false};
420 }
421
422 static EntityTermViewGet entity_chunk_stable(
423 const Entity* pEntities, const Chunk* pChunk, World* pWorld, Entity id, uint16_t rowBase, uint32_t cnt) {
424 uint32_t compIdx = BadIndex;
425 const U* pDataInherited = nullptr;
426 bool direct = false;
427 world_init_query_entity_arg_by_id_chunk_stable_const<U>(
428 *pWorld, *pChunk, pEntities, id, direct, compIdx, pDataInherited);
429 const U* pData = nullptr;
430 if (direct)
431 pData = reinterpret_cast<const U*>(pChunk->comp_ptr(compIdx, rowBase));
432
433 return {pData, nullptr, pWorld, id, cnt, pDataInherited, nullptr, EntityBad, false};
434 }
435
436 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
437 GAIA_ASSERT(idx < cnt);
438 if (pData != nullptr)
439 return pData[idx];
440 if (pDataInherited != nullptr) {
441 GAIA_ASSERT(pDataInherited != nullptr);
442 return *pDataInherited;
443 }
444
445 return world_query_entity_arg_by_id_cached_const<const U&>(
446 *pWorld, pEntities[idx], id, pLastArchetype, cachedOwner, cachedDirect);
447 }
448
449 GAIA_NODISCARD constexpr size_t size() const noexcept {
450 return cnt;
451 }
452
453 GAIA_NODISCARD const U* data() const noexcept {
454 return pData;
455 }
456 };
457
460 template <typename U>
461 struct EntityTermViewSet {
462 U* pData = nullptr;
463 const Entity* pEntities = nullptr;
464 World* pWorld = nullptr;
465 Entity id = EntityBad;
466 uint32_t cnt = 0;
467 bool writeIm = true;
468
469 static EntityTermViewSet pointer(U* pData, uint32_t cnt) {
470 return {pData, nullptr, nullptr, EntityBad, cnt, true};
471 }
472
473 static EntityTermViewSet
474 entity(const Entity* pEntities, World* pWorld, Entity id, uint32_t cnt, bool writeIm = true) {
475 return {nullptr, pEntities, pWorld, id, cnt, writeIm};
476 }
477
478 GAIA_NODISCARD decltype(auto) operator[](size_t idx) {
479 GAIA_ASSERT(idx < cnt);
480 if (pData != nullptr)
481 return pData[idx];
482
483 if (writeIm)
484 return EntityTermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}[idx];
485 return EntityTermViewSetEntity<U, false>{pEntities, pWorld, id, cnt}[idx];
486 }
487
488 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
489 GAIA_ASSERT(idx < cnt);
490 if (pData != nullptr)
491 return static_cast<const U&>(pData[idx]);
492
493 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
494 }
495
496 GAIA_NODISCARD constexpr size_t size() const noexcept {
497 return cnt;
498 }
499
500 GAIA_NODISCARD U* data() noexcept {
501 return pData;
502 }
503
504 GAIA_NODISCARD const U* data() const noexcept {
505 return pData;
506 }
507 };
508
511 template <typename U>
512 struct SoATermRowWriteProxyPointer {
513 using raw_view_policy = mem::data_view_policy_soa<U::gaia_Data_Layout, U>;
514
515 uint8_t* pData = nullptr;
516 uint32_t dataSize = 0;
517 uint32_t idx = 0;
518
519 GAIA_NODISCARD operator U() const {
520 return raw_view_policy::get(std::span<const uint8_t>{pData, dataSize}, idx);
521 }
522
523 SoATermRowWriteProxyPointer& operator=(const U& value) {
524 raw_view_policy::set(std::span<uint8_t>{pData, dataSize}, idx) = value;
525 return *this;
526 }
527 };
528
531 template <typename U, bool WriteIm>
532 struct SoATermRowWriteProxyEntity {
533 const Entity* pEntities = nullptr;
534 World* pWorld = nullptr;
535 Entity id = EntityBad;
536 uint32_t idx = 0;
537
538 GAIA_NODISCARD operator U() const {
539 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
540 }
541
542 SoATermRowWriteProxyEntity& operator=(const U& value) {
543 if constexpr (WriteIm)
544 world_query_entity_arg_by_id<U&>(*pWorld, pEntities[idx], id) = value;
545 else
546 world_query_entity_arg_by_id_raw<U&>(*pWorld, pEntities[idx], id) = value;
547 return *this;
548 }
549 };
550
553 template <typename U, size_t Item>
554 struct SoATermFieldReadProxyPointer {
555 using view_policy = mem::data_view_policy_soa_get<U::gaia_Data_Layout, U>;
556 using value_type = typename view_policy::template data_view_policy_idx_info<Item>::const_value_type;
557
558 const value_type* pData = nullptr;
559 uint32_t cnt = 0;
560
561 GAIA_NODISCARD value_type operator[](size_t idx) const {
562 GAIA_ASSERT(idx < cnt);
563 return pData[idx];
564 }
565
566 GAIA_NODISCARD constexpr size_t size() const noexcept {
567 return cnt;
568 }
569 };
570
573 template <typename U, size_t Item>
574 struct SoATermFieldReadProxyEntity {
575 using view_policy = mem::data_view_policy_soa_get<U::gaia_Data_Layout, U>;
576 using value_type = typename view_policy::template data_view_policy_idx_info<Item>::const_value_type;
577
578 const Entity* pEntities = nullptr;
579 World* pWorld = nullptr;
580 Entity id = EntityBad;
581 uint32_t cnt = 0;
582
583 GAIA_NODISCARD value_type operator[](size_t idx) const {
584 GAIA_ASSERT(idx < cnt);
585 const U value = world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
586 return std::get<Item>(meta::struct_to_tuple(value));
587 }
588
589 GAIA_NODISCARD constexpr size_t size() const noexcept {
590 return cnt;
591 }
592 };
593
596 template <typename U, size_t Item>
597 struct SoATermFieldWriteProxyPointer {
598 using view_policy = mem::data_view_policy_soa_set<U::gaia_Data_Layout, U>;
599 using value_type = typename view_policy::template data_view_policy_idx_info<Item>::value_type;
600
601 value_type* pData = nullptr;
602 uint32_t cnt = 0;
603
604 GAIA_NODISCARD value_type& operator[](size_t idx) {
605 GAIA_ASSERT(idx < cnt);
606 return pData[idx];
607 }
608
609 GAIA_NODISCARD const value_type& operator[](size_t idx) const {
610 GAIA_ASSERT(idx < cnt);
611 return pData[idx];
612 }
613
614 GAIA_NODISCARD constexpr size_t size() const noexcept {
615 return cnt;
616 }
617 };
618
621 template <typename U, size_t Item, bool WriteIm>
622 struct SoATermFieldWriteProxyEntity {
623 using view_policy = mem::data_view_policy_soa_set<U::gaia_Data_Layout, U>;
624 using value_type = typename view_policy::template data_view_policy_idx_info<Item>::value_type;
625
627 struct ElementProxy {
628 const Entity* pEntities = nullptr;
629 World* pWorld = nullptr;
630 Entity id = EntityBad;
631 uint32_t idx = 0;
632
633 GAIA_NODISCARD operator value_type() const {
634 const U value = world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
635 return std::get<Item>(meta::struct_to_tuple(value));
636 }
637
638 ElementProxy& operator=(const value_type& value) {
639 auto data = world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
640 auto tuple = meta::struct_to_tuple(data);
641 std::get<Item>(tuple) = value;
642 if constexpr (WriteIm)
643 world_query_entity_arg_by_id<U&>(*pWorld, pEntities[idx], id) = meta::tuple_to_struct<U>(GAIA_MOV(tuple));
644 else
645 world_query_entity_arg_by_id_raw<U&>(*pWorld, pEntities[idx], id) =
646 meta::tuple_to_struct<U>(GAIA_MOV(tuple));
647 return *this;
648 }
649
650 template <typename V>
651 ElementProxy& operator+=(V&& value) {
652 const value_type current = operator value_type();
653 return operator=(current + GAIA_FWD(value));
654 }
655
656 template <typename V>
657 ElementProxy& operator-=(V&& value) {
658 const value_type current = operator value_type();
659 return operator=(current - GAIA_FWD(value));
660 }
661
662 template <typename V>
663 ElementProxy& operator*=(V&& value) {
664 const value_type current = operator value_type();
665 return operator=(current * GAIA_FWD(value));
666 }
667
668 template <typename V>
669 ElementProxy& operator/=(V&& value) {
670 const value_type current = operator value_type();
671 return operator=(current / GAIA_FWD(value));
672 }
673 };
674
675 const Entity* pEntities = nullptr;
676 World* pWorld = nullptr;
677 Entity id = EntityBad;
678 uint32_t cnt = 0;
679
680 GAIA_NODISCARD ElementProxy operator[](size_t idx) const {
681 GAIA_ASSERT(idx < cnt);
682 return ElementProxy{pEntities, pWorld, id, (uint32_t)idx};
683 }
684
685 GAIA_NODISCARD constexpr size_t size() const noexcept {
686 return cnt;
687 }
688 };
689
692 template <typename U>
693 struct SoATermViewGetPointer {
694 using raw_view_policy = mem::data_view_policy_soa<U::gaia_Data_Layout, U>;
695 using read_view_policy = mem::data_view_policy_soa_get<U::gaia_Data_Layout, U>;
696
697 const uint8_t* pData = nullptr;
698 uint32_t dataSize = 0;
699 uint32_t idxBase = 0;
700 uint32_t cnt = 0;
701
702 GAIA_NODISCARD U operator[](size_t idx) const {
703 GAIA_ASSERT(idx < cnt);
704 return raw_view_policy::get(std::span<const uint8_t>{pData, dataSize}, idxBase + idx);
705 }
706
707 template <size_t Item>
708 GAIA_NODISCARD auto get() const {
709 const auto field = read_view_policy{std::span<const uint8_t>{pData, dataSize}}.template get<Item>();
710 return SoATermFieldReadProxyPointer<U, Item>{field.data() + idxBase, cnt};
711 }
712
713 GAIA_NODISCARD constexpr size_t size() const noexcept {
714 return cnt;
715 }
716 };
717
720 template <typename U>
721 struct SoATermViewGetEntity {
722 const Entity* pEntities = nullptr;
723 World* pWorld = nullptr;
724 Entity id = EntityBad;
725 uint32_t cnt = 0;
726
727 GAIA_NODISCARD U operator[](size_t idx) const {
728 GAIA_ASSERT(idx < cnt);
729 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
730 }
731
732 template <size_t Item>
733 GAIA_NODISCARD auto get() const {
734 return SoATermFieldReadProxyEntity<U, Item>{pEntities, pWorld, id, cnt};
735 }
736
737 GAIA_NODISCARD constexpr size_t size() const noexcept {
738 return cnt;
739 }
740 };
741
744 template <typename U>
745 struct SoATermViewSetPointer {
746 using raw_view_policy = mem::data_view_policy_soa<U::gaia_Data_Layout, U>;
747 using read_view_policy = mem::data_view_policy_soa_get<U::gaia_Data_Layout, U>;
748 using write_view_policy = mem::data_view_policy_soa_set<U::gaia_Data_Layout, U>;
749
750 uint8_t* pData = nullptr;
751 uint32_t dataSize = 0;
752 uint32_t idxBase = 0;
753 uint32_t cnt = 0;
754
755 GAIA_NODISCARD auto operator[](size_t idx) {
756 GAIA_ASSERT(idx < cnt);
757 return SoATermRowWriteProxyPointer<U>{pData, dataSize, idxBase + (uint32_t)idx};
758 }
759
760 GAIA_NODISCARD U operator[](size_t idx) const {
761 GAIA_ASSERT(idx < cnt);
762 return raw_view_policy::get(std::span<const uint8_t>{pData, dataSize}, idxBase + idx);
763 }
764
765 template <size_t Item>
766 GAIA_NODISCARD auto get() const {
767 const auto field = read_view_policy{std::span<const uint8_t>{pData, dataSize}}.template get<Item>();
768 return SoATermFieldReadProxyPointer<U, Item>{field.data() + idxBase, cnt};
769 }
770
771 template <size_t Item>
772 GAIA_NODISCARD auto set() {
773 auto field = write_view_policy{std::span<uint8_t>{pData, dataSize}}.template set<Item>();
774 return SoATermFieldWriteProxyPointer<U, Item>{field.data() + idxBase, cnt};
775 }
776
777 GAIA_NODISCARD constexpr size_t size() const noexcept {
778 return cnt;
779 }
780 };
781
784 template <typename U, bool WriteIm>
785 struct SoATermViewSetEntity {
786 const Entity* pEntities = nullptr;
787 World* pWorld = nullptr;
788 Entity id = EntityBad;
789 uint32_t cnt = 0;
790
791 GAIA_NODISCARD auto operator[](size_t idx) {
792 GAIA_ASSERT(idx < cnt);
793 return SoATermRowWriteProxyEntity<U, WriteIm>{pEntities, pWorld, id, (uint32_t)idx};
794 }
795
796 GAIA_NODISCARD U operator[](size_t idx) const {
797 GAIA_ASSERT(idx < cnt);
798 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
799 }
800
801 template <size_t Item>
802 GAIA_NODISCARD auto get() const {
803 return SoATermFieldReadProxyEntity<U, Item>{pEntities, pWorld, id, cnt};
804 }
805
806 template <size_t Item>
807 GAIA_NODISCARD auto set() {
808 return SoATermFieldWriteProxyEntity<U, Item, WriteIm>{pEntities, pWorld, id, cnt};
809 }
810
811 GAIA_NODISCARD constexpr size_t size() const noexcept {
812 return cnt;
813 }
814 };
815
818 template <typename U>
819 struct SoATermRowWriteProxy {
820 uint8_t* pData = nullptr;
821 uint32_t dataSize = 0;
822 const Entity* pEntities = nullptr;
823 World* pWorld = nullptr;
824 Entity id = EntityBad;
825 uint32_t idx = 0;
826 bool writeIm = true;
827
828 GAIA_NODISCARD operator U() const {
829 if (pData != nullptr)
830 return (U)SoATermRowWriteProxyPointer<U>{pData, dataSize, idx};
831
832 if (writeIm)
833 return (U)SoATermRowWriteProxyEntity<U, true>{pEntities, pWorld, id, idx};
834 return (U)SoATermRowWriteProxyEntity<U, false>{pEntities, pWorld, id, idx};
835 }
836
837 SoATermRowWriteProxy& operator=(const U& value) {
838 if (pData != nullptr) {
839 SoATermRowWriteProxyPointer<U>{pData, dataSize, idx} = value;
840 } else if (writeIm)
841 SoATermRowWriteProxyEntity<U, true>{pEntities, pWorld, id, idx} = value;
842 else
843 SoATermRowWriteProxyEntity<U, false>{pEntities, pWorld, id, idx} = value;
844 return *this;
845 }
846 };
847
850 template <typename U, size_t Item>
851 struct SoATermFieldReadProxy {
852 using value_type = typename SoATermFieldReadProxyPointer<U, Item>::value_type;
853
854 const value_type* pData = nullptr;
855 const Entity* pEntities = nullptr;
856 World* pWorld = nullptr;
857 Entity id = EntityBad;
858 uint32_t cnt = 0;
859
860 GAIA_NODISCARD value_type operator[](size_t idx) const {
861 GAIA_ASSERT(idx < cnt);
862 if (pData != nullptr)
863 return SoATermFieldReadProxyPointer<U, Item>{pData, cnt}[idx];
864
865 return SoATermFieldReadProxyEntity<U, Item>{pEntities, pWorld, id, cnt}[idx];
866 }
867
868 GAIA_NODISCARD constexpr size_t size() const noexcept {
869 return cnt;
870 }
871 };
872
875 template <typename U, size_t Item>
876 struct SoATermFieldWriteProxy {
877 using value_type = typename SoATermFieldWriteProxyPointer<U, Item>::value_type;
878
879 value_type* pData = nullptr;
880 const Entity* pEntities = nullptr;
881 World* pWorld = nullptr;
882 Entity id = EntityBad;
883 uint32_t cnt = 0;
884 bool writeIm = true;
885
888 struct ElementProxy {
889 value_type* pData = nullptr;
890 const Entity* pEntities = nullptr;
891 World* pWorld = nullptr;
892 Entity id = EntityBad;
893 uint32_t idx = 0;
894 bool writeIm = true;
895
896 GAIA_NODISCARD operator value_type() const {
897 if (pData != nullptr)
898 return SoATermFieldWriteProxyPointer<U, Item>{pData, idx + 1}[idx];
899
900 if (writeIm)
901 return SoATermFieldWriteProxyEntity<U, Item, true>{pEntities, pWorld, id, idx + 1}[idx];
902 return SoATermFieldWriteProxyEntity<U, Item, false>{pEntities, pWorld, id, idx + 1}[idx];
903 }
904
905 ElementProxy& operator=(const value_type& value) {
906 if (pData != nullptr) {
907 SoATermFieldWriteProxyPointer<U, Item>{pData, idx + 1}[idx] = value;
908 return *this;
909 }
910
911 if (writeIm)
912 SoATermFieldWriteProxyEntity<U, Item, true>{pEntities, pWorld, id, idx + 1}[idx] = value;
913 else
914 SoATermFieldWriteProxyEntity<U, Item, false>{pEntities, pWorld, id, idx + 1}[idx] = value;
915 return *this;
916 }
917
918 template <typename V>
919 ElementProxy& operator+=(V&& value) {
920 const value_type current = operator value_type();
921 return operator=(current + GAIA_FWD(value));
922 }
923
924 template <typename V>
925 ElementProxy& operator-=(V&& value) {
926 const value_type current = operator value_type();
927 return operator=(current - GAIA_FWD(value));
928 }
929
930 template <typename V>
931 ElementProxy& operator*=(V&& value) {
932 const value_type current = operator value_type();
933 return operator=(current * GAIA_FWD(value));
934 }
935
936 template <typename V>
937 ElementProxy& operator/=(V&& value) {
938 const value_type current = operator value_type();
939 return operator=(current / GAIA_FWD(value));
940 }
941 };
942
943 GAIA_NODISCARD ElementProxy operator[](size_t idx) const {
944 GAIA_ASSERT(idx < cnt);
945 return ElementProxy{pData, pEntities, pWorld, id, (uint32_t)idx, writeIm};
946 }
947
948 GAIA_NODISCARD constexpr size_t size() const noexcept {
949 return cnt;
950 }
951 };
952
955 template <typename U>
956 struct SoATermViewGet {
957 const uint8_t* pData = nullptr;
958 uint32_t dataSize = 0;
959 const Entity* pEntities = nullptr;
960 World* pWorld = nullptr;
961 Entity id = EntityBad;
962 uint32_t idxBase = 0;
963 uint32_t cnt = 0;
964
965 GAIA_NODISCARD U operator[](size_t idx) const {
966 GAIA_ASSERT(idx < cnt);
967 if (pData != nullptr)
968 return SoATermViewGetPointer<U>{pData, dataSize, idxBase, cnt}[idx];
969
970 return SoATermViewGetEntity<U>{pEntities, pWorld, id, cnt}[idx];
971 }
972
973 template <size_t Item>
974 GAIA_NODISCARD auto get() const {
975 if (pData != nullptr) {
976 const auto field = SoATermViewGetPointer<U>{pData, dataSize, idxBase, cnt}.template get<Item>();
977 return SoATermFieldReadProxy<U, Item>{field.pData, nullptr, pWorld, id, cnt};
978 }
979
980 const auto field = SoATermViewGetEntity<U>{pEntities, pWorld, id, cnt}.template get<Item>();
981 return SoATermFieldReadProxy<U, Item>{nullptr, field.pEntities, field.pWorld, field.id, field.cnt};
982 }
983
984 GAIA_NODISCARD constexpr size_t size() const noexcept {
985 return cnt;
986 }
987 };
988
991 template <typename U>
992 struct SoATermViewSet {
993 uint8_t* pData = nullptr;
994 uint32_t dataSize = 0;
995 const Entity* pEntities = nullptr;
996 World* pWorld = nullptr;
997 Entity id = EntityBad;
998 uint32_t idxBase = 0;
999 uint32_t cnt = 0;
1000 bool writeIm = true;
1001
1002 GAIA_NODISCARD auto operator[](size_t idx) {
1003 GAIA_ASSERT(idx < cnt);
1004 return SoATermRowWriteProxy<U>{pData, dataSize, pEntities, pWorld, id, idxBase + (uint32_t)idx, writeIm};
1005 }
1006
1007 GAIA_NODISCARD U operator[](size_t idx) const {
1008 GAIA_ASSERT(idx < cnt);
1009 if (pData != nullptr)
1010 return SoATermViewSetPointer<U>{pData, dataSize, idxBase, cnt}[idx];
1011
1012 return SoATermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}[idx];
1013 }
1014
1015 template <size_t Item>
1016 GAIA_NODISCARD auto get() const {
1017 if (pData != nullptr) {
1018 const auto field = SoATermViewSetPointer<U>{pData, dataSize, idxBase, cnt}.template get<Item>();
1019 return SoATermFieldReadProxy<U, Item>{field.pData, nullptr, pWorld, id, cnt};
1020 }
1021
1022 const auto field = SoATermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}.template get<Item>();
1023 return SoATermFieldReadProxy<U, Item>{nullptr, field.pEntities, field.pWorld, field.id, field.cnt};
1024 }
1025
1026 template <size_t Item>
1027 GAIA_NODISCARD auto set() {
1028 if (pData != nullptr) {
1029 auto field = SoATermViewSetPointer<U>{pData, dataSize, idxBase, cnt}.template set<Item>();
1030 return SoATermFieldWriteProxy<U, Item>{field.pData, nullptr, pWorld, id, cnt};
1031 }
1032
1033 if (writeIm) {
1034 const auto field = SoATermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}.template set<Item>();
1035 return SoATermFieldWriteProxy<U, Item>{nullptr, field.pEntities, field.pWorld, field.id, field.cnt, true};
1036 }
1037
1038 const auto field = SoATermViewSetEntity<U, false>{pEntities, pWorld, id, cnt}.template set<Item>();
1039 return SoATermFieldWriteProxy<U, Item>{nullptr, field.pEntities, field.pWorld, field.id, field.cnt, false};
1040 }
1041
1042 GAIA_NODISCARD constexpr size_t size() const noexcept {
1043 return cnt;
1044 }
1045 };
1046
1047 class ChunkIterImpl {
1048 friend struct ChunkIterTypedOps;
1049
1050 protected:
1051 using CompIndicesBitView = core::bit_view<ChunkHeader::MAX_COMPONENTS_BITS>;
1052
1054 const World* m_pWorld = nullptr;
1056 const Archetype* m_pArchetype = nullptr;
1058 Chunk* m_pChunk = nullptr;
1060 const uint8_t* m_pCompIndices = nullptr;
1062 InheritedTermDataView m_inheritedData;
1064 const Entity* m_pTermIdMapping = nullptr;
1066 bool m_writeIm = true;
1068 Constraints m_constraints = Constraints::EnabledOnly;
1070 uint8_t m_touchedCompIndices[ChunkHeader::MAX_COMPONENTS];
1071 uint8_t m_touchedCompCnt = 0;
1073 Entity m_touchedTerms[ChunkHeader::MAX_COMPONENTS];
1074 uint8_t m_touchedTermCnt = 0;
1076 Entity m_entitySnapshot[ChunkHeader::MAX_CHUNK_ENTITIES];
1077 bool m_entitySnapshotValid = false;
1079 uint16_t m_from;
1081 uint16_t m_to;
1083 GroupId m_groupId = 0;
1085 void* m_pCtx = nullptr;
1086
1087 public:
1088 ChunkIterImpl() = default;
1089 ~ChunkIterImpl() = default;
1090 ChunkIterImpl(ChunkIterImpl&&) noexcept = default;
1091 ChunkIterImpl& operator=(ChunkIterImpl&&) noexcept = default;
1092 ChunkIterImpl(const ChunkIterImpl&) = delete;
1093 ChunkIterImpl& operator=(const ChunkIterImpl&) = delete;
1094
1095 void set_world(const World* pWorld) {
1096 GAIA_ASSERT(pWorld != nullptr);
1097 m_pWorld = pWorld;
1098 }
1099
1100 GAIA_NODISCARD World* world() {
1101 GAIA_ASSERT(m_pWorld != nullptr);
1102 return const_cast<World*>(m_pWorld);
1103 }
1104
1105 GAIA_NODISCARD const World* world() const {
1106 GAIA_ASSERT(m_pWorld != nullptr);
1107 return m_pWorld;
1108 }
1109
1110 void set_archetype(const Archetype* pArchetype) {
1111 GAIA_ASSERT(pArchetype != nullptr);
1112 m_pArchetype = pArchetype;
1113 }
1114
1115 // GAIA_NODISCARD Archetype* archetype() {
1116 // GAIA_ASSERT(m_pArchetype != nullptr);
1117 // return m_pArchetype;
1118 // }
1119
1120 GAIA_NODISCARD const Archetype* archetype() const {
1121 GAIA_ASSERT(m_pArchetype != nullptr);
1122 return m_pArchetype;
1123 }
1124
1125 void set_chunk(Chunk* pChunk) {
1126 GAIA_ASSERT(pChunk != nullptr);
1127 m_pChunk = pChunk;
1128 m_entitySnapshotValid = false;
1129 m_from = start_index(m_pChunk, m_constraints);
1130 m_to = end_index(m_pChunk, m_constraints);
1131 }
1132
1133 void set_chunk(Chunk* pChunk, uint16_t from, uint16_t to) {
1134 if (from == 0 && to == 0) {
1135 set_chunk(pChunk);
1136 return;
1137 }
1138
1139 GAIA_ASSERT(pChunk != nullptr);
1140 m_pChunk = pChunk;
1141 m_entitySnapshotValid = false;
1142 m_from = from;
1143 m_to = to;
1144 }
1145
1146 GAIA_NODISCARD const Chunk* chunk() const {
1147 GAIA_ASSERT(m_pChunk != nullptr);
1148 return m_pChunk;
1149 }
1150
1151 void set_comp_indices(const uint8_t* pCompIndices) {
1152 m_pCompIndices = pCompIndices;
1153 }
1154
1155 void set_inherited_data(InheritedTermDataView inheritedData) {
1156 m_inheritedData = inheritedData;
1157 }
1158
1159 void set_term_ids(const Entity* pTermIds) {
1160 m_pTermIdMapping = pTermIds;
1161 }
1162
1163 GAIA_NODISCARD const uint8_t* comp_indices() const {
1164 return m_pCompIndices;
1165 }
1166
1167 GAIA_NODISCARD InheritedTermDataView inherited_data() const {
1168 return m_inheritedData;
1169 }
1170
1171 GAIA_NODISCARD const Entity* term_ids() const {
1172 return m_pTermIdMapping;
1173 }
1174
1175 void set_write_im(bool value) {
1176 m_writeIm = value;
1177 clear_touched_writes();
1178 }
1179
1180 void set_constraints(Constraints constraints) {
1181 m_constraints = constraints;
1182 if (m_pChunk != nullptr) {
1183 m_from = start_index(m_pChunk, m_constraints);
1184 m_to = end_index(m_pChunk, m_constraints);
1185 m_entitySnapshotValid = false;
1186 }
1187 }
1188
1193 void init_query_state(const World* pWorld, Constraints constraints, bool writeIm) {
1194 set_world(pWorld);
1195 m_constraints = constraints;
1196 m_writeIm = writeIm;
1197 clear_touched_writes();
1198 }
1199
1206 void set_query_chunk(
1207 const Archetype* pArchetype, const uint8_t* pCompIndices, Chunk* pChunk, uint16_t from, uint16_t to) {
1208 GAIA_ASSERT(pArchetype != nullptr);
1209 GAIA_ASSERT(pChunk != nullptr);
1210 if (m_pArchetype != pArchetype)
1211 m_pArchetype = pArchetype;
1212 if (m_pCompIndices != pCompIndices)
1213 m_pCompIndices = pCompIndices;
1214 m_pChunk = pChunk;
1215 m_entitySnapshotValid = false;
1216 m_from = from;
1217 m_to = to;
1218 }
1219
1220 GAIA_NODISCARD bool write_im() const {
1221 return m_writeIm;
1222 }
1223
1224 GAIA_NODISCARD Constraints constraints() const {
1225 return m_constraints;
1226 }
1227
1228 void clear_touched_writes() {
1229 m_touchedCompCnt = 0;
1230 m_touchedTermCnt = 0;
1231 }
1232
1233 GAIA_NODISCARD const Entity* entity_snapshot() {
1234 if (!m_entitySnapshotValid) {
1235 const auto cnt = size();
1236 GAIA_ASSERT(cnt <= ChunkHeader::MAX_CHUNK_ENTITIES);
1237
1238 const auto entities = m_pChunk->entity_view();
1239 GAIA_FOR(cnt) {
1240 m_entitySnapshot[i] = entities[from() + i];
1241 }
1242
1243 m_entitySnapshotValid = true;
1244 }
1245
1246 return m_entitySnapshot;
1247 }
1248
1249 GAIA_NODISCARD auto touched_comp_indices() const {
1250 return std::span<const uint8_t>{m_touchedCompIndices, m_touchedCompCnt};
1251 }
1252
1253 GAIA_NODISCARD auto touched_terms() const {
1254 return std::span<const Entity>{m_touchedTerms, m_touchedTermCnt};
1255 }
1256
1257 GAIA_NODISCARD auto entity_rows() {
1258 if (m_entitySnapshotValid)
1259 return std::span<const Entity>{m_entitySnapshot, size()};
1260
1261 return std::span<const Entity>{m_pChunk->entity_view().data() + from(), size()};
1262 }
1263
1264 template <typename U>
1265 GAIA_NODISCARD auto entity_view_set(Entity termId, bool writeIm) {
1266 return EntityTermViewSet<U>::entity(entity_snapshot(), world(), termId, size(), writeIm);
1267 }
1268
1270 template <typename U>
1271 GAIA_NODISCARD static auto entity_view_set_empty(bool writeIm) {
1272 return EntityTermViewSet<U>::entity(nullptr, nullptr, EntityBad, 0, writeIm);
1273 }
1274
1275 template <typename U>
1276 GAIA_NODISCARD auto entity_soa_view_set(Entity termId, bool writeIm) {
1277 return SoATermViewSet<U>{nullptr, 0, entity_snapshot(), world(), termId, 0, size(), writeIm};
1278 }
1279
1281 template <typename U>
1282 GAIA_NODISCARD static auto entity_soa_view_set_empty(bool writeIm) {
1283 return SoATermViewSet<U>{nullptr, 0, nullptr, nullptr, EntityBad, 0, 0, writeIm};
1284 }
1285
1286 void set_group_id(GroupId groupId) {
1287 m_groupId = groupId;
1288 }
1289
1290 GAIA_NODISCARD GroupId group_id() const {
1291 return m_groupId;
1292 }
1293
1299
1302 void ctx(void* pCtx) {
1303 m_pCtx = pCtx;
1304 }
1305
1308 GAIA_NODISCARD void* ctx() const {
1309 return m_pCtx;
1310 }
1312
1313 GAIA_NODISCARD CommandBufferST& cmd_buffer_st() const {
1314 auto* pWorld = const_cast<World*>(m_pWorld);
1315 return cmd_buffer_st_get(*pWorld);
1316 }
1317
1318 GAIA_NODISCARD CommandBufferMT& cmd_buffer_mt() const {
1319 auto* pWorld = const_cast<World*>(m_pWorld);
1320 return cmd_buffer_mt_get(*pWorld);
1321 }
1322
1323 GAIA_NODISCARD IterTermDesc resolved_term_desc(uint32_t termIdx, IterTermDesc desc) const {
1324 if (m_pTermIdMapping != nullptr) {
1325 const auto mappedTermId = m_pTermIdMapping[termIdx];
1326 if (mappedTermId != EntityBad)
1327 desc.termId = mappedTermId;
1328 }
1329
1330 if (!desc.storageKnown && !desc.isEntity && desc.termId != EntityBad)
1331 desc.usesSparseStorage = world_component_uses_sparse_storage(*world(), desc.termId);
1332
1333 return desc;
1334 }
1335
1336 void touch_comp_idx(uint8_t compIdx) {
1337 GAIA_ASSERT(compIdx != 0xFF);
1338 GAIA_FOR(m_touchedCompCnt) {
1339 if (m_touchedCompIndices[i] == compIdx)
1340 return;
1341 }
1342
1343 GAIA_ASSERT(m_touchedCompCnt < ChunkHeader::MAX_COMPONENTS);
1344 m_touchedCompIndices[m_touchedCompCnt++] = compIdx;
1345 }
1346
1347 GAIA_NODISCARD bool touch_term(Entity term) {
1348 GAIA_ASSERT(term != EntityBad);
1349 GAIA_FOR(m_touchedTermCnt) {
1350 if (m_touchedTerms[i] == term)
1351 return true;
1352 }
1353
1354 if (m_touchedTermCnt >= ChunkHeader::MAX_COMPONENTS)
1355 return false;
1356
1357 m_touchedTerms[m_touchedTermCnt++] = term;
1358 return true;
1359 }
1360
1361 GAIA_NODISCARD bool touch_term_desc(const IterTermDesc& desc) {
1362 if (desc.isEntity)
1363 return true;
1364 if (desc.usesSparseStorage)
1365 return touch_term(desc.termId);
1366 touch_comp_idx((uint8_t)m_pChunk->comp_idx(desc.termId));
1367 return true;
1368 }
1369
1373 GAIA_NODISCARD bool touch_raw_component(Entity component) {
1374 if (!world_component_uses_sparse_storage(*world(), component)) {
1375 const auto compIdx = core::get_index(m_pChunk->ids_view(), component);
1376 if (compIdx != BadIndex) {
1377 touch_comp_idx((uint8_t)compIdx);
1378 return true;
1379 }
1380 }
1381
1382 return touch_term(component);
1383 }
1384
1388 GAIA_NODISCARD bool owns_raw_component(Entity component) {
1389 const auto* pEntities = entity_snapshot();
1390 GAIA_FOR(size()) {
1391 if (!world_mut_raw(*world(), pEntities[i], component).valid())
1392 return false;
1393 }
1394
1395 return true;
1396 }
1397
1398 GAIA_NODISCARD RawTermViewGet raw_term_view(uint32_t termIdx) const {
1399 if (m_pCompIndices == nullptr || m_pChunk == nullptr)
1400 return {};
1401
1402 const auto compIdx = m_pCompIndices[termIdx];
1403 if (compIdx == 0xFF)
1404 return {};
1405
1406 const auto recs = m_pChunk->comp_rec_view();
1407 if (compIdx >= recs.size())
1408 return {};
1409
1410 const auto term = m_pChunk->ids_view()[compIdx];
1411 const auto& rec = recs[compIdx];
1412 if (rec.comp.soa() != 0)
1413 return {};
1414
1415 const auto elemSize = rec.comp.size();
1416 const auto row = (uint32_t)(from() * (1U - (uint32_t)term.kind()));
1417 const auto* pData = elemSize != 0 ? m_pChunk->comp_ptr(compIdx, row) : nullptr;
1418 return {pData, elemSize, size(), ComponentRawViewFlag_Valid};
1419 }
1420
1428 GAIA_NODISCARD bool raw_term_field_info(
1429 uint32_t termIdx, uint32_t fieldIdx, uint8_t& compIdx, const ComponentCacheItem*& pItem) const {
1430 if (m_pCompIndices == nullptr || m_pChunk == nullptr || size() == 0)
1431 return false;
1432
1433 compIdx = m_pCompIndices[termIdx];
1434 if (compIdx == 0xFF)
1435 return false;
1436
1437 const auto recs = m_pChunk->comp_rec_view();
1438 if (compIdx >= recs.size())
1439 return false;
1440
1441 const auto& rec = recs[compIdx];
1442 pItem = rec.pItem;
1443 return pItem != nullptr && pItem->entity.kind() == EntityKind::EK_Gen &&
1444 rec.comp.storage_type() == DataStorageType::Table && rec.comp.soa() != 0 &&
1445 fieldIdx < rec.comp.soa() && pItem->soaSizes[fieldIdx] != 0;
1446 }
1447
1452 GAIA_NODISCARD RawTermViewGet raw_term_field_view(uint32_t termIdx, uint32_t fieldIdx) const {
1453 uint8_t compIdx;
1454 const ComponentCacheItem* pItem;
1455 if (!raw_term_field_info(termIdx, fieldIdx, compIdx, pItem))
1456 return {};
1457
1458 const auto& rec = m_pChunk->comp_rec_view()[compIdx];
1459 const std::span<const uint8_t> fieldSizes{pItem->soaSizes, rec.comp.soa()};
1460 const auto* pData = mem::data_view_policy_soa_erased::get(
1461 m_pChunk->comp_ptr(compIdx), rec.comp.alig(), fieldSizes, fieldIdx, from(), m_pChunk->capacity());
1462 return {pData, pItem->soaSizes[fieldIdx], size(), ComponentRawViewFlag_Valid};
1463 }
1464
1470 GAIA_NODISCARD RawTermViewSet raw_term_field_view_mut(uint32_t termIdx, uint32_t fieldIdx, bool trackWrite) {
1471 uint8_t compIdx;
1472 const ComponentCacheItem* pItem;
1473 if (!raw_term_field_info(termIdx, fieldIdx, compIdx, pItem))
1474 return {};
1475
1476 if (trackWrite) {
1477 touch_comp_idx(compIdx);
1478 if (m_writeIm)
1479 m_pChunk->update_world_version(compIdx);
1480 }
1481
1482 const auto& rec = m_pChunk->comp_rec_view()[compIdx];
1483 const std::span<const uint8_t> fieldSizes{pItem->soaSizes, rec.comp.soa()};
1484 auto* pData = mem::data_view_policy_soa_erased::set(
1485 m_pChunk->comp_ptr_mut(compIdx), rec.comp.alig(), fieldSizes, fieldIdx, from(), m_pChunk->capacity());
1486 return {pData, pItem->soaSizes[fieldIdx], size(), ComponentRawViewFlag_Valid};
1487 }
1488
1489 GAIA_NODISCARD RawTermViewSet raw_term_view_mut(uint32_t termIdx, bool trackWrite) {
1490 if (m_pCompIndices == nullptr || m_pChunk == nullptr)
1491 return {};
1492
1493 const auto compIdx = m_pCompIndices[termIdx];
1494 if (compIdx == 0xFF)
1495 return {};
1496
1497 const auto recs = m_pChunk->comp_rec_view();
1498 if (compIdx >= recs.size())
1499 return {};
1500
1501 const auto term = m_pChunk->ids_view()[compIdx];
1502 const auto& rec = recs[compIdx];
1503 if (rec.comp.soa() != 0)
1504 return {};
1505
1506 if (trackWrite) {
1507 touch_comp_idx(compIdx);
1508 if (m_writeIm)
1509 m_pChunk->update_world_version(compIdx);
1510 }
1511
1512 const auto elemSize = rec.comp.size();
1513 const auto row = (uint32_t)(from() * (1U - (uint32_t)term.kind()));
1514 auto* pData = elemSize != 0 ? m_pChunk->comp_ptr_mut(compIdx, row) : nullptr;
1515 return {pData, elemSize, size(), ComponentRawViewFlag_Valid};
1516 }
1517
1522 GAIA_NODISCARD RawTermViewSetEntity raw_term_view_any_mut(Entity component, bool trackWrite) {
1523 if (component == EntityBad || m_pChunk == nullptr || size() == 0)
1524 return {};
1525
1526 const auto* pEntities = entity_snapshot();
1527 RawSparseStoreOps sparse{};
1528 if (world_bind_raw_sparse_store(*world(), component, sparse)) {
1529 GAIA_FOR(size()) {
1530 if (!sparse.funcHas(sparse.pStore, pEntities[i]))
1531 return {};
1532 }
1533 } else if (!owns_raw_component(component))
1534 return {};
1535 if (trackWrite && !touch_raw_component(component))
1536 return {};
1537
1538 return {pEntities, world(), component, size(), sparse};
1539 }
1540
1544 GAIA_NODISCARD RawTermViewGet view_raw(uint32_t termIdx) const {
1545 return raw_term_view(termIdx);
1546 }
1547
1555 GAIA_NODISCARD RawTermViewGet view_raw_field(uint32_t termIdx, uint32_t fieldIdx) const {
1556 return raw_term_field_view(termIdx, fieldIdx);
1557 }
1558
1566 GAIA_NODISCARD RawTermViewSet view_raw_field_mut(uint32_t termIdx, uint32_t fieldIdx) {
1567 return raw_term_field_view_mut(termIdx, fieldIdx, true);
1568 }
1569
1577 GAIA_NODISCARD RawTermViewSet sview_raw_field_mut(uint32_t termIdx, uint32_t fieldIdx) {
1578 return raw_term_field_view_mut(termIdx, fieldIdx, false);
1579 }
1580
1585 GAIA_NODISCARD RawTermViewSet view_raw_mut(uint32_t termIdx) {
1586 return raw_term_view_mut(termIdx, true);
1587 }
1588
1593 GAIA_NODISCARD RawTermViewSet sview_raw_mut(uint32_t termIdx) {
1594 return raw_term_view_mut(termIdx, false);
1595 }
1596
1602 GAIA_NODISCARD RawTermViewGetEntity view_raw_any(Entity component) const {
1603 if (component == EntityBad || m_pChunk == nullptr || size() == 0)
1604 return {};
1605
1606 const auto* pEntities = m_pChunk->entity_view().data() + from();
1607 RawSparseStoreOps sparse{};
1608 if (!world_bind_raw_sparse_store(*world(), component, sparse) &&
1609 !world_get_raw(*world(), pEntities[0], component).valid())
1610 return {};
1611
1612 return {pEntities, world(), component, size(), sparse};
1613 }
1614
1621 GAIA_NODISCARD RawTermViewSetEntity view_raw_any_mut(Entity component) {
1622 return raw_term_view_any_mut(component, true);
1623 }
1624
1630 GAIA_NODISCARD RawTermViewSetEntity sview_raw_any_mut(Entity component) {
1631 return raw_term_view_any_mut(component, false);
1632 }
1633
1636 void modify_raw(uint32_t termIdx) {
1637 if (m_pCompIndices == nullptr || m_pChunk == nullptr)
1638 return;
1639
1640 const auto compIdx = m_pCompIndices[termIdx];
1641 if (compIdx == 0xFF || compIdx >= m_pChunk->comp_rec_view().size())
1642 return;
1643
1644 const auto& rec = m_pChunk->comp_rec_view()[compIdx];
1645 if (rec.comp.soa() != 0) {
1646 uint8_t fieldCompIdx;
1647 const ComponentCacheItem* pItem;
1648 if (!raw_term_field_info(termIdx, 0, fieldCompIdx, pItem))
1649 return;
1650 }
1651
1652 touch_comp_idx(compIdx);
1653 }
1654
1660 GAIA_NODISCARD bool modify_raw(Entity component) {
1661 if (component == EntityBad || m_pChunk == nullptr || size() == 0 || !owns_raw_component(component))
1662 return false;
1663
1664 return touch_raw_component(component);
1665 }
1666
1673 template <typename T>
1674 GAIA_NODISCARD auto view_any() const {
1675 return ChunkIterTypedOps::template view_any<T>(*this);
1676 }
1677
1685 template <typename T>
1686 GAIA_NODISCARD auto view_any(uint32_t termIdx) {
1687 return ChunkIterTypedOps::template view_any<T>(*this, termIdx);
1688 }
1689
1697 template <typename T>
1698 GAIA_NODISCARD auto view() const {
1699 return ChunkIterTypedOps::template view<T>(*this);
1700 }
1701
1709 template <typename T>
1710 GAIA_NODISCARD auto view(uint32_t termIdx) const {
1711 return ChunkIterTypedOps::template view<T>(*this, termIdx);
1712 }
1713
1720 template <typename T>
1721 GAIA_NODISCARD auto view_any_mut() {
1722 return ChunkIterTypedOps::template view_any_mut<T>(*this);
1723 }
1724
1730 template <typename T>
1731 GAIA_NODISCARD auto view_mut() {
1732 return ChunkIterTypedOps::template view_mut<T>(*this);
1733 }
1734
1742 template <typename T>
1743 GAIA_NODISCARD auto view_mut(uint32_t termIdx) {
1744 return ChunkIterTypedOps::template view_mut<T>(*this, termIdx);
1745 }
1746
1754 template <typename T>
1755 GAIA_NODISCARD auto view_any_mut(uint32_t termIdx) {
1756 return ChunkIterTypedOps::template view_any_mut<T>(*this, termIdx);
1757 }
1758
1766 template <typename T>
1767 GAIA_NODISCARD auto sview_any_mut() {
1768 return ChunkIterTypedOps::template sview_any_mut<T>(*this);
1769 }
1770
1776 template <typename T>
1777 GAIA_NODISCARD auto sview_mut() {
1778 return ChunkIterTypedOps::template sview_mut<T>(*this);
1779 }
1780
1788 template <typename T>
1789 GAIA_NODISCARD auto sview_mut(uint32_t termIdx) {
1790 return ChunkIterTypedOps::template sview_mut<T>(*this, termIdx);
1791 }
1792
1801 template <typename T>
1802 GAIA_NODISCARD auto sview_any_mut(uint32_t termIdx) {
1803 return ChunkIterTypedOps::template sview_any_mut<T>(*this, termIdx);
1804 }
1805
1809 template <typename T, bool TriggerHooks>
1810 void modify() {
1811 m_pChunk->template modify<T, TriggerHooks>();
1812 }
1813
1820 template <typename T>
1821 GAIA_NODISCARD auto view_auto() {
1822 using UOriginal = typename actual_type_t<T>::TypeOriginal;
1823 if constexpr (core::is_mut_v<UOriginal>)
1824 return view_mut<T>();
1825 else
1826 return view<T>();
1827 }
1828
1835 template <typename T>
1836 GAIA_NODISCARD auto view_auto_any() {
1837 using UOriginal = typename actual_type_t<T>::TypeOriginal;
1838 if constexpr (core::is_mut_v<UOriginal>)
1839 return view_any_mut<T>();
1840 else
1841 return view_any<T>();
1842 }
1843
1851 template <typename T>
1852 GAIA_NODISCARD auto sview_auto_any() {
1853 using UOriginal = typename actual_type_t<T>::TypeOriginal;
1854 if constexpr (core::is_mut_v<UOriginal>)
1855 return sview_any_mut<T>();
1856 else
1857 return view_any<T>();
1858 }
1859
1867 template <typename T>
1868 GAIA_NODISCARD auto sview_auto() {
1869 using UOriginal = typename actual_type_t<T>::TypeOriginal;
1870 if constexpr (core::is_mut_v<UOriginal>)
1871 return sview_mut<T>();
1872 else
1873 return view<T>();
1874 }
1875
1878 GAIA_NODISCARD bool enabled(uint32_t index) const {
1879 const auto row = (uint16_t)(from() + index);
1880 return m_pChunk->enabled(row);
1881 }
1882
1886 GAIA_NODISCARD bool has(Entity entity) const {
1887 return m_pChunk->has(entity);
1888 }
1889
1893 GAIA_NODISCARD bool has(Pair pair) const {
1894 return m_pChunk->has((Entity)pair);
1895 }
1896
1900 template <typename T>
1901 GAIA_NODISCARD bool has() const {
1902 return m_pChunk->template has<T>();
1903 }
1904
1905 GAIA_NODISCARD static uint16_t start_index(Chunk* pChunk, Constraints constraints) noexcept {
1906 if (constraints == Constraints::EnabledOnly)
1907 return pChunk->size_disabled();
1908 return 0;
1909 }
1910
1911 GAIA_NODISCARD static uint16_t end_index(Chunk* pChunk, Constraints constraints) noexcept {
1912 if (constraints == Constraints::DisabledOnly)
1913 return pChunk->size_disabled();
1914 return pChunk->size();
1915 }
1916
1917 GAIA_NODISCARD static uint16_t size(Chunk* pChunk, Constraints constraints) noexcept {
1918 if (constraints == Constraints::EnabledOnly)
1919 return pChunk->size_enabled();
1920 if (constraints == Constraints::DisabledOnly)
1921 return pChunk->size_disabled();
1922 return pChunk->size();
1923 }
1924
1926 GAIA_NODISCARD uint16_t size() const noexcept {
1927 return (uint16_t)(to() - from());
1928 }
1929
1931 GAIA_NODISCARD uint16_t row_begin() const noexcept {
1932 return from();
1933 }
1934
1936 GAIA_NODISCARD uint16_t row_end() const noexcept {
1937 return to();
1938 }
1939
1943 template <typename T>
1944 uint32_t acc_index(uint32_t idx) const noexcept {
1945 using U = typename actual_type_t<T>::Type;
1946 if constexpr (mem::is_soa_layout_v<U>)
1947 return idx + from();
1948 else
1949 return idx;
1950 }
1951
1952 protected:
1954 GAIA_NODISCARD uint16_t from() const noexcept {
1955 return m_from;
1956 }
1957
1959 GAIA_NODISCARD uint16_t to() const noexcept {
1960 return m_to;
1961 }
1962 };
1963 } // namespace detail
1965
1968 class GAIA_API Iter: public detail::ChunkIterImpl {
1969 public:
1971 static constexpr Constraints ConstraintMode = Constraints::EnabledOnly;
1972
1973 using detail::ChunkIterImpl::size;
1974
1975 Iter() {
1976 set_constraints(ConstraintMode);
1977 }
1978
1982 GAIA_NODISCARD static uint16_t start_index(Chunk* pChunk) noexcept {
1983 return detail::ChunkIterImpl::start_index(pChunk, ConstraintMode);
1984 }
1985
1989 GAIA_NODISCARD static uint16_t end_index(Chunk* pChunk) noexcept {
1990 return detail::ChunkIterImpl::end_index(pChunk, ConstraintMode);
1991 }
1992
1996 GAIA_NODISCARD static uint16_t size(Chunk* pChunk) noexcept {
1997 return detail::ChunkIterImpl::size(pChunk, ConstraintMode);
1998 }
1999
2002 GAIA_NODISCARD uint16_t size_enabled() const noexcept {
2003 return m_pChunk->size_enabled();
2004 }
2005
2009 GAIA_NODISCARD uint16_t size_disabled() const noexcept {
2010 return m_pChunk->size_disabled();
2011 }
2012 };
2013
2015 class GAIA_API CopyIter final {
2016 protected:
2019
2021 const World* m_pWorld = nullptr;
2023 const Archetype* m_pArchetype = nullptr;
2025 Chunk* m_pChunk = nullptr;
2027 uint16_t m_from;
2029 uint16_t m_cnt;
2030
2031 public:
2032 CopyIter() = default;
2033 ~CopyIter() = default;
2034 CopyIter(CopyIter&&) noexcept = default;
2035 CopyIter& operator=(CopyIter&&) noexcept = default;
2036
2037 CopyIter& operator=(const CopyIter&) = delete;
2038
2042 void set_range(uint16_t from, uint16_t cnt) {
2043 GAIA_ASSERT(from < m_pChunk->size());
2044 GAIA_ASSERT(from + cnt <= m_pChunk->size());
2045 m_from = from;
2046 m_cnt = cnt;
2047 }
2048
2051 void set_world(const World* pWorld) {
2052 GAIA_ASSERT(pWorld != nullptr);
2053 m_pWorld = pWorld;
2054 }
2055
2058 GAIA_NODISCARD World* world() {
2059 GAIA_ASSERT(m_pWorld != nullptr);
2060 return const_cast<World*>(m_pWorld);
2061 }
2062
2065 GAIA_NODISCARD const World* world() const {
2066 GAIA_ASSERT(m_pWorld != nullptr);
2067 return m_pWorld;
2068 }
2069
2072 void set_archetype(const Archetype* pArchetype) {
2073 GAIA_ASSERT(pArchetype != nullptr);
2074 m_pArchetype = pArchetype;
2075 }
2076
2077 // GAIA_NODISCARD Archetype* archetype() {
2078 // GAIA_ASSERT(m_pArchetype != nullptr);
2079 // return m_pArchetype;
2080 // }
2081
2084 GAIA_NODISCARD const Archetype* archetype() const {
2085 GAIA_ASSERT(m_pArchetype != nullptr);
2086 return m_pArchetype;
2087 }
2088
2091 void set_chunk(Chunk* pChunk) {
2092 GAIA_ASSERT(pChunk != nullptr);
2093 m_pChunk = pChunk;
2094 }
2095
2098 GAIA_NODISCARD const Chunk* chunk() const {
2099 GAIA_ASSERT(m_pChunk != nullptr);
2100 return m_pChunk;
2101 }
2102
2105 GAIA_NODISCARD CommandBufferST& cmd_buffer_st() const {
2106 auto* pWorld = const_cast<World*>(m_pWorld);
2107 return cmd_buffer_st_get(*pWorld);
2108 }
2109
2112 GAIA_NODISCARD CommandBufferMT& cmd_buffer_mt() const {
2113 auto* pWorld = const_cast<World*>(m_pWorld);
2114 return cmd_buffer_mt_get(*pWorld);
2115 }
2116
2121 template <typename T>
2122 GAIA_NODISCARD auto view() const {
2123 return m_pChunk->template view<T>(from(), to());
2124 }
2125
2130 template <typename T>
2131 GAIA_NODISCARD auto view_mut() {
2132 return m_pChunk->template view_mut<T>(from(), to());
2133 }
2134
2140 template <typename T>
2141 GAIA_NODISCARD auto sview_mut() {
2142 return m_pChunk->template sview_mut<T>(from(), to());
2143 }
2144
2148 template <typename T, bool TriggerHooks>
2149 void modify() {
2150 m_pChunk->template modify<T, TriggerHooks>();
2151 }
2152
2158 template <typename T>
2159 GAIA_NODISCARD auto view_auto() {
2160 return m_pChunk->template view_auto<T>(from(), to());
2161 }
2162
2169 template <typename T>
2170 GAIA_NODISCARD auto sview_auto() {
2171 return m_pChunk->template sview_auto<T>(from(), to());
2172 }
2173
2177 GAIA_NODISCARD bool enabled(uint32_t index) const {
2178 const auto row = (uint16_t)(from() + index);
2179 return m_pChunk->enabled(row);
2180 }
2181
2185 GAIA_NODISCARD bool has(Entity entity) const {
2186 return m_pChunk->has(entity);
2187 }
2188
2192 GAIA_NODISCARD bool has(Pair pair) const {
2193 return m_pChunk->has((Entity)pair);
2194 }
2195
2199 template <typename T>
2200 GAIA_NODISCARD bool has() const {
2201 return m_pChunk->template has<T>();
2202 }
2203
2206 GAIA_NODISCARD uint16_t size() const noexcept {
2207 return m_cnt;
2208 }
2209
2210 private:
2212 GAIA_NODISCARD uint16_t from() const noexcept {
2213 return m_from;
2214 }
2215
2217 GAIA_NODISCARD uint16_t to() const noexcept {
2218 return m_from + m_cnt;
2219 }
2220 };
2221 } // namespace ecs
2222} // namespace gaia
2223
2224#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:1432
GAIA_NODISCARD bool has(Entity entity) const
Checks if a component/entity entity is present in the chunk.
Definition chunk.h:1527
Iterator used when copying entities.
Definition chunk_iterator.h:2015
uint16_t m_from
Row of the first entity we iterate from.
Definition chunk_iterator.h:2027
GAIA_NODISCARD CommandBufferST & cmd_buffer_st() const
Returns the world's single-threaded command buffer.
Definition chunk_iterator.h:2105
GAIA_NODISCARD auto view() const
Returns a read-only entity or component view.
Definition chunk_iterator.h:2122
void set_world(const World *pWorld)
Associates the iterator with its owning world.
Definition chunk_iterator.h:2051
GAIA_NODISCARD const Chunk * chunk() const
Returns the associated source chunk.
Definition chunk_iterator.h:2098
GAIA_NODISCARD CommandBufferMT & cmd_buffer_mt() const
Returns the world's multi-threaded command buffer.
Definition chunk_iterator.h:2112
GAIA_NODISCARD auto sview_auto()
Returns either a mutable or immutable entity/component view based on the requested type....
Definition chunk_iterator.h:2170
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:2141
GAIA_NODISCARD World * world()
Returns mutable access to the associated world.
Definition chunk_iterator.h:2058
void set_archetype(const Archetype *pArchetype)
Associates the iterator with the source archetype.
Definition chunk_iterator.h:2072
GAIA_NODISCARD bool has() const
Checks if component T is present in the chunk.
Definition chunk_iterator.h:2200
GAIA_NODISCARD auto view_mut()
Returns a mutable entity or component view.
Definition chunk_iterator.h:2131
GAIA_NODISCARD bool has(Pair pair) const
Checks if relationship pair pair is present in the chunk.
Definition chunk_iterator.h:2192
uint16_t m_cnt
The number of entities accessible via the iterator.
Definition chunk_iterator.h:2029
GAIA_NODISCARD auto view_auto()
Returns either a mutable or immutable entity/component view based on the requested type....
Definition chunk_iterator.h:2159
GAIA_NODISCARD bool has(Entity entity) const
Checks if entity entity is present in the chunk.
Definition chunk_iterator.h:2185
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:2149
GAIA_NODISCARD const Archetype * archetype() const
Returns the associated source archetype.
Definition chunk_iterator.h:2084
GAIA_NODISCARD const World * world() const
Returns read-only access to the associated world.
Definition chunk_iterator.h:2065
void set_chunk(Chunk *pChunk)
Associates the iterator with a source chunk.
Definition chunk_iterator.h:2091
GAIA_NODISCARD uint16_t size() const noexcept
Returns the number of entities accessible via the iterator.
Definition chunk_iterator.h:2206
GAIA_NODISCARD bool enabled(uint32_t index) const
Checks if the entity at the current iterator index is enabled.
Definition chunk_iterator.h:2177
Iterator for iterating entity subsets selected by Constraints. Disabled entities always precede enabl...
Definition chunk_iterator.h:1968
static GAIA_NODISCARD uint16_t size(Chunk *pChunk) noexcept
Returns the number of enabled rows in a chunk.
Definition chunk_iterator.h:1996
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:1989
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:2009
GAIA_NODISCARD uint16_t size_enabled() const noexcept
Returns the number of enabled entities accessible via the iterator.
Definition chunk_iterator.h:2002
static GAIA_NODISCARD uint16_t start_index(Chunk *pChunk) noexcept
Returns the first enabled row in a chunk.
Definition chunk_iterator.h:1982
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:52
Wrapper for two Entities forming a relationship pair.
Definition id.h:614
Wrapper for two types forming a relationship pair. Depending on what types are used to form a pair it...
Definition id.h:262
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:296
Prebound operations for one runtime sparse component store.
Definition chunk_iterator.h:24
uint32_t elemSize
Size of one stored component value in bytes.
Definition chunk_iterator.h:34
bool(* funcHas)(const void *, Entity)
Tests whether an entity has a value in the store.
Definition chunk_iterator.h:32
const void * pStore
Type-erased sparse store instance.
Definition chunk_iterator.h:26