Skip to content

Instantly share code, notes, and snippets.

@ZeroErrors
Created December 2, 2023 16:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZeroErrors/629deb70cda163eec38826c27f17b667 to your computer and use it in GitHub Desktop.
Save ZeroErrors/629deb70cda163eec38826c27f17b667 to your computer and use it in GitHub Desktop.
flecs - C lifeclcye hooks example
#include <flecs.h>
#include <stdio.h>
typedef struct Data {
int x;
} Data;
typedef struct Test {
Data* ptr;
} Test;
ECS_COMPONENT_DECLARE(Test);
ECS_CTOR(Test, ptr, {
ptr->ptr = ecs_os_malloc(sizeof(Data));
ptr->ptr->x = 0; // Default value
printf("ctor: %d\n", ptr->ptr->x);
})
ECS_DTOR(Test, ptr, {
printf("dtor: %d\n", ptr->ptr->x);
ecs_os_free(ptr->ptr);
})
ECS_MOVE(Test, dst, src, {
printf("move: %d->%d\n", src->ptr->x, dst->ptr->x);
dst->ptr = src->ptr;
// Clear the pointer in src since it's been moved tp dst and we
// don't want to free it when `src` ges destroyed
src->ptr = NULL;
})
void testRemoved(ecs_iter_t *it) {
Test *test = ecs_field(it, Test, 1);
for (int i = 0; i < it->count; i++) {
printf("on_remove: %d\n", test[i].ptr->x);
}
}
void testSet(ecs_iter_t *it) {
Test *test = ecs_field(it, Test, 1);
for (int i = 0; i < it->count; i++) {
printf("on_set: %d\n", test[i].ptr->x);
}
}
void ecs_copy_illegal(void *dst, const void *src, int32_t c, const ecs_type_info_t *ti) {
ecs_abort(ECS_INVALID_OPERATION, "invalid copy assignment for %s", ti->name);
}
int main(int argc, char *argv[]) {
ecs_world_t *ecs = ecs_init();
ECS_COMPONENT_DEFINE(ecs, Test);
ecs_set_hooks(ecs, Test, {
.ctor = ecs_ctor(Test),
.dtor = ecs_dtor(Test),
.move = ecs_move(Test),
.copy = ecs_copy_illegal, // Prevent Test from being copied so that they never share the same pointer
.on_remove = testRemoved,
.on_set = testSet
});
ecs_entity_t entity = ecs_new_id(ecs);
Test* test = ecs_emplace(ecs, entity, Test); // Emplace the component, this doesn't call the ctor allowing us to initialize the data in the table directly
Data* ptr = ecs_os_malloc(sizeof(Data));
ptr->x = 1;
test->ptr = ptr;
ecs_modified(ecs, entity, Test); // Tell the ECS that we are done with modifying the component
// Modify the data in the component without doing any copy/move
test = ecs_get_mut(ecs, entity, Test);
test->ptr->x = 2;
ecs_modified(ecs, entity, Test);
ecs_remove(ecs, entity, Test); // testRemoved called for {2}
// Since the component was previously removed this will call the constructor to initialize the
// default value in the table, and then return that.
test = ecs_get_mut(ecs, entity, Test);
test->ptr->x = 3;
ecs_modified(ecs, entity, Test);
ecs_defer_begin(ecs);
ecs_remove(ecs, entity, Test);
test = ecs_get_mut(ecs, entity, Test);
test->ptr->x = 4;
ecs_modified(ecs, entity, Test);
ecs_defer_end(ecs);
ecs_fini(ecs); // testRemoved called for {4}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment