18 void *on_add =
nullptr;
19 void *on_remove =
nullptr;
20 void *on_set =
nullptr;
21 void *on_replace =
nullptr;
22 void *on_validate =
nullptr;
30 if (on_add && free_on_add) {
33 if (on_remove && free_on_remove) {
34 free_on_remove(on_remove);
36 if (on_set && free_on_set) {
39 if (on_replace && free_on_replace) {
40 free_on_replace(on_replace);
42 if (on_validate && free_on_validate) {
43 free_on_validate(on_validate);
56template <
typename ... Components>
61 populate_impl(
iter, std::index_sequence_for<Components...>{});
65 populate_self_impl(
iter, std::index_sequence_for<Components...>{});
73 using A = remove_pointer_t<actual_type_t<T>>;
74 if constexpr (!is_empty_v<A>) {
75 if (
iter->row_fields & (1llu << index)) {
77 fields_[index].is_row =
true;
78 fields_[index].is_ref =
true;
79 fields_[index].index =
static_cast<int8_t
>(index);
82 static_cast<int8_t
>(index));
83 fields_[index].is_ref =
iter->sources[index] != 0;
90 (void)
iter; (void)index;
92 using A = remove_pointer_t<actual_type_t<T>>;
93 if constexpr (!is_empty_v<A>) {
95 static_cast<int8_t
>(index));
96 fields_[index].is_ref =
false;
100 template <
size_t... Is>
101 void populate_impl(
const ecs_iter_t *
iter, std::index_sequence<Is...>) {
103 (populate_field<Components>(
iter, Is), ...);
106 template <
size_t... Is>
107 void populate_self_impl(
const ecs_iter_t *
iter, std::index_sequence<Is...>) {
109 (populate_self_field<Components>(
iter, Is), ...);
117template <
typename T,
typename =
int>
123 : field_(
field), row_(row) {
134 !is_empty<actual_type_t<T>>::value &&
is_actual<T>::value > >
141 return static_cast<T*
>(this->field_.ptr)[this->row_];
150 !is_empty<actual_type_t<T>>::value && !
is_actual<T>::value> >
157 return static_cast<actual_type_t<T>*
>(this->field_.ptr)[this->row_];
165 !is_pointer<T>::value > >
172 return actual_type_t<T>();
180 !is_empty<actual_type_t<T>>::value > >
186 actual_type_t<T> get_row() {
187 if (this->field_.ptr) {
188 return &
static_cast<actual_type_t<T>
>(this->field_.ptr)[this->row_];
198template <
typename T,
typename =
int>
200 using A = remove_pointer_t<actual_type_t<T>>;
218 static_cast<int32_t
>(row));
224template <
typename Func,
typename ... Components>
226 using Terms =
typename field_ptrs<Components ...>::array;
228 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
230 : func_(FLECS_MOV(func)) { }
241 iter->flags |= EcsIterCppEach;
243 if (
iter->ref_fields |
iter->up_fields) {
244 terms.populate(
iter);
245 invoke_unpack< each_ref_field >(
iter, func_, 0, terms.fields_);
247 terms.populate_self(
iter);
248 invoke_unpack< each_field >(
iter, func_, 0, terms.fields_);
275 static void destruct(
void *obj) {
276 _::free_obj<each_delegate>(obj);
283 iter->callback_ctx = ctx->on_add;
291 iter->callback_ctx = ctx->on_remove;
299 iter->callback_ctx = ctx->on_set;
307 iter->callback_ctx = ctx->on_replace;
313 template <
template<
typename X,
typename =
int>
class ColumnType,
316 decltype(std::declval<const Fn&>()(
317 std::declval<flecs::entity>(),
318 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...), 0) = 0>
319 static void invoke_callback(
323 "query does not return entities ($this variable is not populated)");
325 (ColumnType< remove_reference_t<Components> >(
iter, comps, i)
330 template <
template<
typename X,
typename =
int>
class ColumnType,
333 decltype(std::declval<const Fn&>()(
334 std::declval<flecs::iter&>(),
335 std::declval<size_t&>(),
336 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...), 0) = 0>
337 static void invoke_callback(
341 func(it, i, (ColumnType< remove_reference_t<Components> >(
iter, comps, i)
346 template <
template<
typename X,
typename =
int>
class ColumnType,
349 decltype(std::declval<const Fn&>()(
350 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...), 0) = 0>
351 static void invoke_callback(
354 func((ColumnType< remove_reference_t<Components> >(
iter, comps, i)
358 template <
template<
typename X,
typename =
int>
class ColumnType,
359 typename... Args,
if_t<
360 sizeof...(Components) ==
sizeof...(Args)> = 0>
361 static void invoke_unpack(
362 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
366 size_t count =
static_cast<size_t>(
iter->
count);
373 for (
size_t i = 0; i < count; i ++) {
374 invoke_callback<ColumnType>(
iter, func, i, comps...);
380 template <
template<
typename X,
typename =
int>
class ColumnType,
381 typename... Args,
if_t<
sizeof...(Components) !=
sizeof...(Args) > = 0>
383 size_t index, Terms& columns, Args... comps)
385 invoke_unpack<ColumnType>(
386 iter, func, index + 1, columns, comps..., columns[index]);
393template <
typename Func,
typename T>
395 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
397 : func_(FLECS_MOV(func)) { }
417template <
typename Func,
typename ... Components>
419 using Terms =
typename field_ptrs<Components ...>::array;
421 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
423 : func_(FLECS_MOV(func)) { }
434 iter->flags |= EcsIterCppEach;
436 if (
iter->ref_fields |
iter->up_fields) {
437 terms.populate(
iter);
438 return invoke_callback< each_ref_field >(
iter, func_, 0, terms.fields_);
440 terms.populate_self(
iter);
441 return invoke_callback< each_field >(
iter, func_, 0, terms.fields_);
448 template <
template<
typename X,
typename =
int>
class ColumnType,
451 if_t<
sizeof...(Components) ==
sizeof...(Args)> = 0,
452 decltype(bool(std::declval<const Fn&>()(
453 std::declval<flecs::entity>(),
454 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...))) =
true>
456 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
461 size_t count =
static_cast<size_t>(
iter->
count);
464 for (
size_t i = 0; i < count; i ++) {
466 (ColumnType< remove_reference_t<Components> >(
iter, comps, i)
481 template <
template<
typename X,
typename =
int>
class ColumnType,
484 if_t<
sizeof...(Components) ==
sizeof...(Args)> = 0,
485 decltype(bool(std::declval<const Fn&>()(
486 std::declval<flecs::iter&>(),
487 std::declval<size_t&>(),
488 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...))) =
true>
490 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
492 size_t count =
static_cast<size_t>(
iter->
count);
504 for (
size_t i = 0; i < count; i ++) {
506 (ColumnType< remove_reference_t<Components> >(
iter, comps, i)
520 template <
template<
typename X,
typename =
int>
class ColumnType,
523 if_t<
sizeof...(Components) ==
sizeof...(Args)> = 0,
524 decltype(bool(std::declval<const Fn&>()(
525 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...))) =
true>
527 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
529 size_t count =
static_cast<size_t>(
iter->
count);
541 for (
size_t i = 0; i < count; i ++) {
543 (ColumnType< remove_reference_t<Components> >(
iter, comps, i)
556 template <
template<
typename X,
typename =
int>
class ColumnType,
557 typename... Args,
if_t<
sizeof...(Components) !=
sizeof...(Args) > = 0>
559 size_t index, Terms& columns, Args... comps)
561 return invoke_callback<ColumnType>(
562 iter, func, index + 1, columns, comps..., columns[index]);
572template <
typename Func>
574 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
576 : func_(FLECS_MOV(func)) { }
586 iter->flags &= ~EcsIterIsValid;
605template <
typename Func>
608 : func_(FLECS_MOV(func)) { }
616 template <
typename F,
617 decltype(std::declval<const F&>()(std::declval<flecs::entity>()), 0) = 0>
624 template <
typename F,
625 decltype(std::declval<const F&>()(), 0) = 0>
635template <
typename Func,
typename Event>
638 : func_(FLECS_MOV(func)) { }
646 template <
typename F,
647 decltype(std::declval<const F&>()(
648 std::declval<Event&>()), 0) = 0>
654 "entity observer invoked without payload");
656 Event *data =
static_cast<Event*
>(
iter->
param);
660 template <
typename F,
661 decltype(std::declval<const F&>()(
662 std::declval<flecs::entity>(),
663 std::declval<Event&>()), 0) = 0>
669 "entity observer invoked without payload");
671 Event *data =
static_cast<Event*
>(
iter->
param);
683template<
typename ... Args>
686template<
typename ... Args>
693 static constexpr bool const_args() {
694 return (is_const_v<remove_reference_t<Args>> && ...);
718 for (int32_t column : columns) {
730 ptrs[i ++] = ecs_record_get_by_column(r, column, 0);
747 template <
typename Func>
760 bool has_components = get_ptrs(
world, e, r,
table, ptrs);
761 if (has_components) {
762 invoke_callback(func, 0, ptrs);
767 return has_components;
770 template <
typename Func>
783 bool has_components = get_ptrs(
world, e, r,
table, ptrs);
784 if (has_components) {
785 invoke_callback(func, 0, ptrs);
790 return has_components;
793 template <
typename Func>
795 if constexpr (const_args()) {
796 return invoke_read(
world, e, func);
798 return invoke_write(
world, e, func);
818 size_t component_count = 0;
822 static int invoke_add(
828 ecs_table_diff_t diff;
830 w, ctx.table, &component_id, &diff);
831 if (next != ctx.table) {
832 ctx.added[ctx.component_count] = component_id;
833 ctx.component_count ++;
835 if (diff.added_flags & EcsTableHasDontFragment) {
838 ctx.added[ctx.component_count] = component_id;
839 ctx.component_count ++;
848 template <
typename Func>
849 static bool invoke_ensure(
876 InvokeCtx ctx(table);
877 DummyArray dummy_before ({ (
878 invoke_add(w,
id, w.
id<Args>(), ctx)
884 if (table != ctx.table) {
886 ids.
array = ctx.added.ptr();
887 ids.
count =
static_cast<ecs_size_t
>(ctx.component_count);
888 ecs_commit(world,
id, r, ctx.table, &ids,
nullptr);
892 if (!get_ptrs(w,
id, r, table, ptrs)) {
896 ECS_TABLE_LOCK(world, table);
900 ensure_ptrs(world,
id, ptrs);
903 invoke_callback(func, 0, ptrs);
906 ECS_TABLE_UNLOCK(world, table);
910 DummyArray dummy_after ({
919 template <
typename Func,
typename ... TArgs,
920 if_t<
sizeof...(TArgs) ==
sizeof...(Args)> = 0>
921 static void invoke_callback(
922 const Func& f,
size_t, ArrayType&, TArgs&& ... comps)
924 f(*
static_cast<typename base_arg_type<Args>::type*
>(comps)...);
927 template <
typename Func,
typename ... TArgs,
928 if_t<
sizeof...(TArgs) !=
sizeof...(Args)> = 0>
929 static void invoke_callback(
const Func& f,
size_t arg, ArrayType& ptrs,
932 invoke_callback(f, arg + 1, ptrs, comps..., ptrs[arg]);
936template <
typename Func,
typename U =
int>
938 static_assert(function_traits<Func>::value,
"type is not callable");
941template <
typename Func>
945 static_assert(function_traits<Func>::arity > 0,
946 "function must have at least one argument");
950template <
typename ArgList>
953template <
typename ... Args>
955 using type = arg_list<remove_reference_t<Args>...>;
960template <
typename ArgList,
typename =
int>
965template <
typename First,
typename ... Args>
967 if_t<is_same<decay_t<First>, flecs::
entity>::value>> {
971template <
typename First,
typename Second,
typename ... Args>
973 if_t<is_same<decay_t<First>, flecs::
iter>::value>> {
985template <
typename Func,
typename ... Args>
#define ecs_assert(condition, error_code,...)
Assert.
#define ECS_INVALID_OPERATION
Invalid operation error code.
#define ECS_INVALID_PARAMETER
Invalid parameter error code.
#define ECS_INTERNAL_ERROR
Internal error code.
#define ecs_abort(error_code,...)
Abort.
const ecs_type_hooks_t * ecs_get_hooks_id(const ecs_world_t *world, ecs_entity_t component)
Get hooks for a component.
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::entity entity(Args &&... args) const
Create an entity.
flecs::id id(E value) const
Convert an enum constant to an entity.
ecs_table_t table_t
Table type.
ecs_entity_t entity_t
Entity type.
ecs_world_t world_t
World type.
void(* ecs_ctx_free_t)(void *ctx)
Function to clean up context data.
void ecs_modified_id(ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
Signal that a component has been modified.
void * ecs_get_mut_id(const ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
Get a mutable pointer to a component.
void * ecs_ensure_id(ecs_world_t *world, ecs_entity_t entity, ecs_id_t component, size_t size)
Ensure an entity has a component and return a pointer.
ecs_entity_t ecs_field_src(const ecs_iter_t *it, int8_t index)
Return the 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 a field at a specified row.
void * ecs_field_w_size(const ecs_iter_t *it, size_t size, int8_t index)
Get data for a field.
int32_t ecs_table_get_column_index(const ecs_world_t *world, const ecs_table_t *table, ecs_id_t component)
Get the column index for a component.
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) an entity to a table.
const ecs_world_t * ecs_get_world(const ecs_poly_t *poly)
Get the world from a poly.
void * binding_ctx
Language binding context.
A type is a list of (component) IDs.
ecs_id_t * array
Array with IDs.
int32_t count
Number of elements in array.
Extract the component argument list from an each-callback signature.
Strip references from each-callback argument types.
const Self & add() const
Add a component to an entity.
Wrapper class around a field.
Class that wraps around a flecs::id_t.
Test if a type is the same as its actual type.
Trait to check if a type is callable.
Class for iterating over query results.
flecs::table table() const
Get the table for the current iterator result.
void * param()
Access param.
size_t count() const
Get the number of entities to iterate over.
flecs::field< const flecs::entity_t > entities() const
Get read-only access to entity IDs.
bool next()
Progress iterator.
flecs::world world() const
Get the world associated with the iterator.
table()
Default constructor.
bool is_stage() const
Test if this is a stage.
bool is_deferred() const
Test whether deferring is enabled.
enable_if_t< V, int > if_t
Convenience enable_if alias using int as default type.