Files
PixelDefense/engine/libs/flecs/test/api/src/TriggerOnRemove.c

421 lines
9.2 KiB
C

#include <api.h>
void Deinit(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);
/* Write to validate columns point to valid memory */
int i;
for (i = 0; i < it->count; i ++) {
p[i].x = 0;
p[i].y = 0;
if (v) {
v[i].x = 0;
v[i].y = 0;
}
}
}
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 ++;
}
}
void TriggerOnRemove_remove(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, Deinit, EcsOnRemove, 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, 0);
ecs_remove(world, e, Position);
test_int(ctx.count, 1);
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);
ecs_fini(world);
}
void TriggerOnRemove_remove_no_match(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, Deinit, EcsOnRemove, 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, 0);
ecs_remove(world, e, Velocity);
test_int(ctx.count, 0);
ecs_fini(world);
}
void TriggerOnRemove_delete(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, Deinit, EcsOnRemove, 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, 0);
ecs_delete(world, e);
test_int(ctx.count, 1);
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);
ecs_fini(world);
}
void TriggerOnRemove_delete_no_match(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_OBSERVER(world, Deinit, EcsOnRemove, 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_delete(world, e);
test_int(ctx.count, 0);
ecs_fini(world);
}
static Position old_position = {0};
static
void RemovePosition(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
test_assert(it->count == 1);
old_position = p[0];
}
void TriggerOnRemove_remove_watched(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, RemovePosition, EcsOnRemove, Position);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
test_assert(e != 0);
/* Make parent entity watched */
ecs_new_w_pair(world, EcsChildOf, e);
ecs_remove(world, e, Position);
test_int(old_position.x, 10);
test_int(old_position.y, 20);
ecs_fini(world);
}
void TriggerOnRemove_delete_watched(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, RemovePosition, EcsOnRemove, Position);
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
test_assert(e != 0);
/* Make parent entity watched */
ecs_new_w_pair(world, EcsChildOf, e);
ecs_delete(world, e);
test_int(old_position.x, 10);
test_int(old_position.y, 20);
ecs_fini(world);
}
static bool dummy_called = false;
static
void Dummy(ecs_iter_t *it) {
dummy_called = true;
}
void TriggerOnRemove_on_remove_in_on_update(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_SYSTEM(world, Remove_from_current, EcsOnUpdate, 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);
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(dummy_called);
ecs_fini(world);
}
static int dummy_dtor_invoked = 0;
typedef struct DummyComp {
int value;
} DummyComp;
static
void RemoveDummyComp(ecs_iter_t *it) {
int i;
for (i = 0; i < it->count; i ++) {
test_assert(ecs_is_valid(it->world, it->entities[i]));
test_assert(ecs_is_alive(it->world, it->entities[i]));
}
dummy_dtor_invoked ++;
}
void TriggerOnRemove_valid_entity_after_delete(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, DummyComp);
ECS_OBSERVER(world, RemoveDummyComp, EcsOnRemove, DummyComp);
ecs_entity_t e = ecs_new(world, DummyComp);
test_assert(e != 0);
ecs_delete(world, e);
test_assert(!ecs_is_valid(world, e));
test_assert(!ecs_is_alive(world, e));
test_int(dummy_dtor_invoked, 1);
ecs_fini(world);
}
void TriggerOnRemove_remove_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 = {EcsOnRemove},
.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, 0);
ecs_remove(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_remove(world, e2, Position);
test_int(dummy_called, 0);
ecs_fini(world);
}
void TriggerOnRemove_remove_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 = {EcsOnRemove},
.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, 0);
ecs_remove(world, e1, Position);
test_int(dummy_called, 1);
dummy_called = 0;
ecs_delete(world, trigger);
test_int(dummy_called, 1);
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_remove(world, e2, Position);
test_int(dummy_called, 0);
ecs_fini(world);
}
typedef struct on_remove_has_tag_t {
ecs_entity_t ent;
ecs_entity_t tag;
} on_remove_has_tag_t;
static
void OnRemoveHasTag(ecs_iter_t *it) {
on_remove_has_tag_t *ctx = it->ctx;
test_assert(ctx != NULL);
test_int(it->count, 1);
test_assert(it->entities[0] == ctx->ent);
test_assert(ecs_field_id(it, 1) == ctx->tag);
test_bool(ecs_has_id(it->world, ctx->ent, ctx->tag), true);
dummy_called = true;
}
void TriggerOnRemove_has_removed_tag_trigger_1_tag(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Tag);
ecs_entity_t e = ecs_new(world, Tag);
test_assert(e != 0);
test_assert(ecs_has(world, e, Tag));
on_remove_has_tag_t ctx = {
.ent = e,
.tag = Tag
};
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = Tag,
.events = {EcsOnRemove},
.callback = OnRemoveHasTag,
.ctx = &ctx
});
ecs_remove(world, e, Tag);
test_int(dummy_called, 1);
ecs_fini(world);
}
void TriggerOnRemove_has_removed_tag_trigger_2_tags(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, TagA);
ECS_TAG(world, TagB);
ecs_entity_t e = ecs_new(world, TagA);
test_assert(e != 0);
test_assert(ecs_has(world, e, TagA));
ecs_add(world, e, TagB);
test_assert(ecs_has(world, e, TagB));
on_remove_has_tag_t ctx = {
.ent = e,
.tag = TagA
};
ecs_observer_init(world, &(ecs_observer_desc_t){
.filter.terms[0].id = TagA,
.events = {EcsOnRemove},
.callback = OnRemoveHasTag,
.ctx = &ctx
});
ecs_remove(world, e, TagA);
test_int(dummy_called, 1);
ecs_fini(world);
}