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

| Flecs v4.0 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
13 struct query_base {
14 query_base() { }
15
16 query_base(query_t *q)
17 : query_(q) {
18 flecs_poly_claim(q);
19 }
20
21 query_base(const query_t *q)
22 : query_(ECS_CONST_CAST(query_t*, q)) {
23 flecs_poly_claim(q);
24 }
25
26 query_base(world_t *world, ecs_query_desc_t *desc) {
27 if (desc->entity && desc->terms[0].id == 0) {
28 const flecs::Poly *query_poly = ecs_get_pair(
29 world, desc->entity, EcsPoly, EcsQuery);
30 if (query_poly) {
31 query_ = static_cast<flecs::query_t*>(query_poly->poly);
32 flecs_poly_claim(query_);
33 return;
34 }
35 }
36
37 query_ = ecs_query_init(world, desc);
38 }
39
40 query_base(const query_base& obj) {
41 this->query_ = obj.query_;
42 flecs_poly_claim(this->query_);
43 }
44
45 query_base& operator=(const query_base& obj) {
46 this->query_ = obj.query_;
47 flecs_poly_claim(this->query_);
48 return *this;
49 }
50
51 query_base(query_base&& obj) noexcept {
52 this->query_ = obj.query_;
53 obj.query_ = nullptr;
54 }
55
56 query_base& operator=(query_base&& obj) noexcept {
57 this->query_ = obj.query_;
58 obj.query_ = nullptr;
59 return *this;
60 }
61
62 flecs::entity entity() {
63 return flecs::entity(query_->world, query_->entity);
64 }
65
66 const flecs::query_t* c_ptr() const {
67 return query_;
68 }
69
70 operator const flecs::query_t*() const {
71 return query_;
72 }
73
74 operator bool() const {
75 return query_ != nullptr;
76 }
77
83 void destruct() {
84 ecs_assert(query_->entity != 0, ECS_INVALID_OPERATION, "destruct() "
85 "should only be called on queries associated with entities");
86 ecs_query_fini(query_);
87 query_ = nullptr;
88 }
89
90 ~query_base() {
91 /* Only free if query is not associated with entity, such as system
92 * queries and named queries. Named queries have to be either explicitly
93 * deleted with the .destruct() method, or will be deleted when the
94 * world is deleted. */
95 if (query_ && !query_->entity) {
96 if (!flecs_poly_release(query_)) {
97 ecs_query_fini(query_);
98 query_ = nullptr;
99 }
100 }
101 }
102
112 bool changed() const {
113 return ecs_query_changed(query_);
114 }
115
121 const flecs::query_group_info_t* group_info(uint64_t group_id) const {
122 return ecs_query_get_group_info(query_, group_id);
123 }
124
130 void* group_ctx(uint64_t group_id) const {
131 const flecs::query_group_info_t *gi = group_info(group_id);
132 if (gi) {
133 return gi->ctx;
134 } else {
135 return NULL;
136 }
137 }
138
139 template <typename Func>
140 void each_term(const Func& func) {
141 for (int i = 0; i < query_->term_count; i ++) {
142 flecs::term t(query_->world, query_->terms[i]);
143 func(t);
144 t.reset(); // prevent freeing resources
145 }
146 }
147
148 flecs::term term(int32_t index) {
149 return flecs::term(query_->world, query_->terms[index]);
150 }
151
152 int32_t term_count() {
153 return query_->term_count;
154 }
155
156 int32_t field_count() {
157 return query_->field_count;
158 }
159
160 int32_t find_var(const char *name) {
161 return ecs_query_find_var(query_, name);
162 }
163
164 flecs::string str() {
165 char *result = ecs_query_str(query_);
166 return flecs::string(result);
167 }
168
173 flecs::string plan() const {
174 char *result = ecs_query_plan(query_);
175 return flecs::string(result);
176 }
177
178 operator query<>() const;
179
180# ifdef FLECS_JSON
181# include "../json/query.inl"
182# endif
183
184protected:
185 query_t *query_ = nullptr;
186};
187
188template<typename ... Components>
189 struct query : query_base, iterable<Components...> {
190private:
191 using Fields = typename _::field_ptrs<Components...>::array;
192
193public:
194 using query_base::query_base;
195
196 query() : query_base() { } // necessary not to confuse msvc
197
198 query(const query& obj) : query_base(obj) { }
199
200 query& operator=(const query& obj) {
201 query_base::operator=(obj);
202 return *this;
203 }
204
205 query(query&& obj) noexcept : query_base(FLECS_MOV(obj)) { }
206
207 query& operator=(query&& obj) noexcept {
208 query_base::operator=(FLECS_FWD(obj));
209 return *this;
210 }
211
212private:
213 ecs_iter_t get_iter(flecs::world_t *world) const override {
214 ecs_assert(query_ != nullptr, ECS_INVALID_PARAMETER,
215 "cannot iterate invalid query");
216 if (!world) {
217 world = query_->world;
218 }
219 return ecs_query_iter(world, query_);
220 }
221
222 ecs_iter_next_action_t next_action() const override {
223 return ecs_query_next;
224 }
225};
226
227// World mixin implementation
228template <typename... Comps, typename... Args>
229 inline flecs::query<Comps...> world::query(Args &&... args) const {
230 return flecs::query_builder<Comps...>(world_, FLECS_FWD(args)...)
231 .build();
232}
233
234 inline flecs::query<> world::query(flecs::entity query_entity) const {
235 ecs_query_desc_t desc = {};
236 desc.entity = query_entity;
237 return flecs::query<>(world_, &desc);
238}
239
240template <typename... Comps, typename... Args>
241 inline flecs::query_builder<Comps...> world::query_builder(Args &&... args) const {
242 return flecs::query_builder<Comps...>(world_, FLECS_FWD(args)...);
243}
244
245// world::each
246namespace _ {
247
248// Each with entity parameter
249template<typename Func, typename ... Args>
250 struct query_delegate_w_ent;
251
252template<typename Func, typename E, typename ... Args>
253 struct query_delegate_w_ent<Func, arg_list<E, Args ...> >
254{
255 query_delegate_w_ent(const flecs::world& world, Func&& func) {
256 auto f = world.query<Args ...>();
257 f.each(FLECS_MOV(func));
258 }
259};
260
261// Each without entity parameter
262template<typename Func, typename ... Args>
263 struct query_delegate_no_ent;
264
265template<typename Func, typename ... Args>
266 struct query_delegate_no_ent<Func, arg_list<Args ...> >
267{
268 query_delegate_no_ent(const flecs::world& world, Func&& func) {
269 auto f = world.query<Args ...>();
270 f.each(FLECS_MOV(func));
271 }
272};
273
274// Switch between function with & without entity parameter
275template<typename Func, typename T = int>
276 struct query_delegate;
277
278template <typename Func>
279 struct query_delegate<Func, if_t<is_same<first_arg_t<Func>, flecs::entity>::value> > {
280 query_delegate(const flecs::world& world, Func&& func) {
281 query_delegate_w_ent<Func, arg_list_t<Func>>(world, FLECS_MOV(func));
282 }
283};
284
285template <typename Func>
286 struct query_delegate<Func, if_not_t<is_same<first_arg_t<Func>, flecs::entity>::value> > {
287 query_delegate(const flecs::world& world, Func&& func) {
288 query_delegate_no_ent<Func, arg_list_t<Func>>(world, FLECS_MOV(func));
289 }
290};
291
292}
293
294template <typename Func>
295 inline void world::each(Func&& func) const {
296 _::query_delegate<Func> f_delegate(*this, FLECS_MOV(func));
297}
298
299template <typename T, typename Func>
300 inline void world::each(Func&& func) const {
301 ecs_iter_t it = ecs_each_id(world_, _::type<T>::id(world_));
302
303 while (ecs_each_next(&it)) {
304 _::each_delegate<Func, T>(func).invoke(&it);
305 }
306}
307
308template <typename Func>
309 inline void world::each(flecs::id_t each_id, Func&& func) const {
310 ecs_iter_t it = ecs_each_id(world_, each_id);
311
312 while (ecs_each_next(&it)) {
313 _::each_delegate<Func>(func).invoke(&it);
314 }
315}
316
317// query_base implementation
318inline query_base::operator flecs::query<> () const {
319 return flecs::query<>(query_);
320}
321
322}
EcsQuery
const ecs_entity_t EcsQuery
Tag added to queries.
ecs_assert
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:368
flecs::world::query
flecs::query< Comps... > query(Args &&... args) const
Create a query.
Definition impl.hpp:229
flecs::world::query_builder
flecs::query_builder< Comps... > query_builder(Args &&... args) const
Create a query builder.
Definition impl.hpp:241
flecs::world::each
void each(Func &&func) const
Iterate over all entities with components in argument list of function.
Definition impl.hpp:295
ecs_each_next
bool ecs_each_next(ecs_iter_t *it)
Progress an iterator created with ecs_each_id().
ecs_each_id
ecs_iter_t ecs_each_id(const ecs_world_t *world, ecs_id_t id)
Iterate all entities with specified (component id).
ecs_iter_next_action_t
bool(* ecs_iter_next_action_t)(ecs_iter_t *it)
Function prototype for iterating an iterator.
Definition flecs.h:555
ecs_query_next
bool ecs_query_next(ecs_iter_t *it)
Progress 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 query group.
ecs_query_find_var
int32_t ecs_query_find_var(const ecs_query_t *query, const char *name)
Find variable index.
ecs_query_fini
void ecs_query_fini(ecs_query_t *query)
Delete a query.
ecs_query_plan
char * ecs_query_plan(const ecs_query_t *query)
Convert 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 query to 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)
Returns whether the query data changed since the last iteration.
builder.hpp
Query builder.
flecs::_
Int to enum.
Definition component.hpp:21
EcsPoly
Component for storing a poly object.
Definition flecs.h:1492
EcsPoly::poly
ecs_poly_t * poly
Pointer to poly object.
Definition flecs.h:1493
ecs_iter_t
Iterator.
Definition flecs.h:1099
ecs_query_desc_t
Used with ecs_query_init().
Definition flecs.h:1199
ecs_query_desc_t::terms
ecs_term_t terms[32]
Query terms.
Definition flecs.h:1204
ecs_query_desc_t::entity
ecs_entity_t entity
Entity associated with query (optional)
Definition flecs.h:1266
ecs_query_group_info_t::ctx
void * ctx
Group context, returned by on_group_create.
Definition flecs.h:1464
ecs_query_t::terms
ecs_term_t terms[32]
Query terms.
Definition flecs.h:793
ecs_query_t::world
ecs_world_t * world
World or stage query was created with.
Definition flecs.h:822
ecs_query_t::entity
ecs_entity_t entity
Entity associated with query (optional)
Definition flecs.h:820
ecs_query_t::term_count
int8_t term_count
Number of query terms.
Definition flecs.h:799
ecs_term_t::id
ecs_id_t id
Component id to be matched by term.
Definition flecs.h:767
flecs::_::arg_list
Definition function_traits.hpp:12
flecs::_::each_delegate
Definition flecs.hpp:41
flecs::_::field_ptrs
Definition delegate.hpp:47
flecs::_::query_delegate_no_ent
Definition impl.hpp:263
flecs::_::query_delegate_w_ent
Definition impl.hpp:250
flecs::_::query_delegate
Definition impl.hpp:276
flecs::_::type
Definition flecs.hpp:38
flecs::array
Definition array.hpp:41
flecs::entity
Entity.
Definition entity.hpp:30
flecs::iterable
Definition iterable.hpp:18
flecs::query_base
Definition impl.hpp:13
flecs::query_base::changed
bool changed() const
Returns whether the query data changed since the last iteration.
Definition impl.hpp:112
flecs::query_base::group_ctx
void * group_ctx(uint64_t group_id) const
Get context for group.
Definition impl.hpp:130
flecs::query_base::plan
flecs::string plan() const
Returns a string representing the query plan.
Definition impl.hpp:173
flecs::query_base::group_info
const flecs::query_group_info_t * group_info(uint64_t group_id) const
Get info for group.
Definition impl.hpp:121
flecs::query_base::destruct
void destruct()
Free persistent query.
Definition impl.hpp:83
flecs::query_builder
Query builder.
Definition decl.hpp:23
flecs::query
Definition impl.hpp:189
flecs::string
Definition string.hpp:13
flecs::term
Class that describes a term.
Definition impl.hpp:16
flecs::world
The world.
Definition world.hpp:137
flecs::world::world
world()
Create world.
Definition world.hpp:140
flecs::world::term
flecs::term term(Args &&... args) const
Create a term.