Flecs v3.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
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 ecs_term_id_t *m_term_id;
120
121protected:
122 virtual flecs::world_t* world_v() = 0;
123
124private:
125 void assert_term_id() {
126 ecs_assert(m_term_id != NULL, ECS_INVALID_PARAMETER,
127 "no active term (call .term() first)");
128 }
129
130 operator Base&() {
131 return *static_cast<Base*>(this);
132 }
133};
134
140template<typename Base>
142 term_builder_i() : m_term(nullptr) { }
143
144 term_builder_i(ecs_term_t *term_ptr) {
145 set_term(term_ptr);
146 }
147
148 Base& term(id_t id) {
149 return this->id(id);
150 }
151
152 /* Call prior to setting values for src identifier */
153 Base& src() {
154 this->assert_term();
155 this->m_term_id = &m_term->src;
156 return *this;
157 }
158
159 /* Call prior to setting values for first identifier. This is either the
160 * component identifier, or first element of a pair (in case second is
161 * populated as well). */
162 Base& first() {
163 this->assert_term();
164 this->m_term_id = &m_term->first;
165 return *this;
166 }
167
168 /* Call prior to setting values for second identifier. This is the second
169 * element of a pair. Requires that first() is populated as well. */
170 Base& second() {
171 this->assert_term();
172 this->m_term_id = &m_term->second;
173 return *this;
174 }
175
176 /* Select src identifier, initialize it with entity id */
177 Base& src(flecs::entity_t id) {
178 this->src();
179 this->id(id);
180 return *this;
181 }
182
183 /* Select src identifier, initialize it with id associated with type */
184 template<typename T>
185 Base& src() {
186 this->src(_::cpp_type<T>::id(this->world_v()));
187 return *this;
188 }
189
190 /* Select src identifier, initialize it with name. If name starts with a $
191 * the name is interpreted as a variable. */
192 Base& src(const char *name) {
193 ecs_assert(name != NULL, ECS_INVALID_PARAMETER, NULL);
194 this->src();
195 if (name[0] == '$') {
196 this->var(&name[1]);
197 } else {
198 this->name(name);
199 }
200 return *this;
201 }
202
203 /* Select first identifier, initialize it with entity id */
204 Base& first(flecs::entity_t id) {
205 this->first();
206 this->id(id);
207 return *this;
208 }
209
210 /* Select first identifier, initialize it with id associated with type */
211 template<typename T>
212 Base& first() {
213 this->first(_::cpp_type<T>::id(this->world_v()));
214 return *this;
215 }
216
217 /* Select first identifier, initialize it with name. If name starts with a $
218 * the name is interpreted as a variable. */
219 Base& first(const char *name) {
220 ecs_assert(name != NULL, ECS_INVALID_PARAMETER, NULL);
221 this->first();
222 if (name[0] == '$') {
223 this->var(&name[1]);
224 } else {
225 this->name(name);
226 }
227 return *this;
228 }
229
230 /* Select second identifier, initialize it with entity id */
231 Base& second(flecs::entity_t id) {
232 this->second();
233 this->id(id);
234 return *this;
235 }
236
237 /* Select second identifier, initialize it with id associated with type */
238 template<typename T>
239 Base& second() {
240 this->second(_::cpp_type<T>::id(this->world_v()));
241 return *this;
242 }
243
244 /* Select second identifier, initialize it with name. If name starts with a $
245 * the name is interpreted as a variable. */
246 Base& second(const char *name) {
247 ecs_assert(name != NULL, ECS_INVALID_PARAMETER, NULL);
248 this->second();
249 if (name[0] == '$') {
250 this->var(&name[1]);
251 } else {
252 this->name(name);
253 }
254 return *this;
255 }
256
258 Base& role(id_t role) {
259 this->assert_term();
260 m_term->id_flags = role;
261 return *this;
262 }
263
265 Base& inout(flecs::inout_kind_t inout) {
266 this->assert_term();
267 m_term->inout = static_cast<ecs_inout_kind_t>(inout);
268 return *this;
269 }
270
279 Base& inout_stage(flecs::inout_kind_t inout) {
280 this->assert_term();
281 m_term->inout = static_cast<ecs_inout_kind_t>(inout);
282 if (m_term->oper != EcsNot) {
283 this->src().entity(0);
284 }
285 return *this;
286 }
287
291 Base& write() {
292 return this->inout_stage(flecs::Out);
293 }
294
298 Base& read() {
299 return this->inout_stage(flecs::In);
300 }
301
305 Base& read_write() {
306 return this->inout_stage(flecs::InOut);
307 }
308
310 Base& in() {
311 return this->inout(flecs::In);
312 }
313
315 Base& out() {
316 return this->inout(flecs::Out);
317 }
318
320 Base& inout() {
321 return this->inout(flecs::InOut);
322 }
323
325 Base& inout_none() {
326 return this->inout(flecs::InOutNone);
327 }
328
330 Base& oper(flecs::oper_kind_t oper) {
331 this->assert_term();
332 m_term->oper = static_cast<ecs_oper_kind_t>(oper);
333 return *this;
334 }
335
336 /* Short for oper(flecs::And) */
337 Base& and_() {
338 return this->oper(flecs::And);
339 }
340
341 /* Short for oper(flecs::Or) */
342 Base& or_() {
343 return this->oper(flecs::Or);
344 }
345
346 /* Short for oper(flecs::Or) */
347 Base& not_() {
348 return this->oper(flecs::Not);
349 }
350
351 /* Short for oper(flecs::Or) */
352 Base& optional() {
353 return this->oper(flecs::Optional);
354 }
355
356 /* Short for oper(flecs::AndFrom) */
357 Base& and_from() {
358 return this->oper(flecs::AndFrom);
359 }
360
361 /* Short for oper(flecs::OrFrom) */
362 Base& or_from() {
363 return this->oper(flecs::OrFrom);
364 }
365
366 /* Short for oper(flecs::NotFrom) */
367 Base& not_from() {
368 return this->oper(flecs::NotFrom);
369 }
370
372 Base& singleton() {
373 this->assert_term();
374 ecs_assert(m_term->id || m_term->first.id, ECS_INVALID_PARAMETER,
375 "no component specified for singleton");
376
377 flecs::id_t sid = m_term->id;
378 if (!sid) {
379 sid = m_term->first.id;
380 }
381
382 ecs_assert(sid != 0, ECS_INVALID_PARAMETER, NULL);
383 m_term->src.id = sid;
384 return *this;
385 }
386
387 /* Filter terms are not triggered on by observers */
388 Base& filter() {
389 m_term->src.flags |= flecs::Filter;
390 return *this;
391 }
392
393 ecs_term_t *m_term;
394
395protected:
396 virtual flecs::world_t* world_v() = 0;
397
398 void set_term(ecs_term_t *term) {
399 m_term = term;
400 if (term) {
401 this->m_term_id = &m_term->src; // default to subject
402 } else {
403 this->m_term_id = nullptr;
404 }
405 }
406
407private:
408 void assert_term() {
409 ecs_assert(m_term != NULL, ECS_INVALID_PARAMETER,
410 "no active term (call .term() first)");
411 }
412
413 operator Base&() {
414 return *static_cast<Base*>(this);
415 }
416};
417
418}
#define ecs_assert(condition, error_code,...)
Assert.
Definition: log.h:352
ecs_inout_kind_t
Specify read/write access for term.
Definition: flecs.h:475
ecs_oper_kind_t
Specify operator for term.
Definition: flecs.h:484
@ EcsNot
The term must not match.
Definition: flecs.h:487
Type that describes a single identifier in a term.
Definition: flecs.h:507
ecs_flags32_t flags
Term flags.
Definition: flecs.h:525
ecs_entity_t trav
Relationship to traverse when looking for the component.
Definition: flecs.h:521
char * name
Name.
Definition: flecs.h:514
ecs_entity_t id
Entity id.
Definition: flecs.h:508
Type that describes a term (single element in a query)
Definition: flecs.h:529
ecs_term_id_t second
Second element of pair.
Definition: flecs.h:537
ecs_id_t id
Component id to be matched by term.
Definition: flecs.h:530
ecs_term_id_t src
Source of term.
Definition: flecs.h:535
ecs_term_id_t first
Component or first element of pair.
Definition: flecs.h:536
ecs_id_t id_flags
Id flags of term id.
Definition: flecs.h:542
ecs_inout_kind_t inout
Access to contents matched by term.
Definition: flecs.h:539
ecs_oper_kind_t oper
Operator of term.
Definition: flecs.h:540
Entity.
Definition: entity.hpp:30
Class that wraps around a flecs::id_t.
Definition: decl.hpp:27
Term builder interface.
Definition: builder_i.hpp:141
Base & inout(flecs::inout_kind_t inout)
Set read/write access of term.
Definition: builder_i.hpp:265
Base & singleton()
Match singleton.
Definition: builder_i.hpp:372
Base & oper(flecs::oper_kind_t oper)
Set operator of term.
Definition: builder_i.hpp:330
Base & read_write()
Short for inout_stage(flecs::InOut).
Definition: builder_i.hpp:305
Base & inout()
Short for inout(flecs::InOut)
Definition: builder_i.hpp:320
Base & in()
Short for inout(flecs::In)
Definition: builder_i.hpp:310
Base & inout_stage(flecs::inout_kind_t inout)
Set read/write access for stage.
Definition: builder_i.hpp:279
Base & out()
Short for inout(flecs::Out)
Definition: builder_i.hpp:315
Base & read()
Short for inout_stage(flecs::In).
Definition: builder_i.hpp:298
Base & inout_none()
Short for inout(flecs::In)
Definition: builder_i.hpp:325
Base & write()
Short for inout_stage(flecs::Out).
Definition: builder_i.hpp:291
Base & role(id_t role)
Set role of term.
Definition: builder_i.hpp:258
Term identifier builder.
Definition: builder_i.hpp:21
Class that describes a term.
Definition: impl.hpp:16
flecs::term term() const
Create a term for a (component) type.