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
8#include "../../utils/signature.hpp"
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 /* The parent flag is short for up(flecs::ChildOf) */
67 Base& parent() {
68 this->assert_term_id();
69 m_term_id->flags |= flecs::Parent;
70 return *this;
71 }
72
73 /* Specify relationship to traverse, and flags to indicate direction */
74 Base& trav(flecs::entity_t trav, flecs::flags32_t flags = 0) {
75 this->assert_term_id();
76 m_term_id->trav = trav;
77 m_term_id->flags |= flags;
78 return *this;
79 }
80
81 /* Specify value of identifier by id */
82 Base& id(flecs::entity_t id) {
83 this->assert_term_id();
84 m_term_id->id = id;
85 return *this;
86 }
87
88 /* Specify value of identifier by id. Amost the same as id(entity), but this
89 * operation explicitly sets the flecs::IsEntity flag. This forces the id to
90 * be interpreted as entity, whereas not setting the flag would implicitly
91 * convert ids for builtin variables such as flecs::This to a variable.
92 *
93 * This function can also be used to disambiguate id(0), which would match
94 * both id(entity_t) and id(const char*).
95 */
96 Base& entity(flecs::entity_t entity) {
97 this->assert_term_id();
98 m_term_id->flags = flecs::IsEntity;
99 m_term_id->id = entity;
100 return *this;
101 }
102
103 /* Specify value of identifier by name */
104 Base& name(const char *name) {
105 this->assert_term_id();
106 m_term_id->flags |= flecs::IsEntity;
107 m_term_id->name = const_cast<char*>(name);
108 return *this;
109 }
110
111 /* Specify identifier is a variable (resolved at query evaluation time) */
112 Base& var(const char *var_name) {
113 this->assert_term_id();
114 m_term_id->flags |= flecs::IsVariable;
115 m_term_id->name = const_cast<char*>(var_name);
116 return *this;
117 }
118
119 /* Override term id flags */
120 Base& flags(flecs::flags32_t flags) {
121 this->assert_term_id();
122 m_term_id->flags = flags;
123 return *this;
124 }
125
126 ecs_term_id_t *m_term_id;
127
128protected:
129 virtual flecs::world_t* world_v() = 0;
130
131private:
132 void assert_term_id() {
133 ecs_assert(m_term_id != NULL, ECS_INVALID_PARAMETER,
134 "no active term (call .term() first)");
135 }
136
137 operator Base&() {
138 return *static_cast<Base*>(this);
139 }
140};
141
147template<typename Base>
149 term_builder_i() : m_term(nullptr) { }
150
151 term_builder_i(ecs_term_t *term_ptr) {
152 set_term(term_ptr);
153 }
154
155 Base& term(id_t id) {
156 return this->id(id);
157 }
158
159 /* Call prior to setting values for src identifier */
160 Base& src() {
161 this->assert_term();
162 this->m_term_id = &m_term->src;
163 return *this;
164 }
165
166 /* Call prior to setting values for first identifier. This is either the
167 * component identifier, or first element of a pair (in case second is
168 * populated as well). */
169 Base& first() {
170 this->assert_term();
171 this->m_term_id = &m_term->first;
172 return *this;
173 }
174
175 /* Call prior to setting values for second identifier. This is the second
176 * element of a pair. Requires that first() is populated as well. */
177 Base& second() {
178 this->assert_term();
179 this->m_term_id = &m_term->second;
180 return *this;
181 }
182
183 /* Select src identifier, initialize it with entity id */
184 Base& src(flecs::entity_t id) {
185 this->src();
186 this->id(id);
187 return *this;
188 }
189
190 /* Select src identifier, initialize it with id associated with type */
191 template<typename T>
192 Base& src() {
193 this->src(_::cpp_type<T>::id(this->world_v()));
194 return *this;
195 }
196
197 /* Select src identifier, initialize it with name. If name starts with a $
198 * the name is interpreted as a variable. */
199 Base& src(const char *name) {
200 ecs_assert(name != NULL, ECS_INVALID_PARAMETER, NULL);
201 this->src();
202 if (name[0] == '$') {
203 this->var(&name[1]);
204 } else {
205 this->name(name);
206 }
207 return *this;
208 }
209
210 /* Select first identifier, initialize it with entity id */
211 Base& first(flecs::entity_t id) {
212 this->first();
213 this->id(id);
214 return *this;
215 }
216
217 /* Select first identifier, initialize it with id associated with type */
218 template<typename T>
219 Base& first() {
220 this->first(_::cpp_type<T>::id(this->world_v()));
221 return *this;
222 }
223
224 /* Select first identifier, initialize it with name. If name starts with a $
225 * the name is interpreted as a variable. */
226 Base& first(const char *name) {
227 ecs_assert(name != NULL, ECS_INVALID_PARAMETER, NULL);
228 this->first();
229 if (name[0] == '$') {
230 this->var(&name[1]);
231 } else {
232 this->name(name);
233 }
234 return *this;
235 }
236
237 /* Select second identifier, initialize it with entity id */
238 Base& second(flecs::entity_t id) {
239 this->second();
240 this->id(id);
241 return *this;
242 }
243
244 /* Select second identifier, initialize it with id associated with type */
245 template<typename T>
246 Base& second() {
247 this->second(_::cpp_type<T>::id(this->world_v()));
248 return *this;
249 }
250
251 /* Select second identifier, initialize it with name. If name starts with a $
252 * the name is interpreted as a variable. */
253 Base& second(const char *name) {
254 ecs_assert(name != NULL, ECS_INVALID_PARAMETER, NULL);
255 this->second();
256 if (name[0] == '$') {
257 this->var(&name[1]);
258 } else {
259 this->name(name);
260 }
261 return *this;
262 }
263
265 Base& role(id_t role) {
266 this->assert_term();
267 m_term->id_flags = role;
268 return *this;
269 }
270
272 Base& inout(flecs::inout_kind_t inout) {
273 this->assert_term();
274 m_term->inout = static_cast<ecs_inout_kind_t>(inout);
275 return *this;
276 }
277
286 Base& inout_stage(flecs::inout_kind_t inout) {
287 this->assert_term();
288 m_term->inout = static_cast<ecs_inout_kind_t>(inout);
289 if (m_term->oper != EcsNot) {
290 this->src().entity(0);
291 }
292 return *this;
293 }
294
298 Base& write() {
299 return this->inout_stage(flecs::Out);
300 }
301
305 Base& read() {
306 return this->inout_stage(flecs::In);
307 }
308
312 Base& read_write() {
313 return this->inout_stage(flecs::InOut);
314 }
315
317 Base& in() {
318 return this->inout(flecs::In);
319 }
320
322 Base& out() {
323 return this->inout(flecs::Out);
324 }
325
327 Base& inout() {
328 return this->inout(flecs::InOut);
329 }
330
332 Base& inout_none() {
333 return this->inout(flecs::InOutNone);
334 }
335
337 Base& oper(flecs::oper_kind_t oper) {
338 this->assert_term();
339 m_term->oper = static_cast<ecs_oper_kind_t>(oper);
340 return *this;
341 }
342
343 /* Short for oper(flecs::And) */
344 Base& and_() {
345 return this->oper(flecs::And);
346 }
347
348 /* Short for oper(flecs::Or) */
349 Base& or_() {
350 return this->oper(flecs::Or);
351 }
352
353 /* Short for oper(flecs::Or) */
354 Base& not_() {
355 return this->oper(flecs::Not);
356 }
357
358 /* Short for oper(flecs::Or) */
359 Base& optional() {
360 return this->oper(flecs::Optional);
361 }
362
363 /* Short for oper(flecs::AndFrom) */
364 Base& and_from() {
365 return this->oper(flecs::AndFrom);
366 }
367
368 /* Short for oper(flecs::OrFrom) */
369 Base& or_from() {
370 return this->oper(flecs::OrFrom);
371 }
372
373 /* Short for oper(flecs::NotFrom) */
374 Base& not_from() {
375 return this->oper(flecs::NotFrom);
376 }
377
379 Base& singleton() {
380 this->assert_term();
381 ecs_assert(m_term->id || m_term->first.id, ECS_INVALID_PARAMETER,
382 "no component specified for singleton");
383
384 flecs::id_t sid = m_term->id;
385 if (!sid) {
386 sid = m_term->first.id;
387 }
388
389 ecs_assert(sid != 0, ECS_INVALID_PARAMETER, NULL);
390
391 if (!ECS_IS_PAIR(sid)) {
392 m_term->src.id = sid;
393 } else {
394 m_term->src.id = ecs_pair_first(world(), sid);
395 }
396 return *this;
397 }
398
399 /* Filter terms are not triggered on by observers */
400 Base& filter() {
401 m_term->src.flags |= flecs::Filter;
402 return *this;
403 }
404
405 ecs_term_t *m_term;
406
407protected:
408 virtual flecs::world_t* world_v() = 0;
409
410 void set_term(ecs_term_t *term) {
411 m_term = term;
412 if (term) {
413 this->m_term_id = &m_term->src; // default to subject
414 } else {
415 this->m_term_id = nullptr;
416 }
417 }
418
419private:
420 void assert_term() {
421 ecs_assert(m_term != NULL, ECS_INVALID_PARAMETER,
422 "no active term (call .term() first)");
423 }
424
425 operator Base&() {
426 return *static_cast<Base*>(this);
427 }
428};
429
430}
#define ecs_assert(condition, error_code,...)
Assert.
Definition: log.h:352
ecs_inout_kind_t
Specify read/write access for term.
Definition: flecs.h:649
ecs_oper_kind_t
Specify operator for term.
Definition: flecs.h:658
@ EcsNot
The term must not match.
Definition: flecs.h:661
Type that describes a single identifier in a term.
Definition: flecs.h:696
ecs_flags32_t flags
Term flags.
Definition: flecs.h:713
ecs_entity_t trav
Relationship to traverse when looking for the component.
Definition: flecs.h:709
const char * name
Name.
Definition: flecs.h:703
ecs_entity_t id
Entity id.
Definition: flecs.h:697
Type that describes a term (single element in a query)
Definition: flecs.h:717
ecs_term_id_t second
Second element of pair.
Definition: flecs.h:725
ecs_id_t id
Component id to be matched by term.
Definition: flecs.h:718
ecs_term_id_t src
Source of term.
Definition: flecs.h:723
ecs_term_id_t first
Component or first element of pair.
Definition: flecs.h:724
ecs_id_t id_flags
Id flags of term id.
Definition: flecs.h:730
ecs_inout_kind_t inout
Access to contents matched by term.
Definition: flecs.h:727
ecs_oper_kind_t oper
Operator of term.
Definition: flecs.h:728
Entity.
Definition: entity.hpp:30
Class that wraps around a flecs::id_t.
Definition: decl.hpp:27
Term builder interface.
Definition: builder_i.hpp:148
Base & inout(flecs::inout_kind_t inout)
Set read/write access of term.
Definition: builder_i.hpp:272
Base & singleton()
Match singleton.
Definition: builder_i.hpp:379
Base & oper(flecs::oper_kind_t oper)
Set operator of term.
Definition: builder_i.hpp:337
Base & read_write()
Short for inout_stage(flecs::InOut).
Definition: builder_i.hpp:312
Base & inout()
Short for inout(flecs::InOut)
Definition: builder_i.hpp:327
Base & in()
Short for inout(flecs::In)
Definition: builder_i.hpp:317
Base & inout_stage(flecs::inout_kind_t inout)
Set read/write access for stage.
Definition: builder_i.hpp:286
Base & out()
Short for inout(flecs::Out)
Definition: builder_i.hpp:322
Base & read()
Short for inout_stage(flecs::In).
Definition: builder_i.hpp:305
Base & inout_none()
Short for inout(flecs::In)
Definition: builder_i.hpp:332
Base & write()
Short for inout_stage(flecs::Out).
Definition: builder_i.hpp:298
Base & role(id_t role)
Set role of term.
Definition: builder_i.hpp:265
Term identifier builder.
Definition: builder_i.hpp:21
Class that describes a term.
Definition: impl.hpp:16
The world.
Definition: world.hpp:132
flecs::term term() const
Create a term for a (component) type.