120 lines
3.3 KiB
C
120 lines
3.3 KiB
C
#include <hooks.h>
|
|
#include <stdio.h>
|
|
|
|
// Component hooks are callbacks that can be registered for a type that are
|
|
// invoked during different parts of the component lifecycle.
|
|
|
|
typedef struct {
|
|
char *value; // Pointer to external memory
|
|
} String;
|
|
|
|
// Resource management hooks. The convenience macros hide details of
|
|
// the callback signature, while allowing hooks to be called on multiple
|
|
// entities.
|
|
|
|
// The constructor should initialize the component value.
|
|
ECS_CTOR(String, ptr, {
|
|
ecs_trace("Ctor");
|
|
ptr->value = NULL;
|
|
})
|
|
|
|
// The destructor should free resources.
|
|
ECS_DTOR(String, ptr, {
|
|
ecs_trace("Dtor");
|
|
ecs_os_free(ptr->value);
|
|
})
|
|
|
|
// The move hook should move resources from one location to another.
|
|
ECS_MOVE(String, dst, src, {
|
|
ecs_trace("Move");
|
|
ecs_os_free(dst->value);
|
|
dst->value = src->value;
|
|
src->value = NULL; // This makes sure the value doesn't get deleted twice,
|
|
// as the destructor is still invoked after a move.
|
|
})
|
|
|
|
// The copy hook should copy resources from one location to another.
|
|
ECS_COPY(String, dst, src, {
|
|
ecs_trace("Copy");
|
|
ecs_os_free(dst->value);
|
|
dst->value = ecs_os_strdup(src->value);
|
|
})
|
|
|
|
// This callback is used for the add, remove and set hooks. Note that the
|
|
// signature is the same as systems, triggers, observers.
|
|
void hook_callback(ecs_iter_t *it) {
|
|
ecs_world_t *world = it->world;
|
|
ecs_entity_t event = it->event;
|
|
|
|
for (int i = 0; i < it->count; i ++) {
|
|
ecs_entity_t e = it->entities[i];
|
|
ecs_trace("%s: %s",
|
|
ecs_get_name(world, event), ecs_get_name(world, e));
|
|
}
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
ecs_world_t *world = ecs_init_w_args(argc, argv);
|
|
|
|
ECS_COMPONENT(world, String);
|
|
ECS_TAG(world, Tag);
|
|
|
|
ecs_set_hooks(world, String, {
|
|
/* Resource management hooks. These hooks should primarily be used for
|
|
* managing memory used by the component. */
|
|
.ctor = ecs_ctor(String),
|
|
.move = ecs_move(String),
|
|
.copy = ecs_copy(String),
|
|
.dtor = ecs_dtor(String),
|
|
|
|
/* Lifecycle hooks. These hooks should be used for application logic. */
|
|
.on_add = hook_callback,
|
|
.on_remove = hook_callback,
|
|
.on_set = hook_callback
|
|
});
|
|
|
|
ecs_log_set_level(0);
|
|
|
|
ecs_entity_t e = ecs_new_entity(world, "Entity");
|
|
|
|
ecs_trace("ecs_add(world, e, String)");
|
|
ecs_log_push();
|
|
ecs_add(world, e, String);
|
|
ecs_log_pop();
|
|
|
|
ecs_trace("ecs_set(world, e, String, {\"Hello World\"})");
|
|
ecs_log_push();
|
|
ecs_set(world, e, String, {ECS_CONST_CAST(char*, "Hello World")});
|
|
ecs_log_pop();
|
|
|
|
// This operation changes the entity's archetype, which invokes a move
|
|
ecs_trace("ecs_add(world, e, Tag)");
|
|
ecs_log_push();
|
|
ecs_add(world, e, Tag);
|
|
ecs_log_pop();
|
|
|
|
ecs_trace("ecs_delete(world, e)");
|
|
ecs_log_push();
|
|
ecs_delete(world, e);
|
|
ecs_log_pop();
|
|
|
|
ecs_log_set_level(-1);
|
|
|
|
return ecs_fini(world);
|
|
|
|
// Output:
|
|
// info: ecs_add(world, e, String)
|
|
// info: | Ctor
|
|
// info: | OnAdd: Entity
|
|
// info: ecs_set(world, e, String, {"Hello World"})
|
|
// info: | Copy
|
|
// info: | OnSet: Entity
|
|
// info: ecs_add(world, e, Tag)
|
|
// info: | Ctor
|
|
// info: | Move
|
|
// info: | Dtor
|
|
// info: ecs_delete(world, e)
|
|
// info: | OnRemove: Entity
|
|
// info: | Dtor
|
|
}
|