Flecs v3.2
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 each(nullptr, FLECS_FWD(func));
32 }
33
34 template <typename Func>
35 void each(flecs::world_t *world, Func&& func) const {
36 iterate<_::each_delegate>(world, FLECS_FWD(func),
37 this->next_each_action());
38 }
39
40 template <typename Func>
41 void each(flecs::iter& it, Func&& func) const {
42 iterate<_::each_delegate>(it.world(), FLECS_FWD(func),
43 this->next_each_action());
44 }
45
46 template <typename Func>
47 void each(flecs::entity e, Func&& func) const {
48 iterate<_::each_delegate>(e.world(), FLECS_FWD(func),
49 this->next_each_action());
50 }
51
52 template <typename Func>
53 flecs::entity find(Func&& func) const {
54 return iterate_find<_::find_delegate>(nullptr, FLECS_FWD(func),
55 this->next_each_action());
56 }
57
69 template <typename Func>
70 void iter(Func&& func) const {
71 iterate<_::iter_delegate>(nullptr, FLECS_FWD(func),
72 this->next_action());
73 }
74
75 template <typename Func>
76 void iter(flecs::world_t *world, Func&& func) const {
77 iterate<_::iter_delegate>(world, FLECS_FWD(func),
78 this->next_action());
79 }
80
81 template <typename Func>
82 void iter(flecs::iter& it, Func&& func) const {
83 iterate<_::iter_delegate>(it.world(), FLECS_FWD(func),
84 this->next_action());
85 }
86
87 template <typename Func>
88 void iter(flecs::entity e, Func&& func) const {
89 iterate<_::iter_delegate>(e.world(), FLECS_FWD(func),
90 this->next_action());
91 }
92
96 iter_iterable<Components...> iter(flecs::world_t *world = nullptr) const;
97
105 page_iterable<Components...> page(int32_t offset, int32_t limit);
106
115 worker_iterable<Components...> worker(int32_t index, int32_t count);
116
118 int32_t count() const {
119 return this->iter().count();
120 }
121
123 bool is_true() const {
124 return this->iter().is_true();
125 }
126
129 return this->iter().first();
130 }
131
132 virtual ~iterable() { }
133protected:
134 friend iter_iterable<Components...>;
135 friend page_iterable<Components...>;
136 friend worker_iterable<Components...>;
137
138 virtual ecs_iter_t get_iter(flecs::world_t *stage) const = 0;
139 virtual ecs_iter_next_action_t next_action() const = 0;
140 virtual ecs_iter_next_action_t next_each_action() const = 0;
141
142 template < template<typename Func, typename ... Comps> class Delegate, typename Func, typename NextFunc, typename ... Args>
143 void iterate(flecs::world_t *stage, Func&& func, NextFunc next, Args &&... args) const {
144 ecs_iter_t it = this->get_iter(stage);
145 if (Delegate<Func, Components...>::instanced()) {
146 ECS_BIT_SET(it.flags, EcsIterIsInstanced);
147 }
148
149 while (next(&it, FLECS_FWD(args)...)) {
150 Delegate<Func, Components...>(func).invoke(&it);
151 }
152 }
153
154 template < template<typename Func, typename ... Comps> class Delegate, typename Func, typename NextFunc, typename ... Args>
155 flecs::entity iterate_find(flecs::world_t *stage, Func&& func, NextFunc next, Args &&... args) const {
156 ecs_iter_t it = this->get_iter(stage);
157 if (Delegate<Func, Components...>::instanced()) {
158 ECS_BIT_SET(it.flags, EcsIterIsInstanced);
159 }
160
161 flecs::entity result;
162 while (!result && next(&it, FLECS_FWD(args)...)) {
163 result = Delegate<Func, Components...>(func).invoke(&it);
164 }
165 if (result) {
166 ecs_iter_fini(&it);
167 }
168 return result;
169 }
170};
171
172template <typename ... Components>
173struct iter_iterable final : iterable<Components...> {
174 template <typename Iterable>
175 iter_iterable(Iterable *it, flecs::world_t *world)
176 {
177 m_it = it->get_iter(world);
178 m_next = it->next_action();
179 m_next_each = it->next_action();
180 }
181
182 iter_iterable<Components...>& set_var(int var_id, flecs::entity_t value) {
183 ecs_assert(var_id != -1, ECS_INVALID_PARAMETER, 0);
184 ecs_iter_set_var(&m_it, var_id, value);
185 return *this;
186 }
187
188# ifdef FLECS_RULES
190# endif
191# ifdef FLECS_JSON
193# endif
194
195 // Return total number of entities in result.
196 int32_t count() {
197 int32_t result = 0;
198 while (m_next_each(&m_it)) {
199 result += m_it.count;
200 }
201 return result;
202 }
203
204 // Returns true if iterator yields at least once result.
205 bool is_true() {
206 bool result = m_next_each(&m_it);
207 if (result) {
208 ecs_iter_fini(&m_it);
209 }
210 return result;
211 }
212
213 // Return first matching entity.
214 flecs::entity first() {
215 flecs::entity result;
216 if (m_next_each(&m_it) && m_it.count) {
217 result = flecs::entity(m_it.world, m_it.entities[0]);
218 ecs_iter_fini(&m_it);
219 }
220 return result;
221 }
222
223 // Limit results to tables with specified group id (grouped queries only)
224 iter_iterable<Components...>& set_group(uint64_t group_id) {
225 ecs_query_set_group(&m_it, group_id);
226 return *this;
227 }
228
229 // Limit results to tables with specified group id (grouped queries only)
230 template <typename Group>
231 iter_iterable<Components...>& set_group() {
232 ecs_query_set_group(&m_it, _::cpp_type<Group>().id(m_it.real_world));
233 return *this;
234 }
235
236protected:
237 ecs_iter_t get_iter(flecs::world_t *world) const {
238 if (world) {
239 ecs_iter_t result = m_it;
240 result.world = world;
241 return result;
242 }
243 return m_it;
244 }
245
246 ecs_iter_next_action_t next_action() const {
247 return m_next;
248 }
249
250 ecs_iter_next_action_t next_each_action() const {
251 return m_next_each;
252 }
253
254private:
255 ecs_iter_t m_it;
257 ecs_iter_next_action_t m_next_each;
258};
259
260template <typename ... Components>
261iter_iterable<Components...> iterable<Components...>::iter(flecs::world_t *world) const
262{
263 return iter_iterable<Components...>(this, world);
264}
265
266template <typename ... Components>
267struct page_iterable final : iterable<Components...> {
268 template <typename Iterable>
269 page_iterable(int32_t offset, int32_t limit, Iterable *it)
270 : m_offset(offset)
271 , m_limit(limit)
272 {
273 m_chain_it = it->get_iter(nullptr);
274 }
275
276protected:
277 ecs_iter_t get_iter(flecs::world_t*) const {
278 return ecs_page_iter(&m_chain_it, m_offset, m_limit);
279 }
280
281 ecs_iter_next_action_t next_action() const {
282 return ecs_page_next;
283 }
284
285 ecs_iter_next_action_t next_each_action() const {
286 return ecs_page_next;
287 }
288
289private:
290 ecs_iter_t m_chain_it;
291 int32_t m_offset;
292 int32_t m_limit;
293};
294
295template <typename ... Components>
297 int32_t offset,
298 int32_t limit)
299{
300 return page_iterable<Components...>(offset, limit, this);
301}
302
303template <typename ... Components>
304struct worker_iterable final : iterable<Components...> {
305 worker_iterable(int32_t offset, int32_t limit, iterable<Components...> *it)
306 : m_offset(offset)
307 , m_limit(limit)
308 {
309 m_chain_it = it->get_iter(nullptr);
310 }
311
312protected:
313 ecs_iter_t get_iter(flecs::world_t*) const {
314 return ecs_worker_iter(&m_chain_it, m_offset, m_limit);
315 }
316
317 ecs_iter_next_action_t next_action() const {
318 return ecs_worker_next;
319 }
320
321 ecs_iter_next_action_t next_each_action() const {
322 return ecs_worker_next;
323 }
324
325private:
326 ecs_iter_t m_chain_it;
327 int32_t m_offset;
328 int32_t m_limit;
329};
330
331template <typename ... Components>
333 int32_t index,
334 int32_t count)
335{
336 return worker_iterable<Components...>(index, count, this);
337}
338
339}
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:351
bool(* ecs_iter_next_action_t)(ecs_iter_t *it)
Function prototype for iterating an iterator.
Definition flecs.h:567
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.
bool ecs_page_next(ecs_iter_t *it)
Progress a paged iterator.
void ecs_query_set_group(ecs_iter_t *it, uint64_t group_id)
Set group to iterate for query iterator.
JSON iterable mixin.
Rule iterable mixin.
Iterable mixin.
Definition flecs.h:673
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:123
flecs::entity first() const
Return first entity matched by iterable.
Definition iterable.hpp:128
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:118
void iter(Func &&func) const
Iter iterator.
Definition iterable.hpp:70
page_iterable< Components... > page(int32_t offset, int32_t limit)
Page iterator.
Definition iterable.hpp:296
worker_iterable< Components... > worker(int32_t index, int32_t count)
Worker iterator.
Definition iterable.hpp:332
iter_iterable< Components... > iter(flecs::world_t *world=nullptr) const
Create iterator.
Definition iterable.hpp:261
The world.
Definition world.hpp:132