16 void *on_add =
nullptr;
17 void *on_remove =
nullptr;
18 void *on_set =
nullptr;
24 if (on_add && free_on_add) {
27 if (on_remove && free_on_remove) {
28 free_on_remove(on_remove);
30 if (on_set && free_on_set) {
42template <
typename ... Components>
46 bool populate(
const ecs_iter_t *
iter) {
47 return populate(
iter, 0,
static_cast<
49 remove_pointer_t<Components>
>
57 bool populate(
const ecs_iter_t*,
size_t) {
return false; }
59 template <
typename T,
typename... Targs>
60 bool populate(
const ecs_iter_t *
iter,
size_t index, T, Targs... comps) {
61 m_terms[index].ptr =
iter->ptrs[index];
62 bool is_ref =
iter->sources &&
iter->sources[index] != 0;
63 m_terms[index].is_ref = is_ref;
64 is_ref |= populate(
iter, index + 1, comps ...);
73template <
typename T,
typename =
int>
79 : m_term(
term), m_row(row) { }
89 !is_empty<actual_type_t<T>>::value &&
is_actual<T>::value > >
96 return static_cast<T*
>(this->m_term.ptr)[this->m_row];
105 !is_empty<actual_type_t<T>>::value && !
is_actual<T>::value> >
112 return static_cast<actual_type_t<T>*
>(this->m_term.ptr)[this->m_row];
121 !is_pointer<T>::value > >
128 return actual_type_t<T>();
136 !is_empty<actual_type_t<T>>::value > >
142 actual_type_t<T> get_row() {
143 if (this->m_term.ptr) {
144 return &
static_cast<actual_type_t<T>
>(this->m_term.ptr)[this->m_row];
154template <
typename T,
typename =
int>
172template <
typename Func,
typename ... Components>
176 static constexpr bool PassEntity =
181 static constexpr bool PassIter =
185 "each() must have at least one argument");
187 using Terms =
typename term_ptrs<Components ...>::array;
189 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
191 : m_func(FLECS_MOV(func)) { }
193 explicit each_delegate(
const Func& func) noexcept
199 void invoke(ecs_iter_t *iter)
const {
200 term_ptrs<Components...> terms;
202 iter->flags |= EcsIterCppEach;
204 if (terms.populate(iter)) {
205 invoke_callback< each_ref_column >(iter, m_func, 0, terms.m_terms);
207 invoke_callback< each_column >(iter, m_func, 0, terms.m_terms);
212 static void run(ecs_iter_t *iter) {
213 auto self =
static_cast<const each_delegate*
>(iter->binding_ctx);
214 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
219 static each_delegate* make(
const Func& func) {
220 return FLECS_NEW(each_delegate)(func);
224 static void destruct(
void *obj) {
225 _::free_obj<each_delegate>(
static_cast<each_delegate*
>(obj));
229 static void run_add(ecs_iter_t *iter) {
230 component_binding_ctx *ctx =
reinterpret_cast<component_binding_ctx*
>(
232 iter->binding_ctx = ctx->on_add;
237 static void run_remove(ecs_iter_t *iter) {
238 component_binding_ctx *ctx =
reinterpret_cast<component_binding_ctx*
>(
240 iter->binding_ctx = ctx->on_remove;
245 static void run_set(ecs_iter_t *iter) {
246 component_binding_ctx *ctx =
reinterpret_cast<component_binding_ctx*
>(
248 iter->binding_ctx = ctx->on_set;
253 static bool instanced() {
260 template <
template<
typename X,
typename =
int>
class ColumnType,
261 typename... Args, if_t<
262 sizeof...(Components) ==
sizeof...(Args) && PassEntity> = 0>
263 static void invoke_callback(
264 ecs_iter_t *iter,
const Func& func,
size_t, Terms&, Args... comps)
266 ECS_TABLE_LOCK(iter->world, iter->table);
269 size_t count =
static_cast<size_t>(iter->count);
271 for (
size_t i = 0; i < count; i ++) {
273 (ColumnType< remove_reference_t<Components> >(comps, i)
277 ECS_TABLE_UNLOCK(iter->world, iter->table);
282 template <
template<
typename X,
typename =
int>
class ColumnType,
283 typename... Args,
int Enabled = PassIter, if_t<
284 sizeof...(Components) ==
sizeof...(Args) && Enabled> = 0>
285 static void invoke_callback(
286 ecs_iter_t *iter,
const Func& func,
size_t, Terms&, Args... comps)
288 size_t count =
static_cast<size_t>(iter->count);
289 if (count == 0 && !iter->table) {
297 ECS_TABLE_LOCK(iter->world, iter->table);
299 for (
size_t i = 0; i < count; i ++) {
300 func(it, i, (ColumnType< remove_reference_t<Components> >(comps, i)
304 ECS_TABLE_UNLOCK(iter->world, iter->table);
308 template <
template<
typename X,
typename =
int>
class ColumnType,
309 typename... Args, if_t<
310 sizeof...(Components) ==
sizeof...(Args) && !PassEntity && !PassIter> = 0>
311 static void invoke_callback(
312 ecs_iter_t *iter,
const Func& func,
size_t, Terms&, Args... comps)
314 size_t count =
static_cast<size_t>(iter->count);
315 if (count == 0 && !iter->table) {
323 ECS_TABLE_LOCK(iter->world, iter->table);
325 for (
size_t i = 0; i < count; i ++) {
326 func( (ColumnType< remove_reference_t<Components> >(comps, i)
330 ECS_TABLE_UNLOCK(iter->world, iter->table);
333 template <
template<
typename X,
typename =
int>
class ColumnType,
334 typename... Args, if_t<
sizeof...(Components) !=
sizeof...(Args) > = 0>
335 static void invoke_callback(ecs_iter_t *iter,
const Func& func,
336 size_t index, Terms& columns, Args... comps)
338 invoke_callback<ColumnType>(
339 iter, func, index + 1, columns, comps..., columns[index]);
345template <
typename Func,
typename ... Components>
349 static constexpr bool PassEntity =
354 static constexpr bool PassIter =
358 "each() must have at least one argument");
360 using Terms =
typename term_ptrs<Components ...>::array;
362 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
364 : m_func(FLECS_MOV(func)) { }
375 if (terms.populate(
iter)) {
376 return invoke_callback< each_ref_column >(
iter, m_func, 0, terms.m_terms);
378 return invoke_callback< each_column >(
iter, m_func, 0, terms.m_terms);
383 static bool instanced() {
390 template <
template<
typename X,
typename =
int>
class ColumnType,
391 typename... Args, if_t<
392 sizeof...(Components) ==
sizeof...(Args) && PassEntity> = 0>
394 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
396 ECS_TABLE_LOCK(
iter->world,
iter->table);
399 size_t count =
static_cast<size_t>(
iter->count);
403 "no entities returned, use find() without flecs::entity argument");
405 for (
size_t i = 0; i < count; i ++) {
407 (ColumnType< remove_reference_t<Components> >(comps, i)
415 ECS_TABLE_UNLOCK(
iter->world,
iter->table);
422 template <
template<
typename X,
typename =
int>
class ColumnType,
423 typename... Args,
int Enabled = PassIter, if_t<
424 sizeof...(Components) ==
sizeof...(Args) && Enabled> = 0>
426 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
428 size_t count =
static_cast<size_t>(
iter->count);
438 ECS_TABLE_LOCK(
iter->world,
iter->table);
440 for (
size_t i = 0; i < count; i ++) {
441 if (func(it, i, (ColumnType< remove_reference_t<Components> >(comps, i)
449 ECS_TABLE_UNLOCK(
iter->world,
iter->table);
455 template <
template<
typename X,
typename =
int>
class ColumnType,
456 typename... Args, if_t<
457 sizeof...(Components) ==
sizeof...(Args) && !PassEntity && !PassIter> = 0>
459 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
461 size_t count =
static_cast<size_t>(
iter->count);
471 ECS_TABLE_LOCK(
iter->world,
iter->table);
473 for (
size_t i = 0; i < count; i ++) {
474 if (func( (ColumnType< remove_reference_t<Components> >(comps, i)
482 ECS_TABLE_UNLOCK(
iter->world,
iter->table);
487 template <
template<
typename X,
typename =
int>
class ColumnType,
488 typename... Args, if_t<
sizeof...(Components) !=
sizeof...(Args) > = 0>
490 size_t index, Terms& columns, Args... comps)
492 return invoke_callback<ColumnType>(
493 iter, func, index + 1, columns, comps..., columns[index]);
503template <
typename Func,
typename ... Components>
508 using Terms =
typename term_ptrs<Components ...>::array;
511 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
513 : m_func(FLECS_MOV(func)) { }
521 void invoke(ecs_iter_t *
iter)
const {
523 terms.populate(
iter);
524 invoke_callback(
iter, m_func, 0, terms.m_terms);
528 static void run(ecs_iter_t *
iter) {
530 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
535 static bool instanced() {
540 template <
typename... Args, if_t<!
sizeof...(Args) && IterOnly> = 0>
541 static void invoke_callback(ecs_iter_t *
iter,
const Func& func,
542 size_t, Terms&, Args...)
546 ECS_TABLE_LOCK(
iter->world,
iter->table);
550 ECS_TABLE_UNLOCK(
iter->world,
iter->table);
553 template <
typename... Targs, if_t<!IterOnly &&
554 (
sizeof...(Targs) ==
sizeof...(Components))> = 0>
555 static void invoke_callback(ecs_iter_t *
iter,
const Func& func,
size_t,
556 Terms&, Targs... comps)
560 ECS_TABLE_LOCK(
iter->world,
iter->table);
562 func(it, (
static_cast<
565 actual_type_t<Components>
> >* >
568 ECS_TABLE_UNLOCK(
iter->world,
iter->table);
571 template <
typename... Targs, if_t<!IterOnly &&
572 (
sizeof...(Targs) !=
sizeof...(Components)) > = 0>
573 static void invoke_callback(ecs_iter_t *
iter,
const Func& func,
574 size_t index, Terms& columns, Targs... comps)
576 invoke_callback(
iter, func, index + 1, columns, comps...,
588template <
typename Func>
591 : m_func(FLECS_MOV(func)) { }
594 static void run(ecs_iter_t *
iter) {
598 template <typename F, if_t<arity<F>::value == 1> = 0>
599 static void invoke(ecs_iter_t *
iter) {
601 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
605 template <typename F, if_t<arity<F>::value == 0> = 0>
606 static void invoke(ecs_iter_t *
iter) {
608 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
615template <
typename Func,
typename Event>
618 : m_func(FLECS_MOV(func)) { }
621 static void run(ecs_iter_t *
iter) {
626 template <typename F, if_t<arity<F>::value == 1> = 0>
627 static void invoke(ecs_iter_t *
iter) {
630 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
632 "entity observer invoked without payload");
634 Event *data =
static_cast<Event*
>(
iter->
param);
638 template <typename F, if_t<arity<F>::value == 2> = 0>
639 static void invoke(ecs_iter_t *
iter) {
642 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
644 "entity observer invoked without payload");
646 Event *data =
static_cast<Event*
>(
iter->
param);
658template<
typename ... Args>
661template<
typename ... Args>
668 static bool const_args() {
669 static flecs::array<bool,
sizeof...(Args)> is_const_args ({
670 flecs::is_const<flecs::remove_reference_t<Args>>::value...
673 for (
auto is_const : is_const_args) {
701 for (int32_t column : columns) {
723 template <
typename Func>
724 static bool invoke_read(world_t *
world, entity_t e,
const Func& func) {
736 bool has_components = get_ptrs(
world, r,
table, ptrs);
737 if (has_components) {
738 invoke_callback(func, 0, ptrs);
743 return has_components;
746 template <
typename Func>
747 static bool invoke_write(world_t *
world, entity_t e,
const Func& func) {
759 bool has_components = get_ptrs(
world, r,
table, ptrs);
760 if (has_components) {
761 invoke_callback(func, 0, ptrs);
766 return has_components;
769 template <
typename Func>
770 static bool invoke_get(world_t *
world, entity_t e,
const Func& func) {
772 return invoke_read(
world, e, func);
774 return invoke_write(
world, e, func);
791 template <
typename Func>
792 static bool invoke_ensure(world_t *
world, entity_t
id,
const Func& func) {
822 elem = store_added(added, elem, prev, next, w.
id<Args>()),
830 ids.array = added.ptr();
831 ids.count =
static_cast<ecs_size_t
>(elem);
836 if (!get_ptrs(w, r,
table, ptrs)) {
844 ensure_ptrs(
world,
id, ptrs);
847 invoke_callback(func, 0, ptrs);
863 template <
typename Func,
typename ... TArgs,
864 if_t<
sizeof...(TArgs) ==
sizeof...(Args)> = 0>
865 static void invoke_callback(
866 const Func& f,
size_t,
ArrayType&, TArgs&& ... comps)
868 f(*
static_cast<typename base_arg_type<Args>::type*
>(comps)...);
871 template <
typename Func,
typename ... TArgs,
872 if_t<
sizeof...(TArgs) !=
sizeof...(Args)> = 0>
873 static void invoke_callback(
const Func& f,
size_t arg,
ArrayType& ptrs,
876 invoke_callback(f, arg + 1, ptrs, comps..., ptrs[arg]);
880template <
typename Func,
typename U =
int>
885template <
typename Func>
890 "function must have at least one argument");
896template <
typename Func,
typename ... Args>
#define ecs_assert(condition, error_code,...)
Assert.
#define ecs_abort(error_code,...)
Abort.
ecs_id_t ecs_entity_t
An entity identifier.
struct ecs_world_t ecs_world_t
A world is the container for all ECS data and supporting features.
struct ecs_record_t ecs_record_t
Information about an entity, like its table and row.
struct ecs_table_t ecs_table_t
A table stores entities and components for a specific type.
flecs::id id(E value) const
Convert enum constant to entity.
void(* ecs_ctx_free_t)(void *ctx)
Function to cleanup context data.
void ecs_read_end(const ecs_record_t *record)
End read access to entity.
void * ecs_ensure_id(ecs_world_t *world, ecs_entity_t entity, ecs_id_t id)
Get a mutable pointer to a component.
void ecs_write_end(ecs_record_t *record)
End exclusive write access to entity.
ecs_record_t * ecs_write_begin(ecs_world_t *world, ecs_entity_t entity)
Begin exclusive write access to entity.
void ecs_modified_id(ecs_world_t *world, ecs_entity_t entity, ecs_id_t id)
Signal that a component has been modified.
const ecs_record_t * ecs_read_begin(ecs_world_t *world, ecs_entity_t entity)
Begin read access to entity.
ecs_entity_t ecs_field_src(const ecs_iter_t *it, int32_t index)
Return field source.
ecs_table_t * ecs_table_add_id(ecs_world_t *world, ecs_table_t *table, ecs_id_t id)
Get table that has all components of current table plus the specified id.
int32_t ecs_table_column_count(const ecs_table_t *table)
Return number of columns in table.
bool ecs_commit(ecs_world_t *world, ecs_entity_t entity, ecs_record_t *record, ecs_table_t *table, const ecs_type_t *added, const ecs_type_t *removed)
Commit (move) entity to a table.
int32_t ecs_table_get_column_index(const ecs_world_t *world, const ecs_table_t *table, ecs_id_t id)
Get column index for id.
void * ecs_record_get_column(const ecs_record_t *r, int32_t column, size_t c_size)
Get component pointer from column/record.
ecs_record_t * ecs_record_find(const ecs_world_t *world, ecs_entity_t entity)
Find record for entity.
const ecs_world_t * ecs_get_world(const ecs_poly_t *poly)
Get world from poly.
A type is a list of (component) ids.
Class that wraps around a flecs::id_t.
Class for iterating over query results.
void * param()
Access param.
flecs::field< const flecs::entity_t > entities() const
Get readonly access to entity ids.
Class that describes a term.
bool is_stage() const
Test if is a stage.
bool is_deferred() const
Test whether deferring is enabled.