Skip to content
Flecs v4.1
systems/system_ctx

  • C

    View on GitHub

    1#include <system_ctx.h>
    2#include <stdio.h>
    3#include <stdlib.h>
    4#include <math.h>
    5
    6// Applications can pass context data to a system. A common use case where this
    7// comes in handy is when a system needs to iterate more than one query. The
    8// following example shows how to pass a custom query into a system for a simple
    9// collision detection example.
    10
    11typedef struct {
    12 double x, y;
    13} Position;
    14
    15typedef struct {
    16 double value;
    17} Radius;
    18
    19double sqr(double value) {
    20 return value * value;
    21}
    22
    23double distance_sqr(const Position *p1, const Position *p2) {
    24 return sqr(p2->x - p1->x) + sqr(p2->y - p1->y);
    25}
    26
    27void Collide(ecs_iter_t *it) {
    28 ecs_query_t *q_collide = it->ctx; // Get query from system context
    29 const Position *p1 = ecs_field(it, Position, 0);
    30 const Radius *r1 = ecs_field(it, Radius, 1);
    31
    32 for (int i = 0; i < it->count; i ++) {
    33 ecs_entity_t e1 = it->entities[i];
    34
    35 // For each matching entity, iterate the query
    36 ecs_iter_t qit = ecs_query_iter(it->stage, q_collide);
    37 while (ecs_query_next(&qit)) {
    38 const Position *p2 = ecs_field(&qit, Position, 0);
    39 const Radius *r2 = ecs_field(&qit, Radius, 1);
    40 for (int j = 0; j < qit.count; j ++) {
    41 ecs_entity_t e2 = qit.entities[j];
    42 if (e1 == e2) {
    43 // don't collide with self
    44 continue;
    45 }
    46
    47 if (e2 > e1) {
    48 // Simple trick to prevent collisions from being detected
    49 // twice with the entities reversed.
    50 continue;
    51 }
    52
    53 // Check for collision
    54 double d_sqr = distance_sqr(&p1[i], &p2[j]);
    55 double r_sqr = sqr(r1[i].value + r2[j].value);
    56 if (r_sqr > d_sqr) {
    57 printf("%u and %u collided!\n", (uint32_t)e1, (uint32_t)e2);
    58 }
    59 }
    60 }
    61 }
    62}
    63
    64int main(int argc, char *argv[]) {
    65 ecs_world_t *ecs = ecs_init_w_args(argc, argv);
    66
    67 ECS_COMPONENT(ecs, Position);
    68 ECS_COMPONENT(ecs, Radius);
    69
    70 // Create a query for Position that we can use inside the collide system to
    71 // check each entity with each other entity.
    72 ecs_query_t *q_position = ecs_query(ecs, {
    73 .terms = {
    74 { ecs_id(Position), .inout = EcsIn },
    75 { ecs_id(Radius), .inout = EcsIn }
    76 }
    77 });
    78
    79 // Create collide system that passes query as context
    80 ecs_entity_t collide = ecs_system(ecs, {
    81 .query.terms = {
    82 { .id = ecs_id(Position), .inout = EcsIn },
    83 { ecs_id(Radius), .inout = EcsIn }
    84 },
    85 .callback = Collide,
    86 .ctx = q_position
    87 });
    88
    89 // Create a few test entities
    90 for (int i = 0; i < 10; i ++) {
    91 ecs_entity_t e = ecs_new(ecs);
    92 ecs_set(ecs, e, Position, { .x = rand() % 100, .y = rand() % 100 });
    93 ecs_set(ecs, e, Radius, { rand() % 10 + 1 });
    94 }
    95
    96 // Run the system
    97 ecs_run(ecs, collide, 0.0f, NULL);
    98
    99 return ecs_fini(ecs);
    100
    101 // Output
    102 // 508 and 505 collided!
    103 // 510 and 508 collided!
    104 // 513 and 506 collided!
    105 // 514 and 512 collided!
    106}
    FLECS_API const ecs_entity_t ecs_id(EcsDocDescription)
    Component ID for EcsDocDescription.
    #define ecs_system(world,...)
    Shorthand for creating a system with ecs_system_init().
    Definition system.h:285
    FLECS_API ecs_entity_t ecs_run(ecs_world_t *world, ecs_entity_t system, ecs_ftime_t delta_time, void *param)
    Run a specific system manually.
    ecs_id_t ecs_entity_t
    An entity identifier.
    Definition flecs.h:395
    struct ecs_world_t ecs_world_t
    A world is the container for all ECS data and supporting features.
    Definition flecs.h:439
    ecs_entity_t ecs_new(ecs_world_t *world)
    Create new entity ID.
    #define ECS_COMPONENT(world, id)
    Declare and define a component.
    Definition flecs_c.h:98
    #define ecs_query(world,...)
    Shorthand for creating a query with ecs_query_init().
    Definition flecs_c.h:215
    #define ecs_set(world, entity, component,...)
    Set a component value.
    Definition flecs_c.h:310
    #define ecs_field(it, T, index)
    Get field data for a component.
    Definition flecs_c.h:720
    bool ecs_query_next(ecs_iter_t *it)
    Progress a query iterator.
    ecs_iter_t ecs_query_iter(const ecs_world_t *world, const ecs_query_t *query)
    Create a query iterator.
    @ EcsIn
    Term is only read.
    Definition flecs.h:731
    int ecs_fini(ecs_world_t *world)
    Delete a world.
    ecs_world_t * ecs_init_w_args(int argc, char *argv[])
    Create a new world with arguments.
    Iterator.
    Definition flecs.h:1183
    void * ctx
    System context.
    Definition flecs.h:1222
    int32_t count
    Number of entities to iterate.
    Definition flecs.h:1189
    const ecs_entity_t * entities
    Entity identifiers.
    Definition flecs.h:1190
    Queries are lists of constraints (terms) that match entities.
    Definition flecs.h:858

  • C++

    View on GitHub

    1#include <system_ctx.h>
    2#include <iostream>
    3
    4// Applications can pass context data to a system. A common use case where this
    5// comes in handy is when a system needs to iterate more than one query. The
    6// following example shows how to pass a custom query into a system for a simple
    7// collision detection example.
    8
    9struct Position {
    10 double x, y;
    11};
    12
    13struct Radius {
    14 double value;
    15};
    16
    17double sqr(double value) {
    18 return value * value;
    19}
    20
    21double distance_sqr(const Position& p1, const Position& p2) {
    22 return sqr(p2.x - p1.x) + sqr(p2.y - p1.y);
    23}
    24
    25double randd(int max) {
    26 return static_cast<double>((rand() % max));
    27}
    28
    30
    31int main(int, char *[]) {
    32 flecs::world ecs;
    33
    34 CollisionQuery q_collide = ecs.query<const Position, const Radius>();
    35
    36 flecs::system sys = ecs.system<const Position, const Radius>("Collide")
    37 .ctx(&q_collide)
    38 .each([](flecs::iter& it, size_t i, const Position& p1, const Radius& r1) {
    39 CollisionQuery *q = it.ctx<CollisionQuery>();
    40 flecs::entity e1 = it.entity(i);
    41
    42 q->each([&](flecs::entity e2, const Position& p2, const Radius& r2) {
    43 if (e1 == e2) {
    44 // don't collide with self
    45 return;
    46 }
    47
    48 if (e1 > e2) {
    49 // Simple trick to prevent collisions from being detected
    50 // twice with the entities reversed.
    51 return;
    52 }
    53
    54 // Check for collision
    55 double d_sqr = distance_sqr(p1, p2);
    56 double r_sqr = sqr(r1.value + r2.value);
    57 if (r_sqr > d_sqr) {
    58 std::cout << e1 << " and " << e2 << " collided!\n";
    59 }
    60 });
    61 });
    62
    63 // Create a few test entities
    64 for (int i = 0; i < 10; i ++) {
    65 ecs.entity()
    66 .set<Position>({ randd(100), randd(100) })
    67 .set<Radius>({ randd(10) + 1 });
    68 }
    69
    70 // Run the system
    71 sys.run();
    72
    73 // Output
    74 // 526 and 529 collided!
    75 // 527 and 534 collided!
    76 // 529 and 531 collided!
    77 // 533 and 535 collided!
    78}
    flecs::system system(flecs::entity e) const
    Upcast an entity to a system.
    Definition impl.hpp:181
    conditional_t< sizeof...(Args)==0 &&_::is_sparse_query< Comps... >::value, flecs::sparse_query< Comps... >, flecs::query< Comps... > > query(Args &&... args) const
    Create a query.
    Definition impl.hpp:326
    flecs::entity entity(Args &&... args) const
    Create an entity.
    Definition impl.hpp:195
    void each(const Func &func) const
    Iterate (component) IDs of an entity.
    Definition impl.hpp:155
    Entity.
    Definition entity.hpp:30
    Class for iterating over query results.
    Definition iter.hpp:68
    void * ctx()
    Access ctx.
    Definition iter.hpp:162
    flecs::entity entity(size_t row) const
    Obtain a mutable handle to the entity being iterated over.
    Definition iter.hpp:36
    Typed query.
    Definition impl.hpp:271
    System.
    Definition impl.hpp:78
    system & each(Func &&func)
    Replace the system's each callback.
    Definition impl.hpp:119
    system & run(Func &&func)
    Replace the system's run callback.
    Definition impl.hpp:108
    The world.
    Definition world.hpp:129