code: updated flecs to 2.4.1

isolation_bkp/dynres
Dominik Madarász 2021-08-15 18:32:11 +02:00
parent 2b891f1cb1
commit 148ddcd2c0
5 changed files with 523 additions and 300 deletions

View File

@ -10,6 +10,7 @@ typedef enum {
// NOTE(zaklaus): Special actions
RPKIND_SPAWN_CAR,
RPKIND_PLACE_ICE_RINK,
RPKIND_SPAWN_CIRCLING_DRIVER,
} replay_kind;
typedef struct {
@ -150,6 +151,7 @@ void debug_replay_run(void) {
}
void ActPlaceIceRink();
void ActSpawnCirclingDriver(void);
void debug_replay_update(void) {
if (!is_playing) return;
@ -178,6 +180,9 @@ void debug_replay_update(void) {
case RPKIND_PLACE_ICE_RINK: {
ActPlaceIceRink();
}break;
case RPKIND_SPAWN_CIRCLING_DRIVER: {
ActSpawnCirclingDriver();
}break;
default: {
ZPL_PANIC("unreachable");
}break;

View File

@ -112,6 +112,7 @@ static debug_item items[] = {
.items = (debug_item[]) {
{ .kind = DITEM_BUTTON, .name = "spawn car", .on_click = ActSpawnCar },
{ .kind = DITEM_BUTTON, .name = "place ice rink", .on_click = ActPlaceIceRink },
{ .kind = DITEM_BUTTON, .name = "spawn circling driver", .on_click = ActSpawnCirclingDriver },
{
.kind = DITEM_LIST,
.name = "demo npcs",

View File

@ -18,6 +18,30 @@ ActSpawnCar(void) {
debug_replay_special_action(RPKIND_SPAWN_CAR);
}
void
ActSpawnCirclingDriver(void) {
ecs_entity_t plr = camera_get().ent_id;
ecs_entity_t ve = vehicle_spawn();
ecs_entity_t e = entity_spawn(EKIND_DEMO_NPC);
Position const *origin = ecs_get(world_ecs(), plr, Position);
Position *veh_dest = ecs_get_mut(world_ecs(), ve, Position, NULL);
Position *dest = ecs_get_mut(world_ecs(), e, Position, NULL);
*veh_dest = *origin;
*dest = *origin;
Input *input = ecs_get_mut(world_ecs(), e, Input, NULL);
input->x = input->y = 1.0f;
input->use = false;
Vehicle *veh = ecs_get_mut(world_ecs(), ve, Vehicle, NULL);
veh->seats[0] = e;
ecs_set(world_ecs(), e, IsInVehicle, { .veh = ve });
debug_replay_special_action(RPKIND_SPAWN_CIRCLING_DRIVER);
}
void
ActPlaceIceRink(void) {
ecs_entity_t plr = camera_get().ent_id;

View File

@ -2950,6 +2950,7 @@ void dtor_component(
int16_t size = column->size;
int16_t alignment = column->alignment;
ecs_assert(column->data != NULL, ECS_INTERNAL_ERROR, NULL);
void *ptr = ecs_vector_get_t(column->data, size, alignment, row);
ecs_assert(ptr != NULL, ECS_INTERNAL_ERROR, NULL);
@ -4549,6 +4550,9 @@ bool flecs_table_match_filter(
const ecs_table_t *table,
const ecs_filter_t * filter)
{
ecs_assert(world != NULL, ECS_INTERNAL_ERROR, NULL);
ecs_assert(table != NULL, ECS_INTERNAL_ERROR, NULL);
if (!filter) {
return true;
}
@ -4767,13 +4771,13 @@ void* get_base_component(
ecs_type_t type = table->type;
ecs_id_t *ids = ecs_vector_first(type, ecs_id_t);
int32_t i = tr_isa->column, count = tr_isa->count;
int32_t i = tr_isa->column, end = tr_isa->count + tr_isa->column;
void *ptr = NULL;
do {
ecs_id_t pair = ids[i];
ecs_id_t pair = ids[i ++];
ecs_entity_t base = ecs_pair_object(world, pair);
ecs_record_t *r = ecs_eis_get(world, base);
if (!r) {
continue;
@ -4794,8 +4798,7 @@ void* get_base_component(
int32_t row = flecs_record_to_row(r->row, &is_monitored);
ptr = get_component_w_index(table, tr->column, row);
}
i ++;
} while (!ptr && (i < count));
} while (!ptr && (i < end));
return ptr;
}
@ -6275,7 +6278,7 @@ ecs_entity_t ecs_new_id(
}
ecs_assert(!unsafe_world->stats.max_id ||
entity <= unsafe_world->stats.max_id,
ecs_entity_t_lo(entity) <= unsafe_world->stats.max_id,
ECS_OUT_OF_RANGE, NULL);
return entity;
@ -6444,7 +6447,7 @@ ecs_table_t *traverse_from_expr(
if (ptr) {
ecs_term_t term = {0};
while (ptr[0] && (ptr = ecs_parse_term(world, name, expr, ptr, &term))){
if (!ecs_term_is_set(&term)) {
if (!ecs_term_is_initialized(&term)) {
break;
}
@ -6530,7 +6533,7 @@ void defer_from_expr(
if (ptr) {
ecs_term_t term = {0};
while (ptr[0] && (ptr = ecs_parse_term(world, name, expr, ptr, &term))) {
if (!ecs_term_is_set(&term)) {
if (!ecs_term_is_initialized(&term)) {
break;
}
@ -7891,6 +7894,8 @@ ecs_entity_t ecs_get_case(
ecs_assert(ecs_is_valid(world, entity), ECS_INVALID_PARAMETER, NULL);
ecs_assert(ecs_is_valid(world, sw_id), ECS_INVALID_PARAMETER, NULL);
world = ecs_get_world(world);
ecs_entity_info_t info;
ecs_table_t *table;
if (!flecs_get_info(world, entity, &info) || !(table = info.table)) {
@ -11270,7 +11275,7 @@ int ecs_plecs_from_str(
}
while (ptr[0] && (ptr = ecs_parse_term(world, name, expr, ptr, &term))) {
if (!ecs_term_is_set(&term)) {
if (!ecs_term_is_initialized(&term)) {
break;
}
@ -12203,10 +12208,7 @@ ecs_data_t* duplicate_data(
ecs_entity_t component = components[i];
ecs_column_t *column = &result->columns[i];
if (component > ECS_HI_COMPONENT_ID) {
column->data = NULL;
continue;
}
component = ecs_get_typeid(world, component);
const ecs_type_info_t *cdata = flecs_get_c_info(world, component);
int16_t size = column->size;
@ -12287,7 +12289,6 @@ ecs_snapshot_t* snapshot_create(
}
ecs_table_leaf_t *l = ecs_vector_add(&result->tables, ecs_table_leaf_t);
l->table = t;
l->type = t->type;
l->data = duplicate_data(world, t, data);
@ -16601,6 +16602,12 @@ bool ecs_id_match(
return false;
}
bool ecs_id_is_pair(
ecs_id_t id)
{
return ECS_HAS_ROLE(id, PAIR);
}
bool ecs_id_is_wildcard(
ecs_id_t id)
{
@ -16620,7 +16627,7 @@ bool ecs_term_id_is_set(
return id->entity != 0 || id->name != NULL;
}
bool ecs_term_is_set(
bool ecs_term_is_initialized(
const ecs_term_t *term)
{
return term->id != 0 || ecs_term_id_is_set(&term->pred);
@ -16819,7 +16826,7 @@ int ecs_filter_init(
} else {
terms = (ecs_term_t*)desc->terms;
for (i = 0; i < ECS_TERM_CACHE_SIZE; i ++) {
if (!ecs_term_is_set(&terms[i])) {
if (!ecs_term_is_initialized(&terms[i])) {
break;
}
@ -16848,7 +16855,7 @@ int ecs_filter_init(
const char *ptr = desc->expr;
ecs_term_t term = {0};
while (ptr[0] && (ptr = ecs_parse_term(world, name, expr, ptr, &term))){
if (!ecs_term_is_set(&term)) {
if (!ecs_term_is_initialized(&term)) {
break;
}
@ -16925,6 +16932,42 @@ error:
return -1;
}
void ecs_filter_copy(
ecs_filter_t *dst,
const ecs_filter_t *src)
{
if (src) {
*dst = *src;
if (src->terms == src->term_cache) {
dst->terms = dst->term_cache;
} else {
/* Copying allocated term arrays is unsupported at this moment */
ecs_abort(ECS_UNSUPPORTED, NULL);
}
} else {
ecs_os_memset_t(dst, 0, ecs_filter_t);
}
}
void ecs_filter_move(
ecs_filter_t *dst,
ecs_filter_t *src)
{
if (src) {
*dst = *src;
if (src->terms == src->term_cache) {
dst->terms = dst->term_cache;
}
src->terms = NULL;
src->term_count = 0;
} else {
ecs_os_memset_t(dst, 0, ecs_filter_t);
}
}
void ecs_filter_fini(
ecs_filter_t *filter)
{
@ -17195,6 +17238,10 @@ bool flecs_filter_match_table(
result = !result;
}
if (oper == EcsOptional) {
result = true;
}
if (is_or) {
or_result |= result;
} else if (!result) {
@ -17215,19 +17262,17 @@ bool flecs_filter_match_table(
int32_t t_i = term->index;
void **ptr = ptrs ? &ptrs[t_i] : NULL;
bool has_data = populate_from_column(world, table, term->id, column,
populate_from_column(world, table, term->id, column,
source, &ids[t_i], &types[t_i], &subjects[t_i], &sizes[t_i],
ptr);
if (!source) {
if (has_data) {
if (column != -1) {
columns[t_i] = column + 1;
} else {
columns[t_i] = 0;
}
}
}
}
return !is_or || or_result;
}
@ -19717,8 +19762,6 @@ add_pair:
references = add_ref(world, query, references, term,
component, entity);
table_data.columns[c] = -ecs_vector_count(references);
} else {
table_data.columns[c] = 0;
}
table_data.subjects[c] = entity;
@ -19729,9 +19772,7 @@ add_pair:
const EcsComponent *cptr = ecs_get(world, type_id, EcsComponent);
if (!cptr || !cptr->size) {
int32_t column = table_data.columns[c];
if (column > 0) {
table_data.columns[c] = 0;
} else if (column) {
if (column < 0) {
ecs_ref_t *r = ecs_vector_get(
references, ecs_ref_t, -column - 1);
r->component = 0;
@ -21877,11 +21918,12 @@ void mark_columns_dirty(
for (i = 0; i < count; i ++) {
ecs_term_t *term = &terms[i];
ecs_term_id_t *subj = &term->args[0];
if (term->inout != EcsIn && (term->inout != EcsInOutDefault ||
(subj->entity == EcsThis && subj->set.mask == EcsSelf)))
{
int32_t table_column = table_data->columns[c];
if (table_column > 0) {
if (table_column > 0 && table_column <= table->column_count) {
table->dirty_state[table_column] ++;
}
}
@ -23708,6 +23750,7 @@ bool ecs_term_is_owned(
int32_t term)
{
ecs_assert(it->is_valid, ECS_INVALID_PARAMETER, NULL);
ecs_assert(term > 0, ECS_INVALID_PARAMETER, NULL);
return it->subjects == NULL || it->subjects[term - 1] == 0;
}
@ -23716,6 +23759,7 @@ bool ecs_term_is_readonly(
int32_t term_index)
{
ecs_assert(it->is_valid, ECS_INVALID_PARAMETER, NULL);
ecs_assert(term_index > 0, ECS_INVALID_PARAMETER, NULL);
ecs_query_t *query = it->query;
@ -23747,6 +23791,17 @@ bool ecs_term_is_readonly(
return false;
}
bool ecs_term_is_set(
const ecs_iter_t *it,
int32_t term)
{
ecs_assert(it->is_valid, ECS_INVALID_PARAMETER, NULL);
ecs_assert(it->columns != NULL, ECS_INTERNAL_ERROR, NULL);
ecs_assert(term > 0, ECS_INVALID_PARAMETER, NULL);
return it->columns[term - 1] != 0;
}
ecs_entity_t ecs_term_source(
const ecs_iter_t *it,
int32_t term)
@ -24179,7 +24234,7 @@ ecs_entity_t ecs_trigger_init(
goto error;
}
if (!ecs_term_is_set(&term)) {
if (!ecs_term_is_initialized(&term)) {
ecs_parser_error(
name, expr, 0, "invalid empty trigger expression");
goto error;

View File

@ -1109,6 +1109,8 @@ private:
int m_index;
};
/* C++ class mainly used as wrapper around internal ecs_vector_t. Do not use
* this class as a replacement for STL datastructures! */
template <typename T>
class vector {
public:
@ -1150,6 +1152,10 @@ public:
ecs_vector_clear(m_vector);
}
void destruct() {
ecs_vector_free(m_vector);
}
void add(T& value) {
T* elem = static_cast<T*>(_ecs_vector_add(&m_vector, ECS_VECTOR_T(T)));
*elem = value;
@ -1402,6 +1408,8 @@ void ecs_map_memory(
namespace flecs {
/* C++ class mainly used as wrapper around internal ecs_map_t. Do not use
* this class as a replacement for STL datastructures! */
template <typename K, typename T>
class map {
public:
@ -1437,6 +1445,10 @@ public:
reinterpret_cast<ecs_map_key_t>(key)));
}
void destruct() {
ecs_map_free(m_map);
}
private:
void init(size_t count) {
m_map = ecs_map_new(T, static_cast<ecs_size_t>(count));
@ -2549,6 +2561,7 @@ struct ecs_iter_t {
ecs_table_t *table; /**< Current table */
ecs_data_t *data;
ecs_id_t *ids;
ecs_type_t *types;
int32_t *columns;
@ -6061,7 +6074,7 @@ bool ecs_term_id_is_set(
* @return True when set, false when not set.
*/
FLECS_API
bool ecs_term_is_set(
bool ecs_term_is_initialized(
const ecs_term_t *term);
/** Test whether a term is a trivial term.
@ -6166,6 +6179,15 @@ bool ecs_id_match(
ecs_id_t id,
ecs_id_t pattern);
/** Utility to check if id is a pair.
*
* @param id The id.
* @return True if id is a pair.
*/
FLECS_API
bool ecs_id_is_pair(
ecs_id_t id);
/** Utility to check if id is a wildcard.
*
* @param id The id.
@ -6272,6 +6294,18 @@ FLECS_API
bool ecs_filter_next(
ecs_iter_t *iter);
/** Move resources of one filter to another. */
FLECS_API
void ecs_filter_move(
ecs_filter_t *dst,
ecs_filter_t *src);
/** Copy resources of one filter to another. */
FLECS_API
void ecs_filter_copy(
ecs_filter_t *dst,
const ecs_filter_t *src);
/** @} */
/**
@ -6673,6 +6707,20 @@ bool ecs_term_is_readonly(
const ecs_iter_t *it,
int32_t index);
/** Test whether term is set.
* This function returns false for terms with the Not operator and for terms
* with the Optional operator if the matched entities (table) do not have the
* (component) id of the term.
*
* @param it The iterator.
* @param term The term.
* @return True if term is set, false if it is not set.
*/
FLECS_API
bool ecs_term_is_set(
const ecs_iter_t *it,
int32_t term);
/** Test whether the term is owned
* This operation returns whether the term is owned by the currently iterated
* entity. This function will return false when the term is owned by another
@ -9248,13 +9296,15 @@ class type;
class pipeline;
class iter;
class term;
class filter;
class filter_iterator;
class child_iterator;
class world_filter;
class snapshot_filter;
class query_base;
template<typename ... Components>
class filter;
template<typename ... Components>
class query;
@ -9264,6 +9314,9 @@ class system;
template<typename ... Components>
class observer;
template <typename ... Components>
class filter_builder;
template <typename ... Components>
class query_builder;
@ -9448,6 +9501,7 @@ using std::is_const;
using std::is_pointer;
using std::is_reference;
using std::is_volatile;
using std::is_same;
// Apply cv modifiers from source type to destination type
@ -9966,6 +10020,7 @@ struct function_traits
} // _
template <typename T>
struct is_callable {
static constexpr bool value = _::function_traits<T>::is_callable;
@ -9982,6 +10037,23 @@ using return_type_t = typename _::function_traits<T>::return_type;
template <typename T>
using arg_list_t = typename _::function_traits<T>::args;
template<typename Func, typename ... Args>
struct first_arg_impl;
template<typename Func, typename T, typename ... Args>
struct first_arg_impl<Func, _::arg_list<T, Args ...> > {
using type = T;
};
template<typename Func>
struct first_arg {
using type = typename first_arg_impl<Func, arg_list_t<Func>>::type;
};
template <typename Func>
using first_arg_t = typename first_arg<Func>::type;
} // flecs
namespace flecs
{
@ -10833,7 +10905,7 @@ public:
* @param index The term index.
*/
bool is_set(int32_t index) const {
return ecs_term_w_size(m_iter, 0, index) != NULL;
return ecs_term_is_set(m_iter, index);
}
/** Returns whether term is readonly.
@ -11744,89 +11816,6 @@ public:
*/
void use(flecs::entity entity, const char *alias = nullptr);
/** Delete all entities matching a filter.
*
* @param filter The filter to use for matching.
*/
void delete_entities(flecs::filter filter) const;
/** Add component to all entities matching a filter.
*
* @tparam T The component to add.
* @param filter The filter to use for matching.
*/
template <typename T>
void add(flecs::filter filter) const;
/** Add type to all entities.
*
* @param type The type to add.
*/
void add(flecs::type type) const;
/** Add type to all entities matching a filter.
*
* @param type The type to add.
* @param filter The filter to use for matching.
*/
void add(flecs::type type, flecs::filter filter) const;
/** Add entity to all entities.
*
* @param entity The entity to add.
*/
void add(flecs::entity entity) const;
/** Add entity to all entities matching a filter.
*
* @param entity The entity to add.
* @param filter The filter to use for matching.
*/
void add(flecs::entity entity, flecs::filter filter) const;
/** Remove component from all entities matching a filter.
*
* @tparam T The component to remove.
* @param filter The filter to use for matching.
*/
template <typename T>
void remove(flecs::filter filter) const;
/** Remove type from all entities.
*
* @param type The component to remove.
*/
void remove(flecs::type type) const;
/** Remove type from all entities matching a filter.
*
* @tparam T The component to remove.
* @param filter The filter to use for matching.
*/
void remove(flecs::type type, flecs::filter filter) const;
/** Remove entity from all entities.
*
* @param entity The entity to remove.
*/
void remove(flecs::entity entity) const;
/** Remove entity from all entities matching a filter.
*
* @param entity The entity to remove.
* @param filter The filter to use for matching.
*/
void remove(flecs::entity entity, flecs::filter filter) const;
/** Create iterable filter for entities in world.
*
* @param filter The filter to create.
*/
world_filter filter(const flecs::filter& filter) const;
flecs::filter_iterator begin() const;
flecs::filter_iterator end() const;
/** Count entities matching a component.
*
* @tparam T The component to use for matching.
@ -11836,11 +11825,8 @@ public:
return ecs_count_id(m_world, _::cpp_type<T>::id(m_world));
}
/** Count entities matching a filter.
*
* @param filter The filter to use for matching.
*/
int count(flecs::filter filter) const;
flecs::filter_iterator begin() const;
flecs::filter_iterator end() const;
/** Enable locking.
*
@ -11920,6 +11906,9 @@ public:
}
/** Iterate over all entities with provided component.
* The function parameter must match the following signature:
* void(*)(T&) or
* void(*)(flecs::entity, T&)
*/
template <typename T, typename Func>
void each(Func&& func) const;
@ -11929,6 +11918,14 @@ public:
template <typename Func>
void each(flecs::id_t term_id, Func&& func) const;
/** Iterate over all entities with components in argument list of function.
* The function parameter must match the following signature:
* void(*)(T&, U&, ...) or
* void(*)(flecs::entity, T&, U&, ...)
*/
template <typename Func>
void each(Func&& func) const;
/** Create a prefab.
*/
template <typename... Args>
@ -11973,6 +11970,16 @@ public:
template <typename... Comps, typename... Args>
flecs::observer_builder<Comps...> observer(Args &&... args) const;
/** Create a filter.
*/
template <typename... Comps, typename... Args>
flecs::filter<Comps...> filter(Args &&... args) const;
/** Create a filter builder.
*/
template <typename... Comps, typename... Args>
flecs::filter_builder<Comps...> filter_builder(Args &&... args) const;
/** Create a query.
*/
template <typename... Comps, typename... Args>
@ -15472,7 +15479,7 @@ public:
}
bool is_set() {
return ecs_term_is_set(&value);
return ecs_term_is_initialized(&value);
}
bool is_trivial() {
@ -15522,7 +15529,7 @@ public:
ecs_assert(term_index > 0, ECS_INVALID_PARAMETER, NULL);
m_term_index = term_index - 1;
this->term();
ecs_assert(ecs_term_is_set(this->m_term), ECS_INVALID_PARAMETER, NULL);
ecs_assert(ecs_term_is_initialized(this->m_term), ECS_INVALID_PARAMETER, NULL);
return *this;
}
@ -15916,6 +15923,66 @@ private:
int32_t m_event_count;
};
// Filter builder
template<typename ... Components>
class filter_builder_base
: public filter_builder_i<filter_builder_base<Components...>, Components ...>
{
public:
filter_builder_base(flecs::world_t *world)
: filter_builder_i<filter_builder_base<Components...>, Components ...>(&m_desc)
, m_desc({})
, m_world(world)
{
this->populate_filter_from_pack();
}
filter_builder_base(const filter_builder_base& obj)
: filter_builder_i<filter_builder_base<Components...>, Components ...>(&m_desc, obj.m_term_index)
{
m_world = obj.m_world;
m_desc = obj.m_desc;
}
filter_builder_base(filter_builder_base&& obj)
: filter_builder_i<filter_builder_base<Components...>, Components ...>(&m_desc, obj.m_term_index)
{
m_world = obj.m_world;
m_desc = obj.m_desc;
}
operator filter<Components ...>() const;
operator ecs_filter_t() const {
ecs_filter_t f;
int res = ecs_filter_init(this->m_world, &f, &this->m_desc);
if (res != 0) {
ecs_abort(ECS_INVALID_PARAMETER, NULL);
}
return f;
}
filter<Components ...> build() const;
ecs_filter_desc_t m_desc;
flecs::world_t* world() override { return m_world; }
protected:
flecs::world_t *m_world;
};
template<typename ... Components>
class filter_builder final : public filter_builder_base<Components...> {
public:
filter_builder(flecs::world_t *world)
: filter_builder_base<Components ...>(world) { }
operator filter<>() const;
};
// Query builder
template<typename ... Components>
class query_builder_base
@ -16025,7 +16092,7 @@ private:
if (is_trigger) {
ecs_trigger_desc_t desc = {};
ecs_term_t term = m_desc.query.filter.terms[0];
if (ecs_term_is_set(&term)) {
if (ecs_term_is_initialized(&term)) {
desc.term = term;
} else {
desc.expr = m_desc.query.filter.expr;
@ -16458,94 +16525,157 @@ flecs::entity import(world& world) {
}
} // namespace flecs
namespace flecs
{
////////////////////////////////////////////////////////////////////////////////
//// A filter is used to match subsets of tables
//// Ad hoc queries (filters)
////////////////////////////////////////////////////////////////////////////////
enum match_kind {
MatchAll = EcsMatchAll,
MatchAny = EcsMatchAny,
MatchExact = EcsMatchExact
};
class filter {
class filter_base {
public:
filter()
: m_world( nullptr )
, m_filter{ } {}
filter_base()
: m_world(nullptr)
, m_filter({}) { }
explicit filter(const world& world)
: m_world( world.c_ptr() )
, m_filter{ } { }
filter& include(type type) {
m_filter.include = ecs_type_merge(m_world, m_filter.include, type.c_ptr(), nullptr);
return *this;
}
filter& include(entity entity) {
m_filter.include = ecs_type_add(m_world, m_filter.include, entity.id());
return *this;
}
template <typename T>
filter& include() {
m_filter.include = ecs_type_add(m_world, m_filter.include, _::cpp_type<T>::id(m_world));
return *this;
}
filter& include_kind(match_kind kind) {
m_filter.include_kind = static_cast<ecs_match_kind_t>(kind);
return *this;
}
type include() {
return type(m_world, m_filter.include);
}
filter& exclude(type type) {
m_filter.exclude = ecs_type_merge(m_world, m_filter.exclude, type.c_ptr(), nullptr);
return *this;
}
filter& exclude(entity entity) {
m_filter.exclude = ecs_type_add(m_world, m_filter.exclude, entity.id());
return *this;
}
template <typename T>
filter& exclude() {
m_filter.exclude = ecs_type_add(m_world, m_filter.exclude, _::cpp_type<T>::id(m_world));
return *this;
}
filter& exclude_kind(match_kind kind) {
m_filter.exclude_kind = static_cast<ecs_match_kind_t>(kind);
return *this;
}
type exclude() {
return type(m_world, m_filter.exclude);
filter_base(world_t *world, ecs_filter_t *filter = NULL)
: m_world(world) {
ecs_filter_move(&m_filter, filter);
}
/** Get pointer to C filter object.
*/
const filter_t* c_ptr() const {
if (m_world) {
if (m_filter.term_count) {
return &m_filter;
} else {
return nullptr;
return NULL;
}
}
private:
filter_base(const filter_base& obj) {
this->m_world = obj.m_world;
ecs_filter_copy(&m_filter, &obj.m_filter);
}
filter_base& operator=(const filter_base& obj) {
this->m_world = obj.m_world;
ecs_filter_copy(&m_filter, &obj.m_filter);
return *this;
}
filter_base(filter_base&& obj) {
this->m_world = obj.m_world;
ecs_filter_move(&m_filter, &obj.m_filter);
}
filter_base& operator=(filter_base&& obj) {
this->m_world = obj.m_world;
ecs_filter_move(&m_filter, &obj.m_filter);
return *this;
}
/** Free the filter.
*/
~filter_base() {
ecs_filter_fini(&m_filter);
}
template <typename Func>
void iter(Func&& func) const {
ecs_iter_t it = ecs_filter_iter(m_world, &m_filter);
while (ecs_filter_next(&it)) {
_::iter_invoker<Func>(func).invoke(&it);
}
}
template <typename Func>
void each_term(const Func& func) {
for (int i = 0; i < m_filter.term_count; i ++) {
flecs::term t(m_world, m_filter.terms[i]);
func(t);
}
}
flecs::term term(int32_t index) {
return flecs::term(m_world, m_filter.terms[index]);
}
int32_t term_count() {
return m_filter.term_count;
}
flecs::string str() {
char *result = ecs_filter_str(m_world, &m_filter);
return flecs::string(result);
}
protected:
world_t *m_world;
filter_t m_filter;
};
} // namespace flecs
template<typename ... Components>
class filter : public filter_base {
using Terms = typename _::term_ptrs<Components...>::array;
public:
filter() { }
filter(world_t *world, filter_t *f)
: filter_base(world, f) { }
explicit filter(const world& world, const char *expr = nullptr)
: filter_base(world.c_ptr())
{
auto qb = world.filter_builder<Components ...>()
.expr(expr);
if (!expr) {
qb.substitute_default();
}
flecs::filter_t f = qb;
ecs_filter_move(&m_filter, &f);
}
filter(const filter& obj) : filter_base(obj) { }
filter& operator=(const filter& obj) {
*this = obj;
return *this;
}
filter(filter&& obj) : filter_base(std::move(obj)) { }
filter& operator=(filter&& obj) {
filter_base(std::move(obj));
return *this;
}
template <typename Func>
void each(Func&& func) const {
iterate<_::each_invoker>(std::forward<Func>(func), ecs_filter_next);
}
template <typename Func>
void iter(Func&& func) const {
iterate<_::iter_invoker>(std::forward<Func>(func), ecs_filter_next);
}
private:
template < template<typename Func, typename ... Comps> class Invoker, typename Func, typename NextFunc, typename ... Args>
void iterate(Func&& func, NextFunc next, Args &&... args) const {
ecs_iter_t it = ecs_filter_iter(m_world, &m_filter);
while (next(&it, std::forward<Args>(args)...)) {
Invoker<Func, Components...>(std::move(func)).invoke(&it);
}
}
};
}
namespace flecs
{
@ -16596,14 +16726,16 @@ public:
m_snapshot = ecs_snapshot_take(m_world.c_ptr());
}
void take(flecs::filter filter) {
template <typename F>
void take(const F& f) {
if (m_snapshot) {
ecs_snapshot_free(m_snapshot);
}
ecs_iter_t it = ecs_filter_iter(m_world.c_ptr(), filter.c_ptr());
m_snapshot = ecs_snapshot_take_w_iter(
&it, ecs_filter_next);
ecs_iter_t it = ecs_filter_iter(m_world, f.c_ptr());
printf("filter = %s\n", ecs_filter_str(m_world, f.c_ptr()));
m_snapshot = ecs_snapshot_take_w_iter(&it, ecs_filter_next);
}
void restore() {
@ -16623,8 +16755,6 @@ public:
return m_snapshot;
}
snapshot_filter filter(const filter& filter);
filter_iterator begin();
filter_iterator end();
@ -16651,17 +16781,17 @@ public:
, m_iter{ }
, m_action(action) { }
filter_iterator(const world& world, const filter& filter, ecs_iter_next_action_t action)
filter_iterator(const world& world, ecs_iter_next_action_t action)
: m_world( world.c_ptr() )
, m_iter( ecs_filter_iter(m_world, filter.c_ptr()) )
, m_iter( ecs_filter_iter(m_world, NULL) )
, m_action(action)
{
m_has_next = m_action(&m_iter);
}
filter_iterator(const world& world, const snapshot& snapshot, const filter& filter, ecs_iter_next_action_t action)
filter_iterator(const world& world, const snapshot& snapshot, ecs_iter_next_action_t action)
: m_world( world.c_ptr() )
, m_iter( ecs_snapshot_iter(snapshot.c_ptr(), filter.c_ptr()) )
, m_iter( ecs_snapshot_iter(snapshot.c_ptr(), NULL) )
, m_action(action)
{
m_has_next = m_action(&m_iter);
@ -16723,18 +16853,18 @@ private:
ecs_iter_t m_iter;
};
////////////////////////////////////////////////////////////////////////////////
//// Utility for creating a world-based filter iterator
////////////////////////////////////////////////////////////////////////////////
class world_filter {
public:
world_filter(const world& world, const filter& filter)
: m_world( world )
, m_filter( filter ) { }
world_filter(const world& world)
: m_world( world ) { }
inline filter_iterator begin() const {
return filter_iterator(m_world, m_filter, ecs_filter_next);
return filter_iterator(m_world, ecs_filter_next);
}
inline filter_iterator end() const {
@ -16743,7 +16873,6 @@ public:
private:
const world& m_world;
const filter& m_filter;
};
@ -16753,13 +16882,12 @@ private:
class snapshot_filter {
public:
snapshot_filter(const world& world, const snapshot& snapshot, const filter& filter)
snapshot_filter(const world& world, const snapshot& snapshot)
: m_world( world )
, m_snapshot( snapshot )
, m_filter( filter ) { }
, m_snapshot( snapshot ) { }
inline filter_iterator begin() const {
return filter_iterator(m_world, m_snapshot, m_filter, ecs_snapshot_next);
return filter_iterator(m_world, m_snapshot, ecs_snapshot_next);
}
inline filter_iterator end() const {
@ -16769,7 +16897,6 @@ public:
private:
const world& m_world;
const snapshot& m_snapshot;
const filter& m_filter;
};
@ -16801,12 +16928,8 @@ private:
//// Filter fwd declared functions
////////////////////////////////////////////////////////////////////////////////
inline snapshot_filter snapshot::filter(const flecs::filter& filter) {
return snapshot_filter(m_world, *this, filter);
}
inline filter_iterator snapshot::begin() {
return filter_iterator(m_world, *this, flecs::filter(m_world), ecs_snapshot_next);
return filter_iterator(m_world, *this, ecs_snapshot_next);
}
inline filter_iterator snapshot::end() {
@ -17022,13 +17145,6 @@ public:
iterate<_::each_invoker>(std::forward<Func>(func), ecs_query_next);
}
template <typename Func>
void each(const flecs::filter& filter, Func&& func) const {
const filter_t* filter_ptr = filter.c_ptr();
iterate<_::each_invoker>(std::forward<Func>(func),
ecs_query_next_w_filter, filter_ptr);
}
template <typename Func>
void each_worker(int32_t stage_current, int32_t stage_count, Func&& func) const {
iterate<_::each_invoker>(std::forward<Func>(func),
@ -17040,13 +17156,6 @@ public:
iterate<_::iter_invoker>(std::forward<Func>(func), ecs_query_next);
}
template <typename Func>
void iter(const flecs::filter& filter, Func&& func) const {
const filter_t* filter_ptr = filter.c_ptr();
iterate<_::iter_invoker>(std::forward<Func>(func),
ecs_query_next_w_filter, filter_ptr);
}
template <typename Func>
void iter_worker(int32_t stage_current, int32_t stage_count, Func&& func) const {
iterate<_::iter_invoker>(std::forward<Func>(func),
@ -17097,8 +17206,9 @@ public:
, m_stage_current(stage_current)
, m_stage_count(stage_count) { }
system_runner_fluent& filter(filter filter) {
m_filter = filter;
template <typename F>
system_runner_fluent& filter(const F& f) {
m_filter = f;
return *this;
}
@ -17128,12 +17238,13 @@ public:
m_filter.c_ptr(), m_param);
}
}
private:
world_t *m_stage;
entity_t m_id;
FLECS_FLOAT m_delta_time;
void *m_param;
flecs::filter m_filter;
flecs::filter<> m_filter;
int32_t m_offset;
int32_t m_limit;
int32_t m_stage_current;
@ -17746,70 +17857,14 @@ inline flecs::id world::pair(entity_t r, entity_t o) const {
ecs_pair(r, o));
}
inline void world::delete_entities(flecs::filter filter) const {
ecs_bulk_delete(m_world, filter.c_ptr());
}
template <typename T>
inline void world::add(flecs::filter filter) const {
ecs_bulk_add_remove_type(
m_world, _::cpp_type<T>::type(m_world), nullptr, filter.c_ptr());
}
inline void world::add(flecs::type t) const {
ecs_bulk_add_remove_type(m_world, t.c_ptr(), nullptr, nullptr);
}
inline void world::add(flecs::type t, flecs::filter filter) const {
ecs_bulk_add_remove_type(m_world, t.c_ptr(), nullptr, filter.c_ptr());
}
inline void world::add(class flecs::entity e) const {
ecs_bulk_add_remove_type(m_world, e.to_type().c_ptr(), nullptr, nullptr);
}
inline void world::add(class flecs::entity e, flecs::filter filter) const {
ecs_bulk_add_remove_type(m_world, e.to_type().c_ptr(), nullptr, filter.c_ptr());
}
template <typename T>
inline void world::remove(flecs::filter filter) const {
ecs_bulk_add_remove_type(
m_world, nullptr, _::cpp_type<T>::type(m_world), filter.c_ptr());
}
inline void world::remove(flecs::type t) const {
ecs_bulk_add_remove_type(m_world, nullptr, t.c_ptr(), nullptr);
}
inline void world::remove(flecs::type t, flecs::filter filter) const {
ecs_bulk_add_remove_type(m_world, nullptr, t.c_ptr(), filter.c_ptr());
}
inline void world::remove(class entity e) const {
ecs_bulk_add_remove_type(m_world, nullptr, e.to_type().c_ptr(), nullptr);
}
inline void world::remove(class entity e, flecs::filter filter) const {
ecs_bulk_add_remove_type(m_world, nullptr, e.to_type().c_ptr(), filter.c_ptr());
}
inline flecs::world_filter world::filter(const flecs::filter& filter) const {
return flecs::world_filter(*this, filter);
}
inline filter_iterator world::begin() const {
return filter_iterator(*this, flecs::filter(*this), ecs_filter_next);
return filter_iterator(*this, ecs_filter_next);
}
inline filter_iterator world::end() const {
return filter_iterator(ecs_filter_next);
}
inline int world::count(flecs::filter filter) const {
return ecs_count_w_filter(m_world, filter.c_ptr());
}
/** All entities created in function are created in scope. All operations
* called in function (such as lookup) are relative to scope.
*/
@ -17957,6 +18012,16 @@ inline flecs::observer_builder<Comps...> world::observer(Args &&... args) const
return flecs::observer_builder<Comps...>(*this, std::forward<Args>(args)...);
}
template <typename... Comps, typename... Args>
inline flecs::filter<Comps...> world::filter(Args &&... args) const {
return flecs::filter<Comps...>(*this, std::forward<Args>(args)...);
}
template <typename... Comps, typename... Args>
inline flecs::filter_builder<Comps...> world::filter_builder(Args &&... args) const {
return flecs::filter_builder<Comps...>(*this, std::forward<Args>(args)...);
}
template <typename... Comps, typename... Args>
inline flecs::query<Comps...> world::query(Args &&... args) const {
return flecs::query<Comps...>(*this, std::forward<Args>(args)...);
@ -18034,6 +18099,61 @@ inline void world::each(flecs::id_t term_id, Func&& func) const {
}
}
namespace _ {
// Each with entity parameter
template<typename Func, typename ... Args>
struct filter_invoker_w_ent;
template<typename Func, typename E, typename ... Args>
struct filter_invoker_w_ent<Func, arg_list<E, Args ...> >
{
filter_invoker_w_ent(const flecs::world& world, Func&& func) {
flecs::filter<Args ...> f(world);
f.each(std::move(func));
}
};
// Each without entity parameter
template<typename Func, typename ... Args>
struct filter_invoker_no_ent;
template<typename Func, typename ... Args>
struct filter_invoker_no_ent<Func, arg_list<Args ...> >
{
filter_invoker_no_ent(const flecs::world& world, Func&& func) {
flecs::filter<Args ...> f(world);
f.each(std::move(func));
}
};
// Switch between function with & without entity parameter
template<typename Func, typename T = int>
class filter_invoker;
template <typename Func>
class filter_invoker<Func, if_t<is_same<first_arg_t<Func>, flecs::entity>::value> > {
public:
filter_invoker(const flecs::world& world, Func&& func) {
filter_invoker_w_ent<Func, arg_list_t<Func>>(world, std::move(func));
}
};
template <typename Func>
class filter_invoker<Func, if_not_t<is_same<first_arg_t<Func>, flecs::entity>::value> > {
public:
filter_invoker(const flecs::world& world, Func&& func) {
filter_invoker_no_ent<Func, arg_list_t<Func>>(world, std::move(func));
}
};
}
template <typename Func>
inline void world::each(Func&& func) const {
_::filter_invoker<Func> f_invoker(*this, std::move(func));
}
} // namespace flecs
namespace flecs
@ -18046,6 +18166,24 @@ inline Base& term_builder_i<Base>::id(const flecs::type& type) {
return *this;
}
template <typename ... Components>
inline filter_builder_base<Components...>::operator filter<Components ...>() const {
ecs_filter_t filter = *this;
return flecs::filter<Components...>(m_world, &filter);
}
template <typename ... Components>
inline filter_builder<Components ...>::operator filter<>() const {
ecs_filter_t filter = *this;
return flecs::filter<>(this->m_world, &filter);
}
template <typename ... Components>
inline filter<Components ...> filter_builder_base<Components...>::build() const {
ecs_filter_t filter = *this;
return flecs::filter<Components...>(m_world, &filter);
}
template <typename ... Components>
inline query_builder_base<Components...>::operator query<Components ...>() const {
ecs_query_t *query = *this;