Flecs v4.0
A fast entity component system (ECS) for C & C++
Loading...
Searching...
No Matches
builder_i.hpp
Go to the documentation of this file.
1
6#pragma once
7
9
10namespace flecs
11{
12
17template<typename Base, typename ... Components>
19 query_builder_i(ecs_query_desc_t *desc, int32_t term_index = 0)
20 : term_index_(term_index)
21 , expr_count_(0)
22 , desc_(desc) { }
23
24 Base& query_flags(ecs_flags32_t flags) {
25 desc_->flags |= flags;
26 return *this;
27 }
28
29 Base& cache_kind(query_cache_kind_t kind) {
30 desc_->cache_kind = static_cast<ecs_query_cache_kind_t>(kind);
31 return *this;
32 }
33
34 Base& cached() {
35 return cache_kind(flecs::QueryCacheAuto);
36 }
37
38 Base& expr(const char *expr) {
39 ecs_check(expr_count_ == 0, ECS_INVALID_OPERATION,
40 "query_builder::expr() called more than once");
41 desc_->expr = expr;
42 expr_count_ ++;
43
44 error:
45 return *this;
46 }
47
48 /* With methods */
49
50 template<typename T>
51 Base& with() {
52 this->term();
53 *this->term_ = flecs::term(_::type<T>::id(this->world_v()));
54 this->term_->inout = static_cast<ecs_inout_kind_t>(
55 _::type_to_inout<T>());
56 return *this;
57 }
58
59 Base& with(id_t id) {
60 this->term();
61 *this->term_ = flecs::term(id);
62 return *this;
63 }
64
65 Base& with(const char *name) {
66 this->term();
67 *this->term_ = flecs::term().first(name);
68 return *this;
69 }
70
71 Base& with(const char *first, const char *second) {
72 this->term();
73 *this->term_ = flecs::term().first(first).second(second);
74 return *this;
75 }
76
77 Base& with(entity_t r, entity_t o) {
78 this->term();
79 *this->term_ = flecs::term(r, o);
80 return *this;
81 }
82
83 Base& with(entity_t r, const char *o) {
84 this->term();
85 *this->term_ = flecs::term(r).second(o);
86 return *this;
87 }
88
89 Base& with(const char *r, entity_t o) {
90 this->term();
91 *this->term_ = flecs::term().first(r).second(o);
92 return *this;
93 }
94
95 template<typename First>
96 Base& with(id_t o) {
97 return this->with(_::type<First>::id(this->world_v()), o);
98 }
99
100 template<typename First>
101 Base& with(const char *second) {
102 return this->with(_::type<First>::id(this->world_v())).second(second);
103 }
104
105 template<typename First, typename Second>
106 Base& with() {
107 return this->with<First>(_::type<Second>::id(this->world_v()));
108 }
109
110 template <typename E, if_t< is_enum<E>::value > = 0>
111 Base& with(E value) {
112 flecs::entity_t r = _::type<E>::id(this->world_v());
113 auto o = enum_type<E>(this->world_v()).entity(value);
114 return this->with(r, o);
115 }
116
117 Base& with(flecs::term& term) {
118 this->term();
119 *this->term_ = term;
120 return *this;
121 }
122
123 Base& with(flecs::term&& term) {
124 this->term();
125 *this->term_ = term;
126 return *this;
127 }
128
129 /* Without methods, shorthand for .with(...).not_(). */
130
131 template <typename ... Args>
132 Base& without(Args&&... args) {
133 return this->with(FLECS_FWD(args)...).not_();
134 }
135
136 template <typename T, typename ... Args>
137 Base& without(Args&&... args) {
138 return this->with<T>(FLECS_FWD(args)...).not_();
139 }
140
141 template <typename First, typename Second>
142 Base& without() {
143 return this->with<First, Second>().not_();
144 }
145
146 /* Write/read methods */
147
148 Base& write() {
150 return *this;
151 }
152
153 template <typename ... Args>
154 Base& write(Args&&... args) {
155 return this->with(FLECS_FWD(args)...).write();
156 }
157
158 template <typename T, typename ... Args>
159 Base& write(Args&&... args) {
160 return this->with<T>(FLECS_FWD(args)...).write();
161 }
162
163 template <typename First, typename Second>
164 Base& write() {
165 return this->with<First, Second>().write();
166 }
167
168 Base& read() {
170 return *this;
171 }
172
173 template <typename ... Args>
174 Base& read(Args&&... args) {
175 return this->with(FLECS_FWD(args)...).read();
176 }
177
178 template <typename T, typename ... Args>
179 Base& read(Args&&... args) {
180 return this->with<T>(FLECS_FWD(args)...).read();
181 }
182
183 template <typename First, typename Second>
184 Base& read() {
185 return this->with<First, Second>().read();
186 }
187
188 /* Scope_open/scope_close shorthand notation. */
189 Base& scope_open() {
190 return this->with(flecs::ScopeOpen).entity(0);
191 }
192
193 Base& scope_close() {
194 return this->with(flecs::ScopeClose).entity(0);
195 }
196
197 /* Term notation for more complex query features */
198
201 Base& term() {
202 if (this->term_) {
204 ECS_INVALID_OPERATION,
205 "query_builder::term() called without initializing term");
206 }
207
208 ecs_check(term_index_ < FLECS_TERM_COUNT_MAX,
209 ECS_INVALID_PARAMETER, "maximum number of terms exceeded");
210
211 this->set_term(&desc_->terms[term_index_]);
212
213 term_index_ ++;
214
215 error:
216 return *this;
217 }
218
223 template <typename T>
224 Base& term_at() {
225 flecs::id_t term_id = _::type<T>::id(this->world_v());
226 for (int i = 0; i < term_index_; i ++) {
227 ecs_term_t cur_term = desc_->terms[i];
228 ecs_id_t cur_term_id = cur_term.id;
229 ecs_id_t cur_term_pair = ecs_pair(cur_term.first.id, cur_term.second.id);
230
231 if ((term_id == cur_term_id || (cur_term_id != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_id))) ||
232 (term_id == cur_term_pair || (cur_term_pair != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_pair)))) {
233 return term_at(i);
234 }
235 }
236
237 ecs_err("term not found");
238 return *this;
239 }
240
243 Base& term_at(int32_t term_index) {
244 ecs_assert(term_index >= 0, ECS_INVALID_PARAMETER, NULL);
245 int32_t prev_index = term_index_;
246 term_index_ = term_index;
247 this->term();
248 term_index_ = prev_index;
250 ECS_INVALID_PARAMETER, NULL);
251 return *this;
252 }
253
256 template <typename T>
257 Base& term_at(int32_t term_index) {
258 this->term_at(term_index);
259#if !defined(FLECS_NDEBUG) || defined(FLECS_KEEP_ASSERT)
260 flecs::id_t term_id = _::type<T>::id(this->world_v());
261 ecs_term_t cur_term = *this->term_;
262 ecs_id_t cur_term_id = cur_term.id;
263 ecs_id_t cur_term_pair = ecs_pair(cur_term.first.id, cur_term.second.id);
264
265 ecs_assert((term_id == cur_term_id || (cur_term_id != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_id))) ||
266 (term_id == cur_term_pair || (cur_term_pair != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_pair))),
267 ECS_INVALID_PARAMETER, "term type mismatch");
268#endif
269 return *this;
270 }
271
290 template <typename T>
291 Base& order_by(int(*compare)(flecs::entity_t, const T*, flecs::entity_t, const T*)) {
292 ecs_order_by_action_t cmp = reinterpret_cast<ecs_order_by_action_t>(compare);
293 return this->order_by(_::type<T>::id(this->world_v()), cmp);
294 }
295
302 Base& order_by(flecs::entity_t component, int(*compare)(flecs::entity_t, const void*, flecs::entity_t, const void*)) {
303 desc_->order_by_callback = reinterpret_cast<ecs_order_by_action_t>(compare);
304 desc_->order_by = component;
305 return *this;
306 }
307
325 template <typename T>
326 Base& group_by(uint64_t(*group_by_action)(flecs::world_t*, flecs::table_t *table, flecs::id_t id, void* ctx)) {
327 ecs_group_by_action_t action = reinterpret_cast<ecs_group_by_action_t>(group_by_action);
328 return this->group_by(_::type<T>::id(this->world_v()), action);
329 }
330
337 Base& group_by(flecs::entity_t component, uint64_t(*group_by_action)(flecs::world_t*, flecs::table_t *table, flecs::id_t id, void* ctx)) {
338 desc_->group_by_callback = reinterpret_cast<ecs_group_by_action_t>(group_by_action);
339 desc_->group_by = component;
340 return *this;
341 }
342
348 template <typename T>
349 Base& group_by() {
350 return this->group_by(_::type<T>::id(this->world_v()), nullptr);
351 }
352
358 Base& group_by(flecs::entity_t component) {
359 return this->group_by(component, nullptr);
360 }
361
367 Base& group_by_ctx(void *ctx, ecs_ctx_free_t ctx_free = nullptr) {
368 desc_->group_by_ctx = ctx;
369 desc_->group_by_ctx_free = ctx_free;
370 return *this;
371 }
372
376 desc_->on_group_create = action;
377 return *this;
378 }
379
383 desc_->on_group_delete = action;
384 return *this;
385 }
386
387protected:
388 virtual flecs::world_t* world_v() override = 0;
389 int32_t term_index_;
390 int32_t expr_count_;
391
392private:
393 operator Base&() {
394 return *static_cast<Base*>(this);
395 }
396
397 ecs_query_desc_t *desc_;
398};
399
400}
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:368
#define ecs_check(condition, error_code,...)
Check.
Definition log.h:415
uint64_t ecs_id_t
Ids are the things that can be added to an entity.
Definition flecs.h:374
uint64_t(* ecs_group_by_action_t)(ecs_world_t *world, ecs_table_t *table, ecs_id_t group_id, void *ctx)
Callback used for grouping tables in a query.
Definition flecs.h:596
void(* ecs_group_delete_action_t)(ecs_world_t *world, uint64_t group_id, void *group_ctx, void *group_by_ctx)
Callback invoked when a query deletes an existing group.
Definition flecs.h:609
void *(* ecs_group_create_action_t)(ecs_world_t *world, uint64_t group_id, void *group_by_ctx)
Callback invoked when a query creates a new group.
Definition flecs.h:603
void(* ecs_ctx_free_t)(void *ctx)
Function to cleanup context data.
Definition flecs.h:625
int(* ecs_order_by_action_t)(ecs_entity_t e1, const void *ptr1, ecs_entity_t e2, const void *ptr2)
Callback used for comparing components.
Definition flecs.h:578
ecs_entity_t ecs_get_typeid(const ecs_world_t *world, ecs_id_t id)
Get the type for an id.
#define FLECS_TERM_COUNT_MAX
Maximum number of terms in queries.
Definition flecs.h:312
bool ecs_term_is_initialized(const ecs_term_t *term)
Test whether a term is set.
ecs_query_cache_kind_t
Specify cache policy for query.
Definition flecs.h:704
ecs_inout_kind_t
Specify read/write access for term.
Definition flecs.h:683
Used with ecs_query_init().
Definition flecs.h:1236
ecs_id_t group_by
Component id to be used for grouping.
Definition flecs.h:1267
ecs_term_t terms[32]
Query terms.
Definition flecs.h:1241
ecs_ctx_free_t group_by_ctx_free
Function to free group_by_ctx.
Definition flecs.h:1288
void * group_by_ctx
Context to pass to group_by.
Definition flecs.h:1285
ecs_entity_t order_by
Component to sort on, used together with order_by_callback or order_by_table_callback.
Definition flecs.h:1263
ecs_order_by_action_t order_by_callback
Callback used for ordering query results.
Definition flecs.h:1255
ecs_group_create_action_t on_group_create
Callback that is invoked when a new group is created.
Definition flecs.h:1278
ecs_group_by_action_t group_by_callback
Callback used for grouping results.
Definition flecs.h:1274
ecs_group_delete_action_t on_group_delete
Callback that is invoked when an existing group is deleted.
Definition flecs.h:1282
ecs_flags32_t flags
Flags for enabling query features.
Definition flecs.h:1250
ecs_query_cache_kind_t cache_kind
Caching policy of query.
Definition flecs.h:1247
const char * expr
Query DSL expression (optional)
Definition flecs.h:1244
ecs_entity_t id
Entity id.
Definition flecs.h:775
Type that describes a term (single element in a query).
Definition flecs.h:789
ecs_id_t id
Component id to be matched by term.
Definition flecs.h:790
ecs_term_ref_t second
Second element of pair.
Definition flecs.h:797
int16_t inout
Access to contents matched by term.
Definition flecs.h:803
ecs_term_ref_t first
Component or first element of pair.
Definition flecs.h:796
Component class.
Query builder interface.
Definition builder_i.hpp:18
Base & term_at(int32_t term_index)
Sets the current term to the one at the provided index and asserts that the type matches.
Base & group_by()
Group and sort matched tables.
Base & on_group_delete(ecs_group_delete_action_t action)
Specify on_group_delete action.
Base & group_by(flecs::entity_t component, uint64_t(*group_by_action)(flecs::world_t *, flecs::table_t *table, flecs::id_t id, void *ctx))
Group and sort matched tables.
Base & on_group_create(ecs_group_create_action_t action)
Specify on_group_create action.
Base & group_by(flecs::entity_t component)
Group and sort matched tables.
Base & group_by(uint64_t(*group_by_action)(flecs::world_t *, flecs::table_t *table, flecs::id_t id, void *ctx))
Group and sort matched tables.
Base & term_at(int32_t term_index)
Sets the current term to the one at the provided index.
Base & term()
Sets the current term to next one in term list.
Base & order_by(int(*compare)(flecs::entity_t, const T *, flecs::entity_t, const T *))
Sort the output of a query.
Base & group_by_ctx(void *ctx, ecs_ctx_free_t ctx_free=nullptr)
Specify context to be passed to group_by function.
Base & term_at()
Sets the current term to the one with the provided type.
Base & order_by(flecs::entity_t component, int(*compare)(flecs::entity_t, const void *, flecs::entity_t, const void *))
Sort the output of a query.
Term builder interface.
Definition builder_i.hpp:99
Base & read()
Short for inout_stage(flecs::In).
Base & write()
Short for inout_stage(flecs::Out).
Class that describes a term.
Definition impl.hpp:16
Term builder interface.