Flecs v4.0
A fast entity component system (ECS) for C & C++
Loading...
Searching...
No Matches
iter.hpp
Go to the documentation of this file.
1
6#pragma once
7
16namespace flecs
17{
18
20
21namespace _ {
22
24
29template <typename T>
31{
32 explicit range_iterator(T value)
33 : value_(value){}
34
35 bool operator!=(range_iterator const& other) const
36 {
37 return value_ != other.value_;
38 }
39
40 T const& operator*() const
41 {
42 return value_;
43 }
44
45 range_iterator& operator++()
46 {
47 ++value_;
48 return *this;
49 }
50
51private:
52 T value_;
53};
54
55} // namespace _
56
57} // namespace flecs
58
59namespace flecs
60{
61
63
68struct iter {
69private:
71
72public:
78 iter(ecs_iter_t *it) : iter_(it) { }
79
80 row_iterator begin() const {
81 return row_iterator(0);
82 }
83
84 row_iterator end() const {
85 return row_iterator(static_cast<size_t>(iter_->count));
86 }
87
88 flecs::entity system() const;
89
90 flecs::entity event() const;
91
92 flecs::id event_id() const;
93
94 flecs::world world() const;
95
96 const flecs::iter_t* c_ptr() const {
97 return iter_;
98 }
99
100 size_t count() const {
101 ecs_check(iter_->flags & EcsIterIsValid, ECS_INVALID_PARAMETER,
102 "operation invalid before calling next()");
103 return static_cast<size_t>(iter_->count);
104 error:
105 return 0;
106 }
107
108 ecs_ftime_t delta_time() const {
109 return iter_->delta_time;
110 }
111
112 ecs_ftime_t delta_system_time() const {
113 return iter_->delta_system_time;
114 }
115
116 flecs::type type() const;
117
118 flecs::table table() const;
119
120 flecs::table other_table() const;
121
122 flecs::table_range range() const;
123
127 void* ctx() {
128 return iter_->ctx;
129 }
130
134 template <typename T>
135 T* ctx() {
136 return static_cast<T*>(iter_->ctx);
137 }
138
142 void* param() {
143 return iter_->param;
144 }
145
149 template <typename T>
150 T* param() {
151 /* TODO: type check */
152 return static_cast<T*>(iter_->param);
153 }
154
159 flecs::entity entity(size_t row) const;
160
165 bool is_self(int8_t index) const {
166 return ecs_field_is_self(iter_, index);
167 }
168
173 bool is_set(int8_t index) const {
174 return ecs_field_is_set(iter_, index);
175 }
176
181 bool is_readonly(int8_t index) const {
182 return ecs_field_is_readonly(iter_, index);
183 }
184
187 int32_t field_count() const {
188 return iter_->field_count;
189 }
190
195 size_t size(int8_t index) const {
196 return ecs_field_size(iter_, index);
197 }
198
203 flecs::entity src(int8_t index) const;
204
209 flecs::id id(int8_t index) const;
210
216 flecs::id pair(int8_t index) const;
217
222 int32_t column_index(int8_t index) const {
223 return ecs_field_column(iter_, index);
224 }
225
228 int8_t term_index() const {
229 return iter_->term_index;
230 }
231
235 char *s = ecs_iter_str(iter_);
236 return flecs::string(s);
237 }
238
251 template <typename T, typename A = actual_type_t<T>,
252 typename std::enable_if<std::is_const<T>::value, void>::type* = nullptr>
253 flecs::field<A> field(int8_t index) const;
254
267 template <typename T, typename A = actual_type_t<T>,
268 typename std::enable_if<
269 std::is_const<T>::value == false, void>::type* = nullptr>
270 flecs::field<A> field(int8_t index) const;
271
282 flecs::untyped_field field(int8_t index) const {
283 ecs_assert(!(iter_->flags & EcsIterCppEach) ||
284 ecs_field_src(iter_, index) != 0, ECS_INVALID_OPERATION,
285 "cannot .field from .each, use .field_at(%d, row) instead", index);
286 return get_unchecked_field(index);
287 }
288
292 void* field_at(int8_t index, size_t row) const {
293 if (iter_->row_fields & (1llu << index)) {
294 return get_unchecked_field_at(index, row)[0];
295 } else {
296 return get_unchecked_field(index)[row];
297 }
298 }
299
303 template <typename T, typename A = actual_type_t<T>,
304 typename std::enable_if<std::is_const<T>::value, void>::type* = nullptr>
305 const A& field_at(int8_t index, size_t row) const {
306 if (iter_->row_fields & (1llu << index)) {
307 return get_field_at<A>(index, row)[0];
308 } else {
309 return get_field<A>(index)[row];
310 }
311 }
312
316 template <typename T, typename A = actual_type_t<T>,
317 typename std::enable_if<
318 std::is_const<T>::value == false, void>::type* = nullptr>
319 A& field_at(int8_t index, size_t row) const {
320 ecs_assert(!ecs_field_is_readonly(iter_, index),
321 ECS_ACCESS_VIOLATION, NULL);
322 if (iter_->row_fields & (1llu << index)) {
323 return get_field_at<A>(index, row)[0];
324 } else {
325 return get_field<A>(index)[row];
326 }
327 }
328
335 iter_->entities, static_cast<size_t>(iter_->count), false);
336 }
337
340 bool changed() {
341 return ecs_iter_changed(iter_);
342 }
343
351 void skip() {
352 ecs_iter_skip(iter_);
353 }
354
355 /* Return group id for current table (grouped queries only) */
356 uint64_t group_id() const {
357 return iter_->group_id;
358 }
359
363 flecs::entity get_var(int var_id) const;
364
368 flecs::entity get_var(const char *name) const;
369
376 bool next() {
377 if (iter_->flags & EcsIterIsValid && iter_->table) {
378 ECS_TABLE_UNLOCK(iter_->world, iter_->table);
379 }
380 bool result = iter_->next(iter_);
381 iter_->flags |= EcsIterIsValid;
382 if (result && iter_->table) {
383 ECS_TABLE_LOCK(iter_->world, iter_->table);
384 }
385 return result;
386 }
387
392 void each() {
393 iter_->callback(iter_);
394 }
395
401 template <typename Func>
402 void targets(int8_t index, const Func& func);
403
413 void fini() {
414 if (iter_->flags & EcsIterIsValid && iter_->table) {
415 ECS_TABLE_UNLOCK(iter_->world, iter_->table);
416 }
417 ecs_iter_fini(iter_);
418 }
419
420private:
421 /* Get field, check if correct type is used */
422 template <typename T, typename A = actual_type_t<T>>
423 flecs::field<T> get_field(int8_t index) const {
424
425#ifndef FLECS_NDEBUG
426 ecs_entity_t term_id = ecs_field_id(iter_, index);
427 ecs_assert(ECS_HAS_ID_FLAG(term_id, PAIR) ||
428 term_id == _::type<T>::id(iter_->world),
429 ECS_COLUMN_TYPE_MISMATCH, NULL);
430#endif
431
432 size_t count;
433 bool is_shared = !ecs_field_is_self(iter_, index);
434
435 /* If a shared column is retrieved with 'column', there will only be a
436 * single value. Ensure that the application does not accidentally read
437 * out of bounds. */
438 if (is_shared) {
439 count = 1;
440 } else {
441 /* If column is owned, there will be as many values as there are
442 * entities. */
443 count = static_cast<size_t>(iter_->count);
444 }
445
446 return flecs::field<A>(
447 static_cast<T*>(ecs_field_w_size(iter_, sizeof(A), index)),
448 count, is_shared);
449 }
450
451 /* Get field, check if correct type is used */
452 template <typename T, typename A = actual_type_t<T>>
453 flecs::field<T> get_field_at(int8_t index, int32_t row) const {
454
455#ifndef FLECS_NDEBUG
456 ecs_entity_t term_id = ecs_field_id(iter_, index);
457 ecs_assert(ECS_HAS_ID_FLAG(term_id, PAIR) ||
458 term_id == _::type<T>::id(iter_->world),
459 ECS_COLUMN_TYPE_MISMATCH, NULL);
460#endif
461
462 return flecs::field<A>(
463 static_cast<T*>(ecs_field_at_w_size(iter_, sizeof(A), index, row)),
464 1, false);
465 }
466
467 flecs::untyped_field get_unchecked_field(int8_t index) const {
468 size_t count;
469 size_t size = ecs_field_size(iter_, index);
470 bool is_shared = !ecs_field_is_self(iter_, index);
471
472 /* If a shared column is retrieved with 'column', there will only be a
473 * single value. Ensure that the application does not accidentally read
474 * out of bounds. */
475 if (is_shared) {
476 count = 1;
477 } else {
478 /* If column is owned, there will be as many values as there are
479 * entities. */
480 count = static_cast<size_t>(iter_->count);
481 }
482
484 ecs_field_w_size(iter_, 0, index), size, count, is_shared);
485 }
486
487 flecs::untyped_field get_unchecked_field_at(int8_t index, size_t row) const {
488 size_t size = ecs_field_size(iter_, index);
490 ecs_field_at_w_size(iter_, 0, index, static_cast<int32_t>(row)),
491 size, 1, false);
492 }
493
494 flecs::iter_t *iter_;
495};
496
497} // namespace flecs
498
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:368
#define ecs_check(condition, error_code,...)
Check.
Definition log.h:415
ecs_id_t ecs_entity_t
An entity identifier.
Definition flecs.h:346
ecs_entity_t ecs_field_src(const ecs_iter_t *it, int8_t index)
Return field source.
bool ecs_iter_changed(ecs_iter_t *it)
Returns whether current iterator result has changed.
bool ecs_field_is_readonly(const ecs_iter_t *it, int8_t index)
Test whether the field is readonly.
void ecs_iter_fini(ecs_iter_t *it)
Cleanup iterator resources.
char * ecs_iter_str(const ecs_iter_t *it)
Convert iterator to string.
void * ecs_field_at_w_size(const ecs_iter_t *it, size_t size, int8_t index, int32_t row)
Get data for field at specified row.
ecs_id_t ecs_field_id(const ecs_iter_t *it, int8_t index)
Return id matched for field.
bool ecs_field_is_set(const ecs_iter_t *it, int8_t index)
Test whether field is set.
bool ecs_field_is_self(const ecs_iter_t *it, int8_t index)
Test whether the field is matched on self.
int32_t ecs_field_column(const ecs_iter_t *it, int8_t index)
Return index of matched table column.
void * ecs_field_w_size(const ecs_iter_t *it, size_t size, int8_t index)
Get data for field.
size_t ecs_field_size(const ecs_iter_t *it, int8_t index)
Return field type size.
#define ecs_ftime_t
Customizable precision for scalar time values.
Definition flecs.h:59
void ecs_iter_skip(ecs_iter_t *it)
Skip a table while iterating.
Iterator.
Definition flecs.h:1099
void * param
Param passed to ecs_run.
Definition flecs.h:1136
ecs_flags32_t flags
Iterator flags.
Definition flecs.h:1152
void * ctx
System context.
Definition flecs.h:1137
ecs_table_t * table
Current table.
Definition flecs.h:1107
ecs_world_t * world
The world.
Definition flecs.h:1101
ecs_flags32_t row_fields
Fields that must be obtained with field_at.
Definition flecs.h:1117
float delta_system_time
Time elapsed since last system invocation.
Definition flecs.h:1144
int8_t term_index
Index of term that emitted an event.
Definition flecs.h:1128
float delta_time
Time elapsed since last frame.
Definition flecs.h:1143
ecs_iter_action_t callback
Callback of system or observer.
Definition flecs.h:1158
int8_t field_count
Number of fields in iterator.
Definition flecs.h:1127
int32_t count
Number of entities to iterate.
Definition flecs.h:1149
uint64_t group_id
Group id for table, if group_by is used.
Definition flecs.h:1114
ecs_iter_next_action_t next
Function to progress iterator.
Definition flecs.h:1157
const ecs_entity_t * entities
Entity identifiers.
Definition flecs.h:1105
Iterate over an integer range (used to iterate over entity range).
Definition iter.hpp:31
Entity.
Definition entity.hpp:30
Wrapper class around a field.
Definition field.hpp:61
Class that wraps around a flecs::id_t.
Definition decl.hpp:27
Class for iterating over query results.
Definition iter.hpp:68
flecs::id id(int8_t index) const
Obtain id matched for field.
Definition iter.hpp:37
size_t size(int8_t index) const
Size of field data type.
Definition iter.hpp:195
flecs::field< A > field(int8_t index) const
Get readonly access to field data.
Definition iter.hpp:68
const A & field_at(int8_t index, size_t row) const
Get reference to field at row.
Definition iter.hpp:305
bool is_self(int8_t index) const
Returns whether field is matched on self.
Definition iter.hpp:165
flecs::string str() const
Convert current iterator result to string.
Definition iter.hpp:234
int32_t field_count() const
Number of fields in iterator.
Definition iter.hpp:187
int32_t column_index(int8_t index) const
Obtain column index for field.
Definition iter.hpp:222
void * param()
Access param.
Definition iter.hpp:142
void * field_at(int8_t index, size_t row) const
Get pointer to field at row.
Definition iter.hpp:292
bool is_readonly(int8_t index) const
Returns whether field is readonly.
Definition iter.hpp:181
bool changed()
Check if the current table has changed since the last iteration.
Definition iter.hpp:340
int8_t term_index() const
Obtain term that triggered an observer.
Definition iter.hpp:228
T * ctx()
Access ctx.
Definition iter.hpp:135
void fini()
Free iterator resources.
Definition iter.hpp:413
bool is_set(int8_t index) const
Returns whether field is set.
Definition iter.hpp:173
A & field_at(int8_t index, size_t row) const
Get reference to field at row.
Definition iter.hpp:319
void * ctx()
Access ctx.
Definition iter.hpp:127
flecs::entity entity(size_t row) const
Obtain mutable handle to entity being iterated over.
Definition iter.hpp:27
void each()
Forward to each.
Definition iter.hpp:392
flecs::untyped_field field(int8_t index) const
Get unchecked access to field data.
Definition iter.hpp:282
flecs::id pair(int8_t index) const
Obtain pair id matched for field.
Definition iter.hpp:41
flecs::entity get_var(int var_id) const
Get value of variable by id.
Definition iter.hpp:89
flecs::field< const flecs::entity_t > entities() const
Get readonly access to entity ids.
Definition iter.hpp:333
iter(ecs_iter_t *it)
Construct iterator from C iterator object.
Definition iter.hpp:78
T * param()
Access param.
Definition iter.hpp:150
void targets(int8_t index, const Func &func)
Iterate targets for pair field.
Definition iter.hpp:106
flecs::entity src(int8_t index) const
Obtain field source (0 if This).
Definition iter.hpp:33
void skip()
Skip current table.
Definition iter.hpp:351
bool next()
Progress iterator.
Definition iter.hpp:376
Type class.
Definition type.hpp:21
Unsafe wrapper class around a field.
Definition field.hpp:26
The world.
Definition world.hpp:137