Skip to content
Flecs v4.1
builder_i.hpp
Go to the documentation of this file.
1/**
2 * @file addons/cpp/mixins/term/builder_i.hpp
3 * @brief Term builder interface.
4 */
5
6#pragma once
7
9#include <stdio.h>
10
11namespace flecs
12{
13
14/** Term identifier builder.
15 * A term identifier describes a single identifier in a term. Identifier
16 * descriptions can reference entities by ID, name, or by variable, which means
17 * the entity will be resolved when the term is evaluated.
18 *
19 * @ingroup cpp_core_queries
20 */
21template<typename Base>
23 /** Default constructor. */
25
26 /** Destructor. */
27 virtual ~term_ref_builder_i() { }
28
29 /** The self flag indicates that the term identifier itself is used. */
30 Base& self() {
31 this->assert_term_ref();
32 term_ref_->id |= flecs::Self;
33 return *this;
34 }
35
36 /** Specify the value of the identifier by ID. */
37 Base& id(flecs::entity_t id) {
38 this->assert_term_ref();
39 term_ref_->id = id;
40 return *this;
41 }
42
43 /** Specify the value of the identifier by ID. Almost the same as id(entity_t), but this
44 * operation explicitly sets the flecs::IsEntity flag. This forces the ID to
45 * be interpreted as an entity, whereas not setting the flag would implicitly
46 * convert IDs for built-in variables such as flecs::This to a variable.
47 *
48 * This function can also be used to disambiguate id(0), which would match
49 * both id(entity_t) and id(const char*).
50 */
52 this->assert_term_ref();
53 term_ref_->id = entity | flecs::IsEntity;
54 return *this;
55 }
56
57 /** Specify the value of the identifier by name. */
58 Base& name(const char *name) {
59 this->assert_term_ref();
60 term_ref_->id |= flecs::IsEntity;
61 term_ref_->name = const_cast<char*>(name);
62 return *this;
63 }
64
65 /** Specify that the identifier is a variable (resolved at query evaluation time). */
66 Base& var(const char *var_name) {
67 this->assert_term_ref();
68 term_ref_->id |= flecs::IsVariable;
69 term_ref_->name = const_cast<char*>(var_name);
70 return *this;
71 }
72
73 /** Override the term ID flags. */
75 this->assert_term_ref();
77 return *this;
78 }
79
80 /** Pointer to the current term reference. */
82
83protected:
84 virtual flecs::world_t* world_v() = 0;
85
86 void assert_term_ref() {
88 "no active term (call .with() first)");
89 }
90
91private:
92 operator Base&() {
93 return *static_cast<Base*>(this);
94 }
95};
96
97/** Term builder interface.
98 * A term is a single element of a query expression.
99 *
100 * @ingroup cpp_core_queries
101 */
102template<typename Base>
104 /** Default constructor. */
105 term_builder_i() : term_(nullptr) { }
106
107 /** Construct from a term pointer. */
109 set_term(term_ptr);
110 }
111
112 /** Set the term ID. */
113 Base& term(id_t id) {
114 return this->id(id);
115 }
116
117 template <typename T = void, typename... Args>
118 Base& src(Args... args) {
119 return select_ref<T>(&ecs_term_t::src, args...);
120 }
121
122 template <typename T = void, typename... Args>
123 Base& first(Args... args) {
124 return select_ref<T>(&ecs_term_t::first, args...);
125 }
126
127 template <typename T = void, typename... Args>
128 Base& second(Args... args) {
129 return select_ref<T>(&ecs_term_t::second, args...);
130 }
131
132 /** The up flag indicates that the term identifier may be substituted by
133 * traversing a relationship upwards. For example, substitute the identifier
134 * with its parent by traversing the ChildOf relationship. */
136 this->assert_term_ref();
138 "up traversal can only be applied to term source");
140 "up traversal can only be applied to term source");
141 this->term_ref_->id |= flecs::Up;
142 if (trav) {
143 term_->trav = trav;
144 }
145 error:
146 return *this;
147 }
148
149 /** Traverse upwards using the specified relationship type. */
150 template <typename Trav>
151 Base& up() {
152 return this->up(_::type<Trav>::id(this->world_v()));
153 }
154
155 /** The cascade flag is like up(), but returns results in breadth-first order.
156 * Only supported for flecs::query. */
158 this->assert_term_ref();
159 this->up();
160 this->term_ref_->id |= flecs::Cascade;
161 if (trav) {
162 term_->trav = trav;
163 }
164 return *this;
165 }
166
167 /** Cascade using the specified relationship type. */
168 template <typename Trav>
169 Base& cascade() {
170 return this->cascade(_::type<Trav>::id(this->world_v()));
171 }
172
173 /** Use with cascade() to iterate results in descending (bottom-to-top) order. */
174 Base& desc() {
175 this->assert_term_ref();
176 this->term_ref_->id |= flecs::Desc;
177 return *this;
178 }
179
180 /** Same as up(). Exists for backwards compatibility. */
181 Base& parent() {
182 return this->up();
183 }
184
185 /** Specify the relationship to traverse, and flags to indicate direction. */
187 this->assert_term_ref();
188 term_->trav = trav;
189 this->term_ref_->id |= flags;
190 return *this;
191 }
192
193 /** Set ID flags for the term. */
195 this->assert_term();
196 term_->id |= flags;
197 return *this;
198 }
199
200 /** Set read/write access of the term. */
202 this->assert_term();
203 term_->inout = static_cast<int16_t>(inout);
204 return *this;
205 }
206
207 /** Set read/write access for a stage. Use this when a system reads or writes
208 * components other than the ones provided by the query. This information
209 * can be used by schedulers to insert sync/merge points between systems
210 * where deferred operations are flushed.
211 *
212 * Setting this is optional. If not set, the value of the accessed component
213 * may be out of sync for at most one frame.
214 */
216 this->assert_term();
217 term_->inout = static_cast<int16_t>(inout);
218 if (term_->oper != EcsNot) {
219 this->src().entity(0);
220 }
221 return *this;
222 }
223
224 /** Short for inout_stage(flecs::Out).
225 * Use when the system uses add(), remove(), or set().
226 */
227 Base& write() {
228 return this->inout_stage(flecs::Out);
229 }
230
231 /** Short for inout_stage(flecs::In).
232 * Use when the system uses get().
233 */
234 Base& read() {
235 return this->inout_stage(flecs::In);
236 }
237
238 /** Short for inout_stage(flecs::InOut).
239 * Use when the system uses ensure().
240 */
241 Base& read_write() {
242 return this->inout_stage(flecs::InOut);
243 }
244
245 /** Short for inout(flecs::In). */
246 Base& in() {
247 return this->inout(flecs::In);
248 }
249
250 /** Short for inout(flecs::Out). */
251 Base& out() {
252 return this->inout(flecs::Out);
253 }
254
255 /** Short for inout(flecs::InOut). */
256 Base& inout() {
257 return this->inout(flecs::InOut);
258 }
259
260 /** Short for inout(flecs::InOutNone). */
261 Base& inout_none() {
262 return this->inout(flecs::InOutNone);
263 }
264
265 /** Set the operator of the term. */
267 this->assert_term();
268 term_->oper = static_cast<int16_t>(oper);
269 return *this;
270 }
271
272 /** Short for oper(flecs::And). */
273 Base& and_() {
274 return this->oper(flecs::And);
275 }
276
277 /** Short for oper(flecs::Or). */
278 Base& or_() {
279 return this->oper(flecs::Or);
280 }
281
282 /** Short for oper(flecs::Not). */
283 Base& not_() {
284 return this->oper(flecs::Not);
285 }
286
287 /** Short for oper(flecs::Optional). */
288 Base& optional() {
289 return this->oper(flecs::Optional);
290 }
291
292 /** Short for oper(flecs::AndFrom). */
293 Base& and_from() {
294 return this->oper(flecs::AndFrom);
295 }
296
297 /** Short for oper(flecs::OrFrom). */
298 Base& or_from() {
299 return this->oper(flecs::OrFrom);
300 }
301
302 /** Short for oper(flecs::NotFrom). */
303 Base& not_from() {
304 return this->oper(flecs::NotFrom);
305 }
306
307 /** Mark the term as a filter. Query terms marked as a filter are not triggered
308 * by observers. */
309 Base& filter() {
311 return *this;
312 }
313
314 /** Pointer to the current term. */
316
317protected:
318 virtual flecs::world_t* world_v() override = 0;
319
320 /** Set the current term pointer. */
322 term_ = term;
323 if (term) {
324 this->term_ref_ = &term_->src; // default to source
325 } else {
326 this->term_ref_ = nullptr;
327 }
328 }
329
330private:
331 Base& set_ref() {
332 return *this;
333 }
334
335 Base& set_ref(flecs::entity_t id) {
336 return this->id(id);
337 }
338
339 Base& set_ref(const char *name) {
340 ecs_assert(name != nullptr, ECS_INVALID_PARAMETER, nullptr);
341 return name[0] == '$' ? this->var(name + 1) : this->name(name);
342 }
343
344 template <typename T, typename... Args>
345 Base& select_ref(ecs_term_ref_t ecs_term_t::*ref, Args... args) {
346 assert_term();
347 this->term_ref_ = &(term_->*ref);
348 if constexpr (std::is_void_v<T>) {
349 return set_ref(args...);
350 } else {
351 return set_ref(_::type<T>::id(this->world_v()));
352 }
353 }
354
355 void assert_term() {
357 "no active term (call .with() first)");
358 }
359
360 operator Base&() {
361 return *static_cast<Base*>(this);
362 }
363};
364
365}
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:473
#define ECS_INVALID_PARAMETER
Invalid parameter error code.
Definition log.h:671
#define ecs_check(condition, error_code,...)
Check.
Definition log.h:527
struct ecs_term_t ecs_term_t
A term is a single element in a query.
Definition flecs.h:448
ecs_id_t id_t
ID type.
Definition c_types.hpp:20
ecs_flags64_t flags64_t
64-bit flags type.
Definition c_types.hpp:36
oper_kind_t
Operator kind.
Definition c_types.hpp:49
ecs_entity_t entity_t
Entity type.
Definition c_types.hpp:21
ecs_flags32_t flags32_t
32-bit flags type.
Definition c_types.hpp:35
ecs_world_t world_t
World type.
Definition c_types.hpp:18
inout_kind_t
Inout kind.
Definition c_types.hpp:39
@ NotFrom
NotFrom operator.
Definition c_types.hpp:56
@ OrFrom
OrFrom operator.
Definition c_types.hpp:55
@ AndFrom
AndFrom operator.
Definition c_types.hpp:54
@ And
And operator.
Definition c_types.hpp:50
@ Optional
Optional operator.
Definition c_types.hpp:53
@ Or
Or operator.
Definition c_types.hpp:51
@ Not
Not operator.
Definition c_types.hpp:52
@ In
In.
Definition c_types.hpp:44
@ Out
Out.
Definition c_types.hpp:45
@ InOut
InOut.
Definition c_types.hpp:43
@ InOutNone
InOutNone.
Definition c_types.hpp:41
struct ecs_term_ref_t ecs_term_ref_t
Type that describes a reference to an entity or variable in a term.
@ EcsInOutFilter
Same as InOutNone + prevents term from triggering observers.
Definition flecs.h:729
@ EcsNot
The term must not match.
Definition flecs.h:739
Compile-time utilities for deriving query attributes from a parameter pack.
Type that describes a reference to an entity or variable in a term.
Definition flecs.h:819
const char * name
Name.
Definition flecs.h:826
ecs_entity_t id
Entity ID.
Definition flecs.h:820
Type that describes a term (single element in a query).
Definition flecs.h:834
ecs_term_ref_t src
Source of term.
Definition flecs.h:840
ecs_id_t id
Component ID to be matched by term.
Definition flecs.h:835
int16_t oper
Operator of term.
Definition flecs.h:849
ecs_term_ref_t second
Second element of pair.
Definition flecs.h:842
ecs_entity_t trav
Relationship to traverse when looking for the component.
Definition flecs.h:844
int16_t inout
Access to contents matched by term.
Definition flecs.h:848
ecs_term_ref_t first
Component or first element of pair.
Definition flecs.h:841
Base & filter()
Mark the term as a filter.
Base & inout(flecs::inout_kind_t inout)
Set read/write access of the term.
Base & or_from()
Short for oper(flecs::OrFrom).
void set_term(ecs_term_t *term)
Set the current term pointer.
Base & cascade(flecs::entity_t trav=0)
The cascade flag is like up(), but returns results in breadth-first order.
Base & oper(flecs::oper_kind_t oper)
Set the operator of the term.
Base & read_write()
Short for inout_stage(flecs::InOut).
Base & term(id_t id)
Set the term ID.
Base & parent()
Same as up().
Base & inout()
Short for inout(flecs::InOut).
Base & desc()
Use with cascade() to iterate results in descending (bottom-to-top) order.
Base & in()
Short for inout(flecs::In).
Base & inout_stage(flecs::inout_kind_t inout)
Set read/write access for a stage.
Base & trav(flecs::entity_t trav, flecs::flags32_t flags=0)
Specify the relationship to traverse, and flags to indicate direction.
Base & or_()
Short for oper(flecs::Or).
Base & and_from()
Short for oper(flecs::AndFrom).
Base & out()
Short for inout(flecs::Out).
Base & up()
Traverse upwards using the specified relationship type.
Base & and_()
Short for oper(flecs::And).
ecs_term_t * term_
Pointer to the current term.
Base & optional()
Short for oper(flecs::Optional).
Base & cascade()
Cascade using the specified relationship type.
Base & read()
Short for inout_stage(flecs::In).
term_builder_i(ecs_term_t *term_ptr)
Construct from a term pointer.
Base & up(flecs::entity_t trav=0)
The up flag indicates that the term identifier may be substituted by traversing a relationship upward...
Base & inout_none()
Short for inout(flecs::InOutNone).
term_builder_i()
Default constructor.
Base & id_flags(id_t flags)
Set ID flags for the term.
Base & not_from()
Short for oper(flecs::NotFrom).
Base & not_()
Short for oper(flecs::Not).
Base & write()
Short for inout_stage(flecs::Out).
Base & name(const char *name)
Specify the value of the identifier by name.
Definition builder_i.hpp:58
Base & id(flecs::entity_t id)
Specify the value of the identifier by ID.
Definition builder_i.hpp:37
ecs_term_ref_t * term_ref_
Pointer to the current term reference.
Definition builder_i.hpp:81
virtual ~term_ref_builder_i()
Destructor.
Definition builder_i.hpp:27
Base & entity(flecs::entity_t entity)
Specify the value of the identifier by ID.
Definition builder_i.hpp:51
Base & var(const char *var_name)
Specify that the identifier is a variable (resolved at query evaluation time).
Definition builder_i.hpp:66
Base & self()
The self flag indicates that the term identifier itself is used.
Definition builder_i.hpp:30
Base & flags(flecs::flags64_t flags)
Override the term ID flags.
Definition builder_i.hpp:74
term_ref_builder_i()
Default constructor.
Definition builder_i.hpp:24