Skip to content
Flecs v4.1
systems/immediate

  • C

    View on GitHub

    1#include <immediate.h>
    2#include <stdio.h>
    3
    4// When an application calls ecs_progress(), the world is put in readonly mode.
    5// This ensures that systems (on multiple threads) can safely iterate
    6// components, without having to worry about components moving around while
    7// they're being read. This has as side effect that any operations (like adding
    8// or removing components) are not visible until the end of the frame (see the
    9// sync_point example for more details).
    10// Sometimes this is not what you want, and you need a change to be visible
    11// immediately. For these use cases, applications can use an immediate system.
    12// This temporarily takes the world out of readonly mode, so a system can make
    13// changes that are directly visible.
    14// Because they mutate the world directly, immediate systems are never ran on
    15// more than one thread, and no other systems are ran at the same time.
    16
    17ECS_DECLARE(Waiter);
    18ECS_DECLARE(Plate);
    19
    20// System that assigns plates to waiter. By making this system immediate
    21// plate assignments are assigned directly (not deferred) to waiters, which
    22// ensures that we won't assign plates to the same waiter more than once.
    23void AssignPlate(ecs_iter_t *it) {
    24 ecs_world_t *ecs = it->stage;
    25 ecs_query_t *q_waiter = it->ctx; // Get query from system context
    26
    27 // Iterate unassigned plates
    28 for (int i = 0; i < it->count; i ++) {
    29 ecs_entity_t plate = it->entities[i];
    30
    31 // Find an available waiter
    32 ecs_iter_t qit = ecs_query_iter(ecs, q_waiter);
    33 ecs_entity_t waiter = ecs_iter_first(&qit); // Get first matching entity
    34 if (waiter) {
    35 // An available waiter was found, assign a plate to it so that the
    36 // next plate will no longer find it.
    37 ecs_add_pair(it->world, waiter, Plate, plate);
    38
    39 ecs_add_pair(ecs, plate, Waiter, waiter);
    40
    41 printf("Assigned %s to %s!\n",
    42 ecs_get_name(ecs, waiter),
    43 ecs_get_name(ecs, plate));
    44
    45 } else {
    46 // No available waiters, can't assign the plate
    47 }
    48 }
    49}
    50
    51int main(int argc, char *argv[]) {
    52 ecs_world_t *ecs = ecs_init_w_args(argc, argv);
    53
    54 ECS_TAG_DEFINE(ecs, Waiter);
    55 ECS_TAG_DEFINE(ecs, Plate);
    56
    57 // Create query to find all waiters without a plate
    58 ecs_query_t *q_waiter = ecs_query(ecs, {
    59 .terms = {
    60 { .id = Waiter },
    61 { .id = ecs_pair(Plate, EcsWildcard), .oper = EcsNot }
    62 }
    63 });
    64
    65 // Find all plates without a Waiter
    66 ecs_system(ecs, {
    67 .entity = ecs_entity(ecs, { .name = "AssignPlate" }),
    68 .phase = EcsOnUpdate,
    69 .query.terms = {
    70 { .id = Plate },
    71 { .id = ecs_pair(Waiter, EcsWildcard), .oper = EcsNot }
    72 },
    73 .callback = AssignPlate,
    74 .ctx = q_waiter,
    75 .immediate = true // disable readonly mode for this system
    76 });
    77
    78 // Create a few plates and waiters
    79 ecs_entity_t waiter_1 = ecs_entity(ecs, { .name = "waiter_1" });
    80 ecs_add_id(ecs, waiter_1, Waiter);
    81 ecs_entity_t waiter_2 = ecs_entity(ecs, { .name = "waiter_2" });
    82 ecs_add_id(ecs, waiter_2, Waiter);
    83 ecs_entity_t waiter_3 = ecs_entity(ecs, { .name = "waiter_3" });
    84 ecs_add_id(ecs, waiter_3, Waiter);
    85
    86 ecs_entity_t plate_1 = ecs_entity(ecs, { .name = "plate_1" });
    87 ecs_add_id(ecs, plate_1, Plate);
    88 ecs_entity_t plate_2 = ecs_entity(ecs, { .name = "plate_2" });
    89 ecs_add_id(ecs, plate_2, Plate);
    90 ecs_add_pair(ecs, plate_2, Waiter, waiter_1); // already assigned
    91 ecs_entity_t plate_3 = ecs_entity(ecs, { .name = "plate_3" });
    92 ecs_add_id(ecs, plate_3, Plate);
    93
    94 // Also assign plate_2 to waiter_1
    95 ecs_add_pair(ecs, waiter_1, Plate, plate_2);
    96
    97 // Run the system
    98 ecs_progress(ecs, 0);
    99
    100 return ecs_fini(ecs);
    101
    102 // Output:
    103 // Assigned waiter_3 to plate_1!
    104 // Assigned waiter_2 to plate_3!
    105}
    void ecs_add_id(ecs_world_t *world, ecs_entity_t entity, ecs_id_t component)
    Add a (component) ID to an entity.
    const ecs_entity_t EcsWildcard
    Wildcard entity ("*").
    const ecs_entity_t EcsOnUpdate
    OnUpdate pipeline phase.
    FLECS_API bool ecs_progress(ecs_world_t *world, ecs_ftime_t delta_time)
    Progress a world.
    #define ecs_system(world,...)
    Shorthand for creating a system with ecs_system_init().
    Definition system.h:285
    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_add_pair(world, subject, first, second)
    Add a pair to an entity.
    Definition flecs_c.h:275
    #define ecs_entity(world,...)
    Shorthand for creating an entity with ecs_entity_init().
    Definition flecs_c.h:188
    #define ECS_DECLARE(id)
    Forward declare an entity, tag, prefab, or any other entity identifier.
    Definition flecs_c.h:25
    #define ecs_query(world,...)
    Shorthand for creating a query with ecs_query_init().
    Definition flecs_c.h:215
    #define ECS_TAG_DEFINE(world, id_)
    Define a forward-declared tag.
    Definition flecs_c.h:39
    ecs_entity_t ecs_iter_first(ecs_iter_t *it)
    Get the first matching entity from an iterator.
    const char * ecs_get_name(const ecs_world_t *world, ecs_entity_t entity)
    Get the name of an entity.
    ecs_iter_t ecs_query_iter(const ecs_world_t *world, const ecs_query_t *query)
    Create a query iterator.
    @ EcsNot
    The term must not match.
    Definition flecs.h:739
    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
    conditional_t< sizeof...(Args)==0 &&_::is_sparse_query< Comps... >::value, flecs::sparse_query< Comps... >, flecs::query< Comps... > > query(Args &&... args) const
    Create a query.

  • C++

    View on GitHub

    1#include <immediate.h>
    2#include <iostream>
    3
    4// When an application calls world.progress(), the world is put in readonly mode.
    5// This ensures that systems (on multiple threads) can safely iterate
    6// components, without having to worry about components moving around while
    7// they're being read. This has as side effect that any operations (like adding
    8// or removing components) are not visible until the end of the frame (see the
    9// sync_point example for more details).
    10// Sometimes this is not what you want, and you need a change to be visible
    11// immediately. For these use cases, applications can use an immediate system.
    12// This temporarily takes the world out of readonly mode, so a system can make
    13// changes that are directly visible.
    14// Because they mutate the world directly, immediate systems are never ran on
    15// more than one thread, and no other systems are ran at the same time.
    16
    17struct Waiter { };
    18struct Plate { };
    19
    20int main(int, char *[]) {
    21 flecs::world ecs;
    22
    23 // Create query to find all waiters without a plate
    24 flecs::query<> q_waiter = ecs.query_builder()
    25 .with<Waiter>()
    26 .without<Plate>(flecs::Wildcard)
    27 .build();
    28
    29 // System that assigns plates to waiter. By making this system immediate
    30 // plate assignments are assigned directly (not deferred) to waiters, which
    31 // ensures that we won't assign plates to the same waiter more than once.
    32 ecs.system("AssignPlate")
    33 .with<Plate>()
    34 .without<Waiter>(flecs::Wildcard)
    35 .immediate()
    36 .each([&](flecs::iter& it, size_t i) {
    37 flecs::entity plate = it.entity(i);
    38
    39 // Find an available waiter
    40 flecs::entity waiter = q_waiter.first();
    41 if (waiter) {
    42 waiter.mut(it.world()).add<Plate>(plate);
    43
    44 plate.add<Waiter>(waiter);
    45
    46 std::cout << "Assigned "
    47 << waiter.name() << " to "
    48 << plate.name() << "!\n";
    49 } else {
    50 // No available waiters, can't assign the plate
    51 }
    52 });
    53
    54 // Create a few plates and waiters
    55 flecs::entity waiter_1 = ecs.entity("waiter_1").add<Waiter>();
    56 ecs.entity("waiter_2").add<Waiter>();
    57 ecs.entity("waiter_3").add<Waiter>();
    58
    59 ecs.entity("plate_1").add<Plate>();
    60 flecs::entity plate_2 = ecs.entity("plate_2").add<Plate>();
    61 ecs.entity("plate_3").add<Plate>();
    62
    63 waiter_1.add<Plate>(plate_2);
    64 plate_2.add<Waiter>(waiter_1);
    65
    66 // run systems
    67 ecs.progress();
    68
    69 // Output:
    70 // Assigned waiter_3 to plate_1!
    71 // Assigned waiter_2 to plate_3!
    72}
    flecs::system system(flecs::entity e) const
    Upcast an entity to a system.
    Definition impl.hpp:181
    flecs::query_builder< Comps... > query_builder(Args &&... args) const
    Create a query builder.
    Definition impl.hpp:342
    flecs::entity entity(Args &&... args) const
    Create an entity.
    Definition impl.hpp:195
    bool progress(ecs_ftime_t delta_time=0.0) const
    Progress the world one tick.
    Definition impl.hpp:47
    flecs::string_view name() const
    Return the entity name.
    flecs::entity mut(const flecs::world &stage) const
    Return a mutable entity handle for the current stage.
    Definition impl.hpp:72
    Entity.
    Definition entity.hpp:30
    Class for iterating over query results.
    Definition iter.hpp:68
    flecs::entity entity(size_t row) const
    Obtain a mutable handle to the entity being iterated over.
    Definition iter.hpp:36
    flecs::world world() const
    Get the world associated with the iterator.
    Definition iter.hpp:27
    flecs::entity first() const
    Return the first entity matched by the iterable.
    Definition iterable.hpp:126
    Typed query.
    Definition impl.hpp:271
    system & each(Func &&func)
    Replace the system's each callback.
    Definition impl.hpp:119
    The world.
    Definition world.hpp:129