18 void *on_add =
nullptr;
19 void *on_remove =
nullptr;
20 void *on_set =
nullptr;
26 if (on_add && free_on_add) {
29 if (on_remove && free_on_remove) {
30 free_on_remove(on_remove);
32 if (on_set && free_on_set) {
46template <
typename ... Components>
51 populate(
iter, 0,
static_cast<
53 remove_pointer_t<Components>
>
58 populate_self(
iter, 0,
static_cast<
60 remove_pointer_t<Components>
>
69 template <
typename T,
typename... Targs,
70 typename A = remove_pointer_t<actual_type_t<T>>,
71 if_not_t< is_empty<A>::value > = 0>
72 void populate(
const ecs_iter_t *
iter,
size_t index, T, Targs... comps) {
73 if (
iter->row_fields & (1llu << index)) {
75 fields_[index].is_row =
true;
76 fields_[index].is_ref =
true;
77 fields_[index].index =
static_cast<int8_t
>(index);
80 static_cast<int8_t
>(index));
81 fields_[index].is_ref =
iter->sources[index] != 0;
84 populate(
iter, index + 1, comps ...);
87 template <
typename T,
typename... Targs,
88 typename A = remove_pointer_t<actual_type_t<T>>,
89 if_t< is_empty<A>::value > = 0>
90 void populate(
const ecs_iter_t *
iter,
size_t index, T, Targs... comps) {
91 populate(
iter, index + 1, comps ...);
94 void populate_self(
const ecs_iter_t*,
size_t) { }
96 template <
typename T,
typename... Targs,
97 typename A = remove_pointer_t<actual_type_t<T>>,
98 if_not_t< is_empty<A>::value > = 0>
99 void populate_self(
const ecs_iter_t *
iter,
size_t index, T, Targs... comps) {
101 static_cast<int8_t
>(index));
102 populate_self(
iter, index + 1, comps ...);
105 template <
typename T,
typename... Targs,
106 typename A = remove_pointer_t<actual_type_t<T>>,
107 if_t< is_empty<A>::value > = 0>
108 void populate_self(
const ecs_iter_t *
iter,
size_t index, T, Targs... comps) {
109 populate(
iter, index + 1, comps ...);
117template <
typename T,
typename =
int>
123 : field_(
field), row_(row) { }
133 !is_empty<actual_type_t<T>>::value &&
is_actual<T>::value > >
140 return static_cast<T*
>(this->field_.ptr)[this->row_];
149 !is_empty<actual_type_t<T>>::value && !
is_actual<T>::value> >
156 return static_cast<actual_type_t<T>*
>(this->field_.ptr)[this->row_];
163struct each_field<T, if_t< is_empty<actual_type_t<T>>::value &&
164 !is_pointer<T>::value > >
171 return actual_type_t<T>();
179 !is_empty<actual_type_t<T>>::value > >
185 actual_type_t<T> get_row() {
186 if (this->field_.ptr) {
187 return &
static_cast<actual_type_t<T>
>(this->field_.ptr)[this->row_];
197template <
typename T,
typename =
int>
215 static_cast<int8_t
>(row));
222template <
typename Func,
typename ... Components>
224 using Terms =
typename field_ptrs<Components ...>::array;
226 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
228 : func_(FLECS_MOV(func)) { }
230 explicit each_delegate(
const Func& func) noexcept
237 field_ptrs<Components...> terms;
239 iter->
flags |= EcsIterCppEach;
242 terms.populate(iter);
243 invoke_unpack< each_ref_field >(iter, func_, 0, terms.fields_);
245 terms.populate_self(iter);
246 invoke_unpack< each_field >(iter, func_, 0, terms.fields_);
252 auto self =
static_cast<const each_delegate*
>(iter->
callback_ctx);
253 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
258 static each_delegate* make(
const Func& func) {
259 return FLECS_NEW(each_delegate)(func);
263 static void destruct(
void *obj) {
264 _::free_obj<each_delegate>(
static_cast<each_delegate*
>(obj));
269 component_binding_ctx *ctx =
reinterpret_cast<component_binding_ctx*
>(
277 component_binding_ctx *ctx =
reinterpret_cast<component_binding_ctx*
>(
285 component_binding_ctx *ctx =
reinterpret_cast<component_binding_ctx*
>(
293 template <
template<
typename X,
typename =
int>
class ColumnType,
296 decltype(std::declval<const Fn&>()(
297 std::declval<flecs::entity>(),
298 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...), 0) = 0>
299 static void invoke_callback(
300 ecs_iter_t *iter,
const Func& func,
size_t i, Args... comps)
303 "no entities returned, use each() without flecs::entity argument");
306 (ColumnType< remove_reference_t<Components> >(iter, comps, i)
311 template <
template<
typename X,
typename =
int>
class ColumnType,
314 decltype(std::declval<const Fn&>()(
315 std::declval<flecs::iter&>(),
316 std::declval<size_t&>(),
317 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...), 0) = 0>
318 static void invoke_callback(
319 ecs_iter_t *iter,
const Func& func,
size_t i, Args... comps)
322 func(it, i, (ColumnType< remove_reference_t<Components> >(iter, comps, i)
327 template <
template<
typename X,
typename =
int>
class ColumnType,
330 decltype(std::declval<const Fn&>()(
331 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...), 0) = 0>
332 static void invoke_callback(
333 ecs_iter_t *iter,
const Func& func,
size_t i, Args... comps)
335 func((ColumnType< remove_reference_t<Components> >(iter, comps, i)
339 template <
template<
typename X,
typename =
int>
class ColumnType,
340 typename... Args, if_t<
341 sizeof...(Components) ==
sizeof...(Args)> = 0>
342 static void invoke_unpack(
343 ecs_iter_t *iter,
const Func& func,
size_t, Terms&, Args... comps)
347 size_t count =
static_cast<size_t>(iter->
count);
348 if (count == 0 && !iter->
table) {
354 for (
size_t i = 0; i < count; i ++) {
355 invoke_callback<ColumnType>(iter, func, i, comps...);
361 template <
template<
typename X,
typename =
int>
class ColumnType,
362 typename... Args, if_t<
sizeof...(Components) !=
sizeof...(Args) > = 0>
363 static void invoke_unpack(
ecs_iter_t *iter,
const Func& func,
364 size_t index, Terms& columns, Args... comps)
366 invoke_unpack<ColumnType>(
367 iter, func, index + 1, columns, comps..., columns[index]);
374template <
typename Func,
typename ... Components>
376 using Terms =
typename field_ptrs<Components ...>::array;
378 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
380 : func_(FLECS_MOV(func)) { }
391 iter->flags |= EcsIterCppEach;
393 if (
iter->ref_fields |
iter->up_fields) {
394 terms.populate(
iter);
395 return invoke_callback< each_ref_field >(
iter, func_, 0, terms.fields_);
397 terms.populate_self(
iter);
398 return invoke_callback< each_field >(
iter, func_, 0, terms.fields_);
405 template <
template<
typename X,
typename =
int>
class ColumnType,
408 if_t<
sizeof...(Components) ==
sizeof...(Args)> = 0,
409 decltype(bool(std::declval<const Fn&>()(
410 std::declval<flecs::entity>(),
411 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...))) =
true>
413 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
415 ECS_TABLE_LOCK(
iter->world,
iter->table);
418 size_t count =
static_cast<size_t>(
iter->count);
422 "no entities returned, use find() without flecs::entity argument");
424 for (
size_t i = 0; i < count; i ++) {
426 (ColumnType< remove_reference_t<Components> >(
iter, comps, i)
434 ECS_TABLE_UNLOCK(
iter->world,
iter->table);
441 template <
template<
typename X,
typename =
int>
class ColumnType,
444 if_t<
sizeof...(Components) ==
sizeof...(Args)> = 0,
445 decltype(bool(std::declval<const Fn&>()(
446 std::declval<flecs::iter&>(),
447 std::declval<size_t&>(),
448 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...))) =
true>
450 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
452 size_t count =
static_cast<size_t>(
iter->count);
462 ECS_TABLE_LOCK(
iter->world,
iter->table);
464 for (
size_t i = 0; i < count; i ++) {
466 (ColumnType< remove_reference_t<Components> >(
iter, comps, i)
474 ECS_TABLE_UNLOCK(
iter->world,
iter->table);
480 template <
template<
typename X,
typename =
int>
class ColumnType,
483 if_t<
sizeof...(Components) ==
sizeof...(Args)> = 0,
484 decltype(bool(std::declval<const Fn&>()(
485 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...))) =
true>
487 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
489 size_t count =
static_cast<size_t>(
iter->count);
499 ECS_TABLE_LOCK(
iter->world,
iter->table);
501 for (
size_t i = 0; i < count; i ++) {
503 (ColumnType< remove_reference_t<Components> >(
iter, comps, i)
511 ECS_TABLE_UNLOCK(
iter->world,
iter->table);
516 template <
template<
typename X,
typename =
int>
class ColumnType,
517 typename... Args, if_t<
sizeof...(Components) !=
sizeof...(Args) > = 0>
519 size_t index, Terms& columns, Args... comps)
521 return invoke_callback<ColumnType>(
522 iter, func, index + 1, columns, comps..., columns[index]);
532template <
typename Func>
534 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
536 : func_(FLECS_MOV(func)) { }
546 iter->flags &= ~EcsIterIsValid;
553 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
565template <
typename Func>
568 : func_(FLECS_MOV(func)) { }
576 template <
typename F,
577 decltype(std::declval<const F&>()(std::declval<flecs::entity>()), 0) = 0>
580 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
584 template <
typename F,
585 decltype(std::declval<const F&>()(), 0) = 0>
588 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
595template <
typename Func,
typename Event>
598 : func_(FLECS_MOV(func)) { }
606 template <
typename F,
607 decltype(std::declval<const F&>()(
608 std::declval<Event&>()), 0) = 0>
612 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
614 "entity observer invoked without payload");
616 Event *data =
static_cast<Event*
>(
iter->
param);
620 template <
typename F,
621 decltype(std::declval<const F&>()(
622 std::declval<flecs::entity>(),
623 std::declval<Event&>()), 0) = 0>
627 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
629 "entity observer invoked without payload");
631 Event *data =
static_cast<Event*
>(
iter->
param);
643template<
typename ... Args>
646template<
typename ... Args>
653 static bool const_args() {
654 static flecs::array<bool,
sizeof...(Args)> is_const_args ({
655 flecs::is_const<flecs::remove_reference_t<Args>>::value...
658 for (
auto is_const : is_const_args) {
692 for (int32_t column : columns) {
721 template <
typename Func>
722 static bool invoke_read(world_t *
world, entity_t e,
const Func& func) {
734 bool has_components = get_ptrs(
world, e, r,
table, ptrs);
735 if (has_components) {
736 invoke_callback(func, 0, ptrs);
741 return has_components;
744 template <
typename Func>
745 static bool invoke_write(world_t *
world, entity_t e,
const Func& func) {
757 bool has_components = get_ptrs(
world, e, r,
table, ptrs);
758 if (has_components) {
759 invoke_callback(func, 0, ptrs);
764 return has_components;
767 template <
typename Func>
768 static bool invoke_get(world_t *
world, entity_t e,
const Func& func) {
770 return invoke_read(
world, e, func);
772 return invoke_write(
world, e, func);
789 template <
typename Func>
790 static bool invoke_ensure(world_t *
world, entity_t
id,
const Func& func) {
820 elem = store_added(added, elem, prev, next, w.
id<Args>()),
828 ids.
array = added.ptr();
829 ids.
count =
static_cast<ecs_size_t
>(elem);
834 if (!get_ptrs(w,
id, r,
table, ptrs)) {
842 ensure_ptrs(
world,
id, ptrs);
845 invoke_callback(func, 0, ptrs);
861 template <
typename Func,
typename ... TArgs,
862 if_t<
sizeof...(TArgs) ==
sizeof...(Args)> = 0>
863 static void invoke_callback(
864 const Func& f,
size_t,
ArrayType&, TArgs&& ... comps)
866 f(*
static_cast<typename base_arg_type<Args>::type*
>(comps)...);
869 template <
typename Func,
typename ... TArgs,
870 if_t<
sizeof...(TArgs) !=
sizeof...(Args)> = 0>
871 static void invoke_callback(
const Func& f,
size_t arg,
ArrayType& ptrs,
874 invoke_callback(f, arg + 1, ptrs, comps..., ptrs[arg]);
878template <
typename Func,
typename U =
int>
883template <
typename Func>
888 "function must have at least one argument");
894template <
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_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_get_mut_id(const ecs_world_t *world, ecs_entity_t entity, ecs_id_t id)
Get a mutable pointer to a component.
void * ecs_record_get_by_column(const ecs_record_t *record, int32_t column, size_t size)
Get component pointer from column/record.
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.
ecs_record_t * ecs_record_find(const ecs_world_t *world, ecs_entity_t entity)
Find record for entity.
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, int8_t index)
Return field source.
void * ecs_field_at_w_size(const ecs_iter_t *it, size_t size, int8_t index, int32_t row)
Get data for field at specified row.
void * ecs_field_w_size(const ecs_iter_t *it, size_t size, int8_t index)
Get data for field.
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.
bool ecs_table_has_flags(ecs_table_t *table, ecs_flags32_t flags)
Test table for flags.
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.
const ecs_world_t * ecs_get_world(const ecs_poly_t *poly)
Get world from poly.
ecs_flags32_t ref_fields
Bitset with fields that aren't component arrays.
ecs_flags32_t flags
Iterator flags.
ecs_table_t * table
Current table.
ecs_world_t * world
The world.
void * callback_ctx
Callback language binding context.
ecs_flags32_t up_fields
Bitset with fields matched through up traversal.
int32_t count
Number of entities to iterate.
const ecs_entity_t * entities
Entity identifiers.
ecs_table_t * table
Identifies a type (and table) in world.
A type is a list of (component) ids.
ecs_id_t * array
Array with ids.
int32_t count
Number of elements in array.
Wrapper class around a field.
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.
bool is_stage() const
Test if is a stage.
bool is_deferred() const
Test whether deferring is enabled.