Properly link flecs library
This commit is contained in:
116
engine/libs/flecs/examples/c/queries/instancing/src/main.c
Normal file
116
engine/libs/flecs/examples/c/queries/instancing/src/main.c
Normal file
@@ -0,0 +1,116 @@
|
||||
#include <instancing.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Instancing is the ability of queries to iterate results with fields that have
|
||||
* different numbers of elements. The term "instancing" is borrowed from
|
||||
* graphics APIs, where it means reusing the same data for multiple "instances".
|
||||
*
|
||||
* Query instancing works in much the same way. By default queries match all
|
||||
* components on the same entity. It is however possible to request data from
|
||||
* other entities, like getting the Position from the entity's parent.
|
||||
*
|
||||
* Instancing refers to the ability of queries to iterate components for
|
||||
* multiple entities while at the same time providing "instanced" components,
|
||||
* which are always provided one element at a time.
|
||||
*
|
||||
* Instancing is often used in combination with parent-child relationships and
|
||||
* prefabs, but is applicable to any kind of query where some of the terms are
|
||||
* matched on N entities, and some on a single entity.
|
||||
*
|
||||
* By default queries are not instanced, which means that if a result contains
|
||||
* mixed fields, entities will be iterated one by one instead of in batches.
|
||||
* This is safer, as code doesn't have to do anything different for owned and
|
||||
* shared fields, but does come at a performance penalty.
|
||||
*
|
||||
* The each() iterator function always uses an instanced iterator under the
|
||||
* hood. This is transparent to the application, but improves performance. For
|
||||
* this reason using each() can be faster than using uninstanced iter().
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
double x, y;
|
||||
} Position, Velocity;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
ecs_world_t *world = ecs_init_w_args(argc, argv);
|
||||
|
||||
ECS_COMPONENT(world, Position);
|
||||
ECS_COMPONENT(world, Velocity);
|
||||
|
||||
// Create a query for Position, Velocity. We'll create a few entities that
|
||||
// have Velocity as owned and shared component.
|
||||
ecs_query_t *q = ecs_query(world, {
|
||||
.filter = {
|
||||
.terms = {
|
||||
// Position must always be owned by the entity
|
||||
{ .id = ecs_id(Position), .src.flags = EcsSelf },
|
||||
{ .id = ecs_id(Velocity) } // Velocity may be shared (default)
|
||||
},
|
||||
.instanced = true
|
||||
}
|
||||
});
|
||||
|
||||
// Create a prefab with Velocity. Prefabs are not matched with queries.
|
||||
ecs_entity_t prefab = ecs_new_prefab(world, "p");
|
||||
ecs_set(world, prefab, Velocity, {1, 2});
|
||||
|
||||
// Create a few entities that own Position & share Velocity from the prefab.
|
||||
ecs_entity_t e1 = ecs_new_entity(world, "e1");
|
||||
ecs_add_pair(world, e1, EcsIsA, prefab);
|
||||
ecs_set(world, e1, Position, {10, 20});
|
||||
|
||||
ecs_entity_t e2 = ecs_new_entity(world, "e2");
|
||||
ecs_add_pair(world, e2, EcsIsA, prefab);
|
||||
ecs_set(world, e2, Position, {10, 20});
|
||||
|
||||
// Create a few entities that own all components
|
||||
ecs_entity_t e3 = ecs_new_entity(world, "e3");
|
||||
ecs_set(world, e3, Position, {10, 20});
|
||||
ecs_set(world, e3, Velocity, {3, 4});
|
||||
|
||||
ecs_entity_t e4 = ecs_new_entity(world, "e4");
|
||||
ecs_set(world, e4, Position, {10, 20});
|
||||
ecs_set(world, e4, Velocity, {4, 5});
|
||||
|
||||
// Iterate the instanced query. Note how when a query is instanced, it needs
|
||||
// to check whether a field is owned or not in order to know how to access
|
||||
// it. In the case of an owned field it is iterated as an array, whereas
|
||||
// in the case of a shared field, it is accessed as a pointer.
|
||||
ecs_iter_t it = ecs_query_iter(world, q);
|
||||
while (ecs_query_next(&it)) {
|
||||
Position *p = ecs_field(&it, Position, 1);
|
||||
Velocity *v = ecs_field(&it, Velocity, 2);
|
||||
|
||||
// Check if Velocity is owned, in which case it's accessed as array.
|
||||
// Position will always be owned, since we set the term to Self.
|
||||
if (ecs_field_is_self(&it, 2)) { // Velocity is term 2
|
||||
printf("Velocity is owned\n");
|
||||
for (int i = 0; i < it.count; i ++) {
|
||||
// If Velocity is shared, access the field as an array.
|
||||
p[i].x += v[i].x;
|
||||
p[i].y += v[i].y;
|
||||
printf("%s: {%f, %f}\n", ecs_get_name(it.world, it.entities[i]),
|
||||
p[i].x, p[i].y);
|
||||
}
|
||||
} else {
|
||||
printf("Velocity is shared\n");
|
||||
for (int i = 0; i < it.count; i ++) {
|
||||
// If Velocity is shared, access the field as a pointer.
|
||||
p[i].x += v->x;
|
||||
p[i].y += v->y;
|
||||
printf("%s: {%f, %f}\n", ecs_get_name(it.world, it.entities[i]),
|
||||
p[i].x, p[i].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ecs_fini(world);
|
||||
|
||||
// Output
|
||||
// Velocity is shared
|
||||
// e1: {11.000000, 22.000000}
|
||||
// e2: {11.000000, 22.000000}
|
||||
// Velocity is owned
|
||||
// e3: {13.000000, 24.000000}
|
||||
// e4: {14.000000, 25.000000}
|
||||
}
|
||||
Reference in New Issue
Block a user