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
6#pragma once
7
8#include "builder.hpp"
9
10namespace flecs
11{
12
13struct query_base {
14 query_base() { }
15
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 if (this->query_)
43 {
44 flecs_poly_claim(this->query_);
45 }
46 }
47
48 query_base& operator=(const query_base& obj) {
49 this->~query_base();
50 this->query_ = obj.query_;
51 if (this->query_)
52 {
53 flecs_poly_claim(this->query_);
54 }
55 return *this;
56 }
57
58 query_base(query_base&& obj) noexcept {
59 this->query_ = obj.query_;
60 obj.query_ = nullptr;
61 }
62
63 query_base& operator=(query_base&& obj) noexcept {
64 this->query_ = obj.query_;
65 obj.query_ = nullptr;
66 return *this;
67 }
68
70 return flecs::entity(query_->world, query_->entity);
71 }
72
73 const flecs::query_t* c_ptr() const {
74 return query_;
75 }
76
77 operator const flecs::query_t*() const {
78 return query_;
79 }
80
81 operator bool() const {
82 return query_ != nullptr;
83 }
84
90 void destruct() {
91 ecs_assert(query_->entity != 0, ECS_INVALID_OPERATION, "destruct() "
92 "should only be called on queries associated with entities");
93 ecs_query_fini(query_);
94 query_ = nullptr;
95 }
96
97 ~query_base() {
98 /* Only free if query is not associated with entity, such as system
99 * queries and named queries. Named queries have to be either explicitly
100 * deleted with the .destruct() method, or will be deleted when the
101 * world is deleted. */
102 if (query_ && !query_->entity) {
103 if (!flecs_poly_release(query_)) {
104 ecs_query_fini(query_);
105 query_ = nullptr;
106 }
107 }
108 }
109
119 bool changed() const {
120 return ecs_query_changed(query_);
121 }
122
128 const flecs::query_group_info_t* group_info(uint64_t group_id) const {
129 return ecs_query_get_group_info(query_, group_id);
130 }
131
137 void* group_ctx(uint64_t group_id) const {
138 const flecs::query_group_info_t *gi = group_info(group_id);
139 if (gi) {
140 return gi->ctx;
141 } else {
142 return NULL;
143 }
144 }
145
146 template <typename Func>
147 void each_term(const Func& func) {
148 for (int i = 0; i < query_->term_count; i ++) {
149 flecs::term t(query_->world, query_->terms[i]);
150 func(t);
151 t.reset(); // prevent freeing resources
152 }
153 }
154
155 flecs::term term(int32_t index) {
156 return flecs::term(query_->world, query_->terms[index]);
157 }
158
159 int32_t term_count() {
160 return query_->term_count;
161 }
162
163 int32_t field_count() {
164 return query_->field_count;
165 }
166
167 int32_t find_var(const char *name) {
168 return ecs_query_find_var(query_, name);
169 }
170
171 flecs::string str() {
172 char *result = ecs_query_str(query_);
173 return flecs::string(result);
174 }
175
181 char *result = ecs_query_plan(query_);
182 return flecs::string(result);
183 }
184
185 operator query<>() const;
186
187# ifdef FLECS_JSON
188# include "../json/query.inl"
189# endif
190
191protected:
192 query_t *query_ = nullptr;
193};
194
195template<typename ... Components>
196struct query : query_base, iterable<Components...> {
197private:
198 using Fields = typename _::field_ptrs<Components...>::array;
199
200public:
201 using query_base::query_base;
202
203 query() : query_base() { } // necessary not to confuse msvc
204
205 query(const query& obj) : query_base(obj) { }
206
207 query& operator=(const query& obj) {
208 query_base::operator=(obj);
209 return *this;
210 }
211
212 query(query&& obj) noexcept : query_base(FLECS_MOV(obj)) { }
213
214 query& operator=(query&& obj) noexcept {
215 query_base::operator=(FLECS_FWD(obj));
216 return *this;
217 }
218
219 flecs::query<> cache_query() const {
220 const flecs::query_t *q = ecs_query_get_cache_query(query_);
221 return flecs::query<>(q);
222 }
223
224private:
225 ecs_iter_t get_iter(flecs::world_t *world) const override {
226 ecs_assert(query_ != nullptr, ECS_INVALID_PARAMETER,
227 "cannot iterate invalid query");
228 if (!world) {
229 world = query_->world;
230 }
231 return ecs_query_iter(world, query_);
232 }
233
234 ecs_iter_next_action_t next_action() const override {
235 return ecs_query_next;
236 }
237};
238
239// World mixin implementation
240template <typename... Comps, typename... Args>
241inline flecs::query<Comps...> world::query(Args &&... args) const {
242 return flecs::query_builder<Comps...>(world_, FLECS_FWD(args)...)
243 .build();
244}
245
246inline flecs::query<> world::query(flecs::entity query_entity) const {
247 ecs_query_desc_t desc = {};
248 desc.entity = query_entity;
249 return flecs::query<>(world_, &desc);
250}
251
252template <typename... Comps, typename... Args>
253inline flecs::query_builder<Comps...> world::query_builder(Args &&... args) const {
254 return flecs::query_builder<Comps...>(world_, FLECS_FWD(args)...);
255}
256
257// world::each
258namespace _ {
259
260// Each with entity parameter
261template<typename Func, typename ... Args>
263
264template<typename Func, typename E, typename ... Args>
265struct query_delegate_w_ent<Func, arg_list<E, Args ...> >
266{
267 query_delegate_w_ent(const flecs::world& world, Func&& func) {
268 auto f = world.query<Args ...>();
269 f.each(FLECS_MOV(func));
270 }
271};
272
273// Each without entity parameter
274template<typename Func, typename ... Args>
276
277template<typename Func, typename ... Args>
278struct query_delegate_no_ent<Func, arg_list<Args ...> >
279{
280 query_delegate_no_ent(const flecs::world& world, Func&& func) {
281 auto f = world.query<Args ...>();
282 f.each(FLECS_MOV(func));
283 }
284};
285
286// Switch between function with & without entity parameter
287template<typename Func, typename T = int>
289
290template <typename Func>
291struct query_delegate<Func, if_t<is_same<first_arg_t<Func>, flecs::entity>::value> > {
292 query_delegate(const flecs::world& world, Func&& func) {
294 }
295};
296
297template <typename Func>
298struct query_delegate<Func, if_not_t<is_same<first_arg_t<Func>, flecs::entity>::value> > {
299 query_delegate(const flecs::world& world, Func&& func) {
301 }
302};
303
304}
305
306template <typename Func>
307inline void world::each(Func&& func) const {
308 _::query_delegate<Func> f_delegate(*this, FLECS_MOV(func));
309}
310
311template <typename T, typename Func>
312inline void world::each(Func&& func) const {
313 ecs_iter_t it = ecs_each_id(world_, _::type<T>::id(world_));
314
315 while (ecs_each_next(&it)) {
316 _::each_delegate<Func, T>(func).invoke(&it);
317 }
318}
319
320template <typename Func>
321inline void world::each(flecs::id_t each_id, Func&& func) const {
322 ecs_iter_t it = ecs_each_id(world_, each_id);
323
324 while (ecs_each_next(&it)) {
325 _::each_delegate<Func>(func).invoke(&it);
326 }
327}
328
329// query_base implementation
330inline query_base::operator flecs::query<> () const {
331 return flecs::query<>(query_);
332}
333
334}
const ecs_entity_t EcsQuery
Tag added to queries.
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:368
flecs::query_builder< Comps... > query_builder(Args &&... args) const
Create a query builder.
void each(Func &&func) const
Iterate over all entities with components in argument list of function.
flecs::query< Comps... > query(Args &&... args) const
Create a query.
bool ecs_each_next(ecs_iter_t *it)
Progress an iterator created with 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).
bool(* ecs_iter_next_action_t)(ecs_iter_t *it)
Function prototype for iterating an iterator.
Definition flecs.h:565
bool ecs_query_next(ecs_iter_t *it)
Progress query iterator.
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.
int32_t ecs_query_find_var(const ecs_query_t *query, const char *name)
Find variable index.
void ecs_query_fini(ecs_query_t *query)
Delete a query.
char * ecs_query_plan(const ecs_query_t *query)
Convert query to a string.
ecs_iter_t ecs_query_iter(const ecs_world_t *world, const ecs_query_t *query)
Create a query iterator.
char * ecs_query_str(const ecs_query_t *query)
Convert query to string expression.
ecs_query_t * ecs_query_init(ecs_world_t *world, const ecs_query_desc_t *desc)
Create a query.
bool ecs_query_changed(ecs_query_t *query)
Returns whether the query data changed since the last iteration.
const ecs_query_t * ecs_query_get_cache_query(const ecs_query_t *query)
Get query used to populate cache.
Query builder.
Component for storing a poly object.
Definition flecs.h:1539
ecs_poly_t * poly
Pointer to poly object.
Definition flecs.h:1540
Iterator.
Definition flecs.h:1136
Used with ecs_query_init().
Definition flecs.h:1245
ecs_term_t terms[32]
Query terms.
Definition flecs.h:1250
ecs_entity_t entity
Entity associated with query (optional)
Definition flecs.h:1312
Type that contains information about a query group.
Definition flecs.h:1507
void * ctx
Group context, returned by on_group_create.
Definition flecs.h:1511
Queries are lists of constraints (terms) that match entities.
Definition flecs.h:812
ecs_world_t * world
World or stage query was created with.
Definition flecs.h:845
ecs_entity_t entity
Entity associated with query (optional)
Definition flecs.h:843
ecs_term_t * terms
Query terms.
Definition flecs.h:815
int8_t term_count
Number of query terms.
Definition flecs.h:822
int8_t field_count
Number of fields returned by query.
Definition flecs.h:823
ecs_id_t id
Component id to be matched by term.
Definition flecs.h:789
Entity.
Definition entity.hpp:30
bool changed() const
Returns whether the query data changed since the last iteration.
Definition impl.hpp:119
void * group_ctx(uint64_t group_id) const
Get context for group.
Definition impl.hpp:137
flecs::string plan() const
Returns a string representing the query plan.
Definition impl.hpp:180
const flecs::query_group_info_t * group_info(uint64_t group_id) const
Get info for group.
Definition impl.hpp:128
void destruct()
Free persistent query.
Definition impl.hpp:90
Query builder.
Definition builder.hpp:24
Class that describes a term.
Definition impl.hpp:16
The world.
Definition world.hpp:137