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_invoker>(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_invoker>(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_invoker>(e.world(), FLECS_FWD(func),
49 this->next_each_action());
50 }
51
63 template <typename Func>
64 void iter(Func&& func) const {
65 iterate<_::iter_invoker>(nullptr, FLECS_FWD(func),
66 this->next_action());
67 }
68
69 template <typename Func>
70 void iter(flecs::world_t *world, Func&& func) const {
71 iterate<_::iter_invoker>(world, FLECS_FWD(func),
72 this->next_action());
73 }
74
75 template <typename Func>
76 void iter(flecs::iter& it, Func&& func) const {
77 iterate<_::iter_invoker>(it.world(), FLECS_FWD(func),
78 this->next_action());
79 }
80
81 template <typename Func>
82 void iter(flecs::entity e, Func&& func) const {
83 iterate<_::iter_invoker>(e.world(), FLECS_FWD(func),
84 this->next_action());
85 }
86
90 iter_iterable<Components...> iter(flecs::world_t *world = nullptr) const;
91
99 page_iterable<Components...> page(int32_t offset, int32_t limit);
100
109 worker_iterable<Components...> worker(int32_t index, int32_t count);
110
112 int32_t count() const {
113 return this->iter().count();
114 }
115
117 bool is_true() const {
118 return this->iter().is_true();
119 }
120
123 return this->iter().first();
124 }
125
126 virtual ~iterable() { }
127protected:
128 friend iter_iterable<Components...>;
129 friend page_iterable<Components...>;
130 friend worker_iterable<Components...>;
131
132 virtual ecs_iter_t get_iter(flecs::world_t *stage) const = 0;
133 virtual ecs_iter_next_action_t next_action() const = 0;
134 virtual ecs_iter_next_action_t next_each_action() const = 0;
135
136 template < template<typename Func, typename ... Comps> class Invoker, typename Func, typename NextFunc, typename ... Args>
137 void iterate(flecs::world_t *stage, Func&& func, NextFunc next, Args &&... args) const {
138 ecs_iter_t it = this->get_iter(stage);
139 if (Invoker<Func, Components...>::instanced()) {
140 ECS_BIT_SET(it.flags, EcsIterIsInstanced);
141 }
142
143 while (next(&it, FLECS_FWD(args)...)) {
144 Invoker<Func, Components...>(func).invoke(&it);
145 }
146 }
147};
148
149template <typename ... Components>
150struct iter_iterable final : iterable<Components...> {
151 template <typename Iterable>
152 iter_iterable(Iterable *it, flecs::world_t *world)
153 {
154 m_it = it->get_iter(world);
155 m_next = it->next_action();
156 m_next_each = it->next_action();
157 }
158
159 iter_iterable<Components...>& set_var(int var_id, flecs::entity_t value) {
160 ecs_assert(var_id != -1, ECS_INVALID_PARAMETER, 0);
161 ecs_iter_set_var(&m_it, var_id, value);
162 return *this;
163 }
164
165# ifdef FLECS_RULES
166# include "../mixins/rule/iterable.inl"
167# endif
168# ifdef FLECS_JSON
169# include "../mixins/json/iterable.inl"
170# endif
171
172 // Return total number of entities in result.
173 int32_t count() {
174 int32_t result = 0;
175 while (m_next_each(&m_it)) {
176 result += m_it.count;
177 }
178 return result;
179 }
180
181 // Returns true if iterator yields at least once result.
182 bool is_true() {
183 bool result = m_next_each(&m_it);
184 if (result) {
185 ecs_iter_fini(&m_it);
186 }
187 return result;
188 }
189
190 // Return first matching entity.
191 flecs::entity first() {
192 flecs::entity result;
193 if (m_next_each(&m_it) && m_it.count) {
194 result = flecs::entity(m_it.world, m_it.entities[0]);
195 ecs_iter_fini(&m_it);
196 }
197 return result;
198 }
199
200 // Limit results to tables with specified group id (grouped queries only)
201 iter_iterable<Components...>& set_group(uint64_t group_id) {
202 ecs_query_set_group(&m_it, group_id);
203 return *this;
204 }
205
206 // Limit results to tables with specified group id (grouped queries only)
207 template <typename Group>
208 iter_iterable<Components...>& set_group() {
209 ecs_query_set_group(&m_it, _::cpp_type<Group>().id(m_it.real_world));
210 return *this;
211 }
212
213protected:
214 ecs_iter_t get_iter(flecs::world_t *world) const {
215 if (world) {
216 ecs_iter_t result = m_it;
217 result.world = world;
218 return result;
219 }
220 return m_it;
221 }
222
223 ecs_iter_next_action_t next_action() const {
224 return m_next;
225 }
226
227 ecs_iter_next_action_t next_each_action() const {
228 return m_next_each;
229 }
230
231private:
232 ecs_iter_t m_it;
234 ecs_iter_next_action_t m_next_each;
235};
236
237template <typename ... Components>
238iter_iterable<Components...> iterable<Components...>::iter(flecs::world_t *world) const
239{
240 return iter_iterable<Components...>(this, world);
241}
242
243template <typename ... Components>
244struct page_iterable final : iterable<Components...> {
245 template <typename Iterable>
246 page_iterable(int32_t offset, int32_t limit, Iterable *it)
247 : m_offset(offset)
248 , m_limit(limit)
249 {
250 m_chain_it = it->get_iter(nullptr);
251 }
252
253protected:
254 ecs_iter_t get_iter(flecs::world_t*) const {
255 return ecs_page_iter(&m_chain_it, m_offset, m_limit);
256 }
257
258 ecs_iter_next_action_t next_action() const {
259 return ecs_page_next;
260 }
261
262 ecs_iter_next_action_t next_each_action() const {
263 return ecs_page_next;
264 }
265
266private:
267 ecs_iter_t m_chain_it;
268 int32_t m_offset;
269 int32_t m_limit;
270};
271
272template <typename ... Components>
274 int32_t offset,
275 int32_t limit)
276{
277 return page_iterable<Components...>(offset, limit, this);
278}
279
280template <typename ... Components>
281struct worker_iterable final : iterable<Components...> {
282 worker_iterable(int32_t offset, int32_t limit, iterable<Components...> *it)
283 : m_offset(offset)
284 , m_limit(limit)
285 {
286 m_chain_it = it->get_iter(nullptr);
287 }
288
289protected:
290 ecs_iter_t get_iter(flecs::world_t*) const {
291 return ecs_worker_iter(&m_chain_it, m_offset, m_limit);
292 }
293
294 ecs_iter_next_action_t next_action() const {
295 return ecs_worker_next;
296 }
297
298 ecs_iter_next_action_t next_each_action() const {
299 return ecs_worker_next;
300 }
301
302private:
303 ecs_iter_t m_chain_it;
304 int32_t m_offset;
305 int32_t m_limit;
306};
307
308template <typename ... Components>
310 int32_t index,
311 int32_t count)
312{
313 return worker_iterable<Components...>(index, count, this);
314}
315
316}
#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:407
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.
Entity.
Definition: entity.hpp:30
Class for iterating over query results.
Definition: iter.hpp:169
bool is_true() const
Return whether iterable has any matches.
Definition: iterable.hpp:117
flecs::entity first() const
Return first entity matched by iterable.
Definition: iterable.hpp:122
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:112
void iter(Func &&func) const
Iter iterator.
Definition: iterable.hpp:64
page_iterable< Components... > page(int32_t offset, int32_t limit)
Page iterator.
Definition: iterable.hpp:273
worker_iterable< Components... > worker(int32_t index, int32_t count)
Worker iterator.
Definition: iterable.hpp:309
iter_iterable< Components... > iter(flecs::world_t *world=nullptr) const
Create iterator.
Definition: iterable.hpp:238
The world.
Definition: world.hpp:113