#include void TriggerOnAdd_setup(void) { ecs_log_set_level(-3); } void Init(ecs_iter_t *it) { Position *p = ecs_field(it, Position, 1); Velocity *v = NULL; if (it->field_count >= 2) { v = ecs_field(it, Velocity, 2); } probe_iter(it); int i; for (i = 0; i < it->count; i ++) { p[i].x = 10; p[i].y = 20; if (v) { v[i].x = 30; v[i].y = 40; } } } static void Add_to_current(ecs_iter_t *it) { IterData *ctx = ecs_get_ctx(it->world); int i; for (i = 0; i < it->count; i ++) { if (ctx->component) { ecs_add_id(it->world, it->entities[i], ctx->component); test_assert( !!ecs_get_type(it->world, it->entities[i])); } if (ctx->component_2) { ecs_add_id(it->world, it->entities[i], ctx->component_2); } ctx->entity_count ++; } } static void Remove_from_current(ecs_iter_t *it) { IterData *ctx = ecs_get_ctx(it->world); int i; for (i = 0; i < it->count; i ++) { ecs_entity_t e = it->entities[i]; if (ctx->component) { ecs_remove_id(it->world, e, ctx->component); } if (ctx->component_2) { ecs_remove_id(it->world, e, ctx->component_2); } ctx->entity_count ++; } } static void Set_current(ecs_iter_t *it) { IterData *ctx = ecs_get_ctx(it->world); ecs_entity_t ecs_id(Rotation) = ctx->component; int i; for (i = 0; i < it->count; i ++) { ecs_set(it->world, it->entities[i], Rotation, {10 + it->entities[i]}); ctx->entity_count ++; } } static bool dummy_called = false; static void Dummy(ecs_iter_t *it) { dummy_called = true; } void TriggerOnAdd_new_match_1_of_1(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_OBSERVER(world, Init, EcsOnAdd, Position); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e = ecs_new(world, Position); test_assert(e != 0); test_int(ctx.count, 1); test_int(ctx.invoked, 1); test_int(ctx.system, Init); test_int(ctx.term_count, 1); test_null(ctx.param); test_int(ctx.e[0], e); test_int(ctx.c[0][0], ecs_id(Position)); test_int(ctx.s[0][0], 0); const Position *p = ecs_get(world, e, Position); test_int(p->x, 10); test_int(p->y, 20); ecs_fini(world); } void TriggerOnAdd_new_match_1_of_2(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); ECS_OBSERVER(world, Init, EcsOnAdd, Position); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ECS_ENTITY(world, e, Position, Velocity); test_assert(e != 0); test_int(ctx.count, 1); test_int(ctx.invoked, 1); test_int(ctx.system, Init); test_int(ctx.term_count, 1); test_null(ctx.param); test_int(ctx.e[0], e); test_int(ctx.c[0][0], ecs_id(Position)); test_int(ctx.s[0][0], 0); const Position *p = ecs_get(world, e, Position); test_int(p->x, 10); test_int(p->y, 20); ecs_fini(world); } void TriggerOnAdd_new_no_match_1(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); ECS_OBSERVER(world, Init, EcsOnAdd, Position); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e = ecs_new(world, Velocity); test_assert(e != 0); test_int(ctx.count, 0); ecs_fini(world); } void TriggerOnAdd_add_match_1_of_1(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_OBSERVER(world, Init, EcsOnAdd, Position); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e = ecs_new(world, 0); test_assert(e != 0); test_int(ctx.count, 0); ecs_add(world, e, Position); test_int(ctx.count, 1); test_int(ctx.invoked, 1); test_int(ctx.system, Init); test_int(ctx.term_count, 1); test_null(ctx.param); test_int(ctx.e[0], e); test_int(ctx.c[0][0], ecs_id(Position)); test_int(ctx.s[0][0], 0); const Position *p = ecs_get(world, e, Position); test_int(p->x, 10); test_int(p->y, 20); ecs_fini(world); } void TriggerOnAdd_add_match_1_of_2(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); ECS_OBSERVER(world, Init, EcsOnAdd, Position); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e = ecs_new(world, 0); test_assert(e != 0); test_int(ctx.count, 0); ecs_add(world, e, Position); ecs_add(world, e, Velocity); test_int(ctx.count, 1); test_int(ctx.invoked, 1); test_int(ctx.system, Init); test_int(ctx.term_count, 1); test_null(ctx.param); test_int(ctx.e[0], e); test_int(ctx.c[0][0], ecs_id(Position)); test_int(ctx.s[0][0], 0); const Position *p = ecs_get(world, e, Position); test_int(p->x, 10); test_int(p->y, 20); ecs_fini(world); } void TriggerOnAdd_add_no_match_1(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); ECS_OBSERVER(world, Init, EcsOnAdd, Velocity); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e = ecs_new(world, 0); test_assert(e != 0); test_int(ctx.count, 0); ecs_add(world, e, Position); test_int(ctx.count, 0); ecs_fini(world); } void TriggerOnAdd_set_match_1_of_1(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_OBSERVER(world, Init, EcsOnAdd, Position); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e = ecs_new(world, 0); test_assert(e != 0); test_int(ctx.count, 0); ecs_set(world, e, Position, {1, 2}); test_int(ctx.count, 1); test_int(ctx.invoked, 1); test_int(ctx.system, Init); test_int(ctx.term_count, 1); test_null(ctx.param); test_int(ctx.e[0], e); test_int(ctx.c[0][0], ecs_id(Position)); test_int(ctx.s[0][0], 0); const Position *p = ecs_get(world, e, Position); test_int(p->x, 1); test_int(p->y, 2); ecs_fini(world); } void TriggerOnAdd_set_no_match_1(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); ECS_OBSERVER(world, Init, EcsOnAdd, Velocity); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e = ecs_new(world, 0); test_assert(e != 0); test_int(ctx.count, 0); ecs_set(world, e, Position, {1, 2}); test_int(ctx.count, 0); ecs_fini(world); } void TriggerOnAdd_clone_match_1_of_1(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_OBSERVER(world, Init, EcsOnAdd, Position); ecs_entity_t e1 = ecs_new(world, Position); test_assert(e1 != 0); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e2 = ecs_clone(world, 0, e1, false); test_int(ctx.count, 1); test_int(ctx.invoked, 1); test_int(ctx.system, Init); test_int(ctx.term_count, 1); test_null(ctx.param); test_int(ctx.e[0], e2); test_int(ctx.c[0][0], ecs_id(Position)); test_int(ctx.s[0][0], 0); const Position *p = ecs_get(world, e2, Position); test_int(p->x, 10); test_int(p->y, 20); ecs_fini(world); } void TriggerOnAdd_clone_match_1_of_2(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); ECS_OBSERVER(world, Init, EcsOnAdd, Position); ECS_ENTITY(world, e1, Position, Velocity); test_assert(e1 != 0); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e2 = ecs_clone(world, 0, e1, false); test_int(ctx.count, 1); test_int(ctx.invoked, 1); test_int(ctx.system, Init); test_int(ctx.term_count, 1); test_null(ctx.param); test_int(ctx.e[0], e2); test_int(ctx.c[0][0], ecs_id(Position)); test_int(ctx.s[0][0], 0); const Position *p = ecs_get(world, e2, Position); test_int(p->x, 10); test_int(p->y, 20); ecs_fini(world); } void TriggerOnAdd_add_again_1(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_OBSERVER(world, Init, EcsOnAdd, Position); ecs_entity_t e = ecs_new(world, 0); test_assert(e != 0); ecs_add(world, e, Position); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_add(world, e, Position); test_int(ctx.count, 0); ecs_fini(world); } void TriggerOnAdd_set_again_1(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_OBSERVER(world, Init, EcsOnAdd, Position); ecs_entity_t e = ecs_new(world, 0); test_assert(e != 0); ecs_set(world, e, Position, {10, 20}); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_set(world, e, Position, {30, 40}); test_int(ctx.count, 0); ecs_fini(world); } void TriggerOnAdd_add_again_2(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); ECS_OBSERVER(world, Init, EcsOnAdd, Position); ecs_entity_t e = ecs_new(world, 0); test_assert(e != 0); ecs_add(world, e, Position); ecs_add(world, e, Velocity); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_add(world, e, Position); ecs_add(world, e, Velocity); test_int(ctx.count, 0); ecs_fini(world); } void TriggerOnAdd_new_w_count_match_1_of_1(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_OBSERVER(world, Init, EcsOnAdd, Position); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); const ecs_entity_t *ids = ecs_bulk_new(world, Position, 3); test_assert(ids != NULL); test_int(ctx.count, 3); test_int(ctx.invoked, 1); test_int(ctx.system, Init); test_int(ctx.term_count, 1); test_null(ctx.param); test_int(ctx.e[0], ids[0]); test_int(ctx.e[1], ids[1]); test_int(ctx.e[2], ids[2]); test_int(ctx.c[0][0], ecs_id(Position)); test_int(ctx.s[0][0], 0); int i; for (i = 0; i < 3; i ++) { const Position *p = ecs_get(world, ids[i], Position); test_int(p->x, 10); test_int(p->y, 20); } ecs_fini(world); } static void AddVelocity(ecs_iter_t *it) { Position *p = ecs_field(it, Position, 1); ecs_id_t v = 0; if (it->ctx) { v = *(ecs_id_t*)it->ctx; } if (!v) { v = ecs_field_id(it, 2); } probe_iter(it); int i; for (i = 0; i < it->count; i ++) { p[i].x = 1; p[i].y = 2; ecs_add_id(it->world, it->entities[i], v); } } void TriggerOnAdd_override_after_add_in_on_add(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); ECS_PREFAB(world, Prefab, Position); ecs_set(world, Prefab, Position, {1, 2}); ECS_OBSERVER(world, AddVelocity, EcsOnAdd, Position(self)); ecs_observer_init(world, &(ecs_observer_desc_t){ .entity = ecs_entity(world, {.id = AddVelocity}), .ctx = &ecs_id(Velocity) }); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab); test_assert(e != 0); test_int(ctx.count, 0); ecs_add(world, e, Position); test_assert( ecs_has(world, e, Position)); test_assert( ecs_has(world, e, Velocity)); test_int(ctx.count, 1); test_int(ctx.invoked, 1); test_int(ctx.system, AddVelocity); test_int(ctx.term_count, 1); test_int(ctx.e[0], e); test_int(ctx.c[0][0], ecs_id(Position)); test_int(ctx.s[0][0], 0); const Position *p = ecs_get(world, e, Position); test_int(p->x, 1); test_int(p->y, 2); ecs_fini(world); } static void OnSetPosition(ecs_iter_t *it) { Position *p = ecs_field(it, Position, 1); int i; for (i = 0; i < it->count; i ++) { p[i].x ++; p[i].y ++; } } void TriggerOnAdd_set_after_add_in_on_add(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); ECS_OBSERVER(world, AddVelocity, EcsOnAdd, Position); ECS_OBSERVER(world, OnSetPosition, EcsOnSet, Position); ecs_observer_init(world, &(ecs_observer_desc_t){ .entity = ecs_entity(world, {.id = AddVelocity}), .ctx = &ecs_id(Velocity) }); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e = ecs_new(world, 0); test_assert(e != 0); test_int(ctx.count, 0); ecs_set(world, e, Position, {1, 2}); test_assert( ecs_has(world, e, Position)); test_assert( ecs_has(world, e, Velocity)); test_int(ctx.count, 1); test_int(ctx.invoked, 1); test_int(ctx.system, AddVelocity); test_int(ctx.term_count, 1); test_int(ctx.e[0], e); test_int(ctx.c[0][0], ecs_id(Position)); test_int(ctx.s[0][0], 0); const Position *p = ecs_get(world, e, Position); test_int(p->x, 2); test_int(p->y, 3); ecs_fini(world); } static void AddAgain(ecs_iter_t *it) { ecs_id_t ecs_id(Position) = ecs_field_id(it, 1); int i; for (i = 0; i < it->count; i ++) { ecs_add(it->world, it->entities[i], Position); } } void TriggerOnAdd_add_again_in_progress(void) { ecs_world_t *world = ecs_init(); ECS_COMPONENT(world, Position); ECS_OBSERVER(world, Init, EcsOnAdd, Position); ECS_SYSTEM(world, AddAgain, EcsOnUpdate, Position); ecs_entity_t e = ecs_new(world, 0); test_assert(e != 0); ecs_add(world, e, Position); Probe ctx = {0}; ecs_set_ctx(world, &ctx, NULL); ecs_progress(world, 1); test_int(ctx.count, 0); ecs_fini(world); } static void AddMass(ecs_iter_t *it) { Mass *m = ecs_field(it, Mass, 1); int i; for (i = 0; i < it->count; i ++) { m[i] = 10; } } void TriggerOnAdd_add_in_progress_before_system_def(void) { ecs_world_t *world = ecs_init(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); ECS_SYSTEM(world, AddVelocity, EcsOnUpdate, Position, Velocity()); ecs_entity_t e = ecs_new(world, Position); test_assert(e != 0); test_assert( ecs_has(world, e, Position)); test_assert( !ecs_has(world, e, Velocity)); ecs_progress(world, 1); test_assert( ecs_has(world, e, Position)); test_assert( ecs_has(world, e, Velocity)); ECS_COMPONENT(world, Mass); ECS_OBSERVER(world, AddMass, EcsOnAdd, Mass); ecs_add(world, e, Mass); test_assert( ecs_has(world, e, Mass)); const Mass *m = ecs_get(world, e, Mass); test_assert(m != NULL); test_int(*m, 10); ecs_fini(world); } void SystemA(ecs_iter_t *it) { int i, tag; for (i = 0; i < it->count; i ++) { for (tag = 1000; tag < 1100; tag ++) { ecs_add_id(it->world, it->entities[i], tag); } } } void SystemB(ecs_iter_t *it) { ecs_id_t ecs_id(Position) = ecs_field_id(it, 1); int i; for (i = 0; i < it->count; i ++) { ecs_has(it->world, it->entities[i], Position); } } void TriggerOnAdd_2_systems_w_table_creation(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_OBSERVER(world, SystemA, EcsOnAdd, Position); ECS_OBSERVER(world, SystemB, EcsOnAdd, Position); ecs_entity_t e = ecs_new(world, Position); test_assert(e != 0); ecs_fini(world); } void NewWithPosition(ecs_iter_t *it) { ecs_id_t ecs_id(Position) = ecs_field_id(it, 1); ecs_entity_t e = ecs_new(it->world, Position); test_assert(e != 0); } void TriggerOnAdd_2_systems_w_table_creation_in_progress(void) { ecs_world_t *world = ecs_init(); ECS_COMPONENT(world, Position); ECS_OBSERVER(world, SystemA, EcsOnAdd, Position); ECS_OBSERVER(world, SystemB, EcsOnAdd, Position); ECS_SYSTEM(world, NewWithPosition, EcsOnUpdate, Position()); ecs_progress(world, 1); ecs_fini(world); } static void TestContext(ecs_iter_t *it) { void *world_ctx = ecs_get_ctx(it->world); test_assert(world_ctx == it->ctx); int32_t *param = it->ctx; (*param) ++; } void TriggerOnAdd_sys_context(void) { ecs_world_t *world = ecs_mini(); int32_t param = 0; ECS_COMPONENT(world, Position); ECS_OBSERVER(world, TestContext, EcsOnAdd, Position); ecs_observer_init(world, &(ecs_observer_desc_t){ .entity = ecs_entity(world, {.id = TestContext}), .ctx = ¶m }); test_assert(ecs_observer_get_ctx(world, TestContext) == ¶m); ecs_fini(world); } void TriggerOnAdd_get_sys_context_from_param(void) { ecs_world_t *world = ecs_mini(); int32_t param = 0; ECS_COMPONENT(world, Position); ECS_OBSERVER(world, TestContext, EcsOnAdd, Position); ecs_observer_init(world, &(ecs_observer_desc_t){ .entity = ecs_entity(world, {.id = TestContext}), .ctx = ¶m }); /* Set world context so system can compare if pointer is correct */ ecs_set_ctx(world, ¶m, NULL); /* Trigger system */ ecs_new(world, Position); test_int(param, 1); ecs_fini(world); } void TriggerOnAdd_remove_added_component_in_on_add_w_set(void) { install_test_abort(); ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_OBSERVER(world, Remove_from_current, EcsOnAdd, Position); IterData ctx = {.component = ecs_id(Position)}; ecs_set_ctx(world, &ctx, NULL); test_expect_abort(); ecs_set(world, 0, Position, {0, 0}); } void Add_3_to_current(ecs_iter_t *it) { IterData *ctx = ecs_get_ctx(it->world); int i; for (i = 0; i < it->count; i ++) { if (ctx->component_3) { ecs_add_id(it->world, it->entities[i], ctx->component_3); } ctx->entity_count ++; } } void TriggerOnAdd_on_add_in_on_add(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); ECS_COMPONENT(world, Mass); ECS_OBSERVER(world, Add_to_current, EcsOnAdd, Position); ECS_OBSERVER(world, Add_3_to_current, EcsOnAdd, Velocity); IterData ctx = {.component = ecs_id(Velocity), .component_3 = ecs_id(Mass)}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e1 = ecs_new(world, Position); ecs_entity_t e2 = ecs_new(world, Position); ecs_entity_t e3 = ecs_new(world, Position); test_assert( ecs_has(world, e1, Position)); test_assert( ecs_has(world, e2, Position)); test_assert( ecs_has(world, e3, Position)); test_assert( ecs_has(world, e1, Velocity)); test_assert( ecs_has(world, e2, Velocity)); test_assert( ecs_has(world, e3, Velocity)); test_assert( ecs_has(world, e1, Mass)); test_assert( ecs_has(world, e2, Mass)); test_assert( ecs_has(world, e3, Mass)); ecs_fini(world); } void TriggerOnAdd_on_remove_in_on_add(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); ECS_OBSERVER(world, Remove_from_current, EcsOnAdd, Position); ECS_OBSERVER(world, Dummy, EcsOnRemove, Velocity); IterData ctx = {.component = ecs_id(Velocity)}; ecs_set_ctx(world, &ctx, NULL); ECS_ENTITY(world, e1, Position, Velocity); ECS_ENTITY(world, e2, Position, Velocity); ECS_ENTITY(world, e3, Position, Velocity); test_assert( ecs_has(world, e1, Position)); test_assert( ecs_has(world, e2, Position)); test_assert( ecs_has(world, e3, Position)); test_assert( !ecs_has(world, e1, Velocity)); test_assert( !ecs_has(world, e2, Velocity)); test_assert( !ecs_has(world, e3, Velocity)); test_assert(dummy_called); ecs_fini(world); } void TriggerOnAdd_on_set_in_on_add(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Rotation); ECS_COMPONENT(world, Mass); ECS_OBSERVER(world, Set_current, EcsOnAdd, Position); ECS_OBSERVER(world, Add_3_to_current, EcsOnSet, Rotation); IterData ctx = {.component = ecs_id(Rotation), .component_3 = ecs_id(Mass)}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e1 = ecs_new(world, Position); ecs_entity_t e2 = ecs_new(world, Position); ecs_entity_t e3 = ecs_new(world, Position); test_assert( ecs_has(world, e1, Position)); test_assert( ecs_has(world, e2, Position)); test_assert( ecs_has(world, e3, Position)); test_assert( ecs_has(world, e1, Rotation)); test_assert( ecs_has(world, e2, Rotation)); test_assert( ecs_has(world, e3, Rotation)); test_assert( ecs_has(world, e1, Mass)); test_assert( ecs_has(world, e2, Mass)); test_assert( ecs_has(world, e3, Mass)); const Rotation *r = ecs_get(world, e1, Rotation); test_assert(r != NULL); test_int(*r, 10 + e1); r = ecs_get(world, e2, Rotation); test_assert(r != NULL); test_int(*r, 10 + e2); r = ecs_get(world, e3, Rotation); test_assert(r != NULL); test_int(*r, 10 + e3); ecs_fini(world); } void TriggerOnAdd_on_add_in_on_update(void) { ecs_world_t *world = ecs_init(); ECS_COMPONENT(world, Position); ECS_COMPONENT(world, Velocity); ECS_COMPONENT(world, Mass); ECS_SYSTEM(world, Add_to_current, EcsOnUpdate, Position); ECS_OBSERVER(world, Add_3_to_current, EcsOnAdd, Velocity); IterData ctx = {.component = ecs_id(Velocity), .component_3 = ecs_id(Mass)}; ecs_set_ctx(world, &ctx, NULL); ecs_entity_t e1 = ecs_new(world, Position); ecs_entity_t e2 = ecs_new(world, Position); ecs_entity_t e3 = ecs_new(world, Position); ecs_progress(world, 1); test_assert( ecs_has(world, e1, Position)); test_assert( ecs_has(world, e2, Position)); test_assert( ecs_has(world, e3, Position)); test_assert( ecs_has(world, e1, Velocity)); test_assert( ecs_has(world, e2, Velocity)); test_assert( ecs_has(world, e3, Velocity)); test_assert( ecs_has(world, e1, Mass)); test_assert( ecs_has(world, e2, Mass)); test_assert( ecs_has(world, e3, Mass)); ecs_fini(world); } void TriggerOnAdd_emplace(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ecs_observer_init(world, &(ecs_observer_desc_t){ .filter.terms[0].id = ecs_id(Position), .events = {EcsOnAdd}, .callback = Dummy }); ecs_entity_t e = ecs_new_id(world); test_assert(e != 0); test_int(dummy_called, 0); Position *p = ecs_emplace(world, e, Position); test_assert(p != NULL); test_bool(dummy_called, true); ecs_fini(world); } void TriggerOnAdd_add_after_delete_trigger(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ecs_entity_t trigger = ecs_observer_init(world, &(ecs_observer_desc_t){ .filter.terms[0].id = ecs_id(Position), .events = {EcsOnAdd}, .callback = Dummy }); ecs_entity_t e1 = ecs_new(world, Position); test_assert(e1 != 0); test_assert(ecs_has(world, e1, Position)); test_int(dummy_called, 1); dummy_called = 0; ecs_delete(world, trigger); test_int(dummy_called, 0); ecs_entity_t e2 = ecs_new(world, Position); test_assert(e2 != 0); test_assert(ecs_has(world, e2, Position)); test_int(dummy_called, 0); ecs_fini(world); } void TriggerOnAdd_add_after_delete_wildcard_id_trigger(void) { ecs_world_t *world = ecs_mini(); ECS_COMPONENT(world, Position); ecs_entity_t trigger = ecs_observer_init(world, &(ecs_observer_desc_t){ .filter.terms[0].id = EcsWildcard, .events = {EcsOnAdd}, .callback = Dummy }); ecs_entity_t e1 = ecs_new(world, Position); test_assert(e1 != 0); test_assert(ecs_has(world, e1, Position)); test_int(dummy_called, 1); dummy_called = 0; ecs_delete(world, trigger); test_int(dummy_called, 0); ecs_entity_t e2 = ecs_new(world, Position); test_assert(e2 != 0); test_assert(ecs_has(world, e2, Position)); test_int(dummy_called, 0); ecs_fini(world); }