Flecs v4.0
A fast entity component system (ECS) for C & C++
Loading...
Searching...
No Matches
iterable.hpp
Go to the documentation of this file.
1
6namespace flecs {
7
8template <typename ... Components>
9struct iter_iterable;
10
11template <typename ... Components>
12struct page_iterable;
13
14template <typename ... Components>
15struct worker_iterable;
16
17template <typename ... Components>
18struct iterable {
19
29 template <typename Func>
30 void each(Func&& func) const {
31 ecs_iter_t it = this->get_iter(nullptr);
32 ECS_BIT_SET(it.flags, EcsIterIsInstanced);
33 ecs_iter_next_action_t next = this->next_each_action();
34 while (next(&it)) {
35 _::each_delegate<Func, Components...>(func).invoke(&it);
36 }
37 }
38
44 template <typename Func>
45 void run(Func&& func) const {
46 ecs_iter_t it = this->get_iter(nullptr);
47 _::run_delegate<Func>(func).invoke(&it);
48 }
49
50 template <typename Func>
51 flecs::entity find(Func&& func) const {
52 ecs_iter_t it = this->get_iter(nullptr);
53 ECS_BIT_SET(it.flags, EcsIterIsInstanced);
54 ecs_iter_next_action_t next = this->next_each_action();
55
56 flecs::entity result;
57 while (!result && next(&it)) {
58 result = _::find_delegate<Func, Components...>(func).invoke(&it);
59 }
60
61 if (result) {
62 ecs_iter_fini(&it);
63 }
64
65 return result;
66 }
67
71 iter_iterable<Components...> iter(flecs::world_t *world = nullptr) const;
72
76 iter_iterable<Components...> iter(flecs::iter& iter) const;
77
81 iter_iterable<Components...> iter(flecs::entity e) const;
82
90 page_iterable<Components...> page(int32_t offset, int32_t limit);
91
100 worker_iterable<Components...> worker(int32_t index, int32_t count);
101
103 int32_t count() const {
104 return this->iter().count();
105 }
106
108 bool is_true() const {
109 return this->iter().is_true();
110 }
111
114 return this->iter().first();
115 }
116
117 iter_iterable<Components...> set_var(int var_id, flecs::entity_t value) {
118 return this->iter().set_var(var_id, value);
119 }
120
121 iter_iterable<Components...> set_var(const char *name, flecs::entity_t value) {
122 return this->iter().set_var(name, value);
123 }
124
125 iter_iterable<Components...> set_var(const char *name, flecs::table_t *value) {
126 return this->iter().set_var(name, value);
127 }
128
129 iter_iterable<Components...> set_var(const char *name, ecs_table_range_t value) {
130 return this->iter().set_var(name, value);
131 }
132
133 iter_iterable<Components...> set_var(const char *name, flecs::table_range value) {
134 return this->iter().set_var(name, value);
135 }
136
137 // Limit results to tables with specified group id (grouped queries only)
138 iter_iterable<Components...> set_group(uint64_t group_id) {
139 return this->iter().set_group(group_id);
140 }
141
142 // Limit results to tables with specified group id (grouped queries only)
143 template <typename Group>
144 iter_iterable<Components...> set_group() {
145 return this->iter().template set_group<Group>();
146 }
147
148 virtual ~iterable() { }
149protected:
150 friend iter_iterable<Components...>;
151 friend page_iterable<Components...>;
152 friend worker_iterable<Components...>;
153
154 virtual ecs_iter_t get_iter(flecs::world_t *stage) const = 0;
155 virtual ecs_iter_next_action_t next_action() const = 0;
156 virtual ecs_iter_next_action_t next_each_action() const = 0;
157};
158
159template <typename ... Components>
160struct iter_iterable final : iterable<Components...> {
161 template <typename Iterable>
162 iter_iterable(Iterable *it, flecs::world_t *world)
163 {
164 it_ = it->get_iter(world);
165 next_ = it->next_action();
166 next_each_ = it->next_action();
167 ecs_assert(next_ != nullptr, ECS_INTERNAL_ERROR, NULL);
168 ecs_assert(next_each_ != nullptr, ECS_INTERNAL_ERROR, NULL);
169 }
170
171 iter_iterable<Components...>& set_var(int var_id, flecs::entity_t value) {
172 ecs_assert(var_id != -1, ECS_INVALID_PARAMETER, 0);
173 ecs_iter_set_var(&it_, var_id, value);
174 return *this;
175 }
176
177 iter_iterable<Components...>& set_var(const char *name, flecs::entity_t value) {
178 ecs_query_iter_t *qit = &it_.priv_.iter.query;
179 int var_id = ecs_query_find_var(qit->query, name);
180 ecs_assert(var_id != -1, ECS_INVALID_PARAMETER, name);
181 ecs_iter_set_var(&it_, var_id, value);
182 return *this;
183 }
184
185 iter_iterable<Components...>& set_var(const char *name, flecs::table_t *value) {
186 ecs_query_iter_t *qit = &it_.priv_.iter.query;
187 int var_id = ecs_query_find_var(qit->query, name);
188 ecs_assert(var_id != -1, ECS_INVALID_PARAMETER, name);
189 ecs_iter_set_var_as_table(&it_, var_id, value);
190 return *this;
191 }
192
193 iter_iterable<Components...>& set_var(const char *name, ecs_table_range_t value) {
194 ecs_query_iter_t *qit = &it_.priv_.iter.query;
195 int var_id = ecs_query_find_var(qit->query, name);
196 ecs_assert(var_id != -1, ECS_INVALID_PARAMETER, name);
197 ecs_iter_set_var_as_range(&it_, var_id, &value);
198 return *this;
199 }
200
201 iter_iterable<Components...>& set_var(const char *name, flecs::table_range value) {
202 ecs_table_range_t range;
203 range.table = value.get_table();
204 range.offset = value.offset();
205 range.count = value.count();
206 return set_var(name, range);
207 }
208
209# ifdef FLECS_JSON
211# endif
212
213 // Return total number of entities in result.
214 int32_t count() {
215 int32_t result = 0;
216 while (next_each_(&it_)) {
217 result += it_.count;
218 }
219 return result;
220 }
221
222 // Returns true if iterator yields at least once result.
223 bool is_true() {
224 bool result = next_each_(&it_);
225 if (result) {
226 ecs_iter_fini(&it_);
227 }
228 return result;
229 }
230
231 // Return first matching entity.
232 flecs::entity first() {
233 flecs::entity result;
234 if (next_each_(&it_) && it_.count) {
235 result = flecs::entity(it_.world, it_.entities[0]);
236 ecs_iter_fini(&it_);
237 }
238 return result;
239 }
240
241 // Limit results to tables with specified group id (grouped queries only)
242 iter_iterable<Components...>& set_group(uint64_t group_id) {
243 ecs_iter_set_group(&it_, group_id);
244 return *this;
245 }
246
247 // Limit results to tables with specified group id (grouped queries only)
248 template <typename Group>
249 iter_iterable<Components...>& set_group() {
251 return *this;
252 }
253
254protected:
255 ecs_iter_t get_iter(flecs::world_t *world) const override {
256 if (world) {
257 ecs_iter_t result = it_;
258 result.world = world;
259 return result;
260 }
261 return it_;
262 }
263
264 ecs_iter_next_action_t next_action() const override {
265 return next_;
266 }
267
268 ecs_iter_next_action_t next_each_action() const override {
269 return next_each_;
270 }
271
272private:
273 ecs_iter_t it_;
275 ecs_iter_next_action_t next_each_;
276};
277
278template <typename ... Components>
279iter_iterable<Components...> iterable<Components...>::iter(flecs::world_t *world) const
280{
281 return iter_iterable<Components...>(this, world);
282}
283
284template <typename ... Components>
286{
287 return iter_iterable<Components...>(this, it.world());
288}
289
290template <typename ... Components>
292{
293 return iter_iterable<Components...>(this, e.world());
294}
295
296template <typename ... Components>
297struct page_iterable final : iterable<Components...> {
298 template <typename Iterable>
299 page_iterable(int32_t offset, int32_t limit, Iterable *it)
300 : offset_(offset)
301 , limit_(limit)
302 {
303 chain_it_ = it->get_iter(nullptr);
304 }
305
306protected:
307 ecs_iter_t get_iter(flecs::world_t*) const {
308 return ecs_page_iter(&chain_it_, offset_, limit_);
309 }
310
311 ecs_iter_next_action_t next_action() const {
312 return ecs_page_next;
313 }
314
315 ecs_iter_next_action_t next_each_action() const {
316 return ecs_page_next;
317 }
318
319private:
320 ecs_iter_t chain_it_;
321 int32_t offset_;
322 int32_t limit_;
323};
324
325template <typename ... Components>
327 int32_t offset,
328 int32_t limit)
329{
330 return page_iterable<Components...>(offset, limit, this);
331}
332
333template <typename ... Components>
334struct worker_iterable final : iterable<Components...> {
335 worker_iterable(int32_t offset, int32_t limit, iterable<Components...> *it)
336 : offset_(offset)
337 , limit_(limit)
338 {
339 chain_it_ = it->get_iter(nullptr);
340 }
341
342protected:
343 ecs_iter_t get_iter(flecs::world_t*) const {
344 return ecs_worker_iter(&chain_it_, offset_, limit_);
345 }
346
347 ecs_iter_next_action_t next_action() const {
348 return ecs_worker_next;
349 }
350
351 ecs_iter_next_action_t next_each_action() const {
352 return ecs_worker_next;
353 }
354
355private:
356 ecs_iter_t chain_it_;
357 int32_t offset_;
358 int32_t limit_;
359};
360
361template <typename ... Components>
363 int32_t index,
364 int32_t count)
365{
366 return worker_iterable<Components...>(index, count, this);
367}
368
369}
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:352
bool(* ecs_iter_next_action_t)(ecs_iter_t *it)
Function prototype for iterating an iterator.
Definition flecs.h:525
ecs_iter_t ecs_worker_iter(const ecs_iter_t *it, int32_t index, int32_t count)
Create a worker iterator.
void ecs_iter_fini(ecs_iter_t *it)
Cleanup iterator resources.
ecs_iter_t ecs_page_iter(const ecs_iter_t *it, int32_t offset, int32_t limit)
Create a paged iterator.
void ecs_iter_set_var(ecs_iter_t *it, int32_t var_id, ecs_entity_t entity)
Set value for iterator variable.
bool ecs_worker_next(ecs_iter_t *it)
Progress a worker iterator.
void ecs_iter_set_var_as_table(ecs_iter_t *it, int32_t var_id, const ecs_table_t *table)
Same as ecs_iter_set_var(), but for a table.
bool ecs_page_next(ecs_iter_t *it)
Progress a paged iterator.
void ecs_iter_set_var_as_range(ecs_iter_t *it, int32_t var_id, const ecs_table_range_t *range)
Same as ecs_iter_set_var(), but for a range of entities This constrains the variable to a range of en...
void ecs_iter_set_group(ecs_iter_t *it, uint64_t group_id)
Set group to iterate for query iterator.
int32_t ecs_query_find_var(const ecs_query_t *query, const char *name)
Find variable index.
JSON iterable mixin.
Iterator.
Definition flecs.h:1025
ecs_world_t * real_world
Actual world.
Definition flecs.h:1028
ecs_flags32_t flags
Iterator flags.
Definition flecs.h:1079
ecs_iter_private_t priv_
Private data.
Definition flecs.h:1081
ecs_world_t * world
The world.
Definition flecs.h:1027
ecs_entity_t * entities
Entity identifiers.
Definition flecs.h:1031
int32_t count
Number of entities to iterate.
Definition flecs.h:1075
Entity.
Definition entity.hpp:30
flecs::entity first() const
Get first element from a pair.
Definition impl.hpp:20
Class for iterating over query results.
Definition iter.hpp:68
bool is_true() const
Return whether iterable has any matches.
Definition iterable.hpp:108
void run(Func &&func) const
Run iterator.
Definition iterable.hpp:45
flecs::entity first() const
Return first entity matched by iterable.
Definition iterable.hpp:113
void each(Func &&func) const
Each iterator.
Definition iterable.hpp:30
int32_t count() const
Return number of entities matched by iterable.
Definition iterable.hpp:103
iter_iterable< Components... > iter(flecs::entity e) const
Create iterator.
Definition iterable.hpp:291
page_iterable< Components... > page(int32_t offset, int32_t limit)
Page iterator.
Definition iterable.hpp:326
iter_iterable< Components... > iter(flecs::iter &iter) const
Create iterator.
Definition iterable.hpp:285
worker_iterable< Components... > worker(int32_t index, int32_t count)
Worker iterator.
Definition iterable.hpp:362
iter_iterable< Components... > iter(flecs::world_t *world=nullptr) const
Create iterator.
Definition iterable.hpp:279
table_t * get_table() const
Get table.
Definition table.hpp:303
The world.
Definition world.hpp:137