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
27 template <typename Func>
28 void each(Func&& func) const {
29 ecs_iter_t it = this->get_iter(nullptr);
30 ecs_iter_next_action_t next = this->next_action();
31 while (next(&it)) {
32 _::each_delegate<Func, Components...>(func).invoke(&it);
33 }
34 }
35
41 template <typename Func>
42 void run(Func&& func) const {
43 ecs_iter_t it = this->get_iter(nullptr);
44 _::run_delegate<Func>(func).invoke(&it);
45 }
46
47 template <typename Func>
48 flecs::entity find(Func&& func) const {
49 ecs_iter_t it = this->get_iter(nullptr);
50 ecs_iter_next_action_t next = this->next_action();
51
52 flecs::entity result;
53 while (!result && next(&it)) {
54 result = _::find_delegate<Func, Components...>(func).invoke(&it);
55 }
56
57 if (result) {
58 ecs_iter_fini(&it);
59 }
60
61 return result;
62 }
63
67 iter_iterable<Components...> iter(flecs::world_t *world = nullptr) const;
68
72 iter_iterable<Components...> iter(flecs::iter& iter) const;
73
77 iter_iterable<Components...> iter(flecs::entity e) const;
78
86 page_iterable<Components...> page(int32_t offset, int32_t limit);
87
96 worker_iterable<Components...> worker(int32_t index, int32_t count);
97
99 int32_t count() const {
100 return this->iter().count();
101 }
102
104 bool is_true() const {
105 return this->iter().is_true();
106 }
107
110 return this->iter().first();
111 }
112
113 iter_iterable<Components...> set_var(int var_id, flecs::entity_t value) const {
114 return this->iter().set_var(var_id, value);
115 }
116
117 iter_iterable<Components...> set_var(const char *name, flecs::entity_t value) const {
118 return this->iter().set_var(name, value);
119 }
120
121 iter_iterable<Components...> set_var(const char *name, flecs::table_t *value) const {
122 return this->iter().set_var(name, value);
123 }
124
125 iter_iterable<Components...> set_var(const char *name, ecs_table_range_t value) const {
126 return this->iter().set_var(name, value);
127 }
128
129 iter_iterable<Components...> set_var(const char *name, flecs::table_range value) const {
130 return this->iter().set_var(name, value);
131 }
132
133 // Limit results to tables with specified group id (grouped queries only)
134 iter_iterable<Components...> set_group(uint64_t group_id) const {
135 return this->iter().set_group(group_id);
136 }
137
138 // Limit results to tables with specified group id (grouped queries only)
139 template <typename Group>
140 iter_iterable<Components...> set_group() const {
141 return this->iter().template set_group<Group>();
142 }
143
144 virtual ~iterable() { }
145protected:
146 friend iter_iterable<Components...>;
147 friend page_iterable<Components...>;
148 friend worker_iterable<Components...>;
149
150 virtual ecs_iter_t get_iter(flecs::world_t *stage) const = 0;
151 virtual ecs_iter_next_action_t next_action() const = 0;
152};
153
154template <typename ... Components>
155struct iter_iterable final : iterable<Components...> {
156 template <typename Iterable>
157 iter_iterable(Iterable *it, flecs::world_t *world)
158 {
159 it_ = it->get_iter(world);
160 next_ = it->next_action();
161 next_each_ = it->next_action();
162 ecs_assert(next_ != nullptr, ECS_INTERNAL_ERROR, NULL);
163 ecs_assert(next_each_ != nullptr, ECS_INTERNAL_ERROR, NULL);
164 }
165
166 iter_iterable<Components...>& set_var(int var_id, flecs::entity_t value) {
167 ecs_assert(var_id != -1, ECS_INVALID_PARAMETER, 0);
168 ecs_iter_set_var(&it_, var_id, value);
169 return *this;
170 }
171
172 iter_iterable<Components...>& set_var(const char *name, flecs::entity_t value) {
173 ecs_query_iter_t *qit = &it_.priv_.iter.query;
174 int var_id = ecs_query_find_var(qit->query, name);
175 ecs_assert(var_id != -1, ECS_INVALID_PARAMETER, name);
176 ecs_iter_set_var(&it_, var_id, value);
177 return *this;
178 }
179
180 iter_iterable<Components...>& set_var(const char *name, flecs::table_t *value) {
181 ecs_query_iter_t *qit = &it_.priv_.iter.query;
182 int var_id = ecs_query_find_var(qit->query, name);
183 ecs_assert(var_id != -1, ECS_INVALID_PARAMETER, name);
184 ecs_iter_set_var_as_table(&it_, var_id, value);
185 return *this;
186 }
187
188 iter_iterable<Components...>& set_var(const char *name, ecs_table_range_t value) {
189 ecs_query_iter_t *qit = &it_.priv_.iter.query;
190 int var_id = ecs_query_find_var(qit->query, name);
191 ecs_assert(var_id != -1, ECS_INVALID_PARAMETER, name);
192 ecs_iter_set_var_as_range(&it_, var_id, &value);
193 return *this;
194 }
195
196 iter_iterable<Components...>& set_var(const char *name, flecs::table_range value) {
197 ecs_table_range_t range;
198 range.table = value.get_table();
199 range.offset = value.offset();
200 range.count = value.count();
201 return set_var(name, range);
202 }
203
204# ifdef FLECS_JSON
206# endif
207
208 // Return total number of entities in result.
209 int32_t count() {
210 int32_t result = 0;
211 while (next_each_(&it_)) {
212 result += it_.count;
213 }
214 return result;
215 }
216
217 // Returns true if iterator yields at least once result.
218 bool is_true() {
219 bool result = next_each_(&it_);
220 if (result) {
221 ecs_iter_fini(&it_);
222 }
223 return result;
224 }
225
226 // Return first matching entity.
227 flecs::entity first() {
228 flecs::entity result;
229 if (next_each_(&it_) && it_.count) {
230 result = flecs::entity(it_.world, it_.entities[0]);
231 ecs_iter_fini(&it_);
232 }
233 return result;
234 }
235
236 // Limit results to tables with specified group id (grouped queries only)
237 iter_iterable<Components...>& set_group(uint64_t group_id) {
238 ecs_iter_set_group(&it_, group_id);
239 return *this;
240 }
241
242 // Limit results to tables with specified group id (grouped queries only)
243 template <typename Group>
244 iter_iterable<Components...>& set_group() {
246 return *this;
247 }
248
249protected:
250 ecs_iter_t get_iter(flecs::world_t *world) const override {
251 if (world) {
252 ecs_iter_t result = it_;
253 result.world = world;
254 return result;
255 }
256 return it_;
257 }
258
259 ecs_iter_next_action_t next_action() const override {
260 return next_;
261 }
262
263private:
264 ecs_iter_t it_;
266 ecs_iter_next_action_t next_each_;
267};
268
269template <typename ... Components>
270iter_iterable<Components...> iterable<Components...>::iter(flecs::world_t *world) const
271{
272 return iter_iterable<Components...>(this, world);
273}
274
275template <typename ... Components>
277{
278 return iter_iterable<Components...>(this, it.world());
279}
280
281template <typename ... Components>
283{
284 return iter_iterable<Components...>(this, e.world());
285}
286
287template <typename ... Components>
288struct page_iterable final : iterable<Components...> {
289 template <typename Iterable>
290 page_iterable(int32_t offset, int32_t limit, Iterable *it)
291 : offset_(offset)
292 , limit_(limit)
293 {
294 chain_it_ = it->get_iter(nullptr);
295 }
296
297protected:
298 ecs_iter_t get_iter(flecs::world_t*) const {
299 return ecs_page_iter(&chain_it_, offset_, limit_);
300 }
301
302 ecs_iter_next_action_t next_action() const {
303 return ecs_page_next;
304 }
305
306private:
307 ecs_iter_t chain_it_;
308 int32_t offset_;
309 int32_t limit_;
310};
311
312template <typename ... Components>
314 int32_t offset,
315 int32_t limit)
316{
317 return page_iterable<Components...>(offset, limit, this);
318}
319
320template <typename ... Components>
321struct worker_iterable final : iterable<Components...> {
322 worker_iterable(int32_t offset, int32_t limit, iterable<Components...> *it)
323 : offset_(offset)
324 , limit_(limit)
325 {
326 chain_it_ = it->get_iter(nullptr);
327 }
328
329protected:
330 ecs_iter_t get_iter(flecs::world_t*) const {
331 return ecs_worker_iter(&chain_it_, offset_, limit_);
332 }
333
334 ecs_iter_next_action_t next_action() const {
335 return ecs_worker_next;
336 }
337
338private:
339 ecs_iter_t chain_it_;
340 int32_t offset_;
341 int32_t limit_;
342};
343
344template <typename ... Components>
346 int32_t index,
347 int32_t count)
348{
349 return worker_iterable<Components...>(index, count, this);
350}
351
352}
#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:557
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:1101
ecs_world_t * real_world
Actual world.
Definition flecs.h:1104
ecs_iter_private_t priv_
Private data.
Definition flecs.h:1156
ecs_world_t * world
The world.
Definition flecs.h:1103
int32_t count
Number of entities to iterate.
Definition flecs.h:1151
const ecs_entity_t * entities
Entity identifiers.
Definition flecs.h:1107
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:104
void run(Func &&func) const
Run iterator.
Definition iterable.hpp:42
flecs::entity first() const
Return first entity matched by iterable.
Definition iterable.hpp:109
void each(Func &&func) const
Each iterator.
Definition iterable.hpp:28
int32_t count() const
Return number of entities matched by iterable.
Definition iterable.hpp:99
iter_iterable< Components... > iter(flecs::entity e) const
Create iterator.
Definition iterable.hpp:282
page_iterable< Components... > page(int32_t offset, int32_t limit)
Page iterator.
Definition iterable.hpp:313
iter_iterable< Components... > iter(flecs::iter &iter) const
Create iterator.
Definition iterable.hpp:276
worker_iterable< Components... > worker(int32_t index, int32_t count)
Worker iterator.
Definition iterable.hpp:345
iter_iterable< Components... > iter(flecs::world_t *world=nullptr) const
Create iterator.
Definition iterable.hpp:270
table_t * get_table() const
Get table.
Definition table.hpp:303
The world.
Definition world.hpp:137