Flecs v3.2
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
20template<typename Base>
22 term_id_builder_i() : m_term_id(nullptr) { }
23
24 virtual ~term_id_builder_i() { }
25
26 /* The self flag indicates the term identifier itself is used */
27 Base& self() {
28 this->assert_term_id();
29 m_term_id->flags |= flecs::Self;
30 return *this;
31 }
32
33 /* The up flag indicates that the term identifier may be substituted by
34 * traversing a relationship upwards. For example: substitute the identifier
35 * with its parent by traversing the ChildOf relationship. */
36 Base& up(flecs::entity_t trav = 0) {
37 this->assert_term_id();
38 m_term_id->flags |= flecs::Up;
39 if (trav) {
40 m_term_id->trav = trav;
41 }
42 return *this;
43 }
44
45 template <typename Trav>
46 Base& up() {
47 return this->up(_::cpp_type<Trav>::id(this->world_v()));
48 }
49
50 /* The cascade flag is like up, but returns results in breadth-first order.
51 * Only supported for flecs::query */
52 Base& cascade(flecs::entity_t trav = 0) {
53 this->assert_term_id();
54 m_term_id->flags |= flecs::Cascade;
55 if (trav) {
56 m_term_id->trav = trav;
57 }
58 return *this;
59 }
60
61 template <typename Trav>
62 Base& cascade() {
63 return this->cascade(_::cpp_type<Trav>::id(this->world_v()));
64 }
65
66 /* Use with cascade to iterate results in descending (bottom -> top) order */
67 Base& desc() {
68 this->assert_term_id();
69 m_term_id->flags |= flecs::Desc;
70 return *this;
71 }
72
73 /* The parent flag is short for up(flecs::ChildOf) */
74 Base& parent() {
75 this->assert_term_id();
76 m_term_id->flags |= flecs::Parent;
77 return *this;
78 }
79
80 /* Specify relationship to traverse, and flags to indicate direction */
81 Base& trav(flecs::entity_t trav, flecs::flags32_t flags = 0) {
82 this->assert_term_id();
83 m_term_id->trav = trav;
84 m_term_id->flags |= flags;
85 return *this;
86 }
87
88 /* Specify value of identifier by id */
89 Base& id(flecs::entity_t id) {
90 this->assert_term_id();
91 m_term_id->id = id;
92 return *this;
93 }
94
95 /* Specify value of identifier by id. Almost the same as id(entity), but this
96 * operation explicitly sets the flecs::IsEntity flag. This forces the id to
97 * be interpreted as entity, whereas not setting the flag would implicitly
98 * convert ids for builtin variables such as flecs::This to a variable.
99 *
100 * This function can also be used to disambiguate id(0), which would match
101 * both id(entity_t) and id(const char*).
102 */
103 Base& entity(flecs::entity_t entity) {
104 this->assert_term_id();
105 m_term_id->flags = flecs::IsEntity;
106 m_term_id->id = entity;
107 return *this;
108 }
109
110 /* Specify value of identifier by name */
111 Base& name(const char *name) {
112 this->assert_term_id();
113 m_term_id->flags |= flecs::IsEntity;
114 m_term_id->name = const_cast<char*>(name);
115 return *this;
116 }
117
118 /* Specify identifier is a variable (resolved at query evaluation time) */
119 Base& var(const char *var_name) {
120 this->assert_term_id();
121 m_term_id->flags |= flecs::IsVariable;
122 m_term_id->name = const_cast<char*>(var_name);
123 return *this;
124 }
125
126 /* Override term id flags */
127 Base& flags(flecs::flags32_t flags) {
128 this->assert_term_id();
129 m_term_id->flags = flags;
130 return *this;
131 }
132
133 ecs_term_id_t *m_term_id;
134
135protected:
136 virtual flecs::world_t* world_v() = 0;
137
138private:
139 void assert_term_id() {
140 ecs_assert(m_term_id != NULL, ECS_INVALID_PARAMETER,
141 "no active term (call .term() first)");
142 }
143
144 operator Base&() {
145 return *static_cast<Base*>(this);
146 }
147};
148
154template<typename Base>
156 term_builder_i() : m_term(nullptr) { }
157
158 term_builder_i(ecs_term_t *term_ptr) {
159 set_term(term_ptr);
160 }
161
162 Base& term(id_t id) {
163 return this->id(id);
164 }
165
166 /* Call prior to setting values for src identifier */
167 Base& src() {
168 this->assert_term();
169 this->m_term_id = &m_term->src;
170 return *this;
171 }
172
173 /* Call prior to setting values for first identifier. This is either the
174 * component identifier, or first element of a pair (in case second is
175 * populated as well). */
176 Base& first() {
177 this->assert_term();
178 this->m_term_id = &m_term->first;
179 return *this;
180 }
181
182 /* Call prior to setting values for second identifier. This is the second
183 * element of a pair. Requires that first() is populated as well. */
184 Base& second() {
185 this->assert_term();
186 this->m_term_id = &m_term->second;
187 return *this;
188 }
189
190 /* Select src identifier, initialize it with entity id */
191 Base& src(flecs::entity_t id) {
192 this->src();
193 this->id(id);
194 return *this;
195 }
196
197 /* Select src identifier, initialize it with id associated with type */
198 template<typename T>
199 Base& src() {
200 this->src(_::cpp_type<T>::id(this->world_v()));
201 return *this;
202 }
203
204 /* Select src identifier, initialize it with name. If name starts with a $
205 * the name is interpreted as a variable. */
206 Base& src(const char *name) {
207 ecs_assert(name != NULL, ECS_INVALID_PARAMETER, NULL);
208 this->src();
209 if (name[0] == '$') {
210 this->var(&name[1]);
211 } else {
212 this->name(name);
213 }
214 return *this;
215 }
216
217 /* Select first identifier, initialize it with entity id */
218 Base& first(flecs::entity_t id) {
219 this->first();
220 this->id(id);
221 return *this;
222 }
223
224 /* Select first identifier, initialize it with id associated with type */
225 template<typename T>
226 Base& first() {
227 this->first(_::cpp_type<T>::id(this->world_v()));
228 return *this;
229 }
230
231 /* Select first identifier, initialize it with name. If name starts with a $
232 * the name is interpreted as a variable. */
233 Base& first(const char *name) {
234 ecs_assert(name != NULL, ECS_INVALID_PARAMETER, NULL);
235 this->first();
236 if (name[0] == '$') {
237 this->var(&name[1]);
238 } else {
239 this->name(name);
240 }
241 return *this;
242 }
243
244 /* Select second identifier, initialize it with entity id */
245 Base& second(flecs::entity_t id) {
246 this->second();
247 this->id(id);
248 return *this;
249 }
250
251 /* Select second identifier, initialize it with id associated with type */
252 template<typename T>
253 Base& second() {
254 this->second(_::cpp_type<T>::id(this->world_v()));
255 return *this;
256 }
257
258 /* Select second identifier, initialize it with name. If name starts with a $
259 * the name is interpreted as a variable. */
260 Base& second(const char *name) {
261 ecs_assert(name != NULL, ECS_INVALID_PARAMETER, NULL);
262 this->second();
263 if (name[0] == '$') {
264 this->var(&name[1]);
265 } else {
266 this->name(name);
267 }
268 return *this;
269 }
270
272 Base& role(id_t role) {
273 this->assert_term();
274 m_term->id_flags = role;
275 return *this;
276 }
277
279 Base& inout(flecs::inout_kind_t inout) {
280 this->assert_term();
281 m_term->inout = static_cast<ecs_inout_kind_t>(inout);
282 return *this;
283 }
284
293 Base& inout_stage(flecs::inout_kind_t inout) {
294 this->assert_term();
295 m_term->inout = static_cast<ecs_inout_kind_t>(inout);
296 if (m_term->oper != EcsNot) {
297 this->src().entity(0);
298 }
299 return *this;
300 }
301
305 Base& write() {
306 return this->inout_stage(flecs::Out);
307 }
308
312 Base& read() {
313 return this->inout_stage(flecs::In);
314 }
315
319 Base& read_write() {
320 return this->inout_stage(flecs::InOut);
321 }
322
324 Base& in() {
325 return this->inout(flecs::In);
326 }
327
329 Base& out() {
330 return this->inout(flecs::Out);
331 }
332
334 Base& inout() {
335 return this->inout(flecs::InOut);
336 }
337
339 Base& inout_none() {
340 return this->inout(flecs::InOutNone);
341 }
342
344 Base& oper(flecs::oper_kind_t oper) {
345 this->assert_term();
346 m_term->oper = static_cast<ecs_oper_kind_t>(oper);
347 return *this;
348 }
349
350 /* Short for oper(flecs::And) */
351 Base& and_() {
352 return this->oper(flecs::And);
353 }
354
355 /* Short for oper(flecs::Or) */
356 Base& or_() {
357 return this->oper(flecs::Or);
358 }
359
360 /* Short for oper(flecs::Or) */
361 Base& not_() {
362 return this->oper(flecs::Not);
363 }
364
365 /* Short for oper(flecs::Or) */
366 Base& optional() {
367 return this->oper(flecs::Optional);
368 }
369
370 /* Short for oper(flecs::AndFrom) */
371 Base& and_from() {
372 return this->oper(flecs::AndFrom);
373 }
374
375 /* Short for oper(flecs::OrFrom) */
376 Base& or_from() {
377 return this->oper(flecs::OrFrom);
378 }
379
380 /* Short for oper(flecs::NotFrom) */
381 Base& not_from() {
382 return this->oper(flecs::NotFrom);
383 }
384
386 Base& singleton() {
387 this->assert_term();
388 ecs_assert(m_term->id || m_term->first.id, ECS_INVALID_PARAMETER,
389 "no component specified for singleton");
390
391 flecs::id_t sid = m_term->id;
392 if (!sid) {
393 sid = m_term->first.id;
394 }
395
396 ecs_assert(sid != 0, ECS_INVALID_PARAMETER, NULL);
397
398 if (!ECS_IS_PAIR(sid)) {
399 m_term->src.id = sid;
400 } else {
401 m_term->src.id = ecs_pair_first(world(), sid);
402 }
403 return *this;
404 }
405
406 /* Filter terms are not triggered on by observers */
407 Base& filter() {
408 m_term->src.flags |= flecs::Filter;
409 return *this;
410 }
411
412 ecs_term_t *m_term;
413
414protected:
415 virtual flecs::world_t* world_v() = 0;
416
417 void set_term(ecs_term_t *term) {
418 m_term = term;
419 if (term) {
420 this->m_term_id = &m_term->src; // default to subject
421 } else {
422 this->m_term_id = nullptr;
423 }
424 }
425
426private:
427 void assert_term() {
428 ecs_assert(m_term != NULL, ECS_INVALID_PARAMETER,
429 "no active term (call .term() first)");
430 }
431
432 operator Base&() {
433 return *static_cast<Base*>(this);
434 }
435};
436
437}
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:351
ecs_inout_kind_t
Specify read/write access for term.
Definition flecs.h:687
ecs_oper_kind_t
Specify operator for term.
Definition flecs.h:696
@ EcsNot
The term must not match.
Definition flecs.h:699
Compile time utilities for deriving query attributes from param pack.
Type that describes a single identifier in a term.
Definition flecs.h:737
ecs_flags32_t flags
Term flags.
Definition flecs.h:754
ecs_entity_t trav
Relationship to traverse when looking for the component.
Definition flecs.h:750
const char * name
Name.
Definition flecs.h:744
ecs_entity_t id
Entity id.
Definition flecs.h:738
Type that describes a term (single element in a query)
Definition flecs.h:758
ecs_term_id_t second
Second element of pair.
Definition flecs.h:766
ecs_id_t id
Component id to be matched by term.
Definition flecs.h:759
ecs_term_id_t src
Source of term.
Definition flecs.h:764
ecs_term_id_t first
Component or first element of pair.
Definition flecs.h:765
ecs_id_t id_flags
Id flags of term id.
Definition flecs.h:771
ecs_inout_kind_t inout
Access to contents matched by term.
Definition flecs.h:768
ecs_oper_kind_t oper
Operator of term.
Definition flecs.h:769
Entity.
Definition entity.hpp:30
Class that wraps around a flecs::id_t.
Definition decl.hpp:27
Term builder interface.
Base & inout(flecs::inout_kind_t inout)
Set read/write access of term.
Base & singleton()
Match singleton.
Base & oper(flecs::oper_kind_t oper)
Set operator of term.
Base & read_write()
Short for inout_stage(flecs::InOut).
Base & inout()
Short for inout(flecs::InOut)
Base & in()
Short for inout(flecs::In)
Base & inout_stage(flecs::inout_kind_t inout)
Set read/write access for stage.
Base & out()
Short for inout(flecs::Out)
Base & read()
Short for inout_stage(flecs::In).
Base & inout_none()
Short for inout(flecs::In)
Base & write()
Short for inout_stage(flecs::Out).
Base & role(id_t role)
Set role of term.
Term identifier builder.
Definition builder_i.hpp:21
Class that describes a term.
Definition impl.hpp:16
The world.
Definition world.hpp:132