Skip to content
Flecs v4.1
observers/propagate

  • C

    View on GitHub

    1#include <propagate.h>
    2#include <stdio.h>
    3
    4// Events are propagated along relationship edges. This means that observers can
    5// listen for events from a parent or prefab, like triggering when a component
    6// inherited from a prefab was set.
    7//
    8// Event propagation happens automatically when an observer contains a query
    9// with the EcsUp flag set (indicating upwards traversal). Observers use the
    10// same matching logic as queries: if a query with upwards traversal matches an
    11// entity, so will an observer.
    12//
    13// Events are only propagated along traversable relationship edges.
    14
    15typedef struct {
    16 double x, y;
    17} Position;
    18
    19void Observer(ecs_iter_t *it) {
    20 ecs_world_t *ecs = it->stage;
    21
    22 // The event kind
    23 ecs_entity_t event = it->event;
    24
    25 // The (component) id for which the event was emitted
    26 ecs_entity_t event_id = it->event_id;
    27
    28 // Grab Position from self and parent
    29 Position *p_self = ecs_field(it, Position, 0);
    30 Position *p_parent = ecs_field(it, Position, 1);
    31
    32 for (int i = 0; i < it->count; i ++) {
    33 ecs_entity_t e = it->entities[i];
    34
    35 printf(" - %s: %s: %s: self: {%f, %f}, parent: {%f, %f}\n",
    36 ecs_get_name(ecs, event),
    37 ecs_get_name(ecs, event_id),
    38 ecs_get_name(ecs, e),
    39 p_self[i].x, p_self[i].y,
    40 p_parent[i].x, p_parent[i].y);
    41 }
    42}
    43
    44int main(int argc, char *argv[]) {
    45 ecs_world_t *ecs = ecs_init_w_args(argc, argv);
    46
    47 ECS_COMPONENT(ecs, Position);
    48
    49 // Create observer that listens for events from both self and parent
    50 ecs_observer(ecs, {
    51 .query = { .terms = {
    52 // Listen for Position events from self
    53 { .id = ecs_id(Position) },
    54 // Listen for Position events from parent
    55 { .id = ecs_id(Position), .src.id = EcsUp, .trav = EcsChildOf }
    56 }},
    57 .events = { EcsOnSet },
    58 .callback = Observer
    59 });
    60
    61 // Create entity and parent
    62 ecs_entity_t p = ecs_entity(ecs, { .name = "p" });
    63 ecs_entity_t e = ecs_entity(ecs, { .name = "p.e" }); // Create as child of p
    64
    65 // Set Position on entity. This doesn't trigger the observer yet, since the
    66 // parent doesn't have Position yet.
    67 ecs_set(ecs, e, Position, {10, 20});
    68
    69 // Set Position on parent. This event will be propagated and trigger the
    70 // observer, as the observer query now matches.
    71 ecs_set(ecs, p, Position, {1, 2});
    72
    73 ecs_fini(ecs);
    74
    75 // Output
    76 // - OnSet: Position: e: self: {10.000000, 20.000000}, parent: {1.000000, 2.000000}
    77}
    const ecs_entity_t EcsOnSet
    Event that triggers when a component is set for an entity.
    const ecs_entity_t EcsChildOf
    Used to express parent-child relationships.
    FLECS_API const ecs_entity_t ecs_id(EcsDocDescription)
    Component ID for EcsDocDescription.
    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
    #define ecs_entity(world,...)
    Shorthand for creating an entity with ecs_entity_init().
    Definition flecs_c.h:188
    #define ecs_observer(world,...)
    Shorthand for creating an observer with ecs_observer_init().
    Definition flecs_c.h:230
    #define ECS_COMPONENT(world, id)
    Declare and define a component.
    Definition flecs_c.h:98
    #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
    const char * ecs_get_name(const ecs_world_t *world, ecs_entity_t entity)
    Get the name of an entity.
    #define EcsUp
    Match by traversing upwards.
    Definition flecs.h:768
    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
    ecs_entity_t event
    The event (if applicable).
    Definition flecs.h:1209
    ecs_id_t event_id
    The (component) ID for the event.
    Definition flecs.h:1210
    int32_t count
    Number of entities to iterate.
    Definition flecs.h:1189
    const ecs_entity_t * entities
    Entity identifiers.
    Definition flecs.h:1190

  • C++

    View on GitHub

    1#include <propagate.h>
    2#include <iostream>
    3
    4// Events are propagated along relationship edges. This means that observers can
    5// listen for events from a parent or prefab, like triggering when a component
    6// inherited from a prefab was set.
    7//
    8// Event propagation happens automatically when an observer contains a query
    9// with the EcsUp flag set (indicating upwards traversal). Observers use the
    10// same matching logic as queries: if a query with upwards traversal matches an
    11// entity, so will an observer.
    12//
    13// Events are only propagated along traversable relationship edges.
    14
    15struct Position {
    16 double x, y;
    17};
    18
    19int main(int, char *[]) {
    20 flecs::world ecs;
    21
    22 // Create observer that listens for events from both self and parent
    23 ecs.observer<Position, Position>()
    24 .term_at(1).parent() // select 2nd Position from parent
    25 .event(flecs::OnSet)
    26 .each([](flecs::iter& it, size_t i, Position& p_self, Position& p_parent) {
    27 std::cout << " - " << it.event().name() << ": "
    28 << it.event_id().str() << ": "
    29 << it.entity(i).name() << ": "
    30 << "self: {" << p_self.x << ", " << p_self.y << "}, "
    31 << "parent: {" << p_parent.x << ", " << p_parent.y << "}\n";
    32 });
    33
    34 // Create entity and parent
    35 flecs::entity p = ecs.entity("p");
    36 flecs::entity e = ecs.entity("e").child_of(p);
    37
    38 // Set Position on entity. This doesn't trigger the observer yet, since the
    39 // parent doesn't have Position yet.
    40 e.set<Position>({10, 20});
    41
    42 // Set Position on parent. This event will be propagated and trigger the
    43 // observer, as the observer query now matches.
    44 p.set<Position>({1, 2});
    45
    46 // Output
    47 // - OnSet: Position: e: self: {10, 20}, parent: {1, 2}
    48}
    flecs::entity entity(Args &&... args) const
    Create an entity.
    Definition impl.hpp:195
    flecs::observer observer(flecs::entity e) const
    Observer world mixin.
    Definition impl.hpp:85
    const Self & child_of(entity_t second) const
    Shortcut for add(ChildOf, entity).
    Definition builder.hpp:139
    flecs::string_view name() const
    Return the entity name.
    flecs::entity parent() const
    Get parent of entity.
    Definition impl.hpp:68
    void each(const Func &func) const
    Iterate (component) IDs of an entity.
    Definition impl.hpp:155
    Entity.
    Definition entity.hpp:30
    flecs::string str() const
    Convert ID to string.
    Definition decl.hpp:128
    Class for iterating over query results.
    Definition iter.hpp:68
    flecs::entity event() const
    Get the event entity associated with the iterator.
    Definition iter.hpp:17
    flecs::entity entity(size_t row) const
    Obtain a mutable handle to the entity being iterated over.
    Definition iter.hpp:36
    flecs::id event_id() const
    Get the event ID associated with the iterator.
    Definition iter.hpp:22
    The world.
    Definition world.hpp:129