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) {
44template <
typename ... Components>
49 return populate(
iter, 0,
static_cast<
51 remove_pointer_t<Components>
>
59 bool populate(
const ecs_iter_t*,
size_t) {
return false; }
61 template <
typename T,
typename... Targs>
62 bool populate(
const ecs_iter_t *
iter,
size_t index, T, Targs... comps) {
63 terms_[index].ptr =
iter->ptrs[index];
64 bool is_ref =
iter->sources &&
iter->sources[index] != 0;
65 terms_[index].is_ref = is_ref;
66 is_ref |= populate(
iter, index + 1, comps ...);
75template <
typename T,
typename =
int>
81 : term_(
term), row_(row) { }
91 !is_empty<actual_type_t<T>>::value &&
is_actual<T>::value > >
98 return static_cast<T*
>(this->term_.ptr)[this->row_];
107 !is_empty<actual_type_t<T>>::value && !
is_actual<T>::value> >
114 return static_cast<actual_type_t<T>*
>(this->term_.ptr)[this->row_];
123 !is_pointer<T>::value > >
130 return actual_type_t<T>();
138 !is_empty<actual_type_t<T>>::value > >
144 actual_type_t<T> get_row() {
145 if (this->term_.ptr) {
146 return &
static_cast<actual_type_t<T>
>(this->term_.ptr)[this->row_];
156template <
typename T,
typename =
int>
174template <
typename Func,
typename ... Components>
176 using Terms =
typename term_ptrs<Components ...>::array;
178 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
180 : func_(FLECS_MOV(func)) { }
191 iter->flags |= EcsIterCppEach;
193 if (terms.populate(
iter)) {
194 invoke_unpack< each_ref_column >(
iter, func_, 0, terms.terms_);
196 invoke_unpack< each_column >(
iter, func_, 0, terms.terms_);
203 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
213 static void destruct(
void *obj) {
214 _::free_obj<each_delegate>(
static_cast<each_delegate*
>(obj));
221 iter->callback_ctx = ctx->on_add;
229 iter->callback_ctx = ctx->on_remove;
237 iter->callback_ctx = ctx->on_set;
242 static bool instanced() {
248 template <
template<
typename X,
typename =
int>
class ColumnType,
251 decltype(std::declval<const Fn&>()(
252 std::declval<flecs::entity>(),
253 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...), 0) = 0>
254 static void invoke_callback(
258 "no entities returned, use each() without flecs::entity argument");
261 (ColumnType< remove_reference_t<Components> >(comps, i)
266 template <
template<
typename X,
typename =
int>
class ColumnType,
269 decltype(std::declval<const Fn&>()(
270 std::declval<flecs::iter&>(),
271 std::declval<size_t&>(),
272 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...), 0) = 0>
273 static void invoke_callback(
277 func(it, i, (ColumnType< remove_reference_t<Components> >(comps, i)
282 template <
template<
typename X,
typename =
int>
class ColumnType,
285 decltype(std::declval<const Fn&>()(
286 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...), 0) = 0>
287 static void invoke_callback(
288 ecs_iter_t*,
const Func& func,
size_t i, Args... comps)
290 func((ColumnType< remove_reference_t<Components> >(comps, i)
294 template <
template<
typename X,
typename =
int>
class ColumnType,
295 typename... Args, if_t<
296 sizeof...(Components) ==
sizeof...(Args)> = 0>
297 static void invoke_unpack(
298 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
300 ECS_TABLE_LOCK(
iter->world,
iter->table);
302 size_t count =
static_cast<size_t>(
iter->count);
303 if (count == 0 && !
iter->table) {
309 for (
size_t i = 0; i < count; i ++) {
310 invoke_callback<ColumnType>(
iter, func, i, comps...);
313 ECS_TABLE_UNLOCK(
iter->world,
iter->table);
316 template <
template<
typename X,
typename =
int>
class ColumnType,
317 typename... Args, if_t<
sizeof...(Components) !=
sizeof...(Args) > = 0>
319 size_t index, Terms& columns, Args... comps)
321 invoke_unpack<ColumnType>(
322 iter, func, index + 1, columns, comps..., columns[index]);
329template <
typename Func,
typename ... Components>
331 using Terms =
typename term_ptrs<Components ...>::array;
333 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
335 : func_(FLECS_MOV(func)) { }
346 if (terms.populate(
iter)) {
347 return invoke_callback< each_ref_column >(
iter, func_, 0, terms.terms_);
349 return invoke_callback< each_column >(
iter, func_, 0, terms.terms_);
354 static bool instanced() {
361 template <
template<
typename X,
typename =
int>
class ColumnType,
364 if_t<
sizeof...(Components) ==
sizeof...(Args)> = 0,
365 decltype(bool(std::declval<const Fn&>()(
366 std::declval<flecs::entity>(),
367 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...))) =
true>
369 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
371 ECS_TABLE_LOCK(
iter->world,
iter->table);
374 size_t count =
static_cast<size_t>(
iter->count);
378 "no entities returned, use find() without flecs::entity argument");
380 for (
size_t i = 0; i < count; i ++) {
382 (ColumnType< remove_reference_t<Components> >(comps, i)
390 ECS_TABLE_UNLOCK(
iter->world,
iter->table);
397 template <
template<
typename X,
typename =
int>
class ColumnType,
400 if_t<
sizeof...(Components) ==
sizeof...(Args)> = 0,
401 decltype(bool(std::declval<const Fn&>()(
402 std::declval<flecs::iter&>(),
403 std::declval<size_t&>(),
404 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...))) =
true>
406 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
408 size_t count =
static_cast<size_t>(
iter->count);
418 ECS_TABLE_LOCK(
iter->world,
iter->table);
420 for (
size_t i = 0; i < count; i ++) {
421 if (func(it, i, (ColumnType< remove_reference_t<Components> >(comps, i)
429 ECS_TABLE_UNLOCK(
iter->world,
iter->table);
435 template <
template<
typename X,
typename =
int>
class ColumnType,
438 if_t<
sizeof...(Components) ==
sizeof...(Args)> = 0,
439 decltype(bool(std::declval<const Fn&>()(
440 std::declval<ColumnType< remove_reference_t<Components> > >().get_row()...))) =
true>
442 ecs_iter_t *
iter,
const Func& func,
size_t, Terms&, Args... comps)
444 size_t count =
static_cast<size_t>(
iter->count);
454 ECS_TABLE_LOCK(
iter->world,
iter->table);
456 for (
size_t i = 0; i < count; i ++) {
457 if (func( (ColumnType< remove_reference_t<Components> >(comps, i)
465 ECS_TABLE_UNLOCK(
iter->world,
iter->table);
470 template <
template<
typename X,
typename =
int>
class ColumnType,
471 typename... Args, if_t<
sizeof...(Components) !=
sizeof...(Args) > = 0>
473 size_t index, Terms& columns, Args... comps)
475 return invoke_callback<ColumnType>(
476 iter, func, index + 1, columns, comps..., columns[index]);
486template <
typename Func>
488 template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
490 : func_(FLECS_MOV(func)) { }
500 iter->flags &= ~EcsIterIsValid;
507 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
519template <
typename Func>
522 : func_(FLECS_MOV(func)) { }
530 template <
typename F,
531 decltype(std::declval<const F&>()(std::declval<flecs::entity>()), 0) = 0>
534 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
538 template <
typename F,
539 decltype(std::declval<const F&>()(), 0) = 0>
542 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
549template <
typename Func,
typename Event>
552 : func_(FLECS_MOV(func)) { }
560 template <
typename F,
561 decltype(std::declval<const F&>()(
562 std::declval<Event&>()), 0) = 0>
566 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
568 "entity observer invoked without payload");
570 Event *data =
static_cast<Event*
>(
iter->
param);
574 template <
typename F,
575 decltype(std::declval<const F&>()(
576 std::declval<flecs::entity>(),
577 std::declval<Event&>()), 0) = 0>
581 ecs_assert(self !=
nullptr, ECS_INTERNAL_ERROR, NULL);
583 "entity observer invoked without payload");
585 Event *data =
static_cast<Event*
>(
iter->
param);
597template<
typename ... Args>
600template<
typename ... Args>
607 static bool const_args() {
608 static flecs::array<bool,
sizeof...(Args)> is_const_args ({
609 flecs::is_const<flecs::remove_reference_t<Args>>::value...
612 for (
auto is_const : is_const_args) {
646 for (int32_t column : columns) {
675 template <
typename Func>
676 static bool invoke_read(world_t *
world, entity_t e,
const Func& func) {
688 bool has_components = get_ptrs(
world, e, r,
table, ptrs);
689 if (has_components) {
690 invoke_callback(func, 0, ptrs);
695 return has_components;
698 template <
typename Func>
699 static bool invoke_write(world_t *
world, entity_t e,
const Func& func) {
711 bool has_components = get_ptrs(
world, e, r,
table, ptrs);
712 if (has_components) {
713 invoke_callback(func, 0, ptrs);
718 return has_components;
721 template <
typename Func>
722 static bool invoke_get(world_t *
world, entity_t e,
const Func& func) {
724 return invoke_read(
world, e, func);
726 return invoke_write(
world, e, func);
743 template <
typename Func>
744 static bool invoke_ensure(world_t *
world, entity_t
id,
const Func& func) {
774 elem = store_added(added, elem, prev, next, w.
id<Args>()),
782 ids.
array = added.ptr();
783 ids.
count =
static_cast<ecs_size_t
>(elem);
788 if (!get_ptrs(w,
id, r,
table, ptrs)) {
796 ensure_ptrs(
world,
id, ptrs);
799 invoke_callback(func, 0, ptrs);
815 template <
typename Func,
typename ... TArgs,
816 if_t<
sizeof...(TArgs) ==
sizeof...(Args)> = 0>
817 static void invoke_callback(
818 const Func& f,
size_t,
ArrayType&, TArgs&& ... comps)
820 f(*
static_cast<typename base_arg_type<Args>::type*
>(comps)...);
823 template <
typename Func,
typename ... TArgs,
824 if_t<
sizeof...(TArgs) !=
sizeof...(Args)> = 0>
825 static void invoke_callback(
const Func& f,
size_t arg,
ArrayType& ptrs,
828 invoke_callback(f, arg + 1, ptrs, comps..., ptrs[arg]);
832template <
typename Func,
typename U =
int>
837template <
typename Func>
842 "function must have at least one argument");
848template <
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_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, 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.
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.
A type is a list of (component) ids.
ecs_id_t * array
Array with ids.
int32_t count
Number of elements in array.
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.