Gaia-ECS v0.9.3
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/id.h"
15#include "gaia/ecs/query_common.h"
16#include "gaia/mem/data_layout_policy.h"
17
18namespace gaia {
19 namespace ecs {
20 class World;
21 void world_finish_write(World& world, Entity term, Entity entity);
22 template <typename T>
23 decltype(auto) world_query_entity_arg_by_id_raw(World& world, Entity entity, Entity id);
24 template <typename T>
25 decltype(auto) world_query_entity_arg_by_id_cached_const(
26 World& world, Entity entity, Entity id, const Archetype*& pLastArchetype, Entity& cachedOwner,
27 bool& cachedDirect);
28 template <typename T>
29 void world_init_query_entity_arg_by_id_chunk_stable_const(
30 World& world, const Chunk& chunk, const Entity* pEntities, Entity id, bool& direct, uint32_t& compIdx,
31 const std::remove_cv_t<std::remove_reference_t<T>>*& pDataInherited);
32 template <typename T>
33 const std::remove_cv_t<std::remove_reference_t<T>>*
34 world_query_inherited_arg_data_const(World& world, Entity owner, Entity id);
35 bool world_term_uses_inherit_policy(const World& world, Entity term);
36 template <typename T>
37 Entity world_query_arg_id(World& world);
38
40 enum class Constraints : uint8_t { EnabledOnly, DisabledOnly, AcceptAll };
41
42 namespace detail {
43 struct BfsChunkRun {
44 const Archetype* pArchetype = nullptr;
45 Chunk* pChunk = nullptr;
46 uint16_t from = 0;
47 uint16_t to = 0;
48 uint32_t offset = 0;
49 };
50
53 template <typename U>
55 const U* pData = nullptr;
56 uint32_t cnt = 0;
57
58 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
59 GAIA_ASSERT(idx < cnt);
60 return pData[idx];
61 }
62
63 GAIA_NODISCARD constexpr size_t size() const noexcept {
64 return cnt;
65 }
66
67 GAIA_NODISCARD const U* data() const noexcept {
68 return pData;
69 }
70 };
71
74 template <typename U>
76 const Entity* pEntities = nullptr;
77 World* pWorld = nullptr;
78 Entity id = EntityBad;
79 uint32_t cnt = 0;
80 mutable const Archetype* pLastArchetype = nullptr;
81 mutable Entity cachedOwner = EntityBad;
82 mutable bool cachedDirect = false;
83
84 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
85 GAIA_ASSERT(idx < cnt);
86 return world_query_entity_arg_by_id_cached_const<const U&>(
87 *pWorld, pEntities[idx], id, pLastArchetype, cachedOwner, cachedDirect);
88 }
89
90 GAIA_NODISCARD constexpr size_t size() const noexcept {
91 return cnt;
92 }
93
94 GAIA_NODISCARD const U* data() const noexcept {
95 return nullptr;
96 }
97 };
98
101 template <typename U>
103 U* pData = nullptr;
104 uint32_t cnt = 0;
105
106 GAIA_NODISCARD decltype(auto) operator[](size_t idx) {
107 GAIA_ASSERT(idx < cnt);
108 return pData[idx];
109 }
110
111 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
112 GAIA_ASSERT(idx < cnt);
113 return static_cast<const U&>(pData[idx]);
114 }
115
116 GAIA_NODISCARD constexpr size_t size() const noexcept {
117 return cnt;
118 }
119
120 GAIA_NODISCARD U* data() noexcept {
121 return pData;
122 }
123
124 GAIA_NODISCARD const U* data() const noexcept {
125 return pData;
126 }
127 };
128
131 template <typename U, bool WriteIm>
133 const Entity* pEntities = nullptr;
134 World* pWorld = nullptr;
135 Entity id = EntityBad;
136 uint32_t cnt = 0;
137
138 GAIA_NODISCARD decltype(auto) operator[](size_t idx) {
139 GAIA_ASSERT(idx < cnt);
140 if constexpr (WriteIm)
141 return world_query_entity_arg_by_id<U&>(*pWorld, pEntities[idx], id);
142 else
143 return world_query_entity_arg_by_id_raw<U&>(*pWorld, pEntities[idx], id);
144 }
145
146 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
147 GAIA_ASSERT(idx < cnt);
148 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
149 }
150
151 GAIA_NODISCARD constexpr size_t size() const noexcept {
152 return cnt;
153 }
154
155 GAIA_NODISCARD U* data() noexcept {
156 return nullptr;
157 }
158
159 GAIA_NODISCARD const U* data() const noexcept {
160 return nullptr;
161 }
162 };
163
166 template <typename U>
168 const U* pData = nullptr;
169 const Entity* pEntities = nullptr;
170 World* pWorld = nullptr;
171 Entity id = EntityBad;
172 uint32_t cnt = 0;
173 const U* pDataInherited = nullptr;
174 mutable const Archetype* pLastArchetype = nullptr;
175 mutable Entity cachedOwner = EntityBad;
176 mutable bool cachedDirect = false;
177
178 static EntityTermViewGet pointer(const U* pData, uint32_t cnt) {
179 return {pData, nullptr, nullptr, EntityBad, cnt, nullptr, nullptr, EntityBad, false};
180 }
181
182 static EntityTermViewGet entity(const Entity* pEntities, World* pWorld, Entity id, uint32_t cnt) {
183 return {nullptr, pEntities, pWorld, id, cnt, nullptr, nullptr, EntityBad, false};
184 }
185
186 static EntityTermViewGet inherited(const U* pDataInherited, uint32_t cnt) {
187 return {nullptr, nullptr, nullptr, EntityBad, cnt, pDataInherited, nullptr, EntityBad, false};
188 }
189
190 static EntityTermViewGet entity_chunk_stable(
191 const Entity* pEntities, const Chunk* pChunk, World* pWorld, Entity id, uint16_t rowBase, uint32_t cnt) {
192 uint32_t compIdx = BadIndex;
193 const U* pDataInherited = nullptr;
194 bool direct = false;
195 world_init_query_entity_arg_by_id_chunk_stable_const<U>(
196 *pWorld, *pChunk, pEntities, id, direct, compIdx, pDataInherited);
197 const U* pData = nullptr;
198 if (direct)
199 pData = reinterpret_cast<const U*>(pChunk->comp_ptr(compIdx, rowBase));
200
201 return {pData, nullptr, pWorld, id, cnt, pDataInherited, nullptr, EntityBad, false};
202 }
203
204 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
205 GAIA_ASSERT(idx < cnt);
206 if (pData != nullptr)
207 return pData[idx];
208 if (pDataInherited != nullptr) {
209 GAIA_ASSERT(pDataInherited != nullptr);
210 return *pDataInherited;
211 }
212
213 return world_query_entity_arg_by_id_cached_const<const U&>(
214 *pWorld, pEntities[idx], id, pLastArchetype, cachedOwner, cachedDirect);
215 }
216
217 GAIA_NODISCARD constexpr size_t size() const noexcept {
218 return cnt;
219 }
220
221 GAIA_NODISCARD const U* data() const noexcept {
222 return pData;
223 }
224 };
225
228 template <typename U>
230 U* pData = nullptr;
231 const Entity* pEntities = nullptr;
232 World* pWorld = nullptr;
233 Entity id = EntityBad;
234 uint32_t cnt = 0;
235 bool writeIm = true;
236
237 static EntityTermViewSet pointer(U* pData, uint32_t cnt) {
238 return {pData, nullptr, nullptr, EntityBad, cnt, true};
239 }
240
241 static EntityTermViewSet
242 entity(const Entity* pEntities, World* pWorld, Entity id, uint32_t cnt, bool writeIm = true) {
243 return {nullptr, pEntities, pWorld, id, cnt, writeIm};
244 }
245
246 GAIA_NODISCARD decltype(auto) operator[](size_t idx) {
247 GAIA_ASSERT(idx < cnt);
248 if (pData != nullptr)
249 return pData[idx];
250
251 if (writeIm)
252 return EntityTermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}[idx];
253 return EntityTermViewSetEntity<U, false>{pEntities, pWorld, id, cnt}[idx];
254 }
255
256 GAIA_NODISCARD decltype(auto) operator[](size_t idx) const {
257 GAIA_ASSERT(idx < cnt);
258 if (pData != nullptr)
259 return static_cast<const U&>(pData[idx]);
260
261 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
262 }
263
264 GAIA_NODISCARD constexpr size_t size() const noexcept {
265 return cnt;
266 }
267
268 GAIA_NODISCARD U* data() noexcept {
269 return pData;
270 }
271
272 GAIA_NODISCARD const U* data() const noexcept {
273 return pData;
274 }
275 };
276
279 template <typename U>
282
283 uint8_t* pData = nullptr;
284 uint32_t dataSize = 0;
285 uint32_t idx = 0;
286
287 GAIA_NODISCARD operator U() const {
288 return raw_view_policy::get(std::span<const uint8_t>{pData, dataSize}, idx);
289 }
290
291 SoATermRowWriteProxyPointer& operator=(const U& value) {
292 raw_view_policy::set(std::span<uint8_t>{pData, dataSize}, idx) = value;
293 return *this;
294 }
295 };
296
299 template <typename U, bool WriteIm>
301 const Entity* pEntities = nullptr;
302 World* pWorld = nullptr;
303 Entity id = EntityBad;
304 uint32_t idx = 0;
305
306 GAIA_NODISCARD operator U() const {
307 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
308 }
309
310 SoATermRowWriteProxyEntity& operator=(const U& value) {
311 if constexpr (WriteIm)
312 world_query_entity_arg_by_id<U&>(*pWorld, pEntities[idx], id) = value;
313 else
314 world_query_entity_arg_by_id_raw<U&>(*pWorld, pEntities[idx], id) = value;
315 return *this;
316 }
317 };
318
321 template <typename U, size_t Item>
324 using value_type = typename view_policy::template data_view_policy_idx_info<Item>::const_value_type;
325
326 const value_type* pData = nullptr;
327 uint32_t cnt = 0;
328
329 GAIA_NODISCARD value_type operator[](size_t idx) const {
330 GAIA_ASSERT(idx < cnt);
331 return pData[idx];
332 }
333
334 GAIA_NODISCARD constexpr size_t size() const noexcept {
335 return cnt;
336 }
337 };
338
341 template <typename U, size_t Item>
344 using value_type = typename view_policy::template data_view_policy_idx_info<Item>::const_value_type;
345
346 const Entity* pEntities = nullptr;
347 World* pWorld = nullptr;
348 Entity id = EntityBad;
349 uint32_t cnt = 0;
350
351 GAIA_NODISCARD value_type operator[](size_t idx) const {
352 GAIA_ASSERT(idx < cnt);
353 const U value = world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
354 return std::get<Item>(meta::struct_to_tuple(value));
355 }
356
357 GAIA_NODISCARD constexpr size_t size() const noexcept {
358 return cnt;
359 }
360 };
361
364 template <typename U, size_t Item>
367 using value_type = typename view_policy::template data_view_policy_idx_info<Item>::value_type;
368
369 value_type* pData = nullptr;
370 uint32_t cnt = 0;
371
372 GAIA_NODISCARD value_type& operator[](size_t idx) {
373 GAIA_ASSERT(idx < cnt);
374 return pData[idx];
375 }
376
377 GAIA_NODISCARD const value_type& operator[](size_t idx) const {
378 GAIA_ASSERT(idx < cnt);
379 return pData[idx];
380 }
381
382 GAIA_NODISCARD constexpr size_t size() const noexcept {
383 return cnt;
384 }
385 };
386
389 template <typename U, size_t Item, bool WriteIm>
392 using value_type = typename view_policy::template data_view_policy_idx_info<Item>::value_type;
393
396 const Entity* pEntities = nullptr;
397 World* pWorld = nullptr;
398 Entity id = EntityBad;
399 uint32_t idx = 0;
400
401 GAIA_NODISCARD operator value_type() const {
402 const U value = world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
403 return std::get<Item>(meta::struct_to_tuple(value));
404 }
405
406 ElementProxy& operator=(const value_type& value) {
407 auto data = world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
408 auto tuple = meta::struct_to_tuple(data);
409 std::get<Item>(tuple) = value;
410 if constexpr (WriteIm)
411 world_query_entity_arg_by_id<U&>(*pWorld, pEntities[idx], id) = meta::tuple_to_struct<U>(GAIA_MOV(tuple));
412 else
413 world_query_entity_arg_by_id_raw<U&>(*pWorld, pEntities[idx], id) =
414 meta::tuple_to_struct<U>(GAIA_MOV(tuple));
415 return *this;
416 }
417
418 template <typename V>
419 ElementProxy& operator+=(V&& value) {
420 const value_type current = operator value_type();
421 return operator=(current + GAIA_FWD(value));
422 }
423
424 template <typename V>
425 ElementProxy& operator-=(V&& value) {
426 const value_type current = operator value_type();
427 return operator=(current - GAIA_FWD(value));
428 }
429
430 template <typename V>
431 ElementProxy& operator*=(V&& value) {
432 const value_type current = operator value_type();
433 return operator=(current * GAIA_FWD(value));
434 }
435
436 template <typename V>
437 ElementProxy& operator/=(V&& value) {
438 const value_type current = operator value_type();
439 return operator=(current / GAIA_FWD(value));
440 }
441 };
442
443 const Entity* pEntities = nullptr;
444 World* pWorld = nullptr;
445 Entity id = EntityBad;
446 uint32_t cnt = 0;
447
448 GAIA_NODISCARD ElementProxy operator[](size_t idx) const {
449 GAIA_ASSERT(idx < cnt);
450 return ElementProxy{pEntities, pWorld, id, (uint32_t)idx};
451 }
452
453 GAIA_NODISCARD constexpr size_t size() const noexcept {
454 return cnt;
455 }
456 };
457
460 template <typename U>
464
465 const uint8_t* pData = nullptr;
466 uint32_t dataSize = 0;
467 uint32_t idxBase = 0;
468 uint32_t cnt = 0;
469
470 GAIA_NODISCARD U operator[](size_t idx) const {
471 GAIA_ASSERT(idx < cnt);
472 return raw_view_policy::get(std::span<const uint8_t>{pData, dataSize}, idxBase + idx);
473 }
474
475 template <size_t Item>
476 GAIA_NODISCARD auto get() const {
477 const auto field = read_view_policy{std::span<const uint8_t>{pData, dataSize}}.template get<Item>();
478 return SoATermFieldReadProxyPointer<U, Item>{field.data() + idxBase, cnt};
479 }
480
481 GAIA_NODISCARD constexpr size_t size() const noexcept {
482 return cnt;
483 }
484 };
485
488 template <typename U>
490 const Entity* pEntities = nullptr;
491 World* pWorld = nullptr;
492 Entity id = EntityBad;
493 uint32_t cnt = 0;
494
495 GAIA_NODISCARD U operator[](size_t idx) const {
496 GAIA_ASSERT(idx < cnt);
497 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
498 }
499
500 template <size_t Item>
501 GAIA_NODISCARD auto get() const {
502 return SoATermFieldReadProxyEntity<U, Item>{pEntities, pWorld, id, cnt};
503 }
504
505 GAIA_NODISCARD constexpr size_t size() const noexcept {
506 return cnt;
507 }
508 };
509
512 template <typename U>
517
518 uint8_t* pData = nullptr;
519 uint32_t dataSize = 0;
520 uint32_t idxBase = 0;
521 uint32_t cnt = 0;
522
523 GAIA_NODISCARD auto operator[](size_t idx) {
524 GAIA_ASSERT(idx < cnt);
525 return SoATermRowWriteProxyPointer<U>{pData, dataSize, idxBase + (uint32_t)idx};
526 }
527
528 GAIA_NODISCARD U operator[](size_t idx) const {
529 GAIA_ASSERT(idx < cnt);
530 return raw_view_policy::get(std::span<const uint8_t>{pData, dataSize}, idxBase + idx);
531 }
532
533 template <size_t Item>
534 GAIA_NODISCARD auto get() const {
535 const auto field = read_view_policy{std::span<const uint8_t>{pData, dataSize}}.template get<Item>();
536 return SoATermFieldReadProxyPointer<U, Item>{field.data() + idxBase, cnt};
537 }
538
539 template <size_t Item>
540 GAIA_NODISCARD auto set() {
541 auto field = write_view_policy{std::span<uint8_t>{pData, dataSize}}.template set<Item>();
542 return SoATermFieldWriteProxyPointer<U, Item>{field.data() + idxBase, cnt};
543 }
544
545 GAIA_NODISCARD constexpr size_t size() const noexcept {
546 return cnt;
547 }
548 };
549
552 template <typename U, bool WriteIm>
554 const Entity* pEntities = nullptr;
555 World* pWorld = nullptr;
556 Entity id = EntityBad;
557 uint32_t cnt = 0;
558
559 GAIA_NODISCARD auto operator[](size_t idx) {
560 GAIA_ASSERT(idx < cnt);
561 return SoATermRowWriteProxyEntity<U, WriteIm>{pEntities, pWorld, id, (uint32_t)idx};
562 }
563
564 GAIA_NODISCARD U operator[](size_t idx) const {
565 GAIA_ASSERT(idx < cnt);
566 return world_query_entity_arg_by_id<const U&>(*pWorld, pEntities[idx], id);
567 }
568
569 template <size_t Item>
570 GAIA_NODISCARD auto get() const {
571 return SoATermFieldReadProxyEntity<U, Item>{pEntities, pWorld, id, cnt};
572 }
573
574 template <size_t Item>
575 GAIA_NODISCARD auto set() {
576 return SoATermFieldWriteProxyEntity<U, Item, WriteIm>{pEntities, pWorld, id, cnt};
577 }
578
579 GAIA_NODISCARD constexpr size_t size() const noexcept {
580 return cnt;
581 }
582 };
583
586 template <typename U>
588 uint8_t* pData = nullptr;
589 uint32_t dataSize = 0;
590 const Entity* pEntities = nullptr;
591 World* pWorld = nullptr;
592 Entity id = EntityBad;
593 uint32_t idx = 0;
594 bool writeIm = true;
595
596 GAIA_NODISCARD operator U() const {
597 if (pData != nullptr)
598 return (U)SoATermRowWriteProxyPointer<U>{pData, dataSize, idx};
599
600 if (writeIm)
601 return (U)SoATermRowWriteProxyEntity<U, true>{pEntities, pWorld, id, idx};
602 return (U)SoATermRowWriteProxyEntity<U, false>{pEntities, pWorld, id, idx};
603 }
604
605 SoATermRowWriteProxy& operator=(const U& value) {
606 if (pData != nullptr) {
607 SoATermRowWriteProxyPointer<U>{pData, dataSize, idx} = value;
608 } else if (writeIm)
609 SoATermRowWriteProxyEntity<U, true>{pEntities, pWorld, id, idx} = value;
610 else
611 SoATermRowWriteProxyEntity<U, false>{pEntities, pWorld, id, idx} = value;
612 return *this;
613 }
614 };
615
618 template <typename U, size_t Item>
620 using value_type = typename SoATermFieldReadProxyPointer<U, Item>::value_type;
621
622 const value_type* pData = nullptr;
623 const Entity* pEntities = nullptr;
624 World* pWorld = nullptr;
625 Entity id = EntityBad;
626 uint32_t cnt = 0;
627
628 GAIA_NODISCARD value_type operator[](size_t idx) const {
629 GAIA_ASSERT(idx < cnt);
630 if (pData != nullptr)
631 return SoATermFieldReadProxyPointer<U, Item>{pData, cnt}[idx];
632
633 return SoATermFieldReadProxyEntity<U, Item>{pEntities, pWorld, id, cnt}[idx];
634 }
635
636 GAIA_NODISCARD constexpr size_t size() const noexcept {
637 return cnt;
638 }
639 };
640
643 template <typename U, size_t Item>
645 using value_type = typename SoATermFieldWriteProxyPointer<U, Item>::value_type;
646
647 value_type* pData = nullptr;
648 const Entity* pEntities = nullptr;
649 World* pWorld = nullptr;
650 Entity id = EntityBad;
651 uint32_t cnt = 0;
652 bool writeIm = true;
653
657 value_type* pData = nullptr;
658 const Entity* pEntities = nullptr;
659 World* pWorld = nullptr;
660 Entity id = EntityBad;
661 uint32_t idx = 0;
662 bool writeIm = true;
663
664 GAIA_NODISCARD operator value_type() const {
665 if (pData != nullptr)
666 return SoATermFieldWriteProxyPointer<U, Item>{pData, idx + 1}[idx];
667
668 if (writeIm)
669 return SoATermFieldWriteProxyEntity<U, Item, true>{pEntities, pWorld, id, idx + 1}[idx];
670 return SoATermFieldWriteProxyEntity<U, Item, false>{pEntities, pWorld, id, idx + 1}[idx];
671 }
672
673 ElementProxy& operator=(const value_type& value) {
674 if (pData != nullptr) {
675 SoATermFieldWriteProxyPointer<U, Item>{pData, idx + 1}[idx] = value;
676 return *this;
677 }
678
679 if (writeIm)
680 SoATermFieldWriteProxyEntity<U, Item, true>{pEntities, pWorld, id, idx + 1}[idx] = value;
681 else
682 SoATermFieldWriteProxyEntity<U, Item, false>{pEntities, pWorld, id, idx + 1}[idx] = value;
683 return *this;
684 }
685
686 template <typename V>
687 ElementProxy& operator+=(V&& value) {
688 const value_type current = operator value_type();
689 return operator=(current + GAIA_FWD(value));
690 }
691
692 template <typename V>
693 ElementProxy& operator-=(V&& value) {
694 const value_type current = operator value_type();
695 return operator=(current - GAIA_FWD(value));
696 }
697
698 template <typename V>
699 ElementProxy& operator*=(V&& value) {
700 const value_type current = operator value_type();
701 return operator=(current * GAIA_FWD(value));
702 }
703
704 template <typename V>
705 ElementProxy& operator/=(V&& value) {
706 const value_type current = operator value_type();
707 return operator=(current / GAIA_FWD(value));
708 }
709 };
710
711 GAIA_NODISCARD ElementProxy operator[](size_t idx) const {
712 GAIA_ASSERT(idx < cnt);
713 return ElementProxy{pData, pEntities, pWorld, id, (uint32_t)idx, writeIm};
714 }
715
716 GAIA_NODISCARD constexpr size_t size() const noexcept {
717 return cnt;
718 }
719 };
720
723 template <typename U>
725 const uint8_t* pData = nullptr;
726 uint32_t dataSize = 0;
727 const Entity* pEntities = nullptr;
728 World* pWorld = nullptr;
729 Entity id = EntityBad;
730 uint32_t idxBase = 0;
731 uint32_t cnt = 0;
732
733 GAIA_NODISCARD U operator[](size_t idx) const {
734 GAIA_ASSERT(idx < cnt);
735 if (pData != nullptr)
736 return SoATermViewGetPointer<U>{pData, dataSize, idxBase, cnt}[idx];
737
738 return SoATermViewGetEntity<U>{pEntities, pWorld, id, cnt}[idx];
739 }
740
741 template <size_t Item>
742 GAIA_NODISCARD auto get() const {
743 if (pData != nullptr) {
744 const auto field = SoATermViewGetPointer<U>{pData, dataSize, idxBase, cnt}.template get<Item>();
745 return SoATermFieldReadProxy<U, Item>{field.pData, nullptr, pWorld, id, cnt};
746 }
747
748 const auto field = SoATermViewGetEntity<U>{pEntities, pWorld, id, cnt}.template get<Item>();
749 return SoATermFieldReadProxy<U, Item>{nullptr, field.pEntities, field.pWorld, field.id, field.cnt};
750 }
751
752 GAIA_NODISCARD constexpr size_t size() const noexcept {
753 return cnt;
754 }
755 };
756
759 template <typename U>
761 uint8_t* pData = nullptr;
762 uint32_t dataSize = 0;
763 const Entity* pEntities = nullptr;
764 World* pWorld = nullptr;
765 Entity id = EntityBad;
766 uint32_t idxBase = 0;
767 uint32_t cnt = 0;
768 bool writeIm = true;
769
770 GAIA_NODISCARD auto operator[](size_t idx) {
771 GAIA_ASSERT(idx < cnt);
772 return SoATermRowWriteProxy<U>{pData, dataSize, pEntities, pWorld, id, idxBase + (uint32_t)idx, writeIm};
773 }
774
775 GAIA_NODISCARD U operator[](size_t idx) const {
776 GAIA_ASSERT(idx < cnt);
777 if (pData != nullptr)
778 return SoATermViewSetPointer<U>{pData, dataSize, idxBase, cnt}[idx];
779
780 return SoATermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}[idx];
781 }
782
783 template <size_t Item>
784 GAIA_NODISCARD auto get() const {
785 if (pData != nullptr) {
786 const auto field = SoATermViewSetPointer<U>{pData, dataSize, idxBase, cnt}.template get<Item>();
787 return SoATermFieldReadProxy<U, Item>{field.pData, nullptr, pWorld, id, cnt};
788 }
789
790 const auto field = SoATermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}.template get<Item>();
791 return SoATermFieldReadProxy<U, Item>{nullptr, field.pEntities, field.pWorld, field.id, field.cnt};
792 }
793
794 template <size_t Item>
795 GAIA_NODISCARD auto set() {
796 if (pData != nullptr) {
797 auto field = SoATermViewSetPointer<U>{pData, dataSize, idxBase, cnt}.template set<Item>();
798 return SoATermFieldWriteProxy<U, Item>{field.pData, nullptr, pWorld, id, cnt};
799 }
800
801 if (writeIm) {
802 const auto field = SoATermViewSetEntity<U, true>{pEntities, pWorld, id, cnt}.template set<Item>();
803 return SoATermFieldWriteProxy<U, Item>{nullptr, field.pEntities, field.pWorld, field.id, field.cnt, true};
804 }
805
806 const auto field = SoATermViewSetEntity<U, false>{pEntities, pWorld, id, cnt}.template set<Item>();
807 return SoATermFieldWriteProxy<U, Item>{nullptr, field.pEntities, field.pWorld, field.id, field.cnt, false};
808 }
809
810 GAIA_NODISCARD constexpr size_t size() const noexcept {
811 return cnt;
812 }
813 };
814
815 template <Constraints IterConstraint>
817 protected:
819
821 const World* m_pWorld = nullptr;
823 const Archetype* m_pArchetype = nullptr;
825 Chunk* m_pChunk = nullptr;
827 const uint8_t* m_pCompIndices = nullptr;
829 InheritedTermDataView m_inheritedData;
831 const Entity* m_pTermIdMapping = nullptr;
833 bool m_writeIm = true;
836 uint8_t m_touchedCompCnt = 0;
839 uint8_t m_touchedTermCnt = 0;
842 bool m_entitySnapshotValid = false;
844 uint16_t m_from;
846 uint16_t m_to;
848 GroupId m_groupId = 0;
849
850 public:
851 ChunkIterImpl() = default;
852 ~ChunkIterImpl() = default;
853 ChunkIterImpl(ChunkIterImpl&&) noexcept = default;
854 ChunkIterImpl& operator=(ChunkIterImpl&&) noexcept = default;
855 ChunkIterImpl(const ChunkIterImpl&) = delete;
856 ChunkIterImpl& operator=(const ChunkIterImpl&) = delete;
857
858 void set_world(const World* pWorld) {
859 GAIA_ASSERT(pWorld != nullptr);
860 m_pWorld = pWorld;
861 }
862
863 GAIA_NODISCARD World* world() {
864 GAIA_ASSERT(m_pWorld != nullptr);
865 return const_cast<World*>(m_pWorld);
866 }
867
868 GAIA_NODISCARD const World* world() const {
869 GAIA_ASSERT(m_pWorld != nullptr);
870 return m_pWorld;
871 }
872
873 void set_archetype(const Archetype* pArchetype) {
874 GAIA_ASSERT(pArchetype != nullptr);
875 m_pArchetype = pArchetype;
876 }
877
878 // GAIA_NODISCARD Archetype* archetype() {
879 // GAIA_ASSERT(m_pArchetype != nullptr);
880 // return m_pArchetype;
881 // }
882
883 GAIA_NODISCARD const Archetype* archetype() const {
884 GAIA_ASSERT(m_pArchetype != nullptr);
885 return m_pArchetype;
886 }
887
888 void set_chunk(Chunk* pChunk) {
889 GAIA_ASSERT(pChunk != nullptr);
890 m_pChunk = pChunk;
891 m_entitySnapshotValid = false;
892
893 if constexpr (IterConstraint == Constraints::EnabledOnly)
895 else
896 m_from = 0;
897
898 if constexpr (IterConstraint == Constraints::DisabledOnly)
900 else
901 m_to = m_pChunk->size();
902 }
903
904 void set_chunk(Chunk* pChunk, uint16_t from, uint16_t to) {
905 if (from == 0 && to == 0) {
906 set_chunk(pChunk);
907 return;
908 }
909
910 GAIA_ASSERT(pChunk != nullptr);
911 m_pChunk = pChunk;
912 m_entitySnapshotValid = false;
913 m_from = from;
914 m_to = to;
915 }
916
917 GAIA_NODISCARD const Chunk* chunk() const {
918 GAIA_ASSERT(m_pChunk != nullptr);
919 return m_pChunk;
920 }
921
922 void set_comp_indices(const uint8_t* pCompIndices) {
923 m_pCompIndices = pCompIndices;
924 }
925
926 void set_inherited_data(InheritedTermDataView inheritedData) {
927 m_inheritedData = inheritedData;
928 }
929
930 void set_term_ids(const Entity* pTermIds) {
931 m_pTermIdMapping = pTermIds;
932 }
933
934 GAIA_NODISCARD const uint8_t* comp_indices() const {
935 return m_pCompIndices;
936 }
937
938 GAIA_NODISCARD InheritedTermDataView inherited_data() const {
939 return m_inheritedData;
940 }
941
942 GAIA_NODISCARD const Entity* term_ids() const {
943 return m_pTermIdMapping;
944 }
945
946 void set_write_im(bool value) {
947 m_writeIm = value;
948 clear_touched_writes();
949 }
950
951 GAIA_NODISCARD bool write_im() const {
952 return m_writeIm;
953 }
954
955 void clear_touched_writes() {
956 m_touchedCompCnt = 0;
957 m_touchedTermCnt = 0;
958 }
959
960 GAIA_NODISCARD const Entity* entity_snapshot() {
961 if (!m_entitySnapshotValid) {
962 const auto cnt = size();
963 GAIA_ASSERT(cnt <= ChunkHeader::MAX_CHUNK_ENTITIES);
964
965 const auto entities = m_pChunk->entity_view();
966 GAIA_FOR(cnt) {
967 m_entitySnapshot[i] = entities[from() + i];
968 }
969
970 m_entitySnapshotValid = true;
971 }
972
973 return m_entitySnapshot;
974 }
975
976 GAIA_NODISCARD auto touched_comp_indices() const {
977 return std::span<const uint8_t>{m_touchedCompIndices, m_touchedCompCnt};
978 }
979
980 GAIA_NODISCARD auto touched_terms() const {
981 return std::span<const Entity>{m_touchedTerms, m_touchedTermCnt};
982 }
983
984 GAIA_NODISCARD auto entity_rows() {
985 if (m_entitySnapshotValid)
987
988 return std::span<const Entity>{m_pChunk->entity_view().data() + from(), size()};
989 }
990
991 template <typename U>
992 GAIA_NODISCARD auto entity_view_set(Entity termId, bool writeIm) {
993 return EntityTermViewSet<U>::entity(entity_snapshot(), world(), termId, size(), writeIm);
994 }
995
996 template <typename U>
997 GAIA_NODISCARD auto entity_soa_view_set(Entity termId, bool writeIm) {
998 return SoATermViewSet<U>{nullptr, 0, entity_snapshot(), world(), termId, 0, size(), writeIm};
999 }
1000
1001 void set_group_id(GroupId groupId) {
1002 m_groupId = groupId;
1003 }
1004
1005 GAIA_NODISCARD GroupId group_id() const {
1006 return m_groupId;
1007 }
1008
1009 GAIA_NODISCARD CommandBufferST& cmd_buffer_st() const {
1010 auto* pWorld = const_cast<World*>(m_pWorld);
1011 return cmd_buffer_st_get(*pWorld);
1012 }
1013
1014 GAIA_NODISCARD CommandBufferMT& cmd_buffer_mt() const {
1015 auto* pWorld = const_cast<World*>(m_pWorld);
1016 return cmd_buffer_mt_get(*pWorld);
1017 }
1018
1019 template <typename T>
1020 GAIA_NODISCARD bool uses_out_of_line_component() const {
1021 using Arg = std::remove_cv_t<std::remove_reference_t<T>>;
1022 if constexpr (std::is_same_v<Arg, Entity>)
1023 return false;
1024 else {
1025 using FT = typename component_type_t<Arg>::TypeFull;
1026 if constexpr (is_pair<FT>::value || mem::is_soa_layout_v<Arg>)
1027 return false;
1028 else {
1029 const auto* pItem = comp_cache(*world()).template find<FT>();
1030 // Type-based iteration switches to the world/store path as soon as the
1031 // payload stops being chunk-backed, even if the id still fragments.
1032 return pItem != nullptr && world_is_out_of_line_component(*world(), pItem->entity);
1033 }
1034 }
1035 }
1036
1037 void touch_comp_idx(uint8_t compIdx) {
1038 GAIA_ASSERT(compIdx != 0xFF);
1039 GAIA_FOR(m_touchedCompCnt) {
1040 if (m_touchedCompIndices[i] == compIdx)
1041 return;
1042 }
1043
1044 GAIA_ASSERT(m_touchedCompCnt < ChunkHeader::MAX_COMPONENTS);
1045 m_touchedCompIndices[m_touchedCompCnt++] = compIdx;
1046 }
1047
1048 void touch_term(Entity term) {
1049 GAIA_ASSERT(term != EntityBad);
1050 GAIA_FOR(m_touchedTermCnt) {
1051 if (m_touchedTerms[i] == term)
1052 return;
1053 }
1054
1055 GAIA_ASSERT(m_touchedTermCnt < ChunkHeader::MAX_COMPONENTS);
1056 m_touchedTerms[m_touchedTermCnt++] = term;
1057 }
1058
1059 template <typename T>
1060 void touch_term_by_type() {
1061 using Arg = std::remove_cv_t<std::remove_reference_t<T>>;
1062 if constexpr (std::is_same_v<Arg, Entity>)
1063 return;
1064 else {
1065 const auto term = world_query_arg_id<Arg>(*world());
1066 if (world_is_out_of_line_component(*world(), term))
1067 touch_term(term);
1068 else
1069 touch_comp_idx((uint8_t)m_pChunk->comp_idx(term));
1070 }
1071 }
1072
1073 template <typename T>
1074 GAIA_NODISCARD Entity fallback_term_id(uint32_t termIdx) const {
1075 if (m_pTermIdMapping != nullptr) {
1076 const auto termId = m_pTermIdMapping[termIdx];
1077 if (termId != EntityBad)
1078 return termId;
1079 }
1080
1081 using Arg = std::remove_cv_t<std::remove_reference_t<T>>;
1082 if constexpr (std::is_same_v<Arg, Entity>)
1083 return EntityBad;
1084 else
1085 return world_query_arg_id<Arg>(*const_cast<World*>(world()));
1086 }
1087
1094 template <typename T>
1095 GAIA_NODISCARD auto view_any() const {
1096 using U = typename actual_type_t<T>::Type;
1097 if constexpr (std::is_same_v<U, Entity> || mem::is_soa_layout_v<U>)
1098 return m_pChunk->view<T>(from(), to());
1099 else {
1100 Entity id = EntityBad;
1101 if (uses_out_of_line_component<T>()) {
1102 using Arg = std::remove_cv_t<std::remove_reference_t<T>>;
1103 using FT = typename component_type_t<Arg>::TypeFull;
1104 id = comp_cache(*world()).template get<FT>().entity;
1105 }
1106
1107 if (id != EntityBad)
1109 m_pChunk->entity_view().data() + from(), const_cast<World*>(world()), id, size());
1110
1111 auto* pData = reinterpret_cast<const U*>(m_pChunk->template view<T>(from(), to()).data());
1112 return EntityTermViewGet<U>::pointer(pData, size());
1113 }
1114 }
1115
1123 template <typename T>
1124 GAIA_NODISCARD auto view_any(uint32_t termIdx) {
1125 using U = typename actual_type_t<T>::Type;
1126
1127 if constexpr (mem::is_soa_layout_v<U>) {
1128 const auto compIdx = m_pCompIndices[termIdx];
1129 if (compIdx == 0xFF) {
1130 const auto* pEntities = m_pChunk->entity_view().data() + from();
1131 const auto termId = fallback_term_id<T>(termIdx);
1132 GAIA_ASSERT(termId != EntityBad);
1133 return SoATermViewGet<U>{nullptr, 0, pEntities, const_cast<World*>(world()), termId, 0, size()};
1134 }
1135
1136 GAIA_ASSERT(compIdx < m_pChunk->ids_view().size());
1137 return SoATermViewGet<U>{
1138 m_pChunk->comp_ptr(compIdx), m_pChunk->capacity(), nullptr, world(), EntityBad, from(), size()};
1139 } else {
1140 const auto termId = fallback_term_id<T>(termIdx);
1141 const auto compIdx = m_pCompIndices[termIdx];
1142 if (termId != EntityBad && world_is_out_of_line_component(*world(), termId))
1144 m_pChunk->entity_view().data() + from(), const_cast<World*>(world()), termId, size());
1145
1146 if (compIdx == 0xFF) {
1147 GAIA_ASSERT(termId != EntityBad);
1148 if (!m_inheritedData.empty()) {
1149 const auto* pInheritedValue = reinterpret_cast<const U*>(m_inheritedData[termIdx]);
1150 if (pInheritedValue != nullptr)
1151 return EntityTermViewGet<U>::inherited(pInheritedValue, size());
1152 }
1153 if (world_term_uses_inherit_policy(*world(), termId)) {
1155 m_pChunk->entity_view().data() + from(), m_pChunk, const_cast<World*>(world()), termId, from(),
1156 size());
1157 }
1159 m_pChunk->entity_view().data() + from(), const_cast<World*>(world()), termId, size());
1160 }
1161 GAIA_ASSERT(compIdx < m_pChunk->ids_view().size());
1162
1163 auto* pData = reinterpret_cast<const U*>(m_pChunk->comp_ptr_mut(compIdx, from()));
1164 return EntityTermViewGet<U>::pointer(pData, size());
1165 }
1166 }
1167
1176 template <typename T>
1177 GAIA_NODISCARD auto view() const {
1178 using U = typename actual_type_t<T>::Type;
1179 if constexpr (std::is_same_v<U, Entity>)
1180 return m_pChunk->view<T>(from(), to());
1181 else if constexpr (mem::is_soa_layout_v<U>) {
1182 const auto view = m_pChunk->view<T>(from(), to());
1183 return SoATermViewGetPointer<U>{(const uint8_t*)view.data(), (uint32_t)view.size(), from(), size()};
1184 } else {
1185 auto* pData = reinterpret_cast<const U*>(m_pChunk->template view<T>(from(), to()).data());
1186 return EntityTermViewGetPointer<U>{pData, size()};
1187 }
1188 }
1189
1198 template <typename T>
1199 GAIA_NODISCARD auto view(uint32_t termIdx) const {
1200 using U = typename actual_type_t<T>::Type;
1201 const auto compIdx = m_pCompIndices[termIdx];
1202 GAIA_ASSERT(compIdx != 0xFF);
1203
1204 if constexpr (mem::is_soa_layout_v<U>)
1205 return SoATermViewGetPointer<U>{m_pChunk->comp_ptr(compIdx), m_pChunk->capacity(), from(), size()};
1206 else {
1207 auto* pData = reinterpret_cast<const U*>(m_pChunk->comp_ptr(compIdx, from()));
1208 return EntityTermViewGetPointer<U>{pData, size()};
1209 }
1210 }
1211
1218 template <typename T>
1219 GAIA_NODISCARD auto view_mut_any() {
1220 using U = typename actual_type_t<T>::Type;
1221 static_assert(!std::is_same_v<U, Entity>, "Modifying chunk entities via view_mut is forbidden");
1222 if constexpr (mem::is_soa_layout_v<U>) {
1223 touch_term_by_type<T>();
1224 if (m_writeIm)
1225 return m_pChunk->view_mut<T>(from(), to());
1226 return m_pChunk->sview_mut<T>(from(), to());
1227 } else {
1228 Entity id = EntityBad;
1229 if (uses_out_of_line_component<T>()) {
1230 using Arg = std::remove_cv_t<std::remove_reference_t<T>>;
1231 using FT = typename component_type_t<Arg>::TypeFull;
1232 id = comp_cache(*world()).template get<FT>().entity;
1233 }
1234
1235 if (id != EntityBad) {
1236 touch_term(id);
1237 return entity_view_set<U>(id, m_writeIm);
1238 }
1239
1240 touch_term_by_type<T>();
1241 auto* pData = reinterpret_cast<U*>((m_writeIm ? m_pChunk->template view_mut<T>(from(), to())
1242 : m_pChunk->template sview_mut<T>(from(), to()))
1243 .data());
1244 return EntityTermViewSet<U>::pointer(pData, size());
1245 }
1246 }
1247
1254 template <typename T>
1255 GAIA_NODISCARD auto view_mut() {
1256 using U = typename actual_type_t<T>::Type;
1257 static_assert(!std::is_same_v<U, Entity>, "Modifying chunk entities via view_mut is forbidden");
1258 touch_term_by_type<T>();
1259 if constexpr (mem::is_soa_layout_v<U>) {
1260 auto view = m_writeIm ? m_pChunk->view_mut<T>(from(), to()) : m_pChunk->sview_mut<T>(from(), to());
1261 return SoATermViewSetPointer<U>{(uint8_t*)view.data(), (uint32_t)view.size(), from(), size()};
1262 } else {
1263 auto* pData = reinterpret_cast<U*>((m_writeIm ? m_pChunk->template view_mut<T>(from(), to())
1264 : m_pChunk->template sview_mut<T>(from(), to()))
1265 .data());
1266 return EntityTermViewSetPointer<U>{pData, size()};
1267 }
1268 }
1269
1278 template <typename T>
1279 GAIA_NODISCARD auto view_mut(uint32_t termIdx) {
1280 using U = typename actual_type_t<T>::Type;
1281 static_assert(!std::is_same_v<U, Entity>, "Modifying chunk entities via view_mut is forbidden");
1282 const auto compIdx = m_pCompIndices[termIdx];
1283 GAIA_ASSERT(compIdx != 0xFF);
1284 touch_comp_idx(compIdx);
1285
1286 if constexpr (mem::is_soa_layout_v<U>) {
1287 if (m_writeIm)
1289 return SoATermViewSetPointer<U>{m_pChunk->comp_ptr_mut(compIdx), m_pChunk->capacity(), from(), size()};
1290 } else {
1291 if (m_writeIm)
1293 auto* pData = reinterpret_cast<U*>(m_pChunk->comp_ptr_mut(compIdx, from()));
1294 return EntityTermViewSetPointer<U>{pData, size()};
1295 }
1296 }
1297
1306 template <typename T>
1307 GAIA_NODISCARD auto view_mut_any(uint32_t termIdx) {
1308 using U = typename actual_type_t<T>::Type;
1309
1310 if constexpr (mem::is_soa_layout_v<U>) {
1311 const auto compIdx = m_pCompIndices[termIdx];
1312 if (compIdx == 0xFF) {
1313 const auto termId = fallback_term_id<T>(termIdx);
1314 GAIA_ASSERT(termId != EntityBad);
1315 touch_term(termId);
1316 return entity_soa_view_set<U>(termId, m_writeIm);
1317 }
1318
1319 GAIA_ASSERT(compIdx < m_pChunk->comp_rec_view().size());
1320 touch_comp_idx(compIdx);
1321 if (m_writeIm)
1323 return SoATermViewSet<U>{m_pChunk->comp_ptr_mut(compIdx),
1324 m_pChunk->capacity(),
1325 nullptr,
1326 world(),
1327 EntityBad,
1328 from(),
1329 size(),
1330 m_writeIm};
1331 } else {
1332 const auto termId = fallback_term_id<T>(termIdx);
1333 const auto compIdx = m_pCompIndices[termIdx];
1334 if (termId != EntityBad && world_is_out_of_line_component(*world(), termId)) {
1335 touch_term(termId);
1336 return entity_view_set<U>(termId, m_writeIm);
1337 }
1338
1339 if (compIdx == 0xFF) {
1340 GAIA_ASSERT(termId != EntityBad);
1341 touch_term(termId);
1342 return entity_view_set<U>(termId, m_writeIm);
1343 }
1344 GAIA_ASSERT(compIdx < m_pChunk->comp_rec_view().size());
1345
1346 touch_comp_idx(compIdx);
1347 if (m_writeIm)
1349
1350 auto* pData = reinterpret_cast<U*>(m_pChunk->comp_ptr_mut(compIdx, from()));
1351 return EntityTermViewSet<U>::pointer(pData, size());
1352 }
1353 }
1354
1362 template <typename T>
1363 GAIA_NODISCARD auto sview_mut_any() {
1364 using U = typename actual_type_t<T>::Type;
1365 static_assert(!std::is_same_v<U, Entity>, "Modifying chunk entities via sview_mut is forbidden");
1366 if constexpr (mem::is_soa_layout_v<U>)
1367 return m_pChunk->sview_mut<T>(from(), to());
1368 else {
1369 Entity id = EntityBad;
1370 if (uses_out_of_line_component<T>()) {
1371 using Arg = std::remove_cv_t<std::remove_reference_t<T>>;
1372 using FT = typename component_type_t<Arg>::TypeFull;
1373 id = comp_cache(*world()).template get<FT>().entity;
1374 }
1375
1376 if (id != EntityBad)
1377 return entity_view_set<U>(id, false);
1378
1379 auto* pData = reinterpret_cast<U*>(m_pChunk->template sview_mut<T>(from(), to()).data());
1380 return EntityTermViewSet<U>::pointer(pData, size());
1381 }
1382 }
1383
1390 template <typename T>
1391 GAIA_NODISCARD auto sview_mut() {
1392 using U = typename actual_type_t<T>::Type;
1393 static_assert(!std::is_same_v<U, Entity>, "Modifying chunk entities via sview_mut is forbidden");
1394 if constexpr (mem::is_soa_layout_v<U>) {
1395 auto view = m_pChunk->sview_mut<T>(from(), to());
1396 return SoATermViewSetPointer<U>{(uint8_t*)view.data(), (uint32_t)view.size(), from(), size()};
1397 } else {
1398 auto* pData = reinterpret_cast<U*>(m_pChunk->template sview_mut<T>(from(), to()).data());
1399 return EntityTermViewSetPointer<U>{pData, size()};
1400 }
1401 }
1402
1411 template <typename T>
1412 GAIA_NODISCARD auto sview_mut(uint32_t termIdx) {
1413 using U = typename actual_type_t<T>::Type;
1414 static_assert(!std::is_same_v<U, Entity>, "Modifying chunk entities via sview_mut is forbidden");
1415 const auto compIdx = m_pCompIndices[termIdx];
1416 GAIA_ASSERT(compIdx != 0xFF);
1417
1418 if constexpr (mem::is_soa_layout_v<U>)
1419 return SoATermViewSetPointer<U>{m_pChunk->comp_ptr_mut(compIdx), m_pChunk->capacity(), from(), size()};
1420 else {
1421 auto* pData = reinterpret_cast<U*>(m_pChunk->comp_ptr_mut(compIdx, from()));
1422 return EntityTermViewSetPointer<U>{pData, size()};
1423 }
1424 }
1425
1434 template <typename T>
1435 GAIA_NODISCARD auto sview_mut_any(uint32_t termIdx) {
1436 using U = typename actual_type_t<T>::Type;
1437
1438 if constexpr (mem::is_soa_layout_v<U>) {
1439 const auto compIdx = m_pCompIndices[termIdx];
1440 if (compIdx == 0xFF) {
1441 const auto termId = fallback_term_id<T>(termIdx);
1442 GAIA_ASSERT(termId != EntityBad);
1443 return entity_soa_view_set<U>(termId, false);
1444 }
1445
1446 GAIA_ASSERT(compIdx < m_pChunk->ids_view().size());
1447 return SoATermViewSet<U>{m_pChunk->comp_ptr_mut(compIdx),
1448 m_pChunk->capacity(),
1449 nullptr,
1450 world(),
1451 EntityBad,
1452 from(),
1453 size(),
1454 false};
1455 } else {
1456 const auto termId = fallback_term_id<T>(termIdx);
1457 const auto compIdx = m_pCompIndices[termIdx];
1458 if (termId != EntityBad && world_is_out_of_line_component(*world(), termId))
1459 return entity_view_set<U>(termId, false);
1460
1461 if (compIdx == 0xFF) {
1462 GAIA_ASSERT(termId != EntityBad);
1463 return entity_view_set<U>(termId, false);
1464 }
1465 GAIA_ASSERT(compIdx < m_pChunk->ids_view().size());
1466
1467 auto* pData = reinterpret_cast<U*>(m_pChunk->comp_ptr_mut(compIdx, from()));
1468 return EntityTermViewSet<U>::pointer(pData, size());
1469 }
1470 }
1471
1475 template <typename T, bool TriggerHooks>
1476 void modify() {
1477 m_pChunk->modify<T, TriggerHooks>();
1478 }
1479
1487 template <typename T>
1488 GAIA_NODISCARD auto view_auto() {
1489 using UOriginal = typename actual_type_t<T>::TypeOriginal;
1490 if constexpr (core::is_mut_v<UOriginal>)
1491 return view_mut<T>();
1492 else
1493 return view<T>();
1494 }
1495
1502 template <typename T>
1503 GAIA_NODISCARD auto view_auto_any() {
1504 using UOriginal = typename actual_type_t<T>::TypeOriginal;
1505 if constexpr (core::is_mut_v<UOriginal>)
1506 return view_mut_any<T>();
1507 else
1508 return view_any<T>();
1509 }
1510
1518 template <typename T>
1519 GAIA_NODISCARD auto sview_auto_any() {
1520 using UOriginal = typename actual_type_t<T>::TypeOriginal;
1521 if constexpr (core::is_mut_v<UOriginal>)
1522 return sview_mut_any<T>();
1523 else
1524 return view_any<T>();
1525 }
1526
1535 template <typename T>
1536 GAIA_NODISCARD auto sview_auto() {
1537 using UOriginal = typename actual_type_t<T>::TypeOriginal;
1538 if constexpr (core::is_mut_v<UOriginal>)
1539 return sview_mut<T>();
1540 else
1541 return view<T>();
1542 }
1543
1546 GAIA_NODISCARD bool enabled(uint32_t index) const {
1547 const auto row = (uint16_t)(from() + index);
1548 return m_pChunk->enabled(row);
1549 }
1550
1554 GAIA_NODISCARD bool has(Entity entity) const {
1555 return m_pChunk->has(entity);
1556 }
1557
1561 GAIA_NODISCARD bool has(Pair pair) const {
1562 return m_pChunk->has((Entity)pair);
1563 }
1564
1568 template <typename T>
1569 GAIA_NODISCARD bool has() const {
1570 return m_pChunk->has<T>();
1571 }
1572
1573 GAIA_NODISCARD static uint16_t start_index(Chunk* pChunk) noexcept {
1574 if constexpr (IterConstraint == Constraints::EnabledOnly)
1575 return pChunk->size_disabled();
1576 else
1577 return 0;
1578 }
1579
1580 GAIA_NODISCARD static uint16_t end_index(Chunk* pChunk) noexcept {
1581 if constexpr (IterConstraint == Constraints::DisabledOnly)
1582 return pChunk->size_enabled();
1583 else
1584 return pChunk->size();
1585 }
1586
1587 GAIA_NODISCARD static uint16_t size(Chunk* pChunk) noexcept {
1588 if constexpr (IterConstraint == Constraints::EnabledOnly)
1589 return pChunk->size_enabled();
1590 else if constexpr (IterConstraint == Constraints::DisabledOnly)
1591 return pChunk->size_disabled();
1592 else
1593 return pChunk->size();
1594 }
1595
1597 GAIA_NODISCARD uint16_t size() const noexcept {
1598 return (uint16_t)(to() - from());
1599 }
1600
1602 GAIA_NODISCARD uint16_t row_begin() const noexcept {
1603 return from();
1604 }
1605
1607 GAIA_NODISCARD uint16_t row_end() const noexcept {
1608 return to();
1609 }
1610
1614 template <typename T>
1615 uint32_t acc_index(uint32_t idx) const noexcept {
1616 using U = typename actual_type_t<T>::Type;
1617
1618 if constexpr (mem::is_soa_layout_v<U>)
1619 return idx + from();
1620 else
1621 return idx;
1622 }
1623
1626 template <typename T>
1627 uint32_t acc_index_direct(uint32_t idx) const noexcept {
1628 (void)sizeof(typename actual_type_t<T>::Type);
1629 return idx;
1630 }
1631
1632 protected:
1634 GAIA_NODISCARD uint16_t from() const noexcept {
1635 return m_from;
1636 }
1637
1639 GAIA_NODISCARD uint16_t to() const noexcept {
1640 return m_to;
1641 }
1642 };
1643 } // namespace detail
1644
1646 class GAIA_API Iter final: public detail::ChunkIterImpl<Constraints::EnabledOnly> {};
1648 class GAIA_API IterDisabled final: public detail::ChunkIterImpl<Constraints::DisabledOnly> {};
1649
1652 class GAIA_API IterAll final: public detail::ChunkIterImpl<Constraints::AcceptAll> {
1653 public:
1655 GAIA_NODISCARD uint16_t size_enabled() const noexcept {
1656 return m_pChunk->size_enabled();
1657 }
1658
1661 GAIA_NODISCARD uint16_t size_disabled() const noexcept {
1662 return m_pChunk->size_disabled();
1663 }
1664 };
1665
1667 class GAIA_API CopyIter final {
1668 protected:
1670
1672 const World* m_pWorld = nullptr;
1674 const Archetype* m_pArchetype = nullptr;
1676 Chunk* m_pChunk = nullptr;
1678 uint16_t m_from;
1680 uint16_t m_cnt;
1681
1682 public:
1683 CopyIter() = default;
1684 ~CopyIter() = default;
1685 CopyIter(CopyIter&&) noexcept = default;
1686 CopyIter& operator=(CopyIter&&) noexcept = default;
1687 CopyIter(const CopyIter&) = delete;
1688 CopyIter& operator=(const CopyIter&) = delete;
1689
1693 void set_range(uint16_t from, uint16_t cnt) {
1694 GAIA_ASSERT(from < m_pChunk->size());
1695 GAIA_ASSERT(from + cnt <= m_pChunk->size());
1696 m_from = from;
1697 m_cnt = cnt;
1698 }
1699
1700 void set_world(const World* pWorld) {
1701 GAIA_ASSERT(pWorld != nullptr);
1702 m_pWorld = pWorld;
1703 }
1704
1705 GAIA_NODISCARD World* world() {
1706 GAIA_ASSERT(m_pWorld != nullptr);
1707 return const_cast<World*>(m_pWorld);
1708 }
1709
1710 GAIA_NODISCARD const World* world() const {
1711 GAIA_ASSERT(m_pWorld != nullptr);
1712 return m_pWorld;
1713 }
1714
1715 void set_archetype(const Archetype* pArchetype) {
1716 GAIA_ASSERT(pArchetype != nullptr);
1717 m_pArchetype = pArchetype;
1718 }
1719
1720 // GAIA_NODISCARD Archetype* archetype() {
1721 // GAIA_ASSERT(m_pArchetype != nullptr);
1722 // return m_pArchetype;
1723 // }
1724
1725 GAIA_NODISCARD const Archetype* archetype() const {
1726 GAIA_ASSERT(m_pArchetype != nullptr);
1727 return m_pArchetype;
1728 }
1729
1730 void set_chunk(Chunk* pChunk) {
1731 GAIA_ASSERT(pChunk != nullptr);
1732 m_pChunk = pChunk;
1733 }
1734
1735 GAIA_NODISCARD const Chunk* chunk() const {
1736 GAIA_ASSERT(m_pChunk != nullptr);
1737 return m_pChunk;
1738 }
1739
1740 GAIA_NODISCARD CommandBufferST& cmd_buffer_st() const {
1741 auto* pWorld = const_cast<World*>(m_pWorld);
1742 return cmd_buffer_st_get(*pWorld);
1743 }
1744
1745 GAIA_NODISCARD CommandBufferMT& cmd_buffer_mt() const {
1746 auto* pWorld = const_cast<World*>(m_pWorld);
1747 return cmd_buffer_mt_get(*pWorld);
1748 }
1749
1754 template <typename T>
1755 GAIA_NODISCARD auto view() const {
1756 return m_pChunk->view<T>(from(), to());
1757 }
1758
1763 template <typename T>
1764 GAIA_NODISCARD auto view_mut() {
1765 return m_pChunk->view_mut<T>(from(), to());
1766 }
1767
1773 template <typename T>
1774 GAIA_NODISCARD auto sview_mut() {
1775 return m_pChunk->sview_mut<T>(from(), to());
1776 }
1777
1781 template <typename T, bool TriggerHooks>
1782 void modify() {
1783 m_pChunk->modify<T, TriggerHooks>();
1784 }
1785
1791 template <typename T>
1792 GAIA_NODISCARD auto view_auto() {
1793 return m_pChunk->view_auto<T>(from(), to());
1794 }
1795
1802 template <typename T>
1803 GAIA_NODISCARD auto sview_auto() {
1804 return m_pChunk->sview_auto<T>(from(), to());
1805 }
1806
1809 GAIA_NODISCARD bool enabled(uint32_t index) const {
1810 const auto row = (uint16_t)(from() + index);
1811 return m_pChunk->enabled(row);
1812 }
1813
1817 GAIA_NODISCARD bool has(Entity entity) const {
1818 return m_pChunk->has(entity);
1819 }
1820
1824 GAIA_NODISCARD bool has(Pair pair) const {
1825 return m_pChunk->has((Entity)pair);
1826 }
1827
1831 template <typename T>
1832 GAIA_NODISCARD bool has() const {
1833 return m_pChunk->has<T>();
1834 }
1835
1837 GAIA_NODISCARD uint16_t size() const noexcept {
1838 return m_cnt;
1839 }
1840
1841 private:
1843 GAIA_NODISCARD uint16_t from() const noexcept {
1844 return m_from;
1845 }
1846
1848 GAIA_NODISCARD uint16_t to() const noexcept {
1849 return m_from + m_cnt;
1850 }
1851 };
1852 } // namespace ecs
1853} // namespace gaia
Definition span_impl.h:99
Definition archetype.h:83
Definition chunk.h:35
GAIA_NODISCARD decltype(auto) sview_auto(uint16_t from, uint16_t to)
Returns either a mutable or immutable entity/component view based on the requested type....
Definition chunk.h:782
GAIA_NODISCARD uint16_t capacity() const
Returns the number of entities in the chunk.
Definition chunk.h:1813
uint8_t & data(uint32_t offset)
Returns a mutable pointer to chunk data.
Definition chunk.h:1362
GAIA_FORCEINLINE void update_world_version(uint32_t compIdx)
Update the version of a component at the index.
Definition chunk.h:1846
GAIA_NODISCARD decltype(auto) view(uint16_t from, uint16_t to) const
Returns a read-only entity or component view.
Definition chunk.h:609
GAIA_NODISCARD uint16_t size_enabled() const
Return the number of entities in the chunk which are enabled.
Definition chunk.h:1803
GAIA_NODISCARD decltype(auto) view_auto(uint16_t from, uint16_t to)
Returns either a mutable or immutable entity/component view based on the requested type....
Definition chunk.h:760
GAIA_NODISCARD uint16_t size() const
Returns the total number of entities in the chunk (both enabled and disabled)
Definition chunk.h:1793
bool enabled(uint16_t row) const
Checks if the entity is enabled.
Definition chunk.h:1353
GAIA_NODISCARD uint16_t size_disabled() const
Return the number of entities in the chunk which are enabled.
Definition chunk.h:1808
GAIA_NODISCARD uint32_t comp_idx(Entity entity) const
Returns the internal index of a component based on the provided entity.
Definition chunk.h:1688
GAIA_NODISCARD bool has(Entity entity) const
Checks if a component/entity entity is present in the chunk.
Definition chunk.h:1441
GAIA_NODISCARD decltype(auto) view_mut(uint16_t from, uint16_t to)
Returns a mutable entity or component view.
Definition chunk.h:637
GAIA_NODISCARD decltype(auto) sview_mut(uint16_t from, uint16_t to)
Returns a mutable component view. Doesn't update the world version when the access is acquired.
Definition chunk.h:669
GAIA_FORCEINLINE void modify()
Marks the component.
Definition chunk.h:703
Iterator used when copying entities.
Definition chunk_iterator.h:1667
uint16_t m_from
Row of the first entity we iterate from.
Definition chunk_iterator.h:1678
GAIA_NODISCARD auto view() const
Returns a read-only entity or component view.
Definition chunk_iterator.h:1755
GAIA_NODISCARD auto sview_auto()
Returns either a mutable or immutable entity/component view based on the requested type....
Definition chunk_iterator.h:1803
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:1774
GAIA_NODISCARD bool has() const
Checks if component T is present in the chunk.
Definition chunk_iterator.h:1832
GAIA_NODISCARD auto view_mut()
Returns a mutable entity or component view.
Definition chunk_iterator.h:1764
GAIA_NODISCARD bool has(Pair pair) const
Checks if relationship pair pair is present in the chunk.
Definition chunk_iterator.h:1824
uint16_t m_cnt
The number of entities accessible via the iterator.
Definition chunk_iterator.h:1680
GAIA_NODISCARD auto view_auto()
Returns either a mutable or immutable entity/component view based on the requested type....
Definition chunk_iterator.h:1792
GAIA_NODISCARD bool has(Entity entity) const
Checks if entity entity is present in the chunk.
Definition chunk_iterator.h:1817
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:1782
GAIA_NODISCARD uint16_t size() const noexcept
Returns the number of entities accessible via the iterator.
Definition chunk_iterator.h:1837
GAIA_NODISCARD bool enabled(uint32_t index) const
Checks if the entity at the current iterator index is enabled.
Definition chunk_iterator.h:1809
Iterator for iterating both enabled and disabled entities. Disabled entities always precede enabled o...
Definition chunk_iterator.h:1652
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:1661
GAIA_NODISCARD uint16_t size_enabled() const noexcept
Returns the number of enabled entities accessible via the iterator.
Definition chunk_iterator.h:1655
Iterator for iterating disabled entities.
Definition chunk_iterator.h:1648
Iterator for iterating enabled entities.
Definition chunk_iterator.h:1646
Definition world.h:88
Definition chunk_iterator.h:816
GAIA_NODISCARD uint16_t to() const noexcept
Returns the ending index of the iterator (one past the last valid index)
Definition chunk_iterator.h:1639
GAIA_NODISCARD auto sview_auto()
Returns either a mutable or immutable entity/component view for the owned chunk-backed fast path....
Definition chunk_iterator.h:1536
uint32_t acc_index(uint32_t idx) const noexcept
Returns the absolute index that should be used to access an item in the chunk. AoS indices map direct...
Definition chunk_iterator.h:1615
Chunk * m_pChunk
Chunk currently associated with the iterator.
Definition chunk_iterator.h:825
GAIA_NODISCARD auto view() const
Returns a read-only entity or component view for the owned chunk-backed fast path....
Definition chunk_iterator.h:1177
Entity m_touchedTerms[ChunkHeader::MAX_COMPONENTS]
Entity-backed terms that were exposed as mutable during the current callback.
Definition chunk_iterator.h:838
GAIA_NODISCARD auto sview_mut()
Returns a mutable component view for the owned chunk-backed fast path. Doesn't update the world versi...
Definition chunk_iterator.h:1391
GAIA_NODISCARD auto view_any(uint32_t termIdx)
Returns a read-only entity or component view for a query-term index that can resolve non-direct stora...
Definition chunk_iterator.h:1124
GAIA_NODISCARD uint16_t size() const noexcept
Returns the number of entities accessible via the iterator.
Definition chunk_iterator.h:1597
uint32_t acc_index_direct(uint32_t idx) const noexcept
Returns the local row index for direct iterator views. Direct views already encode the iterator row b...
Definition chunk_iterator.h:1627
const Archetype * m_pArchetype
Currently iterated archetype.
Definition chunk_iterator.h:823
GAIA_NODISCARD auto view_auto_any()
Returns either a mutable or immutable entity/component view that can resolve non-direct storage....
Definition chunk_iterator.h:1503
GAIA_NODISCARD uint16_t row_begin() const noexcept
Returns the first row covered by the iterator in the current chunk.
Definition chunk_iterator.h:1602
const uint8_t * m_pCompIndices
ChunkHeader::MAX_COMPONENTS values for component indices mapping for the parent archetype.
Definition chunk_iterator.h:827
GAIA_NODISCARD auto view_mut_any()
Returns a mutable entity or component view that can resolve non-direct storage. This is the fallback ...
Definition chunk_iterator.h:1219
bool m_writeIm
Whether mutable access should finish writes immediately or defer them until the callback returns.
Definition chunk_iterator.h:833
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:1476
GAIA_NODISCARD bool enabled(uint32_t index) const
Checks if the entity at the current iterator index is enabled.
Definition chunk_iterator.h:1546
GAIA_NODISCARD auto sview_mut_any()
Returns a mutable component view that can resolve non-direct storage. This is the fallback accessor f...
Definition chunk_iterator.h:1363
const World * m_pWorld
World pointer.
Definition chunk_iterator.h:821
uint16_t m_from
Row of the first entity we iterate from.
Definition chunk_iterator.h:844
GAIA_NODISCARD auto sview_mut(uint32_t termIdx)
Returns a mutable component view for a query-term owned chunk-backed term. Doesn't update the world v...
Definition chunk_iterator.h:1412
GAIA_NODISCARD auto view_auto()
Returns either a mutable or immutable entity/component view for the owned chunk-backed fast path....
Definition chunk_iterator.h:1488
GAIA_NODISCARD auto view_any() const
Returns a read-only entity or component view that can resolve non-direct storage. This is the fallbac...
Definition chunk_iterator.h:1095
InheritedTermDataView m_inheritedData
Optional inherited term data view for exact semantic self-source terms.
Definition chunk_iterator.h:829
GAIA_NODISCARD uint16_t row_end() const noexcept
Returns one-past-the-end row covered by the iterator in the current chunk.
Definition chunk_iterator.h:1607
GAIA_NODISCARD auto sview_auto_any()
Returns either a mutable or immutable entity/component view that can resolve non-direct storage....
Definition chunk_iterator.h:1519
GAIA_NODISCARD bool has() const
Checks if component T is present in the chunk.
Definition chunk_iterator.h:1569
GroupId m_groupId
GroupId. 0 if not set.
Definition chunk_iterator.h:848
GAIA_NODISCARD bool has(Pair pair) const
Checks if relationship pair pair is present in the chunk.
Definition chunk_iterator.h:1561
GAIA_NODISCARD bool has(Entity entity) const
Checks if entity entity is present in the chunk.
Definition chunk_iterator.h:1554
Entity m_entitySnapshot[ChunkHeader::MAX_CHUNK_ENTITIES]
Stable copy of the currently iterated entity rows for mutable entity-backed views.
Definition chunk_iterator.h:841
uint8_t m_touchedCompIndices[ChunkHeader::MAX_COMPONENTS]
Chunk-backed columns that were exposed as mutable during the current callback.
Definition chunk_iterator.h:835
GAIA_NODISCARD auto view_mut(uint32_t termIdx)
Returns a mutable entity or component view for a query-term owned chunk-backed term....
Definition chunk_iterator.h:1279
GAIA_NODISCARD auto view(uint32_t termIdx) const
Returns a read-only entity or component view for a query-term owned chunk-backed term....
Definition chunk_iterator.h:1199
GAIA_NODISCARD uint16_t from() const noexcept
Returns the starting index of the iterator.
Definition chunk_iterator.h:1634
const Entity * m_pTermIdMapping
Optional per-term ids used by one-row direct iterators when a term resolves semantically.
Definition chunk_iterator.h:831
GAIA_NODISCARD auto sview_mut_any(uint32_t termIdx)
Returns a mutable component view for a query-term index that can resolve non-direct storage....
Definition chunk_iterator.h:1435
GAIA_NODISCARD auto view_mut_any(uint32_t termIdx)
Returns a mutable entity or component view for a query-term index that can resolve non-direct storage...
Definition chunk_iterator.h:1307
GAIA_NODISCARD auto view_mut()
Returns a mutable entity or component view for the owned chunk-backed fast path. Updates world versio...
Definition chunk_iterator.h:1255
uint16_t m_to
Row of the last entity we iterate to.
Definition chunk_iterator.h:846
Wrapper for two Entities forming a relationship pair.
Definition id.h:500
Wrapper for two types forming a relationship pair. Depending on what types are used to form a pair it...
Definition id.h:218
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Definition bit_utils.h:11
static constexpr uint32_t MAX_COMPONENTS
Maximum number of components on archetype.
Definition chunk_header.h:53
static constexpr uint16_t MAX_CHUNK_ENTITIES
Maximum number of entities per chunk. Defined as sizeof(big_chunk) / sizeof(entity)
Definition chunk_header.h:57
Definition id.h:241
Definition chunk_iterator.h:43
Read-only term view for entity-backed AoS data resolved through the world store. Used when the querie...
Definition chunk_iterator.h:75
Read-only term view for chunk-backed AoS data. Used by direct iteration paths that can guarantee cont...
Definition chunk_iterator.h:54
Read-only AoS term view fallback for APIs where storage mode is known only at runtime....
Definition chunk_iterator.h:167
Mutable term view for entity-backed AoS data resolved through the world store. Used when writes targe...
Definition chunk_iterator.h:132
Mutable term view for chunk-backed AoS data. Exposes direct references to contiguous component storag...
Definition chunk_iterator.h:102
Mutable AoS term view fallback for APIs where storage mode is known only at runtime....
Definition chunk_iterator.h:229
Read-only field proxy for a single SoA member in entity-backed storage. Resolves the whole value via ...
Definition chunk_iterator.h:342
Read-only field proxy for a single SoA member in chunk-backed storage. Exposes a contiguous field spa...
Definition chunk_iterator.h:322
Read-only SoA field proxy fallback for APIs where storage mode is known only at runtime....
Definition chunk_iterator.h:619
Proxy representing one writable field element in entity-backed storage.
Definition chunk_iterator.h:395
Mutable field proxy for a single SoA member in entity-backed storage. Updates reconstruct the whole v...
Definition chunk_iterator.h:390
Mutable field proxy for a single SoA member in chunk-backed storage. Returns raw references so arithm...
Definition chunk_iterator.h:365
Proxy representing a single writable SoA field element in the runtime fallback path only....
Definition chunk_iterator.h:656
Mutable SoA field proxy fallback for APIs where storage mode is known only at runtime....
Definition chunk_iterator.h:644
Writable row proxy for entity-backed SoA data. Reads and writes the full structured value through the...
Definition chunk_iterator.h:300
Writable row proxy for chunk-backed SoA data. Reads and writes the full structured value directly fro...
Definition chunk_iterator.h:280
Writable SoA row proxy fallback for APIs where storage mode is known only at runtime....
Definition chunk_iterator.h:587
Read-only SoA term view for entity-backed storage only. Used when the queried SoA payload lives out o...
Definition chunk_iterator.h:489
Read-only SoA term view for chunk-backed storage only. Used by direct iteration paths once the term h...
Definition chunk_iterator.h:461
Read-only SoA term view fallback for APIs where storage mode is known only at runtime....
Definition chunk_iterator.h:724
Mutable SoA term view for entity-backed storage only. Reads and writes rows and fields through the wo...
Definition chunk_iterator.h:553
Mutable SoA term view for chunk-backed storage only. Provides direct row and field access without car...
Definition chunk_iterator.h:513
Mutable SoA term view fallback for APIs where storage mode is known only at runtime....
Definition chunk_iterator.h:760
Definition data_layout_policy.h:432
Definition data_layout_policy.h:482
View policy for accessing and storing data in the SoA way. Good for SIMD processing.
Definition data_layout_policy.h:243