Flecs: include/flecs/addons/cpp/utils/iterable.hpp Source File
Description: A fast entity component system (ECS) for C & C++

| Flecs v4.1 A fast entity component system (ECS) for C & C++

Loading...
Searching...
No Matches
iterable.hpp
Go to the documentation of this file.
1
5
6namespace flecs {
7
8template <typename ... Components>
9struct iter_iterable;
10
11template <typename ... Components>
12 struct page_iterable;
13
14template <typename ... Components>
15struct worker_iterable;
16
17template <typename ... Components>
18 struct 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
109 flecs::entity first() const {
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>
155 struct 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 int var_id = ecs_query_find_var(it_.query, name);
174 ecs_assert(var_id != -1, ECS_INVALID_PARAMETER, name);
175 ecs_iter_set_var(&it_, var_id, value);
176 return *this;
177 }
178
179 iter_iterable<Components...>& set_var(const char *name, flecs::table_t *value) {
180 int var_id = ecs_query_find_var(it_.query, name);
181 ecs_assert(var_id != -1, ECS_INVALID_PARAMETER, name);
182 ecs_iter_set_var_as_table(&it_, var_id, value);
183 return *this;
184 }
185
186 iter_iterable<Components...>& set_var(const char *name, ecs_table_range_t value) {
187 int var_id = ecs_query_find_var(it_.query, name);
188 ecs_assert(var_id != -1, ECS_INVALID_PARAMETER, name);
189 ecs_iter_set_var_as_range(&it_, var_id, &value);
190 return *this;
191 }
192
193 iter_iterable<Components...>& set_var(const char *name, flecs::table_range value) {
194 ecs_table_range_t range;
195 range.table = value.get_table();
196 range.offset = value.offset();
197 range.count = value.count();
198 return set_var(name, range);
199 }
200
201# ifdef FLECS_JSON
202# include "../mixins/json/iterable.inl"
203# endif
204
205 // Return total number of entities in result.
206 int32_t count() {
207 int32_t result = 0;
208 while (next_each_(&it_)) {
209 result += it_.count;
210 }
211 return result;
212 }
213
214 // Returns true if iterator yields at least once result.
215 bool is_true() {
216 bool result = next_each_(&it_);
217 if (result) {
218 ecs_iter_fini(&it_);
219 }
220 return result;
221 }
222
223 // Return first matching entity.
224 flecs::entity first() {
225 flecs::entity result;
226 if (next_each_(&it_) && it_.count) {
227 result = flecs::entity(it_.world, it_.entities[0]);
228 ecs_iter_fini(&it_);
229 }
230 return result;
231 }
232
233 // Limit results to tables with specified group id (grouped queries only)
234 iter_iterable<Components...>& set_group(uint64_t group_id) {
235 ecs_iter_set_group(&it_, group_id);
236 return *this;
237 }
238
239 // Limit results to tables with specified group id (grouped queries only)
240 template <typename Group>
241 iter_iterable<Components...>& set_group() {
242 ecs_iter_set_group(&it_, _::type<Group>().id(it_.real_world));
243 return *this;
244 }
245
246protected:
247 ecs_iter_t get_iter(flecs::world_t *world) const override {
248 if (world) {
249 ecs_iter_t result = it_;
250 result.world = world;
251 return result;
252 }
253 return it_;
254 }
255
256 ecs_iter_next_action_t next_action() const override {
257 return next_;
258 }
259
260private:
261 ecs_iter_t it_;
262 ecs_iter_next_action_t next_;
263 ecs_iter_next_action_t next_each_;
264};
265
266template <typename ... Components>
267 iter_iterable<Components...> iterable<Components...>::iter(flecs::world_t *world) const
268{
269 return iter_iterable<Components...>(this, world);
270}
271
272template <typename ... Components>
273 iter_iterable<Components...> iterable<Components...>::iter(flecs::iter& it) const
274{
275 return iter_iterable<Components...>(this, it.world());
276}
277
278template <typename ... Components>
279 iter_iterable<Components...> iterable<Components...>::iter(flecs::entity e) const
280{
281 return iter_iterable<Components...>(this, e.world());
282}
283
284template <typename ... Components>
285 struct page_iterable final : iterable<Components...> {
286 template <typename Iterable>
287 page_iterable(int32_t offset, int32_t limit, Iterable *it)
288 : offset_(offset)
289 , limit_(limit)
290 {
291 chain_it_ = it->get_iter(nullptr);
292 }
293
294protected:
295 ecs_iter_t get_iter(flecs::world_t*) const {
296 return ecs_page_iter(&chain_it_, offset_, limit_);
297 }
298
299 ecs_iter_next_action_t next_action() const {
300 return ecs_page_next;
301 }
302
303private:
304 ecs_iter_t chain_it_;
305 int32_t offset_;
306 int32_t limit_;
307};
308
309template <typename ... Components>
310 page_iterable<Components...> iterable<Components...>::page(
311 int32_t offset,
312 int32_t limit)
313{
314 return page_iterable<Components...>(offset, limit, this);
315}
316
317template <typename ... Components>
318 struct worker_iterable final : iterable<Components...> {
319 worker_iterable(int32_t offset, int32_t limit, iterable<Components...> *it)
320 : offset_(offset)
321 , limit_(limit)
322 {
323 chain_it_ = it->get_iter(nullptr);
324 }
325
326protected:
327 ecs_iter_t get_iter(flecs::world_t*) const {
328 return ecs_worker_iter(&chain_it_, offset_, limit_);
329 }
330
331 ecs_iter_next_action_t next_action() const {
332 return ecs_worker_next;
333 }
334
335private:
336 ecs_iter_t chain_it_;
337 int32_t offset_;
338 int32_t limit_;
339};
340
341template <typename ... Components>
342 worker_iterable<Components...> iterable<Components...>::worker(
343 int32_t index,
344 int32_t count)
345{
346 return worker_iterable<Components...>(index, count, this);
347}
348
349}
ecs_assert
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:368
ecs_iter_t
struct ecs_iter_t ecs_iter_t
Type used for iterating iterable objects.
Definition flecs.h:447
flecs::component::range
untyped_component & range(double min, double max)
Add member value range.
Definition untyped_component.inl:246
ecs_iter_next_action_t
bool(* ecs_iter_next_action_t)(ecs_iter_t *it)
Function prototype for iterating an iterator.
Definition flecs.h:566
ecs_worker_iter
ecs_iter_t ecs_worker_iter(const ecs_iter_t *it, int32_t index, int32_t count)
Create a worker iterator.
ecs_iter_fini
void ecs_iter_fini(ecs_iter_t *it)
Cleanup iterator resources.
ecs_page_iter
ecs_iter_t ecs_page_iter(const ecs_iter_t *it, int32_t offset, int32_t limit)
Create a paged iterator.
ecs_iter_set_var
void ecs_iter_set_var(ecs_iter_t *it, int32_t var_id, ecs_entity_t entity)
Set value for iterator variable.
ecs_worker_next
bool ecs_worker_next(ecs_iter_t *it)
Progress a worker iterator.
ecs_iter_set_var_as_table
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.
ecs_page_next
bool ecs_page_next(ecs_iter_t *it)
Progress a paged iterator.
ecs_iter_set_var_as_range
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...
ecs_iter_set_group
void ecs_iter_set_group(ecs_iter_t *it, uint64_t group_id)
Set group to iterate for query iterator.
ecs_query_find_var
int32_t ecs_query_find_var(const ecs_query_t *query, const char *name)
Find variable index.
iterable.inl
JSON iterable mixin.
ecs_iter_t
Iterator.
Definition flecs.h:1142
ecs_iter_t::world
ecs_world_t * world
The world.
Definition flecs.h:1144
flecs::_::each_delegate
Definition delegate.hpp:229
flecs::_::find_delegate
Definition delegate.hpp:398
flecs::_::run_delegate
Definition delegate.hpp:553
flecs::_::type
Definition flecs.hpp:39
flecs::entity
Entity.
Definition entity.hpp:30
flecs::id::first
flecs::entity first() const
Get first element from a pair.
Definition impl.hpp:20
flecs::iter_iterable
Definition iterable.hpp:155
flecs::iter
Class for iterating over query results.
Definition iter.hpp:68
flecs::iterable
Definition iterable.hpp:18
flecs::iterable::is_true
bool is_true() const
Return whether iterable has any matches.
Definition iterable.hpp:104
flecs::iterable::run
void run(Func &&func) const
Run iterator.
Definition iterable.hpp:42
flecs::iterable::first
flecs::entity first() const
Return first entity matched by iterable.
Definition iterable.hpp:109
flecs::iterable::each
void each(Func &&func) const
Each iterator.
Definition iterable.hpp:28
flecs::iterable< Components... >::count
int32_t count() const
Definition iterable.hpp:99
flecs::iterable::page
page_iterable< Components... > page(int32_t offset, int32_t limit)
Page iterator.
Definition iterable.hpp:310
flecs::iterable::worker
worker_iterable< Components... > worker(int32_t index, int32_t count)
Worker iterator.
Definition iterable.hpp:342
flecs::iterable::iter
iter_iterable< Components... > iter(flecs::world_t *world=nullptr) const
Create iterator.
Definition iterable.hpp:267
flecs::page_iterable
Definition iterable.hpp:285
flecs::table_range
Definition table.hpp:412
flecs::table::get_table
table_t * get_table() const
Get table.
Definition table.hpp:398
flecs::worker_iterable
Definition iterable.hpp:318
flecs::world
The world.
Definition world.hpp:158