Skip to content
Flecs v4.1
entities/hooks

  • C

    View on GitHub

    1#include <hooks.h>
    2#include <stdio.h>
    3
    4// Component hooks are callbacks that can be registered for a type that are
    5// invoked during different parts of the component lifecycle.
    6
    7typedef struct {
    8 char *value; // Pointer to external memory
    9} String;
    10
    11// Resource management hooks. The convenience macros hide details of
    12// the callback signature, while allowing hooks to be called on multiple
    13// entities.
    14
    15// The constructor should initialize the component value.
    16ECS_CTOR(String, ptr, {
    17 ecs_trace("Ctor");
    18 ptr->value = NULL;
    19})
    20
    21// The destructor should free resources.
    22ECS_DTOR(String, ptr, {
    23 ecs_trace("Dtor");
    24 ecs_os_free(ptr->value);
    25})
    26
    27// The move hook should move resources from one location to another.
    28ECS_MOVE(String, dst, src, {
    29 ecs_trace("Move");
    30 ecs_os_free(dst->value);
    31 dst->value = src->value;
    32 src->value = NULL; // This makes sure the value doesn't get deleted twice,
    33 // as the destructor is still invoked after a move.
    34})
    35
    36// The copy hook should copy resources from one location to another.
    37ECS_COPY(String, dst, src, {
    38 ecs_trace("Copy");
    39 ecs_os_free(dst->value);
    40 dst->value = ecs_os_strdup(src->value);
    41})
    42
    43// This callback is used for the add, remove and set hooks. Note that the
    44// signature is the same as systems, triggers, observers.
    45void hook_callback(ecs_iter_t *it) {
    46 ecs_world_t *world = it->stage;
    47 ecs_entity_t event = it->event;
    48
    49 for (int i = 0; i < it->count; i ++) {
    50 ecs_entity_t e = it->entities[i];
    51 ecs_trace("%s: %s",
    52 ecs_get_name(world, event), ecs_get_name(world, e));
    53 }
    54}
    55
    56int main(int argc, char *argv[]) {
    57 ecs_world_t *world = ecs_init_w_args(argc, argv);
    58
    59 ECS_COMPONENT(world, String);
    60 ECS_TAG(world, Tag);
    61
    62 ecs_set_hooks(world, String, {
    63 /* Resource management hooks. These hooks should primarily be used for
    64 * managing memory used by the component. */
    65 .ctor = ecs_ctor(String),
    66 .move = ecs_move(String),
    67 .copy = ecs_copy(String),
    68 .dtor = ecs_dtor(String),
    69
    70 /* Lifecycle hooks. These hooks should be used for application logic. */
    71 .on_add = hook_callback,
    72 .on_remove = hook_callback,
    73 .on_set = hook_callback
    74 });
    75
    77
    78 ecs_entity_t e = ecs_entity(world, { .name = "Entity" });
    79
    80 ecs_trace("ecs_add(world, e, String)");
    82 ecs_add(world, e, String);
    84
    85 ecs_trace("ecs_set(world, e, String, {\"Hello World\"})");
    87 ecs_set(world, e, String, {ECS_CONST_CAST(char*, "Hello World")});
    89
    90 // This operation changes the entity's archetype, which invokes a move
    91 ecs_trace("ecs_add(world, e, Tag)");
    93 ecs_add(world, e, Tag);
    95
    96 ecs_trace("ecs_delete(world, e)");
    98 ecs_delete(world, e);
    100
    102
    103 return ecs_fini(world);
    104
    105 // Output:
    106 // info: ecs_add(world, e, String)
    107 // info: | Ctor
    108 // info: | OnAdd: Entity
    109 // info: ecs_set(world, e, String, {"Hello World"})
    110 // info: | Copy
    111 // info: | OnSet: Entity
    112 // info: ecs_add(world, e, Tag)
    113 // info: | Ctor
    114 // info: | Move
    115 // info: | Dtor
    116 // info: ecs_delete(world, e)
    117 // info: | OnRemove: Entity
    118 // info: | Dtor
    119}
    #define ecs_log_push()
    Push log indentation at the default level.
    Definition log.h:458
    #define ecs_trace(...)
    Tracing macro.
    Definition log.h:309
    #define ecs_log_pop()
    Pop log indentation at the default level.
    Definition log.h:460
    FLECS_API int ecs_log_set_level(int level)
    Enable or disable log.
    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
    void ecs_delete(ecs_world_t *world, ecs_entity_t entity)
    Delete an entity.
    #define ecs_add(world, entity, T)
    Add a component to an entity.
    Definition flecs_c.h:271
    #define ecs_set_hooks(world, T,...)
    Set component hooks.
    Definition flecs_c.h:623
    #define ecs_move(type)
    Map from typename to move function name.
    Definition flecs_c.h:693
    #define ECS_CTOR(type, var,...)
    Declare a constructor.
    Definition flecs_c.h:637
    #define ECS_MOVE(type, dst_var, src_var,...)
    Declare a move action.
    Definition flecs_c.h:667
    #define ECS_DTOR(type, var,...)
    Declare a destructor.
    Definition flecs_c.h:647
    #define ecs_copy(type)
    Map from typename to copy function name.
    Definition flecs_c.h:691
    #define ecs_dtor(type)
    Map from typename to destructor function name.
    Definition flecs_c.h:689
    #define ECS_COPY(type, dst_var, src_var,...)
    Declare a copy action.
    Definition flecs_c.h:657
    #define ecs_ctor(type)
    Map from typename to constructor function name.
    Definition flecs_c.h:687
    #define ecs_entity(world,...)
    Shorthand for creating an entity with ecs_entity_init().
    Definition flecs_c.h:188
    #define ECS_COMPONENT(world, id)
    Declare and define a component.
    Definition flecs_c.h:98
    #define ECS_TAG(world, id)
    Declare and define a tag.
    Definition flecs_c.h:59
    #define ecs_set(world, entity, component,...)
    Set a component value.
    Definition flecs_c.h:310
    const char * ecs_get_name(const ecs_world_t *world, ecs_entity_t entity)
    Get the name of an entity.
    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
    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 <hooks.h>
    2#include <iostream>
    3
    4// Component hooks are callbacks that can be registered for a type that are
    5// invoked during different parts of the component lifecycle.
    6//
    7// In the C++ API the ctor, dtor, copy and move methods of a type are
    8// automatically registered as component hooks.
    9
    10struct String {
    11 String(const char *v = nullptr) {
    12 flecs::log::trace("Ctor(const char*)");
    13 value = ecs_os_strdup(v);
    14 }
    15
    16 ~String() {
    17 flecs::log::trace("Dtor");
    18 ecs_os_free(value);
    19 }
    20
    21 String(const String& obj) {
    22 flecs::log::trace("Copy");
    23 value = ecs_os_strdup(obj.value);
    24 }
    25
    26 String(String&& obj) {
    27 flecs::log::trace("Move");
    28 value = obj.value;
    29 obj.value = nullptr;
    30 }
    31
    32 String& operator=(const String& obj) {
    33 flecs::log::trace("Copy assign");
    34 ecs_os_free(value);
    35 value = ecs_os_strdup(obj.value);
    36 return *this;
    37 }
    38
    39 String& operator=(String&& obj) {
    40 flecs::log::trace("Move assign");
    41 ecs_os_free(value);
    42 value = obj.value;
    43 obj.value = nullptr;
    44 return *this;
    45 }
    46
    47 char *value;
    48};
    49
    50struct Tag { };
    51
    52int main(int, char *[]) {
    53 flecs::world ecs;
    54
    55 // Register additional add, remove and set hooks for type
    56 ecs.component<String>()
    57 .on_add([](flecs::entity e, String&) {
    58 flecs::log::trace("OnAdd: %s", e.name().c_str());
    59 })
    60 .on_remove([](flecs::entity e, String&) {
    61 flecs::log::trace("OnRemove: %s", e.name().c_str());
    62 })
    63 .on_set([](flecs::entity e, String&) {
    64 flecs::log::trace("OnSet: %s", e.name().c_str());
    65 });
    66
    67 // Register in advance to keep output trace clean
    68 ecs.component<Tag>();
    69
    71
    72 flecs::entity e = ecs.entity("Entity");
    73
    74 flecs::log::push("e.add<String>()");
    75 e.add<String>();
    77
    78 flecs::log::push("e.set<String>({\"Hello World\"})");
    79 e.set<String>({"Hello World"});
    81
    82 // This operation changes the entity's archetype, which invokes a move
    83 flecs::log::push("e.add<Tag>()");
    84 e.add<Tag>();
    86
    87 flecs::log::push("e.destruct()");
    88 e.destruct();
    90
    92
    93 // Output:
    94 // info: e.add<String>()
    95 // info: | Ctor
    96 // info: | OnAdd: Entity
    97 // info: e.set<String>({"Hello World"})
    98 // info: | Ctor
    99 // info: | Move assign
    100 // info: | OnSet: Entity
    101 // info: | Dtor
    102 // info: e.add<Tag>()
    103 // info: | Move
    104 // info: | Dtor
    105 // info: e.destruct()
    106 // info: | OnRemove: Entity
    107 // info: | Dtor
    108}
    flecs::component< T > component(Args &&... args) const
    Find or register a component.
    Definition impl.hpp:11
    flecs::entity entity(Args &&... args) const
    Create an entity.
    Definition impl.hpp:195
    void push()
    Increase log indentation.
    Definition log.hpp:150
    void set_level(int level)
    Set the log level.
    Definition log.hpp:57
    void trace(_::fmt_str fmt,...)
    Trace (level 0).
    Definition log.hpp:108
    void pop()
    Decrease log indentation.
    Definition log.hpp:155
    flecs::string_view name() const
    Return the entity name.
    Entity.
    Definition entity.hpp:30
    void destruct() const
    Delete an entity.
    Definition entity.hpp:208
    const char * c_str() const
    Return the C string.
    Definition string.hpp:109
    The world.
    Definition world.hpp:129