Helios Engine
A modular ECS based data-oriented C++23 game engine framework
Loading...
Searching...
No Matches
iterator.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <helios/assert.hpp>
8#include <helios/ecs/query/details/traits.hpp>
11
12#include <concepts>
13#include <cstddef>
14#include <functional>
15#include <iterator>
16#include <span>
17#include <tuple>
18#include <type_traits>
19#include <utility>
20
21namespace helios::ecs {
22
23namespace details {
24
25/**
26 * @brief Fetches a single component for the current entity from the archetype,
27 * returning the appropriate access type.
28 * @details Handles all access patterns:
29 * - `T&` (mutable ref) -> returns `T&`
30 * - `const T&` (const ref) -> returns `const T&`
31 * - `T&&` (rvalue ref) -> returns `T&&` (via std::move)
32 * - `T` / `const T` (value) -> returns `T` by value
33 * - `T*` (nullable mutable pointer) -> returns `T*`, `nullptr` if absent
34 * - `const T*` (nullable const pointer) -> returns `const T*`, `nullptr` if
35 * absent
36 * @tparam AccessSpec The original access specifier from the query arg list
37 * @param archetype The archetype the entity belongs to
38 * @param entity The entity to fetch the component for
39 * @param components The component manager
40 * @return The component with the appropriate access type
41 */
42template <typename AccessSpec>
43inline auto FetchComponent(const Archetype& archetype, Entity entity,
44 ComponentManager& components)
45 -> ComponentAccessType_t<AccessSpec> {
46 using RawType = ComponentTypeExtractor_t<AccessSpec>;
47 using AccessType = ComponentAccessType_t<AccessSpec>;
48
49 if constexpr (kIsPointerAccess<AccessSpec>) {
50 // Nullable component: return pointer, nullptr if not present
51 constexpr auto storage_type = ComponentStorageTypeOf<RawType>();
52
53 if constexpr (storage_type == ComponentStorageType::kSparseSet) {
54 if constexpr (std::is_const_v<std::remove_pointer_t<AccessType>>) {
55 return std::as_const(components).TryGet<RawType>(entity);
56 } else {
57 return components.TryGet<RawType>(entity);
58 }
59 } else {
60 if constexpr (std::is_const_v<std::remove_pointer_t<AccessType>>) {
61 return std::as_const(archetype).TryGet<RawType>(entity);
62 } else {
63 // Safe: ComponentManager controls mutability; we receive const
64 // Archetype& from the matching list but mutable access is routed
65 // through the manager.
66 return components.TryGet<RawType>(entity);
67 }
68 }
69 } else if constexpr (TagComponentTrait<RawType>) {
70 // Tag component: no data, but we still need to satisfy the return type.
71 // For tag components the user typically does Get<Tag&> or Get<const Tag&>.
72 // We return a reference to a static default-constructed instance.
73 // This is safe because tag components are empty (size 0).
74 static RawType tag_instance{};
75 if constexpr (std::same_as<AccessType, RawType&&>) {
76 return std::move(tag_instance);
77 } else if constexpr (std::is_lvalue_reference_v<AccessType>) {
78 return static_cast<AccessType>(tag_instance);
79 } else {
80 return RawType{};
81 }
82 } else if constexpr (ComponentStorageTypeOf<RawType>() ==
84 // Sparse-set stored component
85 if constexpr (std::same_as<AccessType, RawType&&>) {
86 return std::move(components.Get<RawType>(entity));
87 } else if constexpr (std::same_as<AccessType, RawType&>) {
88 return components.Get<RawType>(entity);
89 } else if constexpr (std::same_as<AccessType, const RawType&>) {
90 return std::as_const(components).Get<RawType>(entity);
91 } else {
92 // Value copy
93 return RawType(std::as_const(components).Get<RawType>(entity));
94 }
95 } else {
96 // Archetype-stored component
97 if constexpr (std::same_as<AccessType, RawType&&>) {
98 return std::move(components.Get<RawType>(entity));
99 } else if constexpr (std::same_as<AccessType, RawType&>) {
100 return components.Get<RawType>(entity);
101 } else if constexpr (std::same_as<AccessType, const RawType&>) {
102 return std::as_const(components).Get<RawType>(entity);
103 } else {
104 // Value copy
105 return RawType(std::as_const(components).Get<RawType>(entity));
106 }
107 }
108}
109
110/// @brief Const-world variant: always returns const access.
111template <typename AccessSpec>
112inline auto FetchComponentConst(const Archetype& archetype, Entity entity,
113 const ComponentManager& components)
114 -> ComponentAccessType_t<AccessSpec> {
115 using RawType = ComponentTypeExtractor_t<AccessSpec>;
116 using AccessType = ComponentAccessType_t<AccessSpec>;
117
118 if constexpr (kIsPointerAccess<AccessSpec>) {
119 constexpr auto storage_type = ComponentStorageTypeOf<RawType>();
120 if constexpr (storage_type == ComponentStorageType::kSparseSet) {
121 return components.TryGet<RawType>(entity);
122 } else {
123 return archetype.TryGet<RawType>(entity);
124 }
125 } else if constexpr (TagComponentTrait<RawType>) {
126 static constexpr RawType tag_instance{};
127 if constexpr (std::is_lvalue_reference_v<AccessType>) {
128 return static_cast<AccessType>(tag_instance);
129 } else {
130 return RawType{};
131 }
132 } else if constexpr (ComponentStorageTypeOf<RawType>() ==
134 if constexpr (std::is_lvalue_reference_v<AccessType>) {
135 return components.Get<RawType>(entity);
136 } else {
137 return RawType(components.Get<RawType>(entity));
138 }
139 } else {
140 if constexpr (std::is_lvalue_reference_v<AccessType>) {
141 return archetype.Get<RawType>(entity);
142 } else {
143 return RawType(archetype.Get<RawType>(entity));
144 }
145 }
146}
147
148} // namespace details
149
150/**
151 * @brief Iterator for query results without entity information.
152 * @details Provides bidirectional iteration over entities matching the query
153 * criteria, returning tuples of requested component references/values. Supports
154 * all access patterns including const ref, mutable ref, rvalue ref (move),
155 * value copy, and nullable pointer (`T*`, `const T*`).
156 * @note Not thread-safe.
157 * @tparam IsConst Whether the query operates on a const world (read-only mode)
158 * @tparam Components Requested component access types (may include const
159 * qualifiers, references, `T*`, `const T*`)
160 */
161template <bool IsConst, typename... Components>
162 requires details::UniqueComponentAccess<Components...> &&
163 (details::ValidComponentAccess<Components> && ...)
165 BasicQueryIter<IsConst, Components...>> {
166public:
168 std::conditional_t<IsConst, const ComponentManager, ComponentManager>;
169
170 using iterator_category = std::bidirectional_iterator_tag;
171 using iterator_concept = std::input_iterator_tag;
172 using value_type = std::tuple<details::ComponentAccessType_t<Components>...>;
174 using pointer = void;
175 using difference_type = ptrdiff_t;
176
177 /**
178 * @brief Constructs iterator for query results.
179 * @param archetypes Span of archetypes matching the query
180 * @param components Component manager for accessing component data
181 * @param archetype_index Starting archetype index
182 * @param entity_index Starting entity index within archetype
183 * @param without_types Span of component types to exclude (default empty)
184 */
186 std::span<const std::reference_wrapper<const Archetype>> archetypes,
187 ComponentManagerType& components, size_t archetype_index,
188 size_t entity_index,
189 std::span<const ComponentTypeIndex> without_types = {}) noexcept
190 : archetypes_(archetypes),
191 components_(components),
192 archetype_index_(archetype_index),
193 entity_index_(entity_index),
194 without_types_(without_types) {
195 AdvanceToValidEntity();
196 }
197
198 BasicQueryIter(const BasicQueryIter&) noexcept = default;
199 BasicQueryIter(BasicQueryIter&&) noexcept = default;
200 ~BasicQueryIter() noexcept = default;
201
202 BasicQueryIter& operator=(const BasicQueryIter&) noexcept = default;
203 BasicQueryIter& operator=(BasicQueryIter&&) noexcept = default;
204
205 /**
206 * @brief Advances iterator to next matching entity.
207 * @return Reference to this iterator after advancement
208 */
209 BasicQueryIter& operator++();
210
211 /**
212 * @brief Advances iterator to next matching entity (postfix).
213 * @return Copy of iterator before advancement
214 */
215 BasicQueryIter operator++(int);
216
217 /**
218 * @brief Moves iterator to previous matching entity.
219 * @return Reference to this iterator after moving backward
220 */
221 BasicQueryIter& operator--();
222
223 /**
224 * @brief Moves iterator to previous matching entity (postfix).
225 * @return Copy of iterator before moving backward
226 */
227 BasicQueryIter operator--(int);
228
229 /**
230 * @brief Dereferences iterator to get component tuple.
231 * @details Returns tuple of component values/references/pointers for the
232 * current entity.
233 * @warning Triggers assertion if iterator is at end or in invalid state.
234 * @return Tuple of component access values
235 */
236 [[nodiscard]] reference operator*() const;
237
238 pointer operator->() const = delete;
239
240 /**
241 * @brief Compares iterators for equality.
242 * @param other Iterator to compare with
243 * @return True if iterators point to the same position
244 */
245 [[nodiscard]] bool operator==(const BasicQueryIter& other) const noexcept {
246 return archetype_index_ == other.archetype_index_ &&
247 entity_index_ == other.entity_index_;
248 }
249
250 /**
251 * @brief Compares iterators for inequality.
252 * @param other Iterator to compare with
253 * @return True if iterators point to different positions
254 */
255 [[nodiscard]] bool operator!=(const BasicQueryIter& other) const noexcept {
256 return !(*this == other);
257 }
258
259 /**
260 * @brief Returns copy of this iterator as begin iterator (for range-based
261 * for).
262 * @return Copy of this iterator
263 */
264 [[nodiscard]] BasicQueryIter begin() const noexcept { return *this; }
265
266 /**
267 * @brief Returns end iterator for this query.
268 * @return End iterator (points past the last valid entity)
269 */
270 [[nodiscard]] BasicQueryIter end() const noexcept {
271 return {archetypes_, components_.get(), archetypes_.size(), 0,
272 without_types_};
273 }
274
275private:
276 /// @brief Advances past empty archetypes to the next valid entity position.
277 void AdvanceToValidEntity();
278
279 /// @brief Checks if iterator has reached the end.
280 [[nodiscard]] bool IsAtEnd() const noexcept {
281 return archetype_index_ >= archetypes_.size();
282 }
283
284 std::span<const std::reference_wrapper<const Archetype>> archetypes_;
285 std::reference_wrapper<ComponentManagerType> components_;
286 size_t archetype_index_ = 0;
287 size_t entity_index_ = 0;
288 std::span<const ComponentTypeIndex> without_types_;
289};
290
291/**
292 * @brief Iterator for query results without entity information.
293 * @details Provides bidirectional iteration over entities matching the query
294 * criteria, returning tuples of requested component references/values. Supports
295 * all access patterns including const ref, mutable ref, rvalue ref (move),
296 * value copy, and nullable pointer (`T*`, `const T*`).
297 * @note Not thread-safe.
298 * @tparam Components Requested component access types (may include const
299 * qualifiers, references, `T*`, `const T*`)
300 */
301template <typename... Components>
302using QueryIter = BasicQueryIter<false, Components...>;
303
304/**
305 * @brief Read-only iterator for query results without entity information.
306 * @details Provides bidirectional iteration over entities matching the query
307 * criteria, returning tuples of requested component references/values. Supports
308 * all access patterns including const ref, mutable ref, rvalue ref (move),
309 * value copy, and nullable pointer (`T*`, `const T*`).
310 * @note Not thread-safe.
311 * @tparam Components Requested component access types (may include const
312 * qualifiers, references, `T*`, `const T*`)
313 */
314template <typename... Components>
315using ReadOnlyQueryIter = BasicQueryIter<true, Components...>;
316
317/**
318 * @brief Iterator for query results including the entity.
319 * @details Same as `BasicQueryIter` but each dereferenced value is a tuple
320 * starting with the Entity, followed by the requested component access values.
321 * @note Not thread-safe.
322 * @tparam IsConst Whether the query operates on a const world
323 * @tparam Components Requested component access types
324 */
325template <bool IsConst, typename... Components>
326 requires details::UniqueComponentAccess<Components...> &&
327 (details::ValidComponentAccess<Components> && ...)
330 BasicQueryWithEntityIter<IsConst, Components...>> {
331public:
333 std::conditional_t<IsConst, const ComponentManager, ComponentManager>;
334
335 using iterator_category = std::bidirectional_iterator_tag;
336 using iterator_concept = std::input_iterator_tag;
338 std::tuple<Entity, details::ComponentAccessType_t<Components>...>;
340 using pointer = void;
341 using difference_type = ptrdiff_t;
342
343 /**
344 * @brief Constructs iterator for query results with entity.
345 * @param archetypes Span of archetypes matching the query
346 * @param components Component manager for accessing component data
347 * @param archetype_index Starting archetype index
348 * @param entity_index Starting entity index within archetype
349 * @param without_types Span of component types to exclude (default empty)
350 */
352 std::span<const std::reference_wrapper<const Archetype>> archetypes,
353 ComponentManagerType& components, size_t archetype_index,
354 size_t entity_index,
355 std::span<const ComponentTypeIndex> without_types = {}) noexcept
356 : archetypes_(archetypes),
357 components_(components),
358 archetype_index_(archetype_index),
359 entity_index_(entity_index),
360 without_types_(without_types) {
361 AdvanceToValidEntity();
362 }
363
366 ~BasicQueryWithEntityIter() noexcept = default;
367
369 const BasicQueryWithEntityIter&) noexcept = default;
371 default;
372
373 /**
374 * @brief Advances iterator to next matching entity.
375 * @return Reference to this iterator after advancement
376 */
378
379 /**
380 * @brief Advances iterator to next matching entity (postfix).
381 * @return Copy of iterator before advancement
382 */
384
385 /**
386 * @brief Moves iterator to previous matching entity.
387 * @return Reference to this iterator after moving backward
388 */
390
391 /**
392 * @brief Moves iterator to previous matching entity (postfix).
393 * @return Copy of iterator before moving backward
394 */
396
397 /**
398 * @brief Dereferences iterator to get entity and component tuple.
399 * @warning Triggers assertion if iterator is at end or in invalid state.
400 * @return Tuple of (Entity, component access values...)
401 */
402 [[nodiscard]] reference operator*() const;
403
404 [[nodiscard]] bool operator==(
405 const BasicQueryWithEntityIter& other) const noexcept {
406 return archetype_index_ == other.archetype_index_ &&
407 entity_index_ == other.entity_index_;
408 }
409
410 [[nodiscard]] bool operator!=(
411 const BasicQueryWithEntityIter& other) const noexcept {
412 return !(*this == other);
413 }
414
415 /**
416 * @brief Returns copy of this iterator as begin iterator (for range-based
417 * for).
418 * @return Copy of this iterator
419 */
420 [[nodiscard]] BasicQueryWithEntityIter begin() const noexcept {
421 return *this;
422 }
423
424 /**
425 * @brief Returns end iterator for this query.
426 * @return End iterator (points past the last valid entity)
427 */
428 [[nodiscard]] BasicQueryWithEntityIter end() const noexcept {
429 return {archetypes_, components_.get(), archetypes_.size(), 0,
430 without_types_};
431 }
432
433private:
434 void AdvanceToValidEntity();
435
436 [[nodiscard]] bool IsAtEnd() const noexcept {
437 return archetype_index_ >= archetypes_.size();
438 }
439
440 std::span<const std::reference_wrapper<const Archetype>> archetypes_;
441 std::reference_wrapper<ComponentManagerType> components_;
442 size_t archetype_index_ = 0;
443 size_t entity_index_ = 0;
444 std::span<const ComponentTypeIndex> without_types_;
445};
446
447template <bool IsConst, typename... Components>
448 requires details::UniqueComponentAccess<Components...> &&
449 (details::ValidComponentAccess<Components> && ...)
451 -> BasicQueryIter& {
452 ++entity_index_;
453 AdvanceToValidEntity();
454 return *this;
455}
456
457template <bool IsConst, typename... Components>
458 requires details::UniqueComponentAccess<Components...> &&
459 (details::ValidComponentAccess<Components> && ...)
461 -> BasicQueryIter {
462 auto copy = *this;
463 ++(*this);
464 return copy;
465}
466
467template <bool IsConst, typename... Components>
468 requires details::UniqueComponentAccess<Components...> &&
469 (details::ValidComponentAccess<Components> && ...)
471 -> BasicQueryIter& {
472 while (true) {
473 if (entity_index_ > 0) {
474 --entity_index_;
475 return *this;
476 }
477
478 if (archetype_index_ == 0) {
479 return *this;
480 }
481
482 --archetype_index_;
483 if (archetype_index_ < archetypes_.size()) {
484 entity_index_ = archetypes_[archetype_index_].get().EntityCount();
485 if (entity_index_ > 0) {
486 --entity_index_;
487 return *this;
488 }
489 }
490 }
491}
492
493template <bool IsConst, typename... Components>
494 requires details::UniqueComponentAccess<Components...> &&
495 (details::ValidComponentAccess<Components> && ...)
497 -> BasicQueryIter {
498 auto copy = *this;
499 --(*this);
500 return copy;
501}
502
503template <bool IsConst, typename... Components>
504 requires details::UniqueComponentAccess<Components...> &&
505 (details::ValidComponentAccess<Components> && ...)
507 -> reference {
508 HELIOS_ASSERT(!IsAtEnd(), "Cannot dereference end iterator!");
509 HELIOS_ASSERT(archetype_index_ < archetypes_.size(),
510 "Archetype index out of bounds!");
512 entity_index_ < archetypes_[archetype_index_].get().Entities().size(),
513 "Entity index out of bounds!");
514
515 const auto& archetype = archetypes_[archetype_index_].get();
516 const Entity entity = archetype.Entities()[entity_index_];
517
518 if constexpr (IsConst) {
520 archetype, entity, components_.get())...);
521 } else {
522 return reference(details::FetchComponent<Components>(archetype, entity,
523 components_.get())...);
524 }
525}
526
527template <bool IsConst, typename... Components>
528 requires details::UniqueComponentAccess<Components...> &&
529 (details::ValidComponentAccess<Components> && ...)
530inline void BasicQueryIter<IsConst, Components...>::AdvanceToValidEntity() {
531 while (!IsAtEnd()) {
532 if (archetype_index_ < archetypes_.size() &&
533 entity_index_ < archetypes_[archetype_index_].get().Entities().size()) {
534 // Check that the current entity has all required (non-pointer) sparse
535 // components. Archetype-stored required components are already guaranteed
536 // by archetype matching.
537 const Entity entity =
538 archetypes_[archetype_index_].get().Entities()[entity_index_];
539 bool has_all_sparse = true;
540 (
541 [&]() {
542 if constexpr (!details::kIsPointerAccess<Components>) {
543 using RawType = details::ComponentTypeExtractor_t<Components>;
544 if constexpr (ComponentStorageTypeOf<RawType>() ==
546 if (!std::as_const(components_.get())
547 .template HasComponent<RawType>(entity)) {
548 has_all_sparse = false;
549 }
550 }
551 }
552 }(),
553 ...);
554 if (has_all_sparse) {
555 // Check that the entity does NOT have any excluded sparse component.
556 bool has_none_excluded = std::ranges::all_of(
557 without_types_, [&entity, this](const ComponentTypeIndex type) {
558 const auto* meta =
559 std::as_const(components_.get()).MetadataByIndex(type);
560 if (meta == nullptr) {
561 return true;
562 }
563 if (meta->storage_type == ComponentStorageType::kSparseSet) {
564 const auto* entry =
565 std::as_const(components_.get()).SparseEntry(type);
566 if (entry != nullptr) {
567 bool has_comp = entry->Contains(entity);
568 if (has_comp) {
569 return false;
570 }
571 }
572 }
573 return true;
574 });
575 if (has_none_excluded) {
576 return;
577 }
578 }
579 ++entity_index_;
580 continue;
581 }
582 ++archetype_index_;
583 entity_index_ = 0;
584 }
585}
586
587template <bool IsConst, typename... Components>
588 requires details::UniqueComponentAccess<Components...> &&
589 (details::ValidComponentAccess<Components> && ...)
592 ++entity_index_;
593 AdvanceToValidEntity();
594 return *this;
595}
596
597template <bool IsConst, typename... Components>
598 requires details::UniqueComponentAccess<Components...> &&
599 (details::ValidComponentAccess<Components> && ...)
602 auto copy = *this;
603 ++(*this);
604 return copy;
605}
606
607template <bool IsConst, typename... Components>
608 requires details::UniqueComponentAccess<Components...> &&
609 (details::ValidComponentAccess<Components> && ...)
612 while (true) {
613 if (entity_index_ > 0) {
614 --entity_index_;
615 return *this;
616 }
617
618 if (archetype_index_ == 0) {
619 return *this;
620 }
621
622 --archetype_index_;
623 if (archetype_index_ < archetypes_.size()) {
624 entity_index_ = archetypes_[archetype_index_].get().EntityCount();
625 if (entity_index_ > 0) {
626 --entity_index_;
627 return *this;
628 }
629 }
630 }
631}
632
633template <bool IsConst, typename... Components>
634 requires details::UniqueComponentAccess<Components...> &&
635 (details::ValidComponentAccess<Components> && ...)
638 auto copy = *this;
639 --(*this);
640 return copy;
641}
642
643template <bool IsConst, typename... Components>
644 requires details::UniqueComponentAccess<Components...> &&
645 (details::ValidComponentAccess<Components> && ...)
647 -> reference {
648 HELIOS_ASSERT(!IsAtEnd(), "Cannot dereference end iterator!");
649 HELIOS_ASSERT(archetype_index_ < archetypes_.size(),
650 "Archetype index out of bounds!");
652 entity_index_ < archetypes_[archetype_index_].get().Entities().size(),
653 "Entity index out of bounds!");
654
655 const auto& archetype = archetypes_[archetype_index_].get();
656 const Entity entity = archetype.Entities()[entity_index_];
657
658 if constexpr (IsConst) {
660 archetype, entity, components_.get())...);
661 } else {
663 archetype, entity, components_.get())...);
664 }
665}
666
667template <bool IsConst, typename... Components>
668 requires details::UniqueComponentAccess<Components...> &&
669 (details::ValidComponentAccess<Components> && ...)
670inline void
671BasicQueryWithEntityIter<IsConst, Components...>::AdvanceToValidEntity() {
672 while (!IsAtEnd()) {
673 if (archetype_index_ < archetypes_.size() &&
674 entity_index_ < archetypes_[archetype_index_].get().Entities().size()) {
675 // Check that the current entity has all required (non-pointer) sparse
676 // components.
677 const Entity entity =
678 archetypes_[archetype_index_].get().Entities()[entity_index_];
679 bool has_all_sparse = true;
680 (
681 [&]() {
682 if constexpr (!details::kIsPointerAccess<Components>) {
683 using RawType = details::ComponentTypeExtractor_t<Components>;
684 if constexpr (ComponentStorageTypeOf<RawType>() ==
686 if (!std::as_const(components_.get())
687 .template HasComponent<RawType>(entity)) {
688 has_all_sparse = false;
689 }
690 }
691 }
692 }(),
693 ...);
694 if (has_all_sparse) {
695 bool has_none_excluded = std::ranges::all_of(
696 without_types_, [&entity, this](const ComponentTypeIndex type) {
697 const auto* meta =
698 std::as_const(components_.get()).MetadataByIndex(type);
699 if (meta == nullptr) {
700 return true;
701 }
702 if (meta->storage_type == ComponentStorageType::kSparseSet) {
703 const auto* entry =
704 std::as_const(components_.get()).SparseEntry(type);
705 if (entry != nullptr && entry->Contains(entity)) {
706 return false;
707 }
708 }
709 return true;
710 });
711 if (has_none_excluded) {
712 return;
713 }
714 }
715 ++entity_index_;
716 continue;
717 }
718 ++archetype_index_;
719 entity_index_ = 0;
720 }
721}
722
723/**
724 * @brief Iterator for query results including the entity.
725 * @details Same as `BasicQueryIter` but each dereferenced value is a tuple
726 * starting with the Entity, followed by the requested component access values.
727 * @note Not thread-safe.
728 * @tparam Components Requested component access types
729 */
730template <typename... Components>
731using QueryWithEntityIter = BasicQueryWithEntityIter<false, Components...>;
732
733/**
734 * @brief Read-only iterator for query results including the entity.
735 * @details Same as `BasicQueryIter` but each dereferenced value is a tuple
736 * starting with the Entity, followed by the requested component access values.
737 * @note Not thread-safe.
738 * @tparam Components Requested component access types
739 */
740template <typename... Components>
742 BasicQueryWithEntityIter<true, Components...>;
743
744} // namespace helios::ecs
#define HELIOS_ASSERT(condition,...)
Assertion macro that aborts execution in debug builds.
Definition assert.hpp:259
Stores entities and their component data in a Structure-of-Arrays layout for a specific archetype.
Definition archetype.hpp:50
Iterator for query results without entity information.
Definition iterator.hpp:165
std::bidirectional_iterator_tag iterator_category
Definition iterator.hpp:170
std::input_iterator_tag iterator_concept
Definition iterator.hpp:171
BasicQueryIter(std::span< const std::reference_wrapper< const Archetype > > archetypes, ComponentManagerType &components, size_t archetype_index, size_t entity_index, std::span< const ComponentTypeIndex > without_types={}) noexcept
Constructs iterator for query results.
Definition iterator.hpp:185
BasicQueryIter end() const noexcept
Returns end iterator for this query.
Definition iterator.hpp:270
BasicQueryIter & operator--()
Moves iterator to previous matching entity.
Definition iterator.hpp:470
BasicQueryIter(const BasicQueryIter &) noexcept=default
std::conditional_t< IsConst, const ComponentManager, ComponentManager > ComponentManagerType
Definition iterator.hpp:167
bool operator!=(const BasicQueryIter &other) const noexcept
Compares iterators for inequality.
Definition iterator.hpp:255
BasicQueryIter & operator++()
Advances iterator to next matching entity.
Definition iterator.hpp:450
std::tuple< details::ComponentAccessType_t< Components >... > value_type
Definition iterator.hpp:172
BasicQueryIter begin() const noexcept
Returns copy of this iterator as begin iterator (for range-based for).
Definition iterator.hpp:264
BasicQueryIter(BasicQueryIter &&) noexcept=default
reference operator*() const
Dereferences iterator to get component tuple.
Definition iterator.hpp:506
Iterator for query results including the entity.
Definition iterator.hpp:330
reference operator*() const
Dereferences iterator to get entity and component tuple.
Definition iterator.hpp:646
std::input_iterator_tag iterator_concept
Definition iterator.hpp:336
bool operator!=(const BasicQueryWithEntityIter &other) const noexcept
Definition iterator.hpp:410
BasicQueryWithEntityIter(BasicQueryWithEntityIter &&) noexcept=default
BasicQueryWithEntityIter(std::span< const std::reference_wrapper< const Archetype > > archetypes, ComponentManagerType &components, size_t archetype_index, size_t entity_index, std::span< const ComponentTypeIndex > without_types={}) noexcept
Constructs iterator for query results with entity.
Definition iterator.hpp:351
BasicQueryWithEntityIter end() const noexcept
Returns end iterator for this query.
Definition iterator.hpp:428
BasicQueryWithEntityIter & operator--()
Moves iterator to previous matching entity.
Definition iterator.hpp:610
BasicQueryWithEntityIter begin() const noexcept
Returns copy of this iterator as begin iterator (for range-based for).
Definition iterator.hpp:420
BasicQueryWithEntityIter & operator++()
Advances iterator to next matching entity.
Definition iterator.hpp:590
std::bidirectional_iterator_tag iterator_category
Definition iterator.hpp:335
std::tuple< Entity, details::ComponentAccessType_t< Components >... > value_type
Definition iterator.hpp:337
std::conditional_t< IsConst, const ComponentManager, ComponentManager > ComponentManagerType
Definition iterator.hpp:332
BasicQueryWithEntityIter(const BasicQueryWithEntityIter &) noexcept=default
Central manager for all component storage (archetype and sparse-set).
Definition manager.hpp:133
Unique identifier for entities with generation counter to handle recycling.
Definition entity.hpp:22
CRTP base class providing common adapter operations.
Concept to check if the type is considered a tag component.
Definition component.hpp:43
auto FetchComponent(const Archetype &archetype, Entity entity, ComponentManager &components) -> ComponentAccessType_t< AccessSpec >
Fetches a single component for the current entity from the archetype, returning the appropriate acces...
Definition iterator.hpp:43
auto FetchComponentConst(const Archetype &archetype, Entity entity, const ComponentManager &components) -> ComponentAccessType_t< AccessSpec >
Const-world variant: always returns const access.
Definition iterator.hpp:112
@ kSparseSet
Component is stored in a sparse set.
Definition component.hpp:22
consteval ComponentStorageType ComponentStorageTypeOf() noexcept
Component storage type.
BasicQueryWithEntityIter< false, Components... > QueryWithEntityIter
Iterator for query results including the entity.
Definition iterator.hpp:731
utils::TypeIndex ComponentTypeIndex
Type index for components.
Definition component.hpp:14
BasicQueryIter< true, Components... > ReadOnlyQueryIter
Read-only iterator for query results without entity information.
Definition iterator.hpp:315
BasicQueryWithEntityIter< true, Components... > ReadOnlyQueryWithEntityIter
Read-only iterator for query results including the entity.
Definition iterator.hpp:741
BasicQueryIter< false, Components... > QueryIter
Iterator for query results without entity information.
Definition iterator.hpp:302