Flecs: include/flecs/addons/cpp/mixins/query/impl.hpp Source File
Description: A fast entity component system (ECS) for C & C++

| Flecs v4.1 A fast entity component system (ECS) for C & C++

Loading...
Searching...
No Matches
impl.hpp
Go to the documentation of this file.
1
5
6#pragma once
7
8#include "builder.hpp"
9
10namespace flecs
11{
12
17 struct query_base {
19 query_base() { }
20
22 query_base(query_t *q)
23 : query_(q) {
24 flecs_poly_claim(q);
25 }
26
28 query_base(const query_t *q)
29 : query_(ECS_CONST_CAST(query_t*, q)) {
30 flecs_poly_claim(q);
31 }
32
34 query_base(world_t *world, const ecs_query_desc_t *desc) {
35 if (desc->entity && desc->terms[0].id == 0) {
36 const flecs::Poly *query_poly = ecs_get_pair(
37 world, desc->entity, EcsPoly, EcsQuery);
38 if (query_poly) {
39 query_ = static_cast<flecs::query_t*>(query_poly->poly);
40 flecs_poly_claim(query_);
41 return;
42 }
43 }
44
45 query_ = ecs_query_init(world, desc);
46 }
47
49 query_base(const query_base& obj) {
50 this->query_ = obj.query_;
51 if (this->query_)
52 {
53 flecs_poly_claim(this->query_);
54 }
55 }
56
58 query_base& operator=(const query_base& obj) {
59 this->~query_base();
60 this->query_ = obj.query_;
61 if (this->query_)
62 {
63 flecs_poly_claim(this->query_);
64 }
65 return *this;
66 }
67
69 query_base(query_base&& obj) noexcept {
70 this->query_ = obj.query_;
71 obj.query_ = nullptr;
72 }
73
75 query_base& operator=(query_base&& obj) noexcept {
76 this->query_ = obj.query_;
77 obj.query_ = nullptr;
78 return *this;
79 }
80
82 flecs::entity entity() const {
83 return flecs::entity(query_->world, query_->entity);
84 }
85
87 const flecs::query_t* c_ptr() const {
88 return query_;
89 }
90
92 operator const flecs::query_t*() const {
93 return query_;
94 }
95
97 operator bool() const {
98 return query_ != nullptr;
99 }
100
106 void destruct() {
107 ecs_assert(query_->entity != 0, ECS_INVALID_OPERATION, "destruct() "
108 "should only be called on queries associated with entities");
109 ecs_query_fini(query_);
110 query_ = nullptr;
111 }
112
114 ~query_base() {
115 if (query_ && !query_->entity) {
116 if (!flecs_poly_release(query_)) {
117 ecs_query_fini(query_);
118 query_ = nullptr;
119 }
120 }
121 }
122
132 bool changed() const {
133 return ecs_query_changed(query_);
134 }
135
141 const flecs::query_group_info_t* group_info(uint64_t group_id) const {
142 return ecs_query_get_group_info(query_, group_id);
143 }
144
151 flecs::map<uint64_t, void*> groups() const {
152 return flecs::map<uint64_t, void*>(ecs_query_get_groups(query_));
153 }
154
160 void* group_ctx(uint64_t group_id) const {
161 const flecs::query_group_info_t *gi = group_info(group_id);
162 if (gi) {
163 return gi->ctx;
164 } else {
165 return nullptr;
166 }
167 }
168
170 template <typename Func>
171 void each_term(const Func& func) {
172 for (int i = 0; i < query_->term_count; i ++) {
173 flecs::term t(query_->world, query_->terms[i]);
174 func(t);
175 t.reset(); // prevent freeing resources
176 }
177 }
178
180 flecs::term term(int32_t index) const {
181 return flecs::term(query_->world, query_->terms[index]);
182 }
183
185 int32_t term_count() const {
186 return query_->term_count;
187 }
188
190 int32_t field_count() const {
191 return query_->field_count;
192 }
193
195 int32_t find_var(const char *name) const {
196 return ecs_query_find_var(query_, name);
197 }
198
199 bool has(flecs::entity_t e) const {
200 ecs_iter_t it;
201 bool result = ecs_query_has(query_, e, &it);
202 if (result) {
203 ecs_iter_fini(&it);
204 }
205 return result;
206 }
207
208 bool has(const flecs::table& t) const {
209 ecs_iter_t it;
210 bool result = ecs_query_has_table(query_, t.get_table(), &it);
211 if (result) {
212 ecs_iter_fini(&it);
213 }
214 return result;
215 }
216
217 bool has(const flecs::table_range& range) const {
218 ecs_table_range_t r = {
219 range.get_table(),
220 range.offset(),
221 range.count()
222 };
223 ecs_iter_t it;
224 bool result = ecs_query_has_range(query_, &r, &it);
225 if (result) {
226 ecs_iter_fini(&it);
227 }
228 return result;
229 }
230
232 flecs::string str() const {
233 char *result = ecs_query_str(query_);
234 return flecs::string(result);
235 }
236
241 flecs::string plan() const {
242 char *result = ecs_query_plan(query_);
243 return flecs::string(result);
244 }
245
247 operator query<>() const;
248
249# ifdef FLECS_JSON
250# include "../json/query.inl"
251# endif
252
253protected:
254 query_t *query_ = nullptr;
255};
256
261template<typename ... Components>
262 struct query : query_base, iterable<Components...> {
263private:
264 using Fields = typename _::field_ptrs<Components...>::array;
265
266public:
267 using query_base::query_base;
268
270 query() : query_base() { } // necessary not to confuse MSVC
271
273 query(const query& obj) : query_base(obj) { }
274
276 query& operator=(const query& obj) {
277 query_base::operator=(obj);
278 return *this;
279 }
280
282 query(query&& obj) noexcept : query_base(FLECS_MOV(obj)) { }
283
285 query& operator=(query&& obj) noexcept {
286 query_base::operator=(FLECS_FWD(obj));
287 return *this;
288 }
289
291 flecs::query<> cache_query() const {
292 const flecs::query_t *q = ecs_query_get_cache_query(query_);
293 return flecs::query<>(q);
294 }
295
296private:
297 ecs_iter_t get_iter(flecs::world_t *world) const override {
298 ecs_assert(query_ != nullptr, ECS_INVALID_PARAMETER,
299 "cannot iterate invalid query");
300 if (!world) {
301 world = query_->world;
302 }
303 return ecs_query_iter(world, query_);
304 }
305
306 ecs_iter_next_action_t next_action() const override {
307 return ecs_query_next;
308 }
309};
310
311// World mixin implementation
312template <typename... Comps, typename... Args>
313 inline flecs::query<Comps...> world::query(Args &&... args) const {
314 return flecs::query_builder<Comps...>(world_, FLECS_FWD(args)...)
315 .build();
316}
317
318 inline flecs::query<> world::query(flecs::entity query_entity) const {
319 ecs_query_desc_t desc = {};
320 desc.entity = query_entity;
321 return flecs::query<>(world_, &desc);
322}
323
324template <typename... Comps, typename... Args>
325 inline flecs::query_builder<Comps...> world::query_builder(Args &&... args) const {
326 return flecs::query_builder<Comps...>(world_, FLECS_FWD(args)...);
327}
328
329// world::each
330namespace _ {
331
332// Each with entity parameter
333template<typename Func, typename ... Args>
334 struct query_delegate_w_ent;
335
336template<typename Func, typename E>
337 struct query_delegate_w_ent<Func, arg_list<E> >
338{
339 query_delegate_w_ent(const flecs::world& world, Func&& func) {
340 ecs_entities_t entities = ecs_get_entities(ecs_get_world(world));
341
342 for (int32_t i = 0; i < entities.alive_count; i ++) {
343 func(flecs::entity(world, entities.ids[i]));
344 }
345 }
346};
347
348template<typename Func, typename E, typename ... Args>
349 struct query_delegate_w_ent<Func, arg_list<E, Args ...> >
350{
351 query_delegate_w_ent(const flecs::world& world, Func&& func) {
352 auto f = world.query<Args ...>();
353 f.each(FLECS_MOV(func));
354 }
355};
356
357// Each without entity parameter
358template<typename Func, typename ... Args>
359 struct query_delegate_no_ent;
360
361template<typename Func, typename ... Args>
362 struct query_delegate_no_ent<Func, arg_list<Args ...> >
363{
364 query_delegate_no_ent(const flecs::world& world, Func&& func) {
365 auto f = world.query<Args ...>();
366 f.each(FLECS_MOV(func));
367 }
368};
369
370// Switch between function with and without entity parameter
371template<typename Func, typename T = int>
372 struct query_delegate;
373
374template <typename Func>
375 struct query_delegate<Func, if_t<is_same<first_arg_t<Func>, flecs::entity>::value> > {
376 query_delegate(const flecs::world& world, Func&& func) {
377 query_delegate_w_ent<Func, arg_list_t<Func>>(world, FLECS_MOV(func));
378 }
379};
380
381template <typename Func>
382 struct query_delegate<Func, if_not_t<is_same<first_arg_t<Func>, flecs::entity>::value> > {
383 query_delegate(const flecs::world& world, Func&& func) {
384 query_delegate_no_ent<Func, arg_list_t<Func>>(world, FLECS_MOV(func));
385 }
386};
387
388}
389
390template <typename Func>
391 inline void world::each(Func&& func) const {
392 _::query_delegate<Func> f_delegate(*this, FLECS_MOV(func));
393}
394
395template <typename T, typename Func>
396 inline void world::each(Func&& func) const {
397 ecs_iter_t it = ecs_each_id(world_, _::type<T>::id(world_));
398
399 while (ecs_each_next(&it)) {
400 _::each_delegate<Func, T>(func).invoke(&it);
401 }
402}
403
404template <typename Func>
405 inline void world::each(flecs::id_t each_id, Func&& func) const {
406 ecs_iter_t it = ecs_each_id(world_, each_id);
407
408 while (ecs_each_next(&it)) {
409 _::each_delegate<Func>(func).invoke(&it);
410 }
411}
412
413// query_base implementation
414inline query_base::operator flecs::query<> () const {
415 return flecs::query<>(query_);
416}
417
418}
flecs::is_same
flecs::first_arg_t
typename first_arg< Func >::type first_arg_t
Convenience alias for the first argument type of a callable.
Definition function_traits.hpp:149
EcsQuery
const ecs_entity_t EcsQuery
Tag added to queries.
ecs_assert
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:473
ECS_INVALID_OPERATION
#define ECS_INVALID_OPERATION
Invalid operation error code.
Definition log.h:669
ECS_INVALID_PARAMETER
#define ECS_INVALID_PARAMETER
Invalid parameter error code.
Definition log.h:671
ecs_iter_t
struct ecs_iter_t ecs_iter_t
Type used for iterating iterable objects.
Definition flecs.h:471
flecs::component::range
untyped_component & range(double min, double max)
Add a member value range.
Definition untyped_component.inl:240
flecs::world::query
flecs::query< Comps... > query(Args &&... args) const
Create a query.
Definition impl.hpp:313
flecs::world::query_builder
flecs::query_builder< Comps... > query_builder(Args &&... args) const
Create a query builder.
Definition impl.hpp:325
flecs::world::each
void each(Func &&func) const
Iterate over all entities with components in the argument list of the function.
Definition impl.hpp:391
flecs::query_t
ecs_query_t query_t
Query type.
Definition c_types.hpp:25
flecs::id_t
ecs_id_t id_t
ID type.
Definition c_types.hpp:20
flecs::entity_t
ecs_entity_t entity_t
Entity type.
Definition c_types.hpp:21
flecs::query_group_info_t
ecs_query_group_info_t query_group_info_t
Query group info type.
Definition c_types.hpp:26
flecs::Poly
EcsPoly Poly
Built-in EcsPoly type.
Definition c_types.hpp:81
flecs::world_t
ecs_world_t world_t
World type.
Definition c_types.hpp:18
ecs_each_id
ecs_iter_t ecs_each_id(const ecs_world_t *world, ecs_id_t component)
Iterate all entities with a specified (component ID).
ecs_each_next
bool ecs_each_next(ecs_iter_t *it)
Progress an iterator created with ecs_each_id().
ecs_get_pair
#define ecs_get_pair(world, subject, First, second)
Get the first element of a pair.
Definition flecs_c.h:390
ecs_iter_next_action_t
bool(* ecs_iter_next_action_t)(ecs_iter_t *it)
Function prototype for iterating an iterator.
Definition flecs.h:591
ecs_iter_fini
void ecs_iter_fini(ecs_iter_t *it)
Clean up iterator resources.
ecs_query_has_table
bool ecs_query_has_table(const ecs_query_t *query, ecs_table_t *table, ecs_iter_t *it)
Match a table with a query.
ecs_query_next
bool ecs_query_next(ecs_iter_t *it)
Progress a query iterator.
ecs_query_get_group_info
const ecs_query_group_info_t * ecs_query_get_group_info(const ecs_query_t *query, uint64_t group_id)
Get information about a query group.
ecs_query_has_range
bool ecs_query_has_range(const ecs_query_t *query, ecs_table_range_t *range, ecs_iter_t *it)
Match a range with a query.
ecs_query_find_var
int32_t ecs_query_find_var(const ecs_query_t *query, const char *name)
Find a variable index.
ecs_query_fini
void ecs_query_fini(ecs_query_t *query)
Delete a query.
ecs_query_has
bool ecs_query_has(const ecs_query_t *query, ecs_entity_t entity, ecs_iter_t *it)
Match an entity with a query.
ecs_query_plan
char * ecs_query_plan(const ecs_query_t *query)
Convert a query to a string.
ecs_query_iter
ecs_iter_t ecs_query_iter(const ecs_world_t *world, const ecs_query_t *query)
Create a query iterator.
ecs_query_str
char * ecs_query_str(const ecs_query_t *query)
Convert a query to a string expression.
ecs_query_init
ecs_query_t * ecs_query_init(ecs_world_t *world, const ecs_query_desc_t *desc)
Create a query.
ecs_query_changed
bool ecs_query_changed(ecs_query_t *query)
Return whether the query data changed since the last iteration.
ecs_query_get_groups
const ecs_map_t * ecs_query_get_groups(const ecs_query_t *query)
Return the map with query groups.
ecs_query_get_cache_query
const ecs_query_t * ecs_query_get_cache_query(const ecs_query_t *query)
Get the query used to populate the cache.
ecs_get_entities
ecs_entities_t ecs_get_entities(const ecs_world_t *world)
Return entity identifiers in the world.
ecs_get_world
const ecs_world_t * ecs_get_world(const ecs_poly_t *poly)
Get the world from a poly.
builder.hpp
Query builder.
flecs::_
Int to enum.
Definition component.hpp:18
query.inl
JSON query mixin.
EcsPoly
Component for storing a poly object.
Definition flecs.h:1606
EcsPoly::poly
ecs_poly_t * poly
Pointer to poly object.
Definition flecs.h:1607
ecs_entities_t
Type returned by ecs_get_entities().
Definition flecs.h:2118
ecs_entities_t::alive_count
int32_t alive_count
Number of alive entity IDs.
Definition flecs.h:2121
ecs_entities_t::ids
const ecs_entity_t * ids
Array with all entity IDs in the world.
Definition flecs.h:2119
ecs_iter_t
Iterator.
Definition flecs.h:1170
ecs_query_desc_t
Used with ecs_query_init().
Definition flecs.h:1301
ecs_query_desc_t::terms
ecs_term_t terms[32]
Query terms.
Definition flecs.h:1306
ecs_query_desc_t::entity
ecs_entity_t entity
Entity associated with query (optional).
Definition flecs.h:1368
ecs_query_group_info_t::ctx
void * ctx
Group context, returned by on_group_create.
Definition flecs.h:1568
ecs_query_t::world
ecs_world_t * world
World or stage the query was created with.
Definition flecs.h:871
ecs_term_t::id
ecs_id_t id
Component ID to be matched by term.
Definition flecs.h:815
flecs::_::each_delegate
Definition delegate.hpp:220
flecs::_::field_ptrs
Definition delegate.hpp:52
flecs::_::query_delegate_no_ent
Definition impl.hpp:359
flecs::_::query_delegate_w_ent
Definition impl.hpp:334
flecs::_::query_delegate
Definition impl.hpp:372
flecs::_::type
Definition flecs.hpp:39
flecs::array
Array class (primary template, disabled).
Definition array.hpp:47
flecs::entity
Entity.
Definition entity.hpp:30
flecs::iterable
Base class for iterable query objects.
Definition iterable.hpp:22
flecs::map
Definition map.hpp:83
flecs::query_base::c_ptr
const flecs::query_t * c_ptr() const
Get a pointer to the underlying C query.
Definition impl.hpp:87
flecs::query_base::changed
bool changed() const
Return whether the query data changed since the last iteration.
Definition impl.hpp:132
flecs::query_base::operator=
query_base & operator=(const query_base &obj)
Copy assignment operator.
Definition impl.hpp:58
flecs::query_base::entity
flecs::entity entity() const
Get the entity associated with the query.
Definition impl.hpp:82
flecs::query_base::each_term
void each_term(const Func &func)
Iterate each term in the query, invoking a callback for each.
Definition impl.hpp:171
flecs::query_base::query_base
query_base(query_base &&obj) noexcept
Move constructor.
Definition impl.hpp:69
flecs::query_base::query_base
query_base()
Default constructor.
Definition impl.hpp:19
flecs::query_base::groups
flecs::map< uint64_t, void * > groups() const
Iterate the active groups of a grouped query.
Definition impl.hpp:151
flecs::query_base::group_ctx
void * group_ctx(uint64_t group_id) const
Get context for a group.
Definition impl.hpp:160
flecs::query_base::query_base
query_base(const query_t *q)
Construct from a const query pointer.
Definition impl.hpp:28
flecs::query_base::plan
flecs::string plan() const
Return a string representing the query plan.
Definition impl.hpp:241
flecs::query_base::term
flecs::term term(int32_t index) const
Get term at the specified index.
Definition impl.hpp:180
flecs::query_base::query_base
query_base(query_t *q)
Construct from a mutable query pointer.
Definition impl.hpp:22
flecs::query_base::query_base
query_base(world_t *world, const ecs_query_desc_t *desc)
Construct from a world and a query descriptor.
Definition impl.hpp:34
flecs::query_base::operator=
query_base & operator=(query_base &&obj) noexcept
Move assignment operator.
Definition impl.hpp:75
flecs::query_base::query_base
query_base(const query_base &obj)
Copy constructor.
Definition impl.hpp:49
flecs::query_base::~query_base
~query_base()
Destructor.
Definition impl.hpp:114
flecs::query_base::term_count
int32_t term_count() const
Get the number of terms in the query.
Definition impl.hpp:185
flecs::query_base::group_info
const flecs::query_group_info_t * group_info(uint64_t group_id) const
Get info for a group.
Definition impl.hpp:141
flecs::query_base::str
flecs::string str() const
Convert the query to a string expression.
Definition impl.hpp:232
flecs::query_base::destruct
void destruct()
Free a persistent query.
Definition impl.hpp:106
flecs::query_base::find_var
int32_t find_var(const char *name) const
Find a variable by name.
Definition impl.hpp:195
flecs::query_base::field_count
int32_t field_count() const
Get the number of fields in the query.
Definition impl.hpp:190
flecs::query_builder
Query builder.
Definition builder.hpp:24
flecs::query
Typed query.
Definition impl.hpp:262
flecs::query::query_base
query_base()
Default constructor.
Definition impl.hpp:19
flecs::query::query
query()
Default constructor.
Definition impl.hpp:270
flecs::query::query
query(const query &obj)
Copy constructor.
Definition impl.hpp:273
flecs::query::cache_query
flecs::query cache_query() const
Get the cache query, if any.
Definition impl.hpp:291
flecs::query::operator=
query & operator=(query &&obj) noexcept
Move assignment operator.
Definition impl.hpp:285
flecs::query::operator=
query & operator=(const query &obj)
Copy assignment operator.
Definition impl.hpp:276
flecs::query::query
query(query &&obj) noexcept
Move constructor.
Definition impl.hpp:282
flecs::string
Owned string wrapper.
Definition string.hpp:15
flecs::table::get_table
table_t * get_table() const
Get the table.
Definition table.hpp:430
flecs::term
Class that describes a term.
Definition impl.hpp:16
flecs::term::reset
void reset()
Reset the term to its default state.
Definition impl.hpp:82
flecs::world
The world.
Definition world.hpp:246
flecs::world::world_
world_t * world_
Pointer to the underlying C world.
Definition world.hpp:1540
flecs::if_not_t
enable_if_t< false==V, int > if_not_t
Convenience enable_if alias for negated conditions.
Definition utils.hpp:172
flecs::if_t
enable_if_t< V, int > if_t
Convenience enable_if alias using int as default type.
Definition utils.hpp:168