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/observer_event.h"
17#include "gaia/ecs/query_common.h"
18#include "gaia/mem/data_layout_policy.h"
19
20namespace gaia {
21 namespace ecs {
22 class World;
23
27 const void* pStore = nullptr;
29 const void* (*funcGet)(const void*, Entity) = nullptr;
31 void* (*funcMut)(void*, Entity) = nullptr;
33 bool (*funcHas)(const void*, Entity) = nullptr;
35 uint32_t elemSize = 0;
36 };
37
38 bool world_bind_raw_sparse_store(const World& world, Entity component, RawSparseStoreOps& ops);
39 void world_notify_on_set_entity(World& world, Entity term, Entity entity);
40 template <typename T>
41 void* world_typed_sparse_store_ptr(World& world, Entity component);
42 template <typename T>
43 const T& world_typed_sparse_store_get(const void* pStore, Entity entity);
44 template <typename T>
45 T& world_typed_sparse_store_mut(void* pStore, Entity entity);
46 template <typename T>
47 bool world_typed_sparse_store_has(const void* pStore, Entity entity);
48 template <typename T>
49 decltype(auto) world_query_entity_arg_by_id_cached_const(
50 World& world, Entity entity, Entity id, const Archetype*& pLastArchetype, Entity& cachedOwner,
51 bool& cachedDirect);
52 template <typename T>
53 void world_init_query_entity_arg_by_id_chunk_stable_const(
54 World& world, const Chunk& chunk, const Entity* pEntities, Entity id, bool& direct, uint32_t& compIdx,
55 const std::remove_cv_t<std::remove_reference_t<T>>*& pDataInherited);
56 template <typename T>
57 const std::remove_cv_t<std::remove_reference_t<T>>*
58 world_query_inherited_arg_data_const(World& world, Entity owner, Entity id);
59 bool world_term_uses_inherit_policy(const World& world, Entity term);
60 template <typename T>
61 Entity world_query_arg_id(World& world);
62
64 enum class Constraints : uint8_t {
66 EnabledOnly,
68 DisabledOnly,
70 AcceptAll
71 };
72
74 namespace detail {
75 class ChunkIterImpl;
76
77 struct IterTermDesc {
78 Entity termId = EntityBad;
79 bool isEntity = false;
80 bool usesSparseStorage = false;
81 bool storageKnown = false;
82 };
83
84 struct ChunkIterTypedOps {
85 template <typename T>
86 static IterTermDesc term_desc(const ChunkIterImpl& self);
87 template <typename T>
88 static auto view_any(const ChunkIterImpl& self);
89 template <typename T>
90 static auto view_any(ChunkIterImpl& self, uint32_t termIdx);
91 template <typename T>
92 static auto view(const ChunkIterImpl& self);
93 template <typename T>
94 static auto view(const ChunkIterImpl& self, uint32_t termIdx);
95 template <typename T>
96 static auto view_any_mut(ChunkIterImpl& self);
97 template <typename T>
98 static auto view_mut(ChunkIterImpl& self);
99 template <typename T>
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);
111 };
112
113 struct BfsChunkRun {
114 const Archetype* pArchetype = nullptr;
115 Chunk* pChunk = nullptr;
116 uint16_t from = 0;
117 uint16_t to = 0;
118 uint32_t offset = 0;
119 };
120
122 struct RawTermViewGet {
123 const uint8_t* pData = nullptr;
124 uint32_t elemSize = 0;
125 uint32_t cnt = 0;
126 uint32_t flags = ComponentRawViewFlag_None;
127
128 GAIA_NODISCARD ComponentRawView operator[](size_t idx) const {
129 GAIA_ASSERT(idx < cnt);
130 if ((flags & ComponentRawViewFlag_Valid) == 0 || idx >= cnt)
131 return {};
132 if (elemSize == 0)
133 return {nullptr, 0, ComponentRawViewFlag_Valid};
134
135 return {pData + (uintptr_t)elemSize * idx, elemSize, ComponentRawViewFlag_Valid};
136 }
137
138 GAIA_NODISCARD constexpr size_t size() const noexcept {
139 return cnt;
140 }
141 };
142
144 struct RawTermViewSet {
145 uint8_t* pData = nullptr;
146 uint32_t elemSize = 0;
147 uint32_t cnt = 0;
148 uint32_t flags = ComponentRawViewFlag_None;
149
150 GAIA_NODISCARD ComponentRawMutView operator[](size_t idx) const {
151 GAIA_ASSERT(idx < cnt);
152 if ((flags & ComponentRawViewFlag_Valid) == 0 || idx >= cnt)
153 return {};
154 if (elemSize == 0)
155 return {nullptr, 0, ComponentRawViewFlag_Valid};
156
157 return {pData + (uintptr_t)elemSize * idx, elemSize, ComponentRawViewFlag_Valid};
158 }
159
160 GAIA_NODISCARD constexpr size_t size() const noexcept {
161 return cnt;
162 }
163 };
164
167 struct RawTermViewGetEntity {
168 const Entity* pEntities = nullptr;
169 const World* pWorld = nullptr;
170 Entity component = EntityBad;
171 uint32_t cnt = 0;
172 RawSparseStoreOps sparse{};
173
174 GAIA_NODISCARD ComponentRawView operator[](size_t idx) const {
175 GAIA_ASSERT(idx < cnt);
176 if (pEntities == nullptr || pWorld == nullptr || component == EntityBad || idx >= cnt)
177 return {};
178
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};
183 }
184
185 return world_get_raw(*pWorld, entity, component);
186 }
187
188 GAIA_NODISCARD constexpr size_t size() const noexcept {
189 return cnt;
190 }
191 };
192
195 struct RawTermViewSetEntity {
196 const Entity* pEntities = nullptr;
197 World* pWorld = nullptr;
198 Entity component = EntityBad;
199 uint32_t cnt = 0;
200 RawSparseStoreOps sparse{};
201
202 GAIA_NODISCARD ComponentRawMutView operator[](size_t idx) const {
203 GAIA_ASSERT(idx < cnt);
204 if (pEntities == nullptr || pWorld == nullptr || component == EntityBad || idx >= cnt)
205 return {};
206
207 const auto entity = pEntities[idx];
208 if (sparse.pStore != nullptr)
209 return {
210 sparse.funcMut(const_cast<void*>(sparse.pStore), entity), sparse.elemSize, ComponentRawViewFlag_Valid};
211
212 return world_mut_raw(*pWorld, entity, component);
213 }
214
215 GAIA_NODISCARD constexpr size_t size() const noexcept {
216 return cnt;
217 }
218 };
219
222 template <typename U>
223 struct EntityTermViewGetPointer {
224 const U* pData = nullptr;
225 uint32_t cnt = 0;
226
227 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
228 GAIA_ASSERT(idx < cnt);
229 return pData[idx];
230 }
231
232 GAIA_NODISCARD constexpr size_t size() const noexcept {
233 return cnt;
234 }
235
236 GAIA_NODISCARD const U* data() const noexcept {
237 return pData;
238 }
239 };
240
243 template <typename U>
244 struct EntityTermViewGetEntity {
245 const Entity* pEntities = nullptr;
246 World* pWorld = nullptr;
247 Entity id = EntityBad;
248 uint32_t cnt = 0;
249 mutable const Archetype* pLastArchetype = nullptr;
250 mutable Entity cachedOwner = EntityBad;
251 mutable bool cachedDirect = false;
252
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);
257 }
258
259 GAIA_NODISCARD constexpr size_t size() const noexcept {
260 return cnt;
261 }
262
263 GAIA_NODISCARD const U* data() const noexcept {
264 return nullptr;
265 }
266 };
267
270 template <typename U>
271 struct EntityTermViewSetPointer {
272 U* pData = nullptr;
273 uint32_t cnt = 0;
274
275 GAIA_NODISCARD decltype(auto) operator[](size_t idx) {
276 GAIA_ASSERT(idx < cnt);
277 return pData[idx];
278 }
279
280 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
281 GAIA_ASSERT(idx < cnt);
282 return static_cast<const U&>(pData[idx]);
283 }
284
285 GAIA_NODISCARD constexpr size_t size() const noexcept {
286 return cnt;
287 }
288
289 GAIA_NODISCARD U* data() noexcept {
290 return pData;
291 }
292
293 GAIA_NODISCARD const U* data() const noexcept {
294 return pData;
295 }
296 };
297
300 template <typename U, bool WriteIm>
301 struct EntityTermViewSetEntity {
302 const Entity* pEntities = nullptr;
303 World* pWorld = nullptr;
304 Entity id = EntityBad;
305 uint32_t cnt = 0;
306
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);
311 else
312 return world_query_entity_arg_by_id_raw<U&>(*pWorld, pEntities[idx], id);
313 }
314
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);
318 }
319
320 GAIA_NODISCARD constexpr size_t size() const noexcept {
321 return cnt;
322 }
323
324 GAIA_NODISCARD U* data() noexcept {
325 return nullptr;
326 }
327
328 GAIA_NODISCARD const U* data() const noexcept {
329 return nullptr;
330 }
331 };
332
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;
340 uint32_t cnt = 0;
341
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);
348 }
349
350 GAIA_NODISCARD constexpr size_t size() const noexcept {
351 return cnt;
352 }
353
354 GAIA_NODISCARD const U* data() const noexcept {
355 return nullptr;
356 }
357 };
358
360 template <typename U>
361 struct EntityTermViewSetSparse {
362 const Entity* pEntities = nullptr;
363 World* pWorld = nullptr;
364 void* pStore = nullptr;
365 Entity id = EntityBad;
366 uint32_t cnt = 0;
367
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);
374 }
375
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);
382 }
383
384 GAIA_NODISCARD constexpr size_t size() const noexcept {
385 return cnt;
386 }
387
388 GAIA_NODISCARD U* data() noexcept {
389 return nullptr;
390 }
391
392 GAIA_NODISCARD const U* data() const noexcept {
393 return nullptr;
394 }
395 };
396
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;
405 uint32_t cnt = 0;
406 const U* pDataInherited = nullptr;
407 mutable const Archetype* pLastArchetype = nullptr;
408 mutable Entity cachedOwner = EntityBad;
409 mutable bool cachedDirect = false;
410
411 static EntityTermViewGet pointer(const U* pData, uint32_t cnt) {
412 return {pData, nullptr, nullptr, EntityBad, cnt, nullptr, nullptr, EntityBad, false};
413 }
414
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};
417 }
418
419 static EntityTermViewGet inherited(const U* pDataInherited, uint32_t cnt) {
420 return {nullptr, nullptr, nullptr, EntityBad, cnt, pDataInherited, nullptr, EntityBad, false};
421 }
422
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;
427 bool direct = false;
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;
431 if (direct)
432 pData = reinterpret_cast<const U*>(pChunk->comp_ptr(compIdx, rowBase));
433
434 return {pData, nullptr, pWorld, id, cnt, pDataInherited, nullptr, EntityBad, false};
435 }
436
437 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
438 GAIA_ASSERT(idx < cnt);
439 if (pData != nullptr)
440 return pData[idx];
441 if (pDataInherited != nullptr) {
442 GAIA_ASSERT(pDataInherited != nullptr);
443 return *pDataInherited;
444 }
445
446 return world_query_entity_arg_by_id_cached_const<const U&>(
447 *pWorld, pEntities[idx], id, pLastArchetype, cachedOwner, cachedDirect);
448 }
449
450 GAIA_NODISCARD constexpr size_t size() const noexcept {
451 return cnt;
452 }
453
454 GAIA_NODISCARD const U* data() const noexcept {
455 return pData;
456 }
457 };
458
461 template <typename U>
462 struct EntityTermViewSet {
463 U* pData = nullptr;
464 const Entity* pEntities = nullptr;
465 World* pWorld = nullptr;
466 Entity id = EntityBad;
467 uint32_t cnt = 0;
468 bool writeIm = true;
469
470 static EntityTermViewSet pointer(U* pData, uint32_t cnt) {
471 return {pData, nullptr, nullptr, EntityBad, cnt, true};
472 }
473
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};
477 }
478
479 GAIA_NODISCARD decltype(auto) operator[](size_t idx) {
480 GAIA_ASSERT(idx < cnt);
481 if (pData != nullptr)
482 return pData[idx];
483
484 if (writeIm)
485 return EntityTermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}[idx];
486 return EntityTermViewSetEntity<U, false>{pEntities, pWorld, id, cnt}[idx];
487 }
488
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]);
493
494 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
495 }
496
497 GAIA_NODISCARD constexpr size_t size() const noexcept {
498 return cnt;
499 }
500
501 GAIA_NODISCARD U* data() noexcept {
502 return pData;
503 }
504
505 GAIA_NODISCARD const U* data() const noexcept {
506 return pData;
507 }
508 };
509
512 template <typename U>
513 struct SoATermRowWriteProxyPointer {
514 using raw_view_policy = mem::data_view_policy_soa<U::gaia_Data_Layout, U>;
515
516 uint8_t* pData = nullptr;
517 uint32_t dataSize = 0;
518 uint32_t idx = 0;
519
520 GAIA_NODISCARD operator U() const {
521 return raw_view_policy::get(std::span<const uint8_t>{pData, dataSize}, idx);
522 }
523
524 SoATermRowWriteProxyPointer& operator=(const U& value) {
525 raw_view_policy::set(std::span<uint8_t>{pData, dataSize}, idx) = value;
526 return *this;
527 }
528 };
529
532 template <typename U, bool WriteIm>
533 struct SoATermRowWriteProxyEntity {
534 const Entity* pEntities = nullptr;
535 World* pWorld = nullptr;
536 Entity id = EntityBad;
537 uint32_t idx = 0;
538
539 GAIA_NODISCARD operator U() const {
540 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
541 }
542
543 SoATermRowWriteProxyEntity& operator=(const U& value) {
544 if constexpr (WriteIm)
545 world_query_entity_arg_by_id<U&>(*pWorld, pEntities[idx], id) = value;
546 else
547 world_query_entity_arg_by_id_raw<U&>(*pWorld, pEntities[idx], id) = value;
548 return *this;
549 }
550 };
551
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;
558
559 const value_type* pData = nullptr;
560 uint32_t cnt = 0;
561
562 GAIA_NODISCARD value_type operator[](size_t idx) const {
563 GAIA_ASSERT(idx < cnt);
564 return pData[idx];
565 }
566
567 GAIA_NODISCARD constexpr size_t size() const noexcept {
568 return cnt;
569 }
570 };
571
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;
578
579 const Entity* pEntities = nullptr;
580 World* pWorld = nullptr;
581 Entity id = EntityBad;
582 uint32_t cnt = 0;
583
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));
588 }
589
590 GAIA_NODISCARD constexpr size_t size() const noexcept {
591 return cnt;
592 }
593 };
594
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;
601
602 value_type* pData = nullptr;
603 uint32_t cnt = 0;
604
605 GAIA_NODISCARD value_type& operator[](size_t idx) {
606 GAIA_ASSERT(idx < cnt);
607 return pData[idx];
608 }
609
610 GAIA_NODISCARD const value_type& operator[](size_t idx) const {
611 GAIA_ASSERT(idx < cnt);
612 return pData[idx];
613 }
614
615 GAIA_NODISCARD constexpr size_t size() const noexcept {
616 return cnt;
617 }
618 };
619
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;
626
628 struct ElementProxy {
629 const Entity* pEntities = nullptr;
630 World* pWorld = nullptr;
631 Entity id = EntityBad;
632 uint32_t idx = 0;
633
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));
637 }
638
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));
645 else
646 world_query_entity_arg_by_id_raw<U&>(*pWorld, pEntities[idx], id) =
647 meta::tuple_to_struct<U>(GAIA_MOV(tuple));
648 return *this;
649 }
650
651 template <typename V>
652 ElementProxy& operator+=(V&& value) {
653 const value_type current = operator value_type();
654 return operator=(current + GAIA_FWD(value));
655 }
656
657 template <typename V>
658 ElementProxy& operator-=(V&& value) {
659 const value_type current = operator value_type();
660 return operator=(current - GAIA_FWD(value));
661 }
662
663 template <typename V>
664 ElementProxy& operator*=(V&& value) {
665 const value_type current = operator value_type();
666 return operator=(current * GAIA_FWD(value));
667 }
668
669 template <typename V>
670 ElementProxy& operator/=(V&& value) {
671 const value_type current = operator value_type();
672 return operator=(current / GAIA_FWD(value));
673 }
674 };
675
676 const Entity* pEntities = nullptr;
677 World* pWorld = nullptr;
678 Entity id = EntityBad;
679 uint32_t cnt = 0;
680
681 GAIA_NODISCARD ElementProxy operator[](size_t idx) const {
682 GAIA_ASSERT(idx < cnt);
683 return ElementProxy{pEntities, pWorld, id, (uint32_t)idx};
684 }
685
686 GAIA_NODISCARD constexpr size_t size() const noexcept {
687 return cnt;
688 }
689 };
690
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>;
697
698 const uint8_t* pData = nullptr;
699 uint32_t dataSize = 0;
700 uint32_t idxBase = 0;
701 uint32_t cnt = 0;
702
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);
706 }
707
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};
712 }
713
714 GAIA_NODISCARD constexpr size_t size() const noexcept {
715 return cnt;
716 }
717 };
718
721 template <typename U>
722 struct SoATermViewGetEntity {
723 const Entity* pEntities = nullptr;
724 World* pWorld = nullptr;
725 Entity id = EntityBad;
726 uint32_t cnt = 0;
727
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);
731 }
732
733 template <size_t Item>
734 GAIA_NODISCARD auto get() const {
735 return SoATermFieldReadProxyEntity<U, Item>{pEntities, pWorld, id, cnt};
736 }
737
738 GAIA_NODISCARD constexpr size_t size() const noexcept {
739 return cnt;
740 }
741 };
742
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>;
750
751 uint8_t* pData = nullptr;
752 uint32_t dataSize = 0;
753 uint32_t idxBase = 0;
754 uint32_t cnt = 0;
755
756 GAIA_NODISCARD auto operator[](size_t idx) {
757 GAIA_ASSERT(idx < cnt);
758 return SoATermRowWriteProxyPointer<U>{pData, dataSize, idxBase + (uint32_t)idx};
759 }
760
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);
764 }
765
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};
770 }
771
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};
776 }
777
778 GAIA_NODISCARD constexpr size_t size() const noexcept {
779 return cnt;
780 }
781 };
782
785 template <typename U, bool WriteIm>
786 struct SoATermViewSetEntity {
787 const Entity* pEntities = nullptr;
788 World* pWorld = nullptr;
789 Entity id = EntityBad;
790 uint32_t cnt = 0;
791
792 GAIA_NODISCARD auto operator[](size_t idx) {
793 GAIA_ASSERT(idx < cnt);
794 return SoATermRowWriteProxyEntity<U, WriteIm>{pEntities, pWorld, id, (uint32_t)idx};
795 }
796
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);
800 }
801
802 template <size_t Item>
803 GAIA_NODISCARD auto get() const {
804 return SoATermFieldReadProxyEntity<U, Item>{pEntities, pWorld, id, cnt};
805 }
806
807 template <size_t Item>
808 GAIA_NODISCARD auto set() {
809 return SoATermFieldWriteProxyEntity<U, Item, WriteIm>{pEntities, pWorld, id, cnt};
810 }
811
812 GAIA_NODISCARD constexpr size_t size() const noexcept {
813 return cnt;
814 }
815 };
816
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;
826 uint32_t idx = 0;
827 bool writeIm = true;
828
829 GAIA_NODISCARD operator U() const {
830 if (pData != nullptr)
831 return (U)SoATermRowWriteProxyPointer<U>{pData, dataSize, idx};
832
833 if (writeIm)
834 return (U)SoATermRowWriteProxyEntity<U, true>{pEntities, pWorld, id, idx};
835 return (U)SoATermRowWriteProxyEntity<U, false>{pEntities, pWorld, id, idx};
836 }
837
838 SoATermRowWriteProxy& operator=(const U& value) {
839 if (pData != nullptr) {
840 SoATermRowWriteProxyPointer<U>{pData, dataSize, idx} = value;
841 } else if (writeIm)
842 SoATermRowWriteProxyEntity<U, true>{pEntities, pWorld, id, idx} = value;
843 else
844 SoATermRowWriteProxyEntity<U, false>{pEntities, pWorld, id, idx} = value;
845 return *this;
846 }
847 };
848
851 template <typename U, size_t Item>
852 struct SoATermFieldReadProxy {
853 using value_type = typename SoATermFieldReadProxyPointer<U, Item>::value_type;
854
855 const value_type* pData = nullptr;
856 const Entity* pEntities = nullptr;
857 World* pWorld = nullptr;
858 Entity id = EntityBad;
859 uint32_t cnt = 0;
860
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];
865
866 return SoATermFieldReadProxyEntity<U, Item>{pEntities, pWorld, id, cnt}[idx];
867 }
868
869 GAIA_NODISCARD constexpr size_t size() const noexcept {
870 return cnt;
871 }
872 };
873
876 template <typename U, size_t Item>
877 struct SoATermFieldWriteProxy {
878 using value_type = typename SoATermFieldWriteProxyPointer<U, Item>::value_type;
879
880 value_type* pData = nullptr;
881 const Entity* pEntities = nullptr;
882 World* pWorld = nullptr;
883 Entity id = EntityBad;
884 uint32_t cnt = 0;
885 bool writeIm = true;
886
889 struct ElementProxy {
890 value_type* pData = nullptr;
891 const Entity* pEntities = nullptr;
892 World* pWorld = nullptr;
893 Entity id = EntityBad;
894 uint32_t idx = 0;
895 bool writeIm = true;
896
897 GAIA_NODISCARD operator value_type() const {
898 if (pData != nullptr)
899 return SoATermFieldWriteProxyPointer<U, Item>{pData, idx + 1}[idx];
900
901 if (writeIm)
902 return SoATermFieldWriteProxyEntity<U, Item, true>{pEntities, pWorld, id, idx + 1}[idx];
903 return SoATermFieldWriteProxyEntity<U, Item, false>{pEntities, pWorld, id, idx + 1}[idx];
904 }
905
906 ElementProxy& operator=(const value_type& value) {
907 if (pData != nullptr) {
908 SoATermFieldWriteProxyPointer<U, Item>{pData, idx + 1}[idx] = value;
909 return *this;
910 }
911
912 if (writeIm)
913 SoATermFieldWriteProxyEntity<U, Item, true>{pEntities, pWorld, id, idx + 1}[idx] = value;
914 else
915 SoATermFieldWriteProxyEntity<U, Item, false>{pEntities, pWorld, id, idx + 1}[idx] = value;
916 return *this;
917 }
918
919 template <typename V>
920 ElementProxy& operator+=(V&& value) {
921 const value_type current = operator value_type();
922 return operator=(current + GAIA_FWD(value));
923 }
924
925 template <typename V>
926 ElementProxy& operator-=(V&& value) {
927 const value_type current = operator value_type();
928 return operator=(current - GAIA_FWD(value));
929 }
930
931 template <typename V>
932 ElementProxy& operator*=(V&& value) {
933 const value_type current = operator value_type();
934 return operator=(current * GAIA_FWD(value));
935 }
936
937 template <typename V>
938 ElementProxy& operator/=(V&& value) {
939 const value_type current = operator value_type();
940 return operator=(current / GAIA_FWD(value));
941 }
942 };
943
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};
947 }
948
949 GAIA_NODISCARD constexpr size_t size() const noexcept {
950 return cnt;
951 }
952 };
953
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;
964 uint32_t cnt = 0;
965
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];
970
971 return SoATermViewGetEntity<U>{pEntities, pWorld, id, cnt}[idx];
972 }
973
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};
979 }
980
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};
983 }
984
985 GAIA_NODISCARD constexpr size_t size() const noexcept {
986 return cnt;
987 }
988 };
989
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;
1000 uint32_t cnt = 0;
1001 bool writeIm = true;
1002
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};
1006 }
1007
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];
1012
1013 return SoATermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}[idx];
1014 }
1015
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};
1021 }
1022
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};
1025 }
1026
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};
1032 }
1033
1034 if (writeIm) {
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};
1037 }
1038
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};
1041 }
1042
1043 GAIA_NODISCARD constexpr size_t size() const noexcept {
1044 return cnt;
1045 }
1046 };
1047
1048 class ChunkIterImpl {
1049 friend struct ChunkIterTypedOps;
1050
1051 protected:
1052 using CompIndicesBitView = core::bit_view<ChunkHeader::MAX_COMPONENTS_BITS>;
1053
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;
1065#endif
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;
1077#endif
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;
1088 uint16_t m_from;
1090 uint16_t m_to;
1092 GroupId m_groupId = 0;
1094 void* m_pCtx = nullptr;
1095
1096 public:
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;
1103
1104 void set_world(const World* pWorld) {
1105 GAIA_ASSERT(pWorld != nullptr);
1106 m_pWorld = pWorld;
1107 }
1108
1109 GAIA_NODISCARD World* world() {
1110 GAIA_ASSERT(m_pWorld != nullptr);
1111 return const_cast<World*>(m_pWorld);
1112 }
1113
1114 GAIA_NODISCARD const World* world() const {
1115 GAIA_ASSERT(m_pWorld != nullptr);
1116 return m_pWorld;
1117 }
1118
1119 void set_archetype(const Archetype* pArchetype) {
1120 GAIA_ASSERT(pArchetype != nullptr);
1121 m_pArchetype = pArchetype;
1122 }
1123
1124 // GAIA_NODISCARD Archetype* archetype() {
1125 // GAIA_ASSERT(m_pArchetype != nullptr);
1126 // return m_pArchetype;
1127 // }
1128
1129 GAIA_NODISCARD const Archetype* archetype() const {
1130 GAIA_ASSERT(m_pArchetype != nullptr);
1131 return m_pArchetype;
1132 }
1133
1134 void set_chunk(Chunk* pChunk) {
1135 GAIA_ASSERT(pChunk != nullptr);
1136 m_pChunk = pChunk;
1137 m_entitySnapshotValid = false;
1138 m_from = start_index(m_pChunk, m_constraints);
1139 m_to = end_index(m_pChunk, m_constraints);
1140 }
1141
1142 void set_chunk(Chunk* pChunk, uint16_t from, uint16_t to) {
1143 if (from == 0 && to == 0) {
1144 set_chunk(pChunk);
1145 return;
1146 }
1147
1148 GAIA_ASSERT(pChunk != nullptr);
1149 m_pChunk = pChunk;
1150 m_entitySnapshotValid = false;
1151 m_from = from;
1152 m_to = to;
1153 }
1154
1155 GAIA_NODISCARD const Chunk* chunk() const {
1156 GAIA_ASSERT(m_pChunk != nullptr);
1157 return m_pChunk;
1158 }
1159
1160 void set_comp_indices(const uint8_t* pCompIndices) {
1161 m_pCompIndices = pCompIndices;
1162 }
1163
1164#if GAIA_ASSERT_ENABLED
1167 void set_query_access(const QueryCtx::Data* pQueryAccess) {
1168 m_pQueryAccess = pQueryAccess;
1169 }
1170
1174 void assert_term_access(uint32_t termIdx, Entity fallbackId = EntityBad) const {
1175 if (m_pQueryAccess == nullptr)
1176 return;
1177 GAIA_ASSERT(termIdx < m_pQueryAccess->idsCnt && "Query field index out of range");
1178 if (!m_pQueryAccess->has_match_terms())
1179 return;
1180
1181 GAIA_FOR(m_pQueryAccess->idsCnt) {
1182 if (m_pQueryAccess->terms[i].fieldIndex == termIdx) {
1183 GAIA_ASSERT(
1184 m_pQueryAccess->terms[i].access != QueryAccess::Match &&
1185 "Presence-only terms have no payload access");
1186 return;
1187 }
1188 }
1189 if (fallbackId != EntityBad)
1190 assert_term_access(fallbackId);
1191 }
1192
1198 GAIA_NODISCARD static bool
1199 allows_term_access(const QueryCtx::Data& data, Entity component, bool selfSourceOnly = true) {
1200 if (!data.has_match_terms())
1201 return true;
1202
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)))
1207 continue;
1208
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()));
1213 if (!matches)
1214 continue;
1215 if (term.access != QueryAccess::Match)
1216 return true;
1217 matchOnly = true;
1218 }
1219 return !matchOnly;
1220 }
1221
1224 void assert_term_access(Entity component) const {
1225 GAIA_ASSERT(
1226 (m_pQueryAccess == nullptr || allows_term_access(*m_pQueryAccess, component)) &&
1227 "Presence-only terms have no payload access");
1228 }
1229#endif
1230
1231 void set_inherited_data(InheritedTermDataView inheritedData) {
1232 m_inheritedData = inheritedData;
1233 }
1234
1235 void set_term_ids(const Entity* pTermIds) {
1236 m_pTermIdMapping = pTermIds;
1237 }
1238
1239 GAIA_NODISCARD const uint8_t* comp_indices() const {
1240 return m_pCompIndices;
1241 }
1242
1243 GAIA_NODISCARD InheritedTermDataView inherited_data() const {
1244 return m_inheritedData;
1245 }
1246
1247 GAIA_NODISCARD const Entity* term_ids() const {
1248 return m_pTermIdMapping;
1249 }
1250
1251 void set_write_im(bool value) {
1252 m_writeIm = value;
1253 clear_touched_writes();
1254 }
1255
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;
1262 }
1263 }
1264
1269 void init_query_state(const World* pWorld, Constraints constraints, bool writeIm) {
1270 set_world(pWorld);
1271 m_constraints = constraints;
1272 m_writeIm = writeIm;
1273 clear_touched_writes();
1274 }
1275
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;
1290 m_pChunk = pChunk;
1291 m_entitySnapshotValid = false;
1292 m_from = from;
1293 m_to = to;
1294 }
1295
1296 GAIA_NODISCARD bool write_im() const {
1297 return m_writeIm;
1298 }
1299
1300 GAIA_NODISCARD Constraints constraints() const {
1301 return m_constraints;
1302 }
1303
1304 void clear_touched_writes() {
1305 m_touchedCompCnt = 0;
1306 m_touchedTermCnt = 0;
1307 }
1308
1309 GAIA_NODISCARD const Entity* entity_snapshot() {
1310 if (!m_entitySnapshotValid) {
1311 const auto cnt = size();
1312 GAIA_ASSERT(cnt <= ChunkHeader::MAX_CHUNK_ENTITIES);
1313
1314 const auto entities = m_pChunk->entity_view();
1315 GAIA_FOR(cnt) {
1316 m_entitySnapshot[i] = entities[from() + i];
1317 }
1318
1319 m_entitySnapshotValid = true;
1320 }
1321
1322 return m_entitySnapshot;
1323 }
1324
1325 GAIA_NODISCARD auto touched_comp_indices() const {
1326 return std::span<const uint8_t>{m_touchedCompIndices, m_touchedCompCnt};
1327 }
1328
1329 GAIA_NODISCARD auto touched_terms() const {
1330 return std::span<const Entity>{m_touchedTerms, m_touchedTermCnt};
1331 }
1332
1333 GAIA_NODISCARD auto entity_rows() {
1334 if (m_entitySnapshotValid)
1335 return std::span<const Entity>{m_entitySnapshot, size()};
1336
1337 return std::span<const Entity>{m_pChunk->entity_view().data() + from(), size()};
1338 }
1339
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);
1344#endif
1345 return EntityTermViewSet<U>::entity(entity_snapshot(), world(), termId, size(), writeIm);
1346 }
1347
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);
1352 }
1353
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);
1358#endif
1359 return SoATermViewSet<U>{nullptr, 0, entity_snapshot(), world(), termId, 0, size(), writeIm};
1360 }
1361
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};
1366 }
1367
1368 void set_group_id(GroupId groupId) {
1369 m_groupId = groupId;
1370 }
1371
1372 GAIA_NODISCARD GroupId group_id() const {
1373 return m_groupId;
1374 }
1375
1381
1384 void ctx(void* pCtx) {
1385 m_pCtx = pCtx;
1386 }
1387
1390 GAIA_NODISCARD void* ctx() const {
1391 return m_pCtx;
1392 }
1394
1395 GAIA_NODISCARD CommandBufferST& cmd_buffer_st() const {
1396 auto* pWorld = const_cast<World*>(m_pWorld);
1397 return cmd_buffer_st_get(*pWorld);
1398 }
1399
1400 GAIA_NODISCARD CommandBufferMT& cmd_buffer_mt() const {
1401 auto* pWorld = const_cast<World*>(m_pWorld);
1402 return cmd_buffer_mt_get(*pWorld);
1403 }
1404
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;
1410 }
1411
1412 if (!desc.storageKnown && !desc.isEntity && desc.termId != EntityBad)
1413 desc.usesSparseStorage = world_component_uses_sparse_storage(*world(), desc.termId);
1414
1415 return desc;
1416 }
1417
1418 void touch_comp_idx(uint8_t compIdx) {
1419 GAIA_ASSERT(compIdx != 0xFF);
1420 GAIA_FOR(m_touchedCompCnt) {
1421 if (m_touchedCompIndices[i] == compIdx)
1422 return;
1423 }
1424
1425 GAIA_ASSERT(m_touchedCompCnt < ChunkHeader::MAX_COMPONENTS);
1426 m_touchedCompIndices[m_touchedCompCnt++] = compIdx;
1427 }
1428
1429 GAIA_NODISCARD bool touch_term(Entity term) {
1430 GAIA_ASSERT(term != EntityBad);
1431 GAIA_FOR(m_touchedTermCnt) {
1432 if (m_touchedTerms[i] == term)
1433 return true;
1434 }
1435
1436 if (m_touchedTermCnt >= ChunkHeader::MAX_COMPONENTS)
1437 return false;
1438
1439 m_touchedTerms[m_touchedTermCnt++] = term;
1440 return true;
1441 }
1442
1443 GAIA_NODISCARD bool touch_term_desc(const IterTermDesc& desc) {
1444 if (desc.isEntity)
1445 return true;
1446 if (desc.usesSparseStorage)
1447 return touch_term(desc.termId);
1448 touch_comp_idx((uint8_t)m_pChunk->comp_idx(desc.termId));
1449 return true;
1450 }
1451
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);
1460 return true;
1461 }
1462 }
1463
1464 return touch_term(component);
1465 }
1466
1470 GAIA_NODISCARD bool owns_raw_component(Entity component) {
1471#if GAIA_ASSERT_ENABLED
1472 assert_term_access(component);
1473#endif
1474 const auto* pEntities = entity_snapshot();
1475 GAIA_FOR(size()) {
1476 if (!world_mut_raw(*world(), pEntities[i], component).valid())
1477 return false;
1478 }
1479
1480 return true;
1481 }
1482
1483 GAIA_NODISCARD RawTermViewGet raw_term_view(uint32_t termIdx) const {
1484#if GAIA_ASSERT_ENABLED
1485 assert_term_access(termIdx);
1486#endif
1487 if (m_pCompIndices == nullptr || m_pChunk == nullptr)
1488 return {};
1489
1490 const auto compIdx = m_pCompIndices[termIdx];
1491 if (compIdx == 0xFF)
1492 return {};
1493
1494 const auto recs = m_pChunk->comp_rec_view();
1495 if (compIdx >= recs.size())
1496 return {};
1497
1498 const auto& rec = recs[compIdx];
1499 if (rec.comp.soa() != 0)
1500 return {};
1501
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};
1506 }
1507
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);
1519#endif
1520 if (m_pCompIndices == nullptr || m_pChunk == nullptr || size() == 0)
1521 return false;
1522
1523 compIdx = m_pCompIndices[termIdx];
1524 if (compIdx == 0xFF)
1525 return false;
1526
1527 const auto recs = m_pChunk->comp_rec_view();
1528 if (compIdx >= recs.size())
1529 return false;
1530
1531 const auto& rec = recs[compIdx];
1532 pItem = rec.pItem;
1533 return pItem != nullptr && rec.comp.storage_type() == DataStorageType::Table && rec.comp.soa() != 0 &&
1534 fieldIdx < rec.comp.soa() && pItem->soaSizes[fieldIdx] != 0;
1535 }
1536
1541 GAIA_NODISCARD RawTermViewGet raw_term_field_view(uint32_t termIdx, uint32_t fieldIdx) const {
1542 uint8_t compIdx;
1543 const ComponentCacheItem* pItem;
1544 if (!raw_term_field_info(termIdx, fieldIdx, compIdx, pItem))
1545 return {};
1546
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};
1553 }
1554
1560 GAIA_NODISCARD RawTermViewSet raw_term_field_view_mut(uint32_t termIdx, uint32_t fieldIdx, bool trackWrite) {
1561 uint8_t compIdx;
1562 const ComponentCacheItem* pItem;
1563 if (!raw_term_field_info(termIdx, fieldIdx, compIdx, pItem))
1564 return {};
1565
1566 if (trackWrite) {
1567 touch_comp_idx(compIdx);
1568 if (m_writeIm)
1569 m_pChunk->update_world_version(compIdx);
1570 }
1571
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};
1578 }
1579
1580 GAIA_NODISCARD RawTermViewSet raw_term_view_mut(uint32_t termIdx, bool trackWrite) {
1581#if GAIA_ASSERT_ENABLED
1582 assert_term_access(termIdx);
1583#endif
1584 if (m_pCompIndices == nullptr || m_pChunk == nullptr)
1585 return {};
1586
1587 const auto compIdx = m_pCompIndices[termIdx];
1588 if (compIdx == 0xFF)
1589 return {};
1590
1591 const auto recs = m_pChunk->comp_rec_view();
1592 if (compIdx >= recs.size())
1593 return {};
1594
1595 const auto& rec = recs[compIdx];
1596 if (rec.comp.soa() != 0)
1597 return {};
1598
1599 if (trackWrite) {
1600 touch_comp_idx(compIdx);
1601 if (m_writeIm)
1602 m_pChunk->update_world_version(compIdx);
1603 }
1604
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};
1609 }
1610
1615 GAIA_NODISCARD RawTermViewSetEntity raw_term_view_any_mut(Entity component, bool trackWrite) {
1616#if GAIA_ASSERT_ENABLED
1617 assert_term_access(component);
1618#endif
1619 if (component == EntityBad || m_pChunk == nullptr || size() == 0)
1620 return {};
1621
1622 const auto* pEntities = entity_snapshot();
1623 RawSparseStoreOps sparse{};
1624 if (world_bind_raw_sparse_store(*world(), component, sparse)) {
1625 GAIA_FOR(size()) {
1626 if (!sparse.funcHas(sparse.pStore, pEntities[i]))
1627 return {};
1628 }
1629 } else if (!owns_raw_component(component))
1630 return {};
1631 if (trackWrite && !touch_raw_component(component))
1632 return {};
1633
1634 return {pEntities, world(), component, size(), sparse};
1635 }
1636
1640 GAIA_NODISCARD RawTermViewGet view_raw(uint32_t termIdx) const {
1641 return raw_term_view(termIdx);
1642 }
1643
1651 GAIA_NODISCARD RawTermViewGet view_raw_field(uint32_t termIdx, uint32_t fieldIdx) const {
1652 return raw_term_field_view(termIdx, fieldIdx);
1653 }
1654
1662 GAIA_NODISCARD RawTermViewSet view_raw_field_mut(uint32_t termIdx, uint32_t fieldIdx) {
1663 return raw_term_field_view_mut(termIdx, fieldIdx, true);
1664 }
1665
1673 GAIA_NODISCARD RawTermViewSet sview_raw_field_mut(uint32_t termIdx, uint32_t fieldIdx) {
1674 return raw_term_field_view_mut(termIdx, fieldIdx, false);
1675 }
1676
1681 GAIA_NODISCARD RawTermViewSet view_raw_mut(uint32_t termIdx) {
1682 return raw_term_view_mut(termIdx, true);
1683 }
1684
1689 GAIA_NODISCARD RawTermViewSet sview_raw_mut(uint32_t termIdx) {
1690 return raw_term_view_mut(termIdx, false);
1691 }
1692
1698 GAIA_NODISCARD RawTermViewGetEntity view_raw_any(Entity component) const {
1699#if GAIA_ASSERT_ENABLED
1700 assert_term_access(component);
1701#endif
1702 if (component == EntityBad || m_pChunk == nullptr || size() == 0)
1703 return {};
1704
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())
1709 return {};
1710
1711 return {pEntities, world(), component, size(), sparse};
1712 }
1713
1720 GAIA_NODISCARD RawTermViewSetEntity view_raw_any_mut(Entity component) {
1721 return raw_term_view_any_mut(component, true);
1722 }
1723
1729 GAIA_NODISCARD RawTermViewSetEntity sview_raw_any_mut(Entity component) {
1730 return raw_term_view_any_mut(component, false);
1731 }
1732
1735 void modify_raw(uint32_t termIdx) {
1736#if GAIA_ASSERT_ENABLED
1737 assert_term_access(termIdx);
1738#endif
1739 if (m_pCompIndices == nullptr || m_pChunk == nullptr)
1740 return;
1741
1742 const auto compIdx = m_pCompIndices[termIdx];
1743 if (compIdx == 0xFF || compIdx >= m_pChunk->comp_rec_view().size())
1744 return;
1745
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))
1752 return;
1753 }
1754
1755 touch_comp_idx(compIdx);
1756 }
1757
1763 GAIA_NODISCARD bool modify_raw(Entity component) {
1764#if GAIA_ASSERT_ENABLED
1765 assert_term_access(component);
1766#endif
1767 if (component == EntityBad || m_pChunk == nullptr || size() == 0 || !owns_raw_component(component))
1768 return false;
1769
1770 return touch_raw_component(component);
1771 }
1772
1779 template <typename T>
1780 GAIA_NODISCARD auto view_any() const {
1781 return ChunkIterTypedOps::template view_any<T>(*this);
1782 }
1783
1791 template <typename T>
1792 GAIA_NODISCARD auto view_any(uint32_t termIdx) {
1793 return ChunkIterTypedOps::template view_any<T>(*this, termIdx);
1794 }
1795
1803 template <typename T>
1804 GAIA_NODISCARD auto view() const {
1805 return ChunkIterTypedOps::template view<T>(*this);
1806 }
1807
1815 template <typename T>
1816 GAIA_NODISCARD auto view(uint32_t termIdx) const {
1817 return ChunkIterTypedOps::template view<T>(*this, termIdx);
1818 }
1819
1826 template <typename T>
1827 GAIA_NODISCARD auto view_any_mut() {
1828 return ChunkIterTypedOps::template view_any_mut<T>(*this);
1829 }
1830
1836 template <typename T>
1837 GAIA_NODISCARD auto view_mut() {
1838 return ChunkIterTypedOps::template view_mut<T>(*this);
1839 }
1840
1848 template <typename T>
1849 GAIA_NODISCARD auto view_mut(uint32_t termIdx) {
1850 return ChunkIterTypedOps::template view_mut<T>(*this, termIdx);
1851 }
1852
1860 template <typename T>
1861 GAIA_NODISCARD auto view_any_mut(uint32_t termIdx) {
1862 return ChunkIterTypedOps::template view_any_mut<T>(*this, termIdx);
1863 }
1864
1872 template <typename T>
1873 GAIA_NODISCARD auto sview_any_mut() {
1874 return ChunkIterTypedOps::template sview_any_mut<T>(*this);
1875 }
1876
1882 template <typename T>
1883 GAIA_NODISCARD auto sview_mut() {
1884 return ChunkIterTypedOps::template sview_mut<T>(*this);
1885 }
1886
1894 template <typename T>
1895 GAIA_NODISCARD auto sview_mut(uint32_t termIdx) {
1896 return ChunkIterTypedOps::template sview_mut<T>(*this, termIdx);
1897 }
1898
1907 template <typename T>
1908 GAIA_NODISCARD auto sview_any_mut(uint32_t termIdx) {
1909 return ChunkIterTypedOps::template sview_any_mut<T>(*this, termIdx);
1910 }
1911
1915 template <typename T, bool TriggerHooks>
1916 void modify() {
1917#if GAIA_ASSERT_ENABLED
1918 assert_term_access(ChunkIterTypedOps::template term_desc<T>(*this).termId);
1919#endif
1920 m_pChunk->template modify<T, TriggerHooks>();
1921 }
1922
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>();
1934 else
1935 return view<T>();
1936 }
1937
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>();
1949 else
1950 return view_any<T>();
1951 }
1952
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>();
1965 else
1966 return view_any<T>();
1967 }
1968
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>();
1981 else
1982 return view<T>();
1983 }
1984
1987 GAIA_NODISCARD bool enabled(uint32_t index) const {
1988 const auto row = (uint16_t)(from() + index);
1989 return m_pChunk->enabled(row);
1990 }
1991
1995 GAIA_NODISCARD bool has(Entity entity) const {
1996 return m_pChunk->has(entity);
1997 }
1998
2002 GAIA_NODISCARD bool has(Pair pair) const {
2003 return m_pChunk->has((Entity)pair);
2004 }
2005
2009 template <typename T>
2010 GAIA_NODISCARD bool has() const {
2011 return m_pChunk->template has<T>();
2012 }
2013
2014 GAIA_NODISCARD static uint16_t start_index(Chunk* pChunk, Constraints constraints) noexcept {
2015 if (constraints == Constraints::EnabledOnly)
2016 return pChunk->size_disabled();
2017 return 0;
2018 }
2019
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();
2024 }
2025
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();
2032 }
2033
2035 GAIA_NODISCARD uint16_t size() const noexcept {
2036 return (uint16_t)(to() - from());
2037 }
2038
2040 GAIA_NODISCARD uint16_t row_begin() const noexcept {
2041 return from();
2042 }
2043
2045 GAIA_NODISCARD uint16_t row_end() const noexcept {
2046 return to();
2047 }
2048
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();
2057 else
2058 return idx;
2059 }
2060
2061 protected:
2063 GAIA_NODISCARD uint16_t from() const noexcept {
2064 return m_from;
2065 }
2066
2068 GAIA_NODISCARD uint16_t to() const noexcept {
2069 return m_to;
2070 }
2071 };
2072 } // namespace detail
2074
2077 class GAIA_API Iter: public detail::ChunkIterImpl {
2078 public:
2080 static constexpr Constraints ConstraintMode = Constraints::EnabledOnly;
2081
2082 using detail::ChunkIterImpl::size;
2083
2084 Iter() {
2085 set_constraints(ConstraintMode);
2086 }
2087
2088#if GAIA_OBSERVERS_ENABLED
2092 void event(ObserverEvent value) noexcept {
2093 m_observerEvent = value;
2094 }
2095
2101 GAIA_NODISCARD ObserverEvent event() const noexcept {
2102 return m_observerEvent;
2103 }
2104#endif
2105
2109 GAIA_NODISCARD static uint16_t start_index(Chunk* pChunk) noexcept {
2110 return detail::ChunkIterImpl::start_index(pChunk, ConstraintMode);
2111 }
2112
2116 GAIA_NODISCARD static uint16_t end_index(Chunk* pChunk) noexcept {
2117 return detail::ChunkIterImpl::end_index(pChunk, ConstraintMode);
2118 }
2119
2123 GAIA_NODISCARD static uint16_t size(Chunk* pChunk) noexcept {
2124 return detail::ChunkIterImpl::size(pChunk, ConstraintMode);
2125 }
2126
2129 GAIA_NODISCARD uint16_t size_enabled() const noexcept {
2130 return m_pChunk->size_enabled();
2131 }
2132
2136 GAIA_NODISCARD uint16_t size_disabled() const noexcept {
2137 return m_pChunk->size_disabled();
2138 }
2139 };
2140
2142 class GAIA_API CopyIter final {
2143 protected:
2146
2148 const World* m_pWorld = nullptr;
2150 const Archetype* m_pArchetype = nullptr;
2152 Chunk* m_pChunk = nullptr;
2154 uint16_t m_from;
2156 uint16_t m_cnt;
2157
2158 public:
2159 CopyIter() = default;
2160 ~CopyIter() = default;
2161 CopyIter(CopyIter&&) noexcept = default;
2162 CopyIter& operator=(CopyIter&&) noexcept = default;
2163
2164 CopyIter& operator=(const CopyIter&) = delete;
2165
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());
2172 m_from = from;
2173 m_cnt = cnt;
2174 }
2175
2178 void set_world(const World* pWorld) {
2179 GAIA_ASSERT(pWorld != nullptr);
2180 m_pWorld = pWorld;
2181 }
2182
2185 GAIA_NODISCARD World* world() {
2186 GAIA_ASSERT(m_pWorld != nullptr);
2187 return const_cast<World*>(m_pWorld);
2188 }
2189
2192 GAIA_NODISCARD const World* world() const {
2193 GAIA_ASSERT(m_pWorld != nullptr);
2194 return m_pWorld;
2195 }
2196
2199 void set_archetype(const Archetype* pArchetype) {
2200 GAIA_ASSERT(pArchetype != nullptr);
2201 m_pArchetype = pArchetype;
2202 }
2203
2204 // GAIA_NODISCARD Archetype* archetype() {
2205 // GAIA_ASSERT(m_pArchetype != nullptr);
2206 // return m_pArchetype;
2207 // }
2208
2211 GAIA_NODISCARD const Archetype* archetype() const {
2212 GAIA_ASSERT(m_pArchetype != nullptr);
2213 return m_pArchetype;
2214 }
2215
2218 void set_chunk(Chunk* pChunk) {
2219 GAIA_ASSERT(pChunk != nullptr);
2220 m_pChunk = pChunk;
2221 }
2222
2225 GAIA_NODISCARD const Chunk* chunk() const {
2226 GAIA_ASSERT(m_pChunk != nullptr);
2227 return m_pChunk;
2228 }
2229
2232 GAIA_NODISCARD CommandBufferST& cmd_buffer_st() const {
2233 auto* pWorld = const_cast<World*>(m_pWorld);
2234 return cmd_buffer_st_get(*pWorld);
2235 }
2236
2239 GAIA_NODISCARD CommandBufferMT& cmd_buffer_mt() const {
2240 auto* pWorld = const_cast<World*>(m_pWorld);
2241 return cmd_buffer_mt_get(*pWorld);
2242 }
2243
2248 template <typename T>
2249 GAIA_NODISCARD auto view() const {
2250 return m_pChunk->template view<T>(from(), to());
2251 }
2252
2257 template <typename T>
2258 GAIA_NODISCARD auto view_mut() {
2259 return m_pChunk->template view_mut<T>(from(), to());
2260 }
2261
2267 template <typename T>
2268 GAIA_NODISCARD auto sview_mut() {
2269 return m_pChunk->template sview_mut<T>(from(), to());
2270 }
2271
2275 template <typename T, bool TriggerHooks>
2276 void modify() {
2277 m_pChunk->template modify<T, TriggerHooks>();
2278 }
2279
2285 template <typename T>
2286 GAIA_NODISCARD auto view_auto() {
2287 return m_pChunk->template view_auto<T>(from(), to());
2288 }
2289
2296 template <typename T>
2297 GAIA_NODISCARD auto sview_auto() {
2298 return m_pChunk->template sview_auto<T>(from(), to());
2299 }
2300
2304 GAIA_NODISCARD bool enabled(uint32_t index) const {
2305 const auto row = (uint16_t)(from() + index);
2306 return m_pChunk->enabled(row);
2307 }
2308
2312 GAIA_NODISCARD bool has(Entity entity) const {
2313 return m_pChunk->has(entity);
2314 }
2315
2319 GAIA_NODISCARD bool has(Pair pair) const {
2320 return m_pChunk->has((Entity)pair);
2321 }
2322
2326 template <typename T>
2327 GAIA_NODISCARD bool has() const {
2328 return m_pChunk->template has<T>();
2329 }
2330
2333 GAIA_NODISCARD uint16_t size() const noexcept {
2334 return m_cnt;
2335 }
2336
2337 private:
2339 GAIA_NODISCARD uint16_t from() const noexcept {
2340 return m_from;
2341 }
2342
2344 GAIA_NODISCARD uint16_t to() const noexcept {
2345 return m_from + m_cnt;
2346 }
2347 };
2348 } // namespace ecs
2349} // namespace gaia
2350
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