Flecs: include/flecs/addons/cpp/mixins/query/builder_i.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
builder_i.hpp
Go to the documentation of this file.
1
5
6#pragma once
7
8#include "../term/builder_i.hpp"
9
10namespace flecs
11{
12
17template<typename Base, typename ... Components>
18 struct query_builder_i : term_builder_i<Base> {
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& detect_changes() {
39 desc_->flags |= EcsQueryDetectChanges;
40 return *this;
41 }
42
43 Base& expr(const char *expr) {
44 ecs_check(expr_count_ == 0, ECS_INVALID_OPERATION,
45 "query_builder::expr() called more than once");
46 desc_->expr = expr;
47 expr_count_ ++;
48
49 error:
50 return *this;
51 }
52
53 /* With methods */
54
55 template<typename T>
56 Base& with() {
57 this->term();
58 *this->term_ = flecs::term(_::type<T>::id(this->world_v()));
59 this->term_->inout = static_cast<ecs_inout_kind_t>(
60 _::type_to_inout<T>());
61 return *this;
62 }
63
64 Base& with(id_t component_id) {
65 this->term();
66 *this->term_ = flecs::term(component_id);
67 return *this;
68 }
69
70 Base& with(const char *component_name) {
71 this->term();
72 *this->term_ = flecs::term().first(component_name);
73 return *this;
74 }
75
76 Base& with(const char *first, const char *second) {
77 this->term();
78 *this->term_ = flecs::term().first(first).second(second);
79 return *this;
80 }
81
82 Base& with(entity_t first, entity_t second) {
83 this->term();
84 *this->term_ = flecs::term(first, second);
85 return *this;
86 }
87
88 Base& with(entity_t first, const char *second) {
89 this->term();
90 *this->term_ = flecs::term(first).second(second);
91 return *this;
92 }
93
94 Base& with(const char *first, entity_t second) {
95 this->term();
96 *this->term_ = flecs::term().first(first).second(second);
97 return *this;
98 }
99
100 template<typename First>
101 Base& with(entity_t second) {
102 return this->with(_::type<First>::id(this->world_v()), second);
103 }
104
105 template<typename First>
106 Base& with(const char *second) {
107 return this->with(_::type<First>::id(this->world_v())).second(second);
108 }
109
110 template<typename First, typename Second>
111 Base& with() {
112 return this->with<First>(_::type<Second>::id(this->world_v()));
113 }
114
115 template <typename E, if_t< is_enum<E>::value > = 0>
116 Base& with(E value) {
117 flecs::entity_t r = _::type<E>::id(this->world_v());
118 auto o = enum_type<E>(this->world_v()).entity(value);
119 return this->with(r, o);
120 }
121
122 Base& with(flecs::term& term) {
123 this->term();
124 *this->term_ = term;
125 return *this;
126 }
127
128 Base& with(flecs::term&& term) {
129 this->term();
130 *this->term_ = term;
131 return *this;
132 }
133
134 /* Without methods, shorthand for .with(...).not_(). */
135
136 template <typename ... Args>
137 Base& without(Args&&... args) {
138 return this->with(FLECS_FWD(args)...).not_();
139 }
140
141 template <typename T, typename ... Args>
142 Base& without(Args&&... args) {
143 return this->with<T>(FLECS_FWD(args)...).not_();
144 }
145
146 template <typename First, typename Second>
147 Base& without() {
148 return this->with<First, Second>().not_();
149 }
150
151 /* Write/read methods */
152
153 Base& write() {
154 term_builder_i<Base>::write();
155 return *this;
156 }
157
158 template <typename ... Args>
159 Base& write(Args&&... args) {
160 return this->with(FLECS_FWD(args)...).write();
161 }
162
163 template <typename T, typename ... Args>
164 Base& write(Args&&... args) {
165 return this->with<T>(FLECS_FWD(args)...).write();
166 }
167
168 template <typename First, typename Second>
169 Base& write() {
170 return this->with<First, Second>().write();
171 }
172
173 Base& read() {
174 term_builder_i<Base>::read();
175 return *this;
176 }
177
178 template <typename ... Args>
179 Base& read(Args&&... args) {
180 return this->with(FLECS_FWD(args)...).read();
181 }
182
183 template <typename T, typename ... Args>
184 Base& read(Args&&... args) {
185 return this->with<T>(FLECS_FWD(args)...).read();
186 }
187
188 template <typename First, typename Second>
189 Base& read() {
190 return this->with<First, Second>().read();
191 }
192
193 /* Scope_open/scope_close shorthand notation. */
194 Base& scope_open() {
195 return this->with(flecs::ScopeOpen).entity(0);
196 }
197
198 Base& scope_close() {
199 return this->with(flecs::ScopeClose).entity(0);
200 }
201
202 /* Term notation for more complex query features */
203
206 Base& term() {
207 if (this->term_) {
208 ecs_check(ecs_term_is_initialized(this->term_),
209 ECS_INVALID_OPERATION,
210 "query_builder::term() called without initializing term");
211 }
212
213 ecs_check(term_index_ < FLECS_TERM_COUNT_MAX,
214 ECS_INVALID_PARAMETER, "maximum number of terms exceeded");
215
216 this->set_term(&desc_->terms[term_index_]);
217
218 term_index_ ++;
219
220 error:
221 return *this;
222 }
223
228 template <typename T>
229 Base& term_at() {
230 flecs::id_t term_id = _::type<T>::id(this->world_v());
231 for (int i = 0; i < term_index_; i ++) {
232 ecs_term_t cur_term = desc_->terms[i];
233 ecs_id_t cur_term_id = cur_term.id;
234 ecs_id_t cur_term_pair = ecs_pair(cur_term.first.id, cur_term.second.id);
235
236 if ((term_id == cur_term_id || (cur_term_id != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_id))) ||
237 (term_id == cur_term_pair || (cur_term_pair != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_pair)))) {
238 return term_at(i);
239 }
240 }
241
242 ecs_err("term not found");
243 return *this;
244 }
245
248 Base& term_at(int32_t term_index) {
249 ecs_assert(term_index >= 0, ECS_INVALID_PARAMETER, NULL);
250 int32_t prev_index = term_index_;
251 term_index_ = term_index;
252 this->term();
253 term_index_ = prev_index;
254 ecs_assert(ecs_term_is_initialized(this->term_),
255 ECS_INVALID_PARAMETER, NULL);
256 return *this;
257 }
258
261 template <typename T>
262 Base& term_at(int32_t term_index) {
263 this->term_at(term_index);
264#if !defined(FLECS_NDEBUG) || defined(FLECS_KEEP_ASSERT)
265 flecs::id_t term_id = _::type<T>::id(this->world_v());
266 ecs_term_t cur_term = *this->term_;
267 ecs_id_t cur_term_id = cur_term.id;
268 ecs_id_t cur_term_pair = ecs_pair(cur_term.first.id, cur_term.second.id);
269
270 ecs_assert((term_id == cur_term_id || (cur_term_id != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_id))) ||
271 (term_id == cur_term_pair || (cur_term_pair != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_pair))),
272 ECS_INVALID_PARAMETER, "term type mismatch");
273#endif
274 return *this;
275 }
276
295 template <typename T>
296 Base& order_by(int(*compare)(flecs::entity_t, const T*, flecs::entity_t, const T*)) {
297 ecs_order_by_action_t cmp = reinterpret_cast<ecs_order_by_action_t>(compare);
298 return this->order_by(_::type<T>::id(this->world_v()), cmp);
299 }
300
307 Base& order_by(flecs::entity_t component, int(*compare)(flecs::entity_t, const void*, flecs::entity_t, const void*)) {
308 desc_->order_by_callback = reinterpret_cast<ecs_order_by_action_t>(compare);
309 desc_->order_by = component;
310 return *this;
311 }
312
330 template <typename T>
331 Base& group_by(uint64_t(*group_by_action)(flecs::world_t*, flecs::table_t *table, flecs::id_t id, void* ctx)) {
332 ecs_group_by_action_t action = reinterpret_cast<ecs_group_by_action_t>(group_by_action);
333 return this->group_by(_::type<T>::id(this->world_v()), action);
334 }
335
342 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)) {
343 desc_->group_by_callback = reinterpret_cast<ecs_group_by_action_t>(group_by_action);
344 desc_->group_by = component;
345 return *this;
346 }
347
353 template <typename T>
354 Base& group_by() {
355 return this->group_by(_::type<T>::id(this->world_v()), nullptr);
356 }
357
363 Base& group_by(flecs::entity_t component) {
364 return this->group_by(component, nullptr);
365 }
366
372 Base& group_by_ctx(void *ctx, ecs_ctx_free_t ctx_free = nullptr) {
373 desc_->group_by_ctx = ctx;
374 desc_->group_by_ctx_free = ctx_free;
375 return *this;
376 }
377
380 Base& on_group_create(ecs_group_create_action_t action) {
381 desc_->on_group_create = action;
382 return *this;
383 }
384
387 Base& on_group_delete(ecs_group_delete_action_t action) {
388 desc_->on_group_delete = action;
389 return *this;
390 }
391
392protected:
393 virtual flecs::world_t* world_v() override = 0;
394 int32_t term_index_;
395 int32_t expr_count_;
396
397private:
398 operator Base&() {
399 return *static_cast<Base*>(this);
400 }
401
402 ecs_query_desc_t *desc_;
403};
404
405}
ecs_assert
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:368
ecs_check
#define ecs_check(condition, error_code,...)
Check.
Definition log.h:412
ecs_id_t
uint64_t ecs_id_t
Ids are the things that can be added to an entity.
Definition flecs.h:354
ecs_group_by_action_t
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
ecs_group_delete_action_t
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
ecs_group_create_action_t
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
ecs_ctx_free_t
void(* ecs_ctx_free_t)(void *ctx)
Function to cleanup context data.
Definition flecs.h:625
ecs_order_by_action_t
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_get_typeid
ecs_entity_t ecs_get_typeid(const ecs_world_t *world, ecs_id_t component)
Get the type for a component.
FLECS_TERM_COUNT_MAX
#define FLECS_TERM_COUNT_MAX
Maximum number of terms in queries.
Definition flecs.h:312
EcsQueryDetectChanges
#define EcsQueryDetectChanges
Enable change detection for query.
Definition flecs.h:1244
ecs_term_is_initialized
bool ecs_term_is_initialized(const ecs_term_t *term)
Test whether a term is set.
ecs_query_cache_kind_t
ecs_query_cache_kind_t
Specify cache policy for query.
Definition flecs.h:704
ecs_inout_kind_t
ecs_inout_kind_t
Specify read/write access for term.
Definition flecs.h:683
ecs_query_desc_t
Used with ecs_query_init().
Definition flecs.h:1251
ecs_term_ref_t::id
ecs_entity_t id
Entity id.
Definition flecs.h:775
ecs_term_t
Type that describes a term (single element in a query).
Definition flecs.h:789
ecs_term_t::id
ecs_id_t id
Component id to be matched by term.
Definition flecs.h:790
ecs_term_t::second
ecs_term_ref_t second
Second element of pair.
Definition flecs.h:797
ecs_term_t::first
ecs_term_ref_t first
Component or first element of pair.
Definition flecs.h:796
flecs::_::type
Definition flecs.hpp:39
flecs::component
Component class.
Definition component.hpp:382
flecs::query_builder_i::term_at
Base & term_at(int32_t term_index)
Sets the current term to the one at the provided index and asserts that the type matches.
Definition builder_i.hpp:262
flecs::query_builder_i::group_by
Base & group_by()
Group and sort matched tables.
Definition builder_i.hpp:354
flecs::query_builder_i::on_group_delete
Base & on_group_delete(ecs_group_delete_action_t action)
Specify on_group_delete action.
Definition builder_i.hpp:387
flecs::query_builder_i::group_by
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.
Definition builder_i.hpp:342
flecs::query_builder_i::on_group_create
Base & on_group_create(ecs_group_create_action_t action)
Specify on_group_create action.
Definition builder_i.hpp:380
flecs::query_builder_i::group_by
Base & group_by(flecs::entity_t component)
Group and sort matched tables.
Definition builder_i.hpp:363
flecs::query_builder_i::group_by
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.
Definition builder_i.hpp:331
flecs::query_builder_i::term_at
Base & term_at(int32_t term_index)
Sets the current term to the one at the provided index.
Definition builder_i.hpp:248
flecs::query_builder_i::term
Base & term()
Sets the current term to next one in term list.
Definition builder_i.hpp:206
flecs::query_builder_i::order_by
Base & order_by(int(*compare)(flecs::entity_t, const T *, flecs::entity_t, const T *))
Sort the output of a query.
Definition builder_i.hpp:296
flecs::query_builder_i::group_by_ctx
Base & group_by_ctx(void *ctx, ecs_ctx_free_t ctx_free=nullptr)
Specify context to be passed to group_by function.
Definition builder_i.hpp:372
flecs::query_builder_i::term_at
Base & term_at()
Sets the current term to the one with the provided type.
Definition builder_i.hpp:229
flecs::query_builder_i::order_by
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.
Definition builder_i.hpp:307
flecs::table
Definition table.hpp:18
flecs::term_builder_i::read
Base & read()
Short for inout_stage(flecs::In).
Definition builder_i.hpp:316
flecs::term_builder_i::write
Base & write()
Short for inout_stage(flecs::Out).
Definition builder_i.hpp:309
flecs::term
Class that describes a term.
Definition impl.hpp:16
builder_i.hpp
Term builder interface.