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

| Flecs v4.1 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 "../../utils/signature.hpp"
9#include <stdio.h>
10
11namespace flecs
12{
13
21template<typename Base>
22 struct term_ref_builder_i {
23 term_ref_builder_i() : term_ref_(nullptr) { }
24
25 virtual ~term_ref_builder_i() { }
26
27 /* The self flag indicates the term identifier itself is used */
28 Base& self() {
29 this->assert_term_ref();
30 term_ref_->id |= flecs::Self;
31 return *this;
32 }
33
34 /* Specify value of identifier by id */
35 Base& id(flecs::entity_t id) {
36 this->assert_term_ref();
37 term_ref_->id = id;
38 return *this;
39 }
40
41 /* Specify value of identifier by id. Almost the same as id(entity), but this
42 * operation explicitly sets the flecs::IsEntity flag. This forces the id to
43 * be interpreted as entity, whereas not setting the flag would implicitly
44 * convert ids for builtin variables such as flecs::This to a variable.
45 *
46 * This function can also be used to disambiguate id(0), which would match
47 * both id(entity_t) and id(const char*).
48 */
49 Base& entity(flecs::entity_t entity) {
50 this->assert_term_ref();
51 term_ref_->id = entity | flecs::IsEntity;
52 return *this;
53 }
54
55 /* Specify value of identifier by name */
56 Base& name(const char *name) {
57 this->assert_term_ref();
58 term_ref_->id |= flecs::IsEntity;
59 term_ref_->name = const_cast<char*>(name);
60 return *this;
61 }
62
63 /* Specify identifier is a variable (resolved at query evaluation time) */
64 Base& var(const char *var_name) {
65 this->assert_term_ref();
66 term_ref_->id |= flecs::IsVariable;
67 term_ref_->name = const_cast<char*>(var_name);
68 return *this;
69 }
70
71 /* Override term id flags */
72 Base& flags(flecs::flags64_t flags) {
73 this->assert_term_ref();
74 term_ref_->id = flags;
75 return *this;
76 }
77
78 ecs_term_ref_t *term_ref_;
79
80protected:
81 virtual flecs::world_t* world_v() = 0;
82
83 void assert_term_ref() {
84 ecs_assert(term_ref_ != NULL, ECS_INVALID_PARAMETER,
85 "no active term (call .with() first)");
86 }
87
88private:
89 operator Base&() {
90 return *static_cast<Base*>(this);
91 }
92};
93
99template<typename Base>
100 struct term_builder_i : term_ref_builder_i<Base> {
101 term_builder_i() : term_(nullptr) { }
102
103 term_builder_i(ecs_term_t *term_ptr) {
104 set_term(term_ptr);
105 }
106
107 Base& term(id_t id) {
108 return this->id(id);
109 }
110
111 /* Call prior to setting values for src identifier */
112 Base& src() {
113 this->assert_term();
114 this->term_ref_ = &term_->src;
115 return *this;
116 }
117
118 /* Call prior to setting values for first identifier. This is either the
119 * component identifier, or first element of a pair (in case second is
120 * populated as well). */
121 Base& first() {
122 this->assert_term();
123 this->term_ref_ = &term_->first;
124 return *this;
125 }
126
127 /* Call prior to setting values for second identifier. This is the second
128 * element of a pair. Requires that first() is populated as well. */
129 Base& second() {
130 this->assert_term();
131 this->term_ref_ = &term_->second;
132 return *this;
133 }
134
135 /* Select src identifier, initialize it with entity id */
136 Base& src(flecs::entity_t id) {
137 this->src();
138 this->id(id);
139 return *this;
140 }
141
142 /* Select src identifier, initialize it with id associated with type */
143 template<typename T>
144 Base& src() {
145 this->src(_::type<T>::id(this->world_v()));
146 return *this;
147 }
148
149 /* Select src identifier, initialize it with name. If name starts with a $
150 * the name is interpreted as a variable. */
151 Base& src(const char *name) {
152 ecs_assert(name != NULL, ECS_INVALID_PARAMETER, NULL);
153 this->src();
154 if (name[0] == '$') {
155 this->var(&name[1]);
156 } else {
157 this->name(name);
158 }
159 return *this;
160 }
161
162 /* Select first identifier, initialize it with entity id */
163 Base& first(flecs::entity_t id) {
164 this->first();
165 this->id(id);
166 return *this;
167 }
168
169 /* Select first identifier, initialize it with id associated with type */
170 template<typename T>
171 Base& first() {
172 this->first(_::type<T>::id(this->world_v()));
173 return *this;
174 }
175
176 /* Select first identifier, initialize it with name. If name starts with a $
177 * the name is interpreted as a variable. */
178 Base& first(const char *name) {
179 ecs_assert(name != NULL, ECS_INVALID_PARAMETER, NULL);
180 this->first();
181 if (name[0] == '$') {
182 this->var(&name[1]);
183 } else {
184 this->name(name);
185 }
186 return *this;
187 }
188
189 /* Select second identifier, initialize it with entity id */
190 Base& second(flecs::entity_t id) {
191 this->second();
192 this->id(id);
193 return *this;
194 }
195
196 /* Select second identifier, initialize it with id associated with type */
197 template<typename T>
198 Base& second() {
199 this->second(_::type<T>::id(this->world_v()));
200 return *this;
201 }
202
203 /* Select second identifier, initialize it with name. If name starts with a $
204 * the name is interpreted as a variable. */
205 Base& second(const char *name) {
206 ecs_assert(name != NULL, ECS_INVALID_PARAMETER, NULL);
207 this->second();
208 if (name[0] == '$') {
209 this->var(&name[1]);
210 } else {
211 this->name(name);
212 }
213 return *this;
214 }
215
216 /* The up flag indicates that the term identifier may be substituted by
217 * traversing a relationship upwards. For example: substitute the identifier
218 * with its parent by traversing the ChildOf relationship. */
219 Base& up(flecs::entity_t trav = 0) {
220 this->assert_term_ref();
221 ecs_check(this->term_ref_ != &term_->first, ECS_INVALID_PARAMETER,
222 "up traversal can only be applied to term source");
223 ecs_check(this->term_ref_ != &term_->second, ECS_INVALID_PARAMETER,
224 "up traversal can only be applied to term source");
225 this->term_ref_->id |= flecs::Up;
226 if (trav) {
227 term_->trav = trav;
228 }
229 error:
230 return *this;
231 }
232
233 template <typename Trav>
234 Base& up() {
235 return this->up(_::type<Trav>::id(this->world_v()));
236 }
237
238 /* The cascade flag is like up, but returns results in breadth-first order.
239 * Only supported for flecs::query */
240 Base& cascade(flecs::entity_t trav = 0) {
241 this->assert_term_ref();
242 this->up();
243 this->term_ref_->id |= flecs::Cascade;
244 if (trav) {
245 term_->trav = trav;
246 }
247 return *this;
248 }
249
250 template <typename Trav>
251 Base& cascade() {
252 return this->cascade(_::type<Trav>::id(this->world_v()));
253 }
254
255 /* Use with cascade to iterate results in descending (bottom -> top) order */
256 Base& desc() {
257 this->assert_term_ref();
258 this->term_ref_->id |= flecs::Desc;
259 return *this;
260 }
261
262 /* Same as up(), exists for backwards compatibility */
263 Base& parent() {
264 return this->up();
265 }
266
267 /* Specify relationship to traverse, and flags to indicate direction */
268 Base& trav(flecs::entity_t trav, flecs::flags32_t flags = 0) {
269 this->assert_term_ref();
270 term_->trav = trav;
271 this->term_ref_->id |= flags;
272 return *this;
273 }
274
276 Base& id_flags(id_t flags) {
277 this->assert_term();
278 term_->id |= flags;
279 return *this;
280 }
281
283 Base& inout(flecs::inout_kind_t inout) {
284 this->assert_term();
285 term_->inout = static_cast<int16_t>(inout);
286 return *this;
287 }
288
297 Base& inout_stage(flecs::inout_kind_t inout) {
298 this->assert_term();
299 term_->inout = static_cast<int16_t>(inout);
300 if (term_->oper != EcsNot) {
301 this->src().entity(0);
302 }
303 return *this;
304 }
305
309 Base& write() {
310 return this->inout_stage(flecs::Out);
311 }
312
316 Base& read() {
317 return this->inout_stage(flecs::In);
318 }
319
323 Base& read_write() {
324 return this->inout_stage(flecs::InOut);
325 }
326
328 Base& in() {
329 return this->inout(flecs::In);
330 }
331
333 Base& out() {
334 return this->inout(flecs::Out);
335 }
336
338 Base& inout() {
339 return this->inout(flecs::InOut);
340 }
341
343 Base& inout_none() {
344 return this->inout(flecs::InOutNone);
345 }
346
348 Base& oper(flecs::oper_kind_t oper) {
349 this->assert_term();
350 term_->oper = static_cast<int16_t>(oper);
351 return *this;
352 }
353
354 /* Short for oper(flecs::And) */
355 Base& and_() {
356 return this->oper(flecs::And);
357 }
358
359 /* Short for oper(flecs::Or) */
360 Base& or_() {
361 return this->oper(flecs::Or);
362 }
363
364 /* Short for oper(flecs::Or) */
365 Base& not_() {
366 return this->oper(flecs::Not);
367 }
368
369 /* Short for oper(flecs::Or) */
370 Base& optional() {
371 return this->oper(flecs::Optional);
372 }
373
374 /* Short for oper(flecs::AndFrom) */
375 Base& and_from() {
376 return this->oper(flecs::AndFrom);
377 }
378
379 /* Short for oper(flecs::OrFrom) */
380 Base& or_from() {
381 return this->oper(flecs::OrFrom);
382 }
383
384 /* Short for oper(flecs::NotFrom) */
385 Base& not_from() {
386 return this->oper(flecs::NotFrom);
387 }
388
389 /* Query terms are not triggered on by observers */
390 Base& filter() {
391 term_->inout = EcsInOutFilter;
392 return *this;
393 }
394
395 ecs_term_t *term_;
396
397protected:
398 virtual flecs::world_t* world_v() override = 0;
399
400 void set_term(ecs_term_t *term) {
401 term_ = term;
402 if (term) {
403 this->term_ref_ = &term_->src; // default to subject
404 } else {
405 this->term_ref_ = nullptr;
406 }
407 }
408
409private:
410 void assert_term() {
411 ecs_assert(term_ != NULL, ECS_INVALID_PARAMETER,
412 "no active term (call .with() first)");
413 }
414
415 operator Base&() {
416 return *static_cast<Base*>(this);
417 }
418};
419
420}
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_term_t
struct ecs_term_t ecs_term_t
A term is a single element in a query.
Definition flecs.h:414
EcsInOutFilter
@ EcsInOutFilter
Same as InOutNone + prevents term from triggering observers.
Definition flecs.h:686
EcsNot
@ EcsNot
The term must not match.
Definition flecs.h:696
signature.hpp
Compile time utilities for deriving query attributes from param pack.
ecs_term_ref_t
Type that describes a reference to an entity or variable in a term.
Definition flecs.h:774
ecs_term_t
Type that describes a term (single element in a query).
Definition flecs.h:789
flecs::_::type
Definition flecs.hpp:39
flecs::term_builder_i::inout
Base & inout(flecs::inout_kind_t inout)
Set read/write access of term.
Definition builder_i.hpp:283
flecs::term_builder_i::oper
Base & oper(flecs::oper_kind_t oper)
Set operator of term.
Definition builder_i.hpp:348
flecs::term_builder_i::read_write
Base & read_write()
Short for inout_stage(flecs::InOut).
Definition builder_i.hpp:323
flecs::term_builder_i::inout
Base & inout()
Short for inout(flecs::InOut).
Definition builder_i.hpp:338
flecs::term_builder_i::in
Base & in()
Short for inout(flecs::In).
Definition builder_i.hpp:328
flecs::term_builder_i::inout_stage
Base & inout_stage(flecs::inout_kind_t inout)
Set read/write access for stage.
Definition builder_i.hpp:297
flecs::term_builder_i::out
Base & out()
Short for inout(flecs::Out).
Definition builder_i.hpp:333
flecs::term_builder_i::read
Base & read()
Short for inout_stage(flecs::In).
Definition builder_i.hpp:316
flecs::term_builder_i::inout_none
Base & inout_none()
Short for inout(flecs::In).
Definition builder_i.hpp:343
flecs::term_builder_i::id_flags
Base & id_flags(id_t flags)
Set id flags for term.
Definition builder_i.hpp:276
flecs::term_builder_i::write
Base & write()
Short for inout_stage(flecs::Out).
Definition builder_i.hpp:309