10FLECS_ALWAYS_INLINE
inline void* field_at_sparse(
11 const ecs_sparse_t *sparse,
size_t size, uint64_t entity,
bool checked)
14 ecs_assert(size ==
static_cast<size_t>(sparse->size),
17 int32_t page_index = FLECS_SPARSE_PAGE(entity);
18 if (checked && page_index >= sparse->pages.count) {
22 ecs_sparse_page_t *page = &
static_cast<ecs_sparse_page_t*
>(
23 sparse->pages.array)[page_index];
24 int32_t offset = FLECS_SPARSE_OFFSET(entity);
30 int32_t dense = page->sparse[offset];
31 if (!dense || dense >= sparse->count) {
36 return ECS_OFFSET(page->data, size *
static_cast<size_t>(offset));
48template <
typename ... Components>
51 "all sparse_query components must have the dont_fragment trait and "
52 "must not declare the on_instantiate::inherit policy");
64 template <
typename Func>
65 void each(Func&& func)
const {
66 each_impl(std::index_sequence_for<Components...>{}, func);
72 each([&](Components&...) { result ++; });
80 template <
size_t ... Is,
typename Func>
81 void each_impl(std::index_sequence<Is...>,
const Func& func)
const {
82 constexpr size_t n =
sizeof...(Components);
84 ecs_sparse_t *
sparse[n] = { storage(ids_[Is])... };
85 for (
size_t f = 0; f < n; f ++) {
92 for (
size_t f = 1; f < n; f ++) {
98 each_impl_dispatch<0>(lead, sparse,
99 std::index_sequence<Is...>{}, func);
102 template <
size_t Lead,
size_t ... Is,
typename Func>
103 void each_impl_dispatch(
105 ecs_sparse_t *
const *sparse,
106 std::index_sequence<Is...> seq,
107 const Func& func)
const
110 each_impl_lead<Lead>(sparse, seq, func);
114 if constexpr (Lead + 1 <
sizeof...(Components)) {
115 each_impl_dispatch<Lead + 1>(lead, sparse, seq, func);
119 template <
size_t Lead,
size_t ... Is,
typename Func>
121 ecs_sparse_t *
const *sparse,
122 std::index_sequence<Is...>,
123 const Func& func)
const
125 const uint64_t *entities =
static_cast<const uint64_t*
>(
126 sparse[Lead]->dense.array) + 1;
127 int32_t
count = sparse[Lead]->count - 1;
129 for (int32_t i = 0; i <
count; i ++) {
130 uint64_t e = entities[i];
131 void *ptrs[
sizeof...(Components)];
132 if (!(... && (ptrs[Is] = _::field_at_sparse(
133 sparse[Is], ECS_SIZEOF(remove_reference_t<Components>), e,
140 if (flecs_table_flags(r->table) &
141 (EcsTableNotQueryable|EcsTableIsPrefab|EcsTableIsDisabled))
146 if constexpr (std::is_invocable<
149 func(flecs::entity(world_, e),
150 (*
static_cast<remove_reference_t<Components>*
>(
153 func((*
static_cast<remove_reference_t<Components>*
>(
161 return cr ? flecs_component_get_sparse(cr) : nullptr;
164 void assert_policies()
const {
170 "sparse_query component has the OnInstantiate Inherit trait, "
171 "which sparse queries cannot match; add the on_instantiate "
172 "trait at compile time instead");
#define ecs_assert(condition, error_code,...)
Assert.
#define ECS_INVALID_OPERATION
Invalid operation error code.
#define ECS_INVALID_PARAMETER
Invalid parameter error code.
struct ecs_component_record_t ecs_component_record_t
Information about a (component) ID, such as type info and tables with the ID.
struct ecs_record_t ecs_record_t
Information about an entity, like its table and row.
ecs_world_t world_t
World type.
ecs_entity_t ecs_get_target(const ecs_world_t *world, ecs_entity_t entity, ecs_entity_t rel, int32_t index)
Get the target of a relationship.
const ecs_world_t * ecs_get_world(const ecs_poly_t *poly)
Get the world from a poly.
int32_t count() const
Return the number of entities matched by the query.
void each(Func &&func) const
Iterate the query.
Trait that marks a component as Sparse at compile time.
flecs::entity entity(Args &&... args) const
Create an entity.