Flecs v3.2
A fast entity component system (ECS) for C & C++
Loading...
Searching...
No Matches
Queries

Functions for working with ecs_query_t. More...

Collaboration diagram for Queries:

Classes

struct  ecs_query_desc_t
 Used with ecs_query_init(). More...
 

Typedefs

typedef struct ecs_query_desc_t ecs_query_desc_t
 Used with ecs_query_init().
 

Functions

ecs_query_tecs_query_init (ecs_world_t *world, const ecs_query_desc_t *desc)
 Create a query.
 
void ecs_query_fini (ecs_query_t *query)
 Destroy a query.
 
const ecs_filter_tecs_query_get_filter (const ecs_query_t *query)
 Get filter from a query.
 
ecs_iter_t ecs_query_iter (const ecs_world_t *world, ecs_query_t *query)
 Return a query iterator.
 
bool ecs_query_next (ecs_iter_t *iter)
 Progress the query iterator.
 
bool ecs_query_next_instanced (ecs_iter_t *iter)
 Same as ecs_query_next, but always instanced.
 
bool ecs_query_next_table (ecs_iter_t *iter)
 Fast alternative to ecs_query_next() that only returns matched tables.
 
int ecs_query_populate (ecs_iter_t *iter, bool when_changed)
 Populate iterator fields.
 
bool ecs_query_changed (ecs_query_t *query, const ecs_iter_t *it)
 Returns whether the query data changed since the last iteration.
 
void ecs_query_skip (ecs_iter_t *it)
 Skip a table while iterating.
 
void ecs_query_set_group (ecs_iter_t *it, uint64_t group_id)
 Set group to iterate for query iterator.
 
void * ecs_query_get_group_ctx (const ecs_query_t *query, uint64_t group_id)
 Get context of query group.
 
const ecs_query_group_info_tecs_query_get_group_info (const ecs_query_t *query, uint64_t group_id)
 Get information about query group.
 
bool ecs_query_orphaned (const ecs_query_t *query)
 Returns whether query is orphaned.
 
char * ecs_query_str (const ecs_query_t *query)
 Convert query to string.
 
int32_t ecs_query_table_count (const ecs_query_t *query)
 Returns number of tables query matched with.
 
int32_t ecs_query_empty_table_count (const ecs_query_t *query)
 Returns number of empty tables query matched with.
 
int32_t ecs_query_entity_count (const ecs_query_t *query)
 Returns number of entities query matched with.
 
void * ecs_query_get_ctx (const ecs_query_t *query)
 Get query ctx.
 
void * ecs_query_get_binding_ctx (const ecs_query_t *query)
 Get query binding ctx.
 

Detailed Description

Functions for working with ecs_query_t.

Function Documentation

◆ ecs_query_changed()

bool ecs_query_changed ( ecs_query_t * query,
const ecs_iter_t * it )

Returns whether the query data changed since the last iteration.

The operation will return true after:

  • new entities have been matched with
  • new tables have been matched/unmatched with
  • matched entities were deleted
  • matched components were changed

The operation will not return true after a write-only (EcsOut) or filter (EcsInOutNone) term has changed, when a term is not matched with the current table (This subject) or for tag terms.

The changed state of a table is reset after it is iterated. If a iterator was not iterated until completion, tables may still be marked as changed.

If no iterator is provided the operation will return the changed state of the all matched tables of the query.

If an iterator is provided, the operation will return the changed state of the currently returned iterator result. The following preconditions must be met before using an iterator with change detection:

  • The iterator is a query iterator (created with ecs_query_iter())
  • The iterator must be valid (ecs_query_next() must have returned true)
  • The iterator must be instanced
Parameters
queryThe query (optional if 'it' is provided).
itThe iterator result to test (optional if 'query' is provided).
Returns
true if entities changed, otherwise false.

◆ ecs_query_empty_table_count()

int32_t ecs_query_empty_table_count ( const ecs_query_t * query)

Returns number of empty tables query matched with.

Parameters
queryThe query.
Returns
The number of matched empty tables.

◆ ecs_query_entity_count()

int32_t ecs_query_entity_count ( const ecs_query_t * query)

Returns number of entities query matched with.

This operation iterates all non-empty tables in the query cache to find the total number of entities.

Parameters
queryThe query.
Returns
The number of matched entities.

◆ ecs_query_fini()

void ecs_query_fini ( ecs_query_t * query)

Destroy a query.

This operation destroys a query and its resources. If the query is used as the parent of subqueries, those subqueries will be orphaned and must be deinitialized as well.

Parameters
queryThe query.

◆ ecs_query_get_binding_ctx()

void * ecs_query_get_binding_ctx ( const ecs_query_t * query)

Get query binding ctx.

Return the value set in ecs_query_desc_t::binding_ctx.

Parameters
queryThe query.
Returns
The context.

◆ ecs_query_get_ctx()

void * ecs_query_get_ctx ( const ecs_query_t * query)

Get query ctx.

Return the value set in ecs_query_desc_t::ctx.

Parameters
queryThe query.
Returns
The context.

◆ ecs_query_get_filter()

const ecs_filter_t * ecs_query_get_filter ( const ecs_query_t * query)

Get filter from a query.

This operation obtains a pointer to the internally constructed filter of the query and can be used to introspect the query terms.

Parameters
queryThe query.
Returns
The filter.

◆ ecs_query_get_group_ctx()

void * ecs_query_get_group_ctx ( const ecs_query_t * query,
uint64_t group_id )

Get context of query group.

This operation returns the context of a query group as returned by the on_group_create callback.

Parameters
queryThe query.
group_idThe group for which to obtain the context.
Returns
The group context, NULL if the group doesn't exist.

◆ ecs_query_get_group_info()

const ecs_query_group_info_t * ecs_query_get_group_info ( const ecs_query_t * query,
uint64_t group_id )

Get information about query group.

This operation returns information about a query group, including the group context returned by the on_group_create callback.

Parameters
queryThe query.
group_idThe group for which to obtain the group info.
Returns
The group info, NULL if the group doesn't exist.

◆ ecs_query_init()

ecs_query_t * ecs_query_init ( ecs_world_t * world,
const ecs_query_desc_t * desc )

Create a query.

This operation creates a query. Queries are used to iterate over entities that match a filter and are the fastest way to find and iterate over entities and their components.

Queries should be created once, and reused multiple times. While iterating a query is a cheap operation, creating and deleting a query is expensive. The reason for this is that queries are "pre-matched", which means that a query stores state about which entities (or rather, tables) match with the query. Building up this state happens during query creation.

Once a query is created, matching only happens when new tables are created. In most applications this is an infrequent process, since it only occurs when a new combination of components is introduced. While matching is expensive, it is important to note that matching does not happen on a per-entity basis, but on a per-table basis. This means that the average time spent on matching per frame should rapidly approach zero over the lifetime of an application.

A query provides direct access to the component arrays. When an application creates/deletes entities or adds/removes components, these arrays can shift component values around, or may grow in size. This can cause unexpected or undefined behavior to occur if these operations are performed while iterating. To prevent this from happening an application should either not perform these operations while iterating, or use deferred operations (see ecs_defer_begin() and ecs_defer_end()).

Queries can be created and deleted dynamically. If a query was not deleted (using ecs_query_fini()) before the world is deleted, it will be deleted automatically.

Parameters
worldThe world.
descA structure describing the query properties.
Returns
The new query.

◆ ecs_query_iter()

ecs_iter_t ecs_query_iter ( const ecs_world_t * world,
ecs_query_t * query )

Return a query iterator.

A query iterator lets an application iterate over entities that match the specified query. If a sorting function is specified, the query will check whether a resort is required upon creating the iterator.

Creating a query iterator is a cheap operation that does not allocate any resources. An application does not need to deinitialize or free a query iterator before it goes out of scope.

To iterate the iterator, an application should use ecs_query_next() to progress the iterator and test if it has data.

Query iteration requires an outer and an inner loop. The outer loop uses ecs_query_next() to test if new tables are available. The inner loop iterates the entities in the table, and is usually a for loop that uses iter.count to loop through the entities and component arrays.

The two loops are necessary because of how data is stored internally. Entities are grouped by the components they have, in tables. A single query can (and often does) match with multiple tables. Because each table has its own set of arrays, an application has to reobtain pointers to those arrays for each matching table.

Parameters
worldThe world or stage, when iterating in readonly mode.
queryThe query to iterate.
Returns
The query iterator.

◆ ecs_query_next()

bool ecs_query_next ( ecs_iter_t * iter)

Progress the query iterator.

This operation progresses the query iterator to the next table. The iterator must have been initialized with ecs_query_iter(). This operation must be invoked at least once before interpreting the contents of the iterator.

Parameters
iterThe iterator.
Returns
True if more data is available, false if not.

◆ ecs_query_next_instanced()

bool ecs_query_next_instanced ( ecs_iter_t * iter)

Same as ecs_query_next, but always instanced.

See "instanced" property of ecs_filter_desc_t.

Parameters
iterThe iterator.
Returns
True if more data is available, false if not.

◆ ecs_query_next_table()

bool ecs_query_next_table ( ecs_iter_t * iter)

Fast alternative to ecs_query_next() that only returns matched tables.

This operation only populates the ecs_iter_t::table field. To access the matched components, call ecs_query_populate().

If this operation is used with a query that has inout/out terms, those terms will not be marked dirty unless ecs_query_populate() is called.

Parameters
iterThe iterator.
Returns
True if more data is available, false if not.

◆ ecs_query_orphaned()

bool ecs_query_orphaned ( const ecs_query_t * query)

Returns whether query is orphaned.

When the parent query of a subquery is deleted, it is left in an orphaned state. The only valid operation on an orphaned query is deleting it. Only subqueries can be orphaned.

Parameters
queryThe query.
Returns
true if query is orphaned, otherwise false.

◆ ecs_query_populate()

int ecs_query_populate ( ecs_iter_t * iter,
bool when_changed )

Populate iterator fields.

This operation can be combined with ecs_query_next_table() to populate the iterator fields for the current table.

Populating fields conditionally can save time when a query uses change detection, and only needs iterator data when the table has changed. When this operation is called, inout/out terms will be marked dirty.

In cases where inout/out terms are conditionally written and no changes were made after calling ecs_query_populate(), the ecs_query_skip() function can be called to prevent the matched table components from being marked dirty.

This operation does should not be used with queries that match disabled components, union relationships, or with queries that use order_by.

When the when_changed argument is set to true, the iterator data will only populate when the data has changed, using query change detection.

Parameters
iterThe iterator.
when_changedOnly populate data when result has changed.

◆ ecs_query_set_group()

void ecs_query_set_group ( ecs_iter_t * it,
uint64_t group_id )

Set group to iterate for query iterator.

This operation limits the results returned by the query to only the selected group id. The query must have a group_by function, and the iterator must be a query iterator.

Groups are sets of tables that are stored together in the query cache based on a group id, which is calculated per table by the group_by function. To iterate a group, an iterator only needs to know the first and last cache node for that group, which can both be found in a fast O(1) operation.

As a result, group iteration is one of the most efficient mechanisms to filter out large numbers of entities, even if those entities are distributed across many tables. This makes it a good fit for things like dividing up a world into cells, and only iterating cells close to a player.

The group to iterate must be set before the first call to ecs_query_next(). No operations that can add/remove components should be invoked between calling ecs_query_set_group() and ecs_query_next().

Parameters
itThe query iterator.
group_idThe group to iterate.

◆ ecs_query_skip()

void ecs_query_skip ( ecs_iter_t * it)

Skip a table while iterating.

This operation lets the query iterator know that a table was skipped while iterating. A skipped table will not reset its changed state, and the query will not update the dirty flags of the table for its out columns.

Only valid iterators must be provided (next has to be called at least once & return true) and the iterator must be a query iterator.

Parameters
itThe iterator result to skip.

◆ ecs_query_str()

char * ecs_query_str ( const ecs_query_t * query)

Convert query to string.

Parameters
queryThe query.
Returns
The query string.

◆ ecs_query_table_count()

int32_t ecs_query_table_count ( const ecs_query_t * query)

Returns number of tables query matched with.

Parameters
queryThe query.
Returns
The number of matched tables.