17 enum Hook { OnAdd, OnRemove, OnSet, OnReplace, OnValidate, Count };
18 void *callbacks[Count] = {};
22 for (
size_t i = 0; i < Count; i ++) {
23 if (callbacks[i] && free[i]) {
24 free[i](callbacks[i]);
38template <
typename ... Components>
43 populate_impl(
iter, std::index_sequence_for<Components...>{});
47 populate_self_impl(
iter, std::index_sequence_for<Components...>{});
55 using A = remove_pointer_t<actual_type_t<T>>;
56 if constexpr (!is_empty_v<A>) {
57 if (
iter->row_fields & (1llu << index)) {
59 fields_[index].is_row =
true;
60 fields_[index].is_ref =
true;
61 fields_[index].index =
static_cast<int8_t
>(index);
64 static_cast<int8_t
>(index));
65 fields_[index].is_ref =
iter->sources[index] != 0;
72 (void)
iter; (void)index;
74 using A = remove_pointer_t<actual_type_t<T>>;
75 if constexpr (!is_empty_v<A>) {
77 static_cast<int8_t
>(index));
78 fields_[index].is_ref =
false;
82 template <
size_t... Is>
83 void populate_impl(
const ecs_iter_t *
iter, std::index_sequence<Is...>) {
85 (populate_field<Components>(
iter, Is), ...);
88 template <
size_t... Is>
89 void populate_self_impl(
const ecs_iter_t *
iter, std::index_sequence<Is...>) {
91 (populate_self_field<Components>(
iter, Is), ...);
97template <
typename T,
bool Ref = false>
104 : iter_(
iter), field_(
field), row_(row) { }
106 decltype(
auto) get_row() {
107 using A = actual_type_t<T>;
108 if constexpr (is_empty<A>::value && !is_pointer<T>::value) {
118 sizeof(remove_pointer_t<A>), field_.index,
119 static_cast<int32_t
>(row_));
122 if constexpr (is_pointer<T>::value) {
123 return field_.ptr ? &
static_cast<A
>(field_.ptr)[row] :
nullptr;
124 }
else if constexpr (is_actual<T>::value) {
125 return static_cast<T*
>(field_.ptr)[row];
127 return T(
static_cast<A*
>(field_.ptr)[row]);
134template <
typename Func,
typename ... Components>
138 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
139 explicit each_delegate(Func&& func) noexcept
140 : func_(FLECS_MOV(func)) { }
142 explicit each_delegate(
const Func& func) noexcept
149 invoke_until<false>(
iter);
154 auto self =
static_cast<const each_delegate*
>(
iter->callback_ctx);
162 auto self =
static_cast<const each_delegate*
>(
iter->run_ctx);
170 static each_delegate* make(
const Func& func) {
171 return FLECS_NEW(each_delegate)(func);
175 static void destruct(
void *obj) {
176 _::free_obj<each_delegate>(obj);
179 template <component_binding_ctx::Hook Hook>
182 auto self =
static_cast<const each_delegate*
>(ctx->callbacks[Hook]);
184 iter->callback_ctx = ctx->callbacks[Hook];
185 self->template invoke_until<
false,
186 Hook != component_binding_ctx::OnReplace>(
iter);
190 template <
bool Find,
bool Shared = true>
193 iter->flags |= EcsIterCppEach;
194 if (Shared && (
iter->ref_fields |
iter->up_fields)) {
195 terms.populate(
iter);
196 return invoke_rows<Find, true>(
iter, terms.fields_,
197 std::index_sequence_for<Components...>{});
199 terms.populate_self(
iter);
200 return invoke_rows<Find, false>(
iter, terms.fields_,
201 std::index_sequence_for<Components...>{});
206 template <
typename... Args>
207 static decltype(
auto) invoke_callback(
210 if constexpr (std::is_invocable_v<
const Func&,
flecs::entity, Args...>) {
212 "query does not return entities ($this variable is not populated)");
215 }
else if constexpr (std::is_invocable_v<
219 return func(it, i, FLECS_FWD(args)...);
221 return func(FLECS_FWD(args)...);
225 template <
bool Find,
bool Ref,
size_t... I>
227 std::index_sequence<I...>)
const
230 size_t count =
static_cast<size_t>(
iter->
count);
231 if constexpr (Find) {
232 if constexpr (!std::is_invocable_v<
const Func&,
flecs::entity,
234 remove_reference_t<Components>, Ref>>().get_row())...>)
245 for (
size_t i = 0; i < count; i ++) {
246 if constexpr (Find) {
247 if (invoke_callback(
iter, func_, i,
248 each_field<remove_reference_t<Components>, Ref>(
249 iter, terms[I], i).get_row()...))
255 invoke_callback(
iter, func_, i,
256 each_field<remove_reference_t<Components>, Ref>(
257 iter, terms[I], i).get_row()...);
268template <
typename Func,
typename T>
270 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
271 explicit validate_delegate(Func&& func) noexcept
272 : func_(FLECS_MOV(func)) { }
274 explicit validate_delegate(
const Func& func) noexcept
283 auto self =
static_cast<const validate_delegate*
>(ctx->callbacks[component_binding_ctx::OnValidate]);
292template <
typename Func,
typename ... Components>
294 using each_delegate<Func, Components...>::each_delegate;
297 return this->
template invoke_until<true>(
iter);
305template <
typename Func>
307 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
308 explicit run_delegate(Func&& func) noexcept
309 : func_(FLECS_MOV(func)) { }
311 explicit run_delegate(
const Func& func) noexcept
319 iter->flags &= ~EcsIterIsValid;
325 auto self =
static_cast<const run_delegate*
>(
iter->run_ctx);
338template <
typename Func,
typename Event =
void>
340 template <
typename F>
341 explicit entity_observer_delegate(F&& func) noexcept
342 : func_(FLECS_FWD(func)) { }
345 auto self =
static_cast<const entity_observer_delegate*
>(
iter->callback_ctx);
347 if constexpr (std::is_void_v<Event> || is_empty_v<Event>) {
351 "entity observer invoked without payload");
357 template <
typename... Args>
359 if constexpr (std::is_invocable_v<
const Func&,
flecs::entity, Args&...>) {
373template <
typename ArgList>
376template <
typename... Args>
387 for (
auto id : ids) {
390 ecs_record_get_by_column(record, column, 0);
399 template <
typename Func>
402 if (!record || !record->table) {
411 invoke_callback(func, ptrs, std::index_sequence_for<Args...>{});
417 template <
typename Func>
426 flecs_add_ids(
world,
entity, ids.ptr(),
static_cast<int32_t
>(
sizeof...(Args)));
436 invoke_callback(func, ptrs, std::index_sequence_for<Args...>{});
440 for (
auto id : ids) {
447 template <
typename Func,
size_t... I>
448 static void invoke_callback(
const Func& func, ArrayType& ptrs, std::index_sequence<I...>) {
453template <
typename Func,
typename =
int>
455 static_assert(arity<Func>::value > 0,
"function must have at least one argument");
459template <
typename ArgList,
bool Normalize>
462template <
bool Normalize,
typename ... Args>
464 using type = arg_list<conditional_t<Normalize, remove_reference_t<Args>, Args>...>;
469template <
typename ArgList,
typename =
int,
bool Normalize = true>
474template <
bool Normalize,
typename First,
typename ... Args>
480template <
bool Normalize,
typename First,
typename Second,
typename ... Args>
487 typename Desc,
typename Func>
488void set_callback(Desc& desc, Func&& func) {
489 (Run ? desc.run : desc.callback) = Action;
490 (Run ? desc.run_ctx : desc.callback_ctx) = FLECS_NEW(Delegate)(FLECS_FWD(func));
491 (Run ? desc.run_ctx_free : desc.callback_ctx_free) = free_obj<Delegate>;
494template <
bool Run,
typename Desc,
typename Func,
typename... Components>
495void set_each_callback(Desc& desc, Func&& func, arg_list<Components...>) {
496 using Delegate = each_delegate<decay_t<Func>, Components...>;
497 set_callback<Delegate, Run ? Delegate::run_each : Delegate::run, Run>(
498 desc, FLECS_FWD(func));
509template <
typename Func,
typename ... Args>
_::each_delegate< typename std::decay< Func >::type, Args... > delegate
Delegate type for each callbacks.
#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.
bool ecs_is_deferred(const ecs_world_t *world)
Test if deferring is enabled for the current stage.
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.
ecs_iter_t iter_t
Iterator type.
ecs_entity_t entity_t
Entity type.
ecs_world_t world_t
World type.
typename base_arg_type< T >::type base_arg_type_t
Convenience alias for base_arg_type.
void(*) ecs_ctx_free_t(void *ctx)
Function to clean up context data.
void(*) ecs_iter_action_t(ecs_iter_t *it)
Function prototype for iterables.
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.
const ecs_world_t * ecs_get_world(const ecs_poly_t *poly)
Get the world from a poly.
#define flecs_poly_is(object, type)
Test if a pointer is of the specified type.
void * binding_ctx
Language binding context.
Extract the component argument list from an each-callback signature.
Strip references from each-callback argument types.
Array class (primary template, disabled).
Wrapper class around a field.
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.
enable_if_t< V, int > if_t
Convenience enable_if alias using int as default type.