3658 lines
85 KiB
C
3658 lines
85 KiB
C
#include <api.h>
|
|
|
|
void Commands_defer_new(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
test_assert(e != 0);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_bulk_new(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
const ecs_entity_t *temp_ids = ecs_bulk_new(world, Position, 3);
|
|
ecs_entity_t ids[3];
|
|
memcpy(ids, temp_ids, sizeof(ecs_entity_t) * 3);
|
|
|
|
test_assert(!ecs_has(world, ids[0], Position));
|
|
test_assert(!ecs_has(world, ids[1], Position));
|
|
test_assert(!ecs_has(world, ids[2], Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has(world, ids[0], Position));
|
|
test_assert(!ecs_has(world, ids[1], Position));
|
|
test_assert(!ecs_has(world, ids[2], Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, ids[0], Position));
|
|
test_assert(ecs_has(world, ids[1], Position));
|
|
test_assert(ecs_has(world, ids[2], Position));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(ecs_has(world, ids[0], Position));
|
|
test_assert(ecs_has(world, ids[1], Position));
|
|
test_assert(ecs_has(world, ids[2], Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_add(world, e, Position);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_two(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_add(world, e, Position);
|
|
ecs_add(world, e, Velocity);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_remove(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_remove(world, e, Position);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_remove_two(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
ecs_add(world, e, Position);
|
|
ecs_add(world, e, Velocity);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_remove(world, e, Position);
|
|
ecs_remove(world, e, Velocity);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_set(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
ecs_set(world, e, Position, {1, 2});
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 1);
|
|
test_int(p->y, 2);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
/* set will not be deferred if the component exists */
|
|
ecs_set(world, e, Position, {3, 4});
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 3);
|
|
test_int(p->y, 4);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 3);
|
|
test_int(p->y, 4);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 3);
|
|
test_int(p->y, 4);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 3);
|
|
test_int(p->y, 4);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_delete(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, e);
|
|
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_twice(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_set(world, e, Velocity, {1, 2});
|
|
|
|
ecs_defer_end(world);
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
ecs_defer_end(world);
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
const Velocity *v = ecs_get(world, e, Velocity);
|
|
test_assert(v != NULL);
|
|
test_int(v->x, 1);
|
|
test_int(v->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_twice_in_progress(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_frame_begin(world, 0);
|
|
ecs_readonly_begin(world);
|
|
ecs_world_t *stage = ecs_get_stage(world, 0);
|
|
|
|
ecs_defer_begin(stage);
|
|
ecs_defer_begin(stage);
|
|
|
|
ecs_set(stage, e, Velocity, {1, 2});
|
|
|
|
ecs_defer_end(stage);
|
|
test_assert(!ecs_has(stage, e, Velocity));
|
|
ecs_defer_end(stage);
|
|
test_assert(!ecs_has(stage, e, Velocity));
|
|
|
|
ecs_readonly_end(world);
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
ecs_frame_end(world);
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
const Velocity *v = ecs_get(world, e, Velocity);
|
|
test_assert(v != NULL);
|
|
test_int(v->x, 1);
|
|
test_int(v->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
static
|
|
void AddVelocity(ecs_iter_t *it) {
|
|
ecs_id_t ecs_id(Velocity) = ecs_field_id(it, 2);
|
|
|
|
ecs_defer_begin(it->world);
|
|
|
|
int i;
|
|
for (i = 0; i < it->count; i ++) {
|
|
ecs_add(it->world, it->entities[i], Velocity);
|
|
}
|
|
|
|
ecs_defer_end(it->world);
|
|
}
|
|
|
|
void Commands_run_w_defer(void) {
|
|
ecs_world_t *world = ecs_init();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ECS_SYSTEM(world, AddVelocity, 0, Position, [in] Velocity());
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_run(world, AddVelocity, 0, NULL);
|
|
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_system_in_progress_w_defer(void) {
|
|
ecs_world_t *world = ecs_init();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ECS_SYSTEM(world, AddVelocity, EcsOnUpdate, Position, [in] Velocity());
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_progress(world, 0);
|
|
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
static bool on_set_invoked = 0;
|
|
|
|
static
|
|
void OnSetTestInvoked(ecs_iter_t *it) {
|
|
on_set_invoked = 1;
|
|
}
|
|
|
|
void Commands_defer_get_mut_no_modify(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ECS_OBSERVER(world, OnSetTestInvoked, EcsOnSet, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
Velocity *v = ecs_get_mut(world, e, Velocity);
|
|
v->x = 1;
|
|
v->y = 2;
|
|
|
|
test_assert(!on_set_invoked);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!on_set_invoked);
|
|
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
const Velocity *vptr = ecs_get(world, e, Velocity);
|
|
test_int(vptr->x, 1);
|
|
test_int(vptr->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_get_mut_w_modify(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ECS_OBSERVER(world, OnSetTestInvoked, EcsOnSet, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
Velocity *v = ecs_get_mut(world, e, Velocity);
|
|
v->x = 1;
|
|
v->y = 2;
|
|
test_assert(!on_set_invoked);
|
|
|
|
ecs_modified(world, e, Velocity);
|
|
|
|
test_assert(!on_set_invoked);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(on_set_invoked);
|
|
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
const Velocity *vptr = ecs_get(world, e, Velocity);
|
|
test_int(vptr->x, 1);
|
|
test_int(vptr->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_modify(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ECS_OBSERVER(world, OnSetTestInvoked, EcsOnSet, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new(world, Velocity);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_modified(world, e, Velocity);
|
|
|
|
test_assert(!on_set_invoked);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(on_set_invoked);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_set_pair(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_set_pair(world, e, Velocity, ecs_id(Position), {1, 2});
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has_pair(world, e, ecs_id(Velocity), ecs_id(Position)));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_clear(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_clear(world, e);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_after_delete(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, e);
|
|
ecs_add(world, e, Velocity);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
test_int(ecs_count(world, Position), 0);
|
|
test_int(ecs_count(world, Velocity), 0);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_set_after_delete(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, e);
|
|
ecs_set(world, e, Velocity, {1, 2});
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
test_int(ecs_count(world, Position), 0);
|
|
test_int(ecs_count(world, Velocity), 0);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_get_mut_after_delete(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, e);
|
|
Velocity *v = ecs_get_mut(world, e, Velocity);
|
|
v->x = 1;
|
|
v->y = 2;
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
test_int(ecs_count(world, Position), 0);
|
|
test_int(ecs_count(world, Velocity), 0);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_get_mut_after_delete_2nd_to_last(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
/* Create 2nd position. This will cause deletion of the entity in the sparse
|
|
* set to take a different path since it's not the last. */
|
|
ecs_new(world, Position);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, e);
|
|
Velocity *v = ecs_get_mut(world, e, Velocity);
|
|
v->x = 1;
|
|
v->y = 2;
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
test_int(ecs_count(world, Position), 1);
|
|
test_int(ecs_count(world, Velocity), 0);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_child_to_deleted_parent(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t parent = ecs_new(world, 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t child = ecs_new_w_pair(world, EcsChildOf, parent);
|
|
ecs_add(world, child, Velocity);
|
|
ecs_delete(world, parent);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, parent));
|
|
test_assert(!ecs_is_alive(world, child));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_recreate_deleted_entity_while_deferred(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e_old = ecs_new(world, 0);
|
|
test_assert(e_old != 0);
|
|
|
|
ecs_delete(world, e_old);
|
|
test_assert(!ecs_is_alive(world, e_old));
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
test_assert(e != 0);
|
|
test_assert(e != e_old);
|
|
test_assert((e & ECS_ENTITY_MASK) == (e_old & ECS_ENTITY_MASK));
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_to_recycled_id(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t id = ecs_new_id(world);
|
|
test_assert(id != 0);
|
|
|
|
ecs_delete(world, id);
|
|
|
|
ecs_entity_t id_2 = ecs_new_id(world);
|
|
test_assert(id != id_2);
|
|
test_assert((int32_t)id == (int32_t)id_2);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t child = ecs_new_w_id(world, id_2);
|
|
ecs_add(world, child, Velocity);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, id));
|
|
test_assert(ecs_is_alive(world, id_2));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(ecs_has_id(world, child, id_2));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_to_recycled_id_w_role(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t id = ecs_new_id(world);
|
|
test_assert(id != 0);
|
|
|
|
ecs_delete(world, id);
|
|
|
|
ecs_entity_t id_2 = ecs_new_id(world);
|
|
test_assert(id != id_2);
|
|
test_assert((int32_t)id == (int32_t)id_2);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t child = ecs_new_w_id(world, ECS_TOGGLE | id_2);
|
|
ecs_add(world, child, Velocity);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, id));
|
|
test_assert(ecs_is_alive(world, id_2));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(ecs_has_id(world, child, ECS_TOGGLE | id_2));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_to_recycled_relation(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t target = ecs_new_id(world);
|
|
test_assert(target != 0);
|
|
|
|
ecs_entity_t rel = ecs_new_id(world);
|
|
test_assert(rel != 0);
|
|
|
|
ecs_delete(world, rel);
|
|
|
|
ecs_entity_t rel_2 = ecs_new_id(world);
|
|
test_assert(rel != rel_2);
|
|
test_assert((int32_t)rel == (int32_t)rel_2);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t child = ecs_new_w_pair(world, rel_2, target);
|
|
ecs_add(world, child, Velocity);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(ecs_is_alive(world, target));
|
|
test_assert(!ecs_is_alive(world, rel));
|
|
test_assert(ecs_is_alive(world, rel_2));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(ecs_has_pair(world, child, rel_2, target));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_to_recycled_object(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
ECS_TAG(world, Rel);
|
|
|
|
ecs_entity_t target = ecs_new(world, 0);
|
|
test_assert(target != 0);
|
|
|
|
ecs_delete(world, target);
|
|
|
|
ecs_entity_t object_2 = ecs_new_id(world);
|
|
test_assert(target != object_2);
|
|
test_assert((int32_t)target == (int32_t)object_2);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t child = ecs_new_w_pair(world, Rel, object_2);
|
|
ecs_add(world, child, Velocity);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, target));
|
|
test_assert(ecs_is_alive(world, object_2));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(ecs_has_pair(world, child, Rel, object_2));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_to_recycled_object_childof(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t parent = ecs_new(world, 0);
|
|
test_assert(parent != 0);
|
|
|
|
ecs_delete(world, parent);
|
|
|
|
ecs_entity_t parent_2 = ecs_new_id(world);
|
|
test_assert(parent != parent_2);
|
|
test_assert((int32_t)parent == (int32_t)parent_2);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t child = ecs_new_w_pair(world, EcsChildOf, parent_2);
|
|
ecs_add(world, child, Velocity);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, parent));
|
|
test_assert(ecs_is_alive(world, parent_2));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(ecs_has_pair(world, child, EcsChildOf, parent_2));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_to_deleted_id(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t id = ecs_new_id(world);
|
|
test_assert(id != 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, id);
|
|
ecs_entity_t child = ecs_new_w_id(world, id);
|
|
ecs_add(world, child, Velocity);
|
|
|
|
ecs_defer_end(world);
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, id));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(!ecs_has_id(world, child, id));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_to_deleted_id_w_role(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t id = ecs_new_id(world);
|
|
test_assert(id != 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, id);
|
|
ecs_entity_t child = ecs_new_w_id(world, ECS_TOGGLE | id);
|
|
ecs_add(world, child, Velocity);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, id));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(!ecs_has_id(world, child, ECS_TOGGLE | id));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_to_deleted_relation(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t target = ecs_new_id(world);
|
|
test_assert(target != 0);
|
|
|
|
ecs_entity_t rel = ecs_new_id(world);
|
|
test_assert(rel != 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, rel);
|
|
ecs_entity_t child = ecs_new_w_pair(world, rel, target);
|
|
ecs_add(world, child, Velocity);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(ecs_is_alive(world, target));
|
|
test_assert(!ecs_is_alive(world, rel));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(!ecs_has_pair(world, child, rel, target));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_to_deleted_object(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ECS_TAG(world, Rel);
|
|
|
|
ecs_entity_t target = ecs_new(world, 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, target);
|
|
ecs_entity_t child = ecs_new_w_pair(world, Rel, target);
|
|
ecs_add(world, child, Velocity);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, target));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(!ecs_has_pair(world, child, Rel, target));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_to_deleted_object_childof(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t parent = ecs_new(world, 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, parent);
|
|
ecs_entity_t child = ecs_new_w_pair(world, EcsChildOf, parent);
|
|
ecs_add(world, child, Velocity);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, parent));
|
|
test_assert(!ecs_is_alive(world, child));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_delete_added_id(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t id = ecs_new_id(world);
|
|
test_assert(id != 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t child = ecs_new_w_id(world, id);
|
|
ecs_add(world, child, Velocity);
|
|
ecs_delete(world, id);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, id));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(!ecs_has_id(world, child, id));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_delete_added_id_w_role(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t id = ecs_new_id(world);
|
|
test_assert(id != 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t child = ecs_new_w_id(world, ECS_TOGGLE | id);
|
|
ecs_add(world, child, Velocity);
|
|
ecs_delete(world, id);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, id));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(!ecs_has_id(world, child, ECS_TOGGLE | id));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_delete_added_relation(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t target = ecs_new_id(world);
|
|
test_assert(target != 0);
|
|
|
|
ecs_entity_t rel = ecs_new_id(world);
|
|
test_assert(rel != 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t child = ecs_new_w_pair(world, rel, target);
|
|
ecs_add(world, child, Velocity);
|
|
ecs_delete(world, rel);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(ecs_is_alive(world, target));
|
|
test_assert(!ecs_is_alive(world, rel));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(!ecs_has_pair(world, child, rel, target));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_delete_added_object(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ECS_TAG(world, Rel);
|
|
|
|
ecs_entity_t target = ecs_new(world, 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t child = ecs_new_w_pair(world, Rel, target);
|
|
ecs_add(world, child, Velocity);
|
|
ecs_delete(world, target);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, target));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(!ecs_has_pair(world, child, Rel, target));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_delete_added_object_childof(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t parent = ecs_new(world, 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t child = ecs_new_w_pair(world, EcsChildOf, parent);
|
|
ecs_add(world, child, Velocity);
|
|
ecs_delete(world, parent);
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, parent));
|
|
test_assert(!ecs_is_alive(world, child));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_discard_add(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, e);
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_add(world, e, Position);
|
|
|
|
test_assert(ecs_is_alive(world, e));
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_is_alive(world, e));
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_discard_remove(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, e);
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_remove(world, e, Position);
|
|
|
|
test_assert(ecs_is_alive(world, e));
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_is_alive(world, e));
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_discard_add_two(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, e);
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_add(world, e, Position);
|
|
ecs_add(world, e, Velocity);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_discard_remove_two(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
ecs_add(world, e, Position);
|
|
ecs_add(world, e, Velocity);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_delete(world, e);
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_remove(world, e, Position);
|
|
ecs_remove(world, e, Velocity);
|
|
|
|
test_assert(ecs_is_alive(world, e));
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_is_alive(world, e));
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_discard_child(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
test_assert(e != 0);
|
|
test_assert(!ecs_has(world, e, Position));
|
|
ecs_delete(world, e);
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_entity_t child = ecs_new_w_pair(world, EcsChildOf, e);
|
|
test_assert(child != 0);
|
|
test_assert(!ecs_has_pair(world, child, EcsChildOf, e));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_is_alive(world, e));
|
|
test_assert(ecs_is_alive(world, child));
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_assert(!ecs_has_pair(world, child, EcsChildOf, e));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
test_assert(!ecs_is_alive(world, child));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
test_assert(!ecs_is_alive(world, child));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_discard_child_w_add(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_frame_begin(world, 1);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
test_assert(e != 0);
|
|
test_assert(!ecs_has(world, e, Position));
|
|
ecs_delete(world, e);
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_entity_t child = ecs_new(world, 0);
|
|
test_assert(child != 0);
|
|
|
|
ecs_add_pair(world, child, EcsChildOf, e);
|
|
test_assert(!ecs_has_pair(world, child, EcsChildOf, e));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_is_alive(world, e));
|
|
test_assert(ecs_is_alive(world, child));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
test_assert(!ecs_is_alive(world, child));
|
|
|
|
ecs_frame_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
test_assert(!ecs_is_alive(world, child));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_return_value(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
test_bool(ecs_defer_begin(world), true);
|
|
|
|
test_bool(ecs_defer_begin(world), false);
|
|
|
|
test_bool(ecs_defer_end(world), false);
|
|
|
|
test_bool(ecs_defer_end(world), true);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_get_mut_pair(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_TAG(world, Pair);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
Position *p = ecs_get_mut_pair(world, e, Position, Pair);
|
|
test_assert(p != NULL);
|
|
p->x = 10;
|
|
p->y = 20;
|
|
|
|
ecs_defer_end(world);
|
|
|
|
const Position *pc = ecs_get_pair(world, e, Position, Pair);
|
|
test_assert(pc != NULL);
|
|
test_int(pc->x, 10);
|
|
test_int(pc->y, 20);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_async_stage_add(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_world_t *async = ecs_async_stage_new(world);
|
|
ecs_add(async, e, Position);
|
|
test_assert(!ecs_has(world, e, Position));
|
|
ecs_merge(async);
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_async_stage_free(async);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_async_stage_add_twice(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_world_t *async = ecs_async_stage_new(world);
|
|
ecs_add(async, e, Position);
|
|
test_assert(!ecs_has(world, e, Position));
|
|
ecs_merge(async);
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_add(async, e, Velocity);
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
ecs_merge(async);
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
ecs_async_stage_free(async);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
|
|
void Commands_async_stage_remove(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_world_t *async = ecs_async_stage_new(world);
|
|
ecs_remove(async, e, Position);
|
|
test_assert(ecs_has(world, e, Position));
|
|
ecs_merge(async);
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_async_stage_free(async);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_async_stage_clear(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
ecs_add(world, e, Velocity);
|
|
|
|
ecs_world_t *async = ecs_async_stage_new(world);
|
|
ecs_clear(async, e);
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
ecs_merge(async);
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
|
|
ecs_async_stage_free(async);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_async_stage_delete(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
ecs_add(world, e, Velocity);
|
|
|
|
ecs_world_t *async = ecs_async_stage_new(world);
|
|
ecs_delete(async, e);
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
test_assert(ecs_is_alive(world, e));
|
|
ecs_merge(async);
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_async_stage_free(async);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_async_stage_new(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_world_t *async = ecs_async_stage_new(world);
|
|
ecs_entity_t e = ecs_new(async, 0);
|
|
ecs_add(async, e, Position);
|
|
ecs_add(async, e, Velocity);
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
ecs_merge(async);
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
test_assert(ecs_is_alive(world, e));
|
|
|
|
ecs_async_stage_free(async);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_async_stage_no_get(void) {
|
|
install_test_abort();
|
|
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_world_t *async = ecs_async_stage_new(world);
|
|
|
|
test_expect_abort();
|
|
ecs_get(async, e, Position);
|
|
}
|
|
|
|
void Commands_async_stage_readonly(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ecs_world_t *async = ecs_async_stage_new(world);
|
|
test_assert(!ecs_stage_is_readonly(async));
|
|
|
|
ecs_async_stage_free(async);
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_async_stage_is_async(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ecs_world_t *async = ecs_async_stage_new(world);
|
|
test_assert(ecs_stage_is_async(async));
|
|
|
|
ecs_async_stage_free(async);
|
|
ecs_fini(world);
|
|
}
|
|
|
|
static
|
|
void RegisterComponent(ecs_iter_t *it) {
|
|
ecs_entity_t ecs_id(Position) = ecs_component_init(it->world,
|
|
&(ecs_component_desc_t){
|
|
.entity = ecs_entity(it->world, {.name = "Position"}),
|
|
.type.size = ECS_SIZEOF(Position),
|
|
.type.alignment = ECS_ALIGNOF(Position)
|
|
});
|
|
|
|
test_assert(ecs_id(Position) != 0);
|
|
}
|
|
|
|
void Commands_register_component_while_in_progress(void) {
|
|
ecs_world_t *world = ecs_init();
|
|
|
|
ECS_SYSTEM(world, RegisterComponent, EcsOnUpdate, 0);
|
|
|
|
ecs_progress(world, 0);
|
|
|
|
ecs_entity_t ecs_id(Position) = ecs_lookup(world, "Position");
|
|
test_assert(ecs_id(Position) != 0);
|
|
test_assert(ecs_has(world, ecs_id(Position), EcsComponent));
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
ecs_set(world, e, Position, {10, 20});
|
|
test_assert(ecs_has_id(world, e, ecs_id(Position)));
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_register_component_while_staged(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, Tag);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
ecs_entity_t canary = ecs_new_id(world);
|
|
|
|
ecs_readonly_begin(world);
|
|
|
|
ecs_world_t *stage = ecs_get_stage(world, 0);
|
|
|
|
ecs_add_id(stage, canary, Tag);
|
|
|
|
ecs_entity_t ecs_id(Position) = ecs_component_init(stage,
|
|
&(ecs_component_desc_t){
|
|
.entity = ecs_entity(stage, {.name = "Position"}),
|
|
.type.size = ECS_SIZEOF(Position),
|
|
.type.alignment = ECS_ALIGNOF(Position)
|
|
});
|
|
|
|
test_assert(ecs_id(Position) != 0);
|
|
|
|
ecs_set(stage, e, Position, {10, 20});
|
|
test_assert(!ecs_has_id(world, e, ecs_id(Position)));
|
|
test_assert(!ecs_has_id(world, canary, Tag));
|
|
|
|
ecs_readonly_end(world);
|
|
|
|
test_assert(ecs_has_id(world, e, ecs_id(Position)));
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_register_component_while_deferred(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, Tag);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
ecs_entity_t canary = ecs_new_id(world);
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_add_id(world, canary, Tag);
|
|
|
|
ecs_entity_t ecs_id(Position) = ecs_component_init(world,
|
|
&(ecs_component_desc_t){
|
|
.entity = ecs_entity(world, {.name = "Position"}),
|
|
.type.size = ECS_SIZEOF(Position),
|
|
.type.alignment = ECS_ALIGNOF(Position)
|
|
});
|
|
|
|
test_assert(ecs_id(Position) != 0);
|
|
|
|
ecs_set(world, e, Position, {10, 20});
|
|
test_assert(!ecs_has_id(world, e, ecs_id(Position)));
|
|
test_assert(!ecs_has_id(world, canary, Tag));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_enable(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_enable(world, e, false);
|
|
test_assert(!ecs_has_id(world, e, EcsDisabled));
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has_id(world, e, EcsDisabled));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_disable(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ecs_entity_t e = ecs_new_w_id(world, EcsDisabled);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_enable(world, e, true);
|
|
test_assert(ecs_has_id(world, e, EcsDisabled));
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has_id(world, e, EcsDisabled));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_delete_with(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, TagA);
|
|
ECS_TAG(world, TagB);
|
|
|
|
ecs_entity_t e_1 = ecs_new(world, TagA);
|
|
ecs_entity_t e_2 = ecs_new(world, TagA);
|
|
ecs_entity_t e_3 = ecs_new(world, TagA);
|
|
ecs_add(world, e_1, TagB);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_delete_with(world, TagA);
|
|
test_assert(ecs_is_alive(world, e_1));
|
|
test_assert(ecs_is_alive(world, e_2));
|
|
test_assert(ecs_is_alive(world, e_3));
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e_1));
|
|
test_assert(!ecs_is_alive(world, e_2));
|
|
test_assert(!ecs_is_alive(world, e_3));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_remove_all(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, TagA);
|
|
ECS_TAG(world, TagB);
|
|
|
|
ecs_entity_t e_1 = ecs_new(world, TagA);
|
|
ecs_entity_t e_2 = ecs_new(world, TagA);
|
|
ecs_entity_t e_3 = ecs_new(world, TagA);
|
|
ecs_add(world, e_1, TagB);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_remove_all(world, TagA);
|
|
test_assert(ecs_is_alive(world, e_1));
|
|
test_assert(ecs_is_alive(world, e_2));
|
|
test_assert(ecs_is_alive(world, e_3));
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_is_alive(world, e_1));
|
|
test_assert(ecs_is_alive(world, e_2));
|
|
test_assert(ecs_is_alive(world, e_3));
|
|
|
|
test_assert(!ecs_has_id(world, e_1, TagA));
|
|
test_assert(!ecs_has_id(world, e_2, TagA));
|
|
test_assert(!ecs_has_id(world, e_3, TagA));
|
|
test_assert(ecs_has_id(world, e_1, TagB));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_deferred_modified_after_remove(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 = { EcsOnSet },
|
|
.callback = OnSetTestInvoked
|
|
});
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_modified(world, e, Position);
|
|
|
|
test_int(on_set_invoked, 1);
|
|
on_set_invoked = 0;
|
|
|
|
ecs_defer_begin(world);
|
|
|
|
ecs_remove(world, e, Position);
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_modified(world, e, Position);
|
|
ecs_defer_end(world);
|
|
|
|
test_int(on_set_invoked, 0);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
typedef struct {
|
|
int value;
|
|
} Counter;
|
|
|
|
ECS_COMPONENT_DECLARE(Counter);
|
|
|
|
static int update_counter_invoked = 0;
|
|
static int remove_counter_invoked = 0;
|
|
|
|
static void update_counter(ecs_iter_t *it) {
|
|
ecs_world_t *world = it->world;
|
|
|
|
for (int i = 0; i < it->count; i ++) {
|
|
ecs_entity_t e = it->entities[i];
|
|
ecs_entity_t parent = ecs_get_target(world, e, EcsChildOf, 0);
|
|
test_assert(parent != 0);
|
|
|
|
Counter *ptr = ecs_get_mut(world, parent, Counter);
|
|
test_assert(ptr != NULL);
|
|
|
|
if (it->event == EcsOnAdd) {
|
|
ptr->value ++;
|
|
} else if (it->event == EcsOnRemove) {
|
|
ptr->value --;
|
|
}
|
|
|
|
update_counter_invoked ++;
|
|
}
|
|
}
|
|
|
|
static void remove_counter(ecs_iter_t *it) {
|
|
Counter *ptr = ecs_field(it, Counter, 1);
|
|
|
|
for (int i = 0; i < it->count; i ++) {
|
|
test_int(ptr[i].value, 0);
|
|
remove_counter_invoked ++;
|
|
}
|
|
}
|
|
|
|
void Commands_merge_cleanup_ops_before_delete(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT_DEFINE(world, Counter);
|
|
ECS_TAG(world, Tag);
|
|
|
|
ecs_observer_init(world, &(ecs_observer_desc_t){
|
|
.filter.terms[0].id = Tag,
|
|
.events = {EcsOnAdd, EcsOnRemove},
|
|
.callback = update_counter
|
|
});
|
|
|
|
ecs_observer_init(world, &(ecs_observer_desc_t){
|
|
.filter.terms[0] = {
|
|
.id = ecs_id(Counter),
|
|
.src.flags = EcsSelf
|
|
},
|
|
.events = {EcsOnRemove},
|
|
.callback = remove_counter
|
|
});
|
|
|
|
ecs_entity_t parent = ecs_new_id(world);
|
|
ecs_set(world, parent, Counter, {0});
|
|
|
|
ecs_entity_t child = ecs_new_w_pair(world, EcsChildOf, parent);
|
|
ecs_add(world, child, Tag);
|
|
|
|
test_int(update_counter_invoked, 1);
|
|
|
|
const Counter *ptr = ecs_get(world, parent, Counter);
|
|
test_assert(ptr != NULL);
|
|
test_assert(ptr->value == 1);
|
|
|
|
ecs_delete(world, parent);
|
|
|
|
test_int(update_counter_invoked, 2);
|
|
test_int(remove_counter_invoked, 1);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_merge_nested_cleanup_ops_before_delete(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT_DEFINE(world, Counter);
|
|
ECS_TAG(world, Tag);
|
|
|
|
ecs_observer_init(world, &(ecs_observer_desc_t){
|
|
.filter.terms[0] = {
|
|
.id = Tag,
|
|
.src.flags = EcsSelf
|
|
},
|
|
.events = {EcsOnAdd, EcsOnRemove},
|
|
.callback = update_counter
|
|
});
|
|
|
|
ecs_observer_init(world, &(ecs_observer_desc_t){
|
|
.filter.terms[0] = {
|
|
.id = ecs_id(Counter),
|
|
.src.flags = EcsSelf
|
|
},
|
|
.events = {EcsOnRemove},
|
|
.callback = remove_counter
|
|
});
|
|
|
|
ecs_entity_t parent = ecs_new_id(world);
|
|
ecs_set(world, parent, Counter, {0});
|
|
|
|
ecs_entity_t child = ecs_new_w_pair(world, EcsChildOf, parent);
|
|
ecs_add(world, child, Tag);
|
|
test_int(update_counter_invoked, 1);
|
|
ecs_set(world, child, Counter, {0});
|
|
|
|
ecs_entity_t grand_child = ecs_new_w_pair(world, EcsChildOf, child);
|
|
ecs_add(world, grand_child, Tag);
|
|
test_int(update_counter_invoked, 2);
|
|
|
|
const Counter *ptr = ecs_get(world, parent, Counter);
|
|
test_assert(ptr != NULL);
|
|
test_assert(ptr->value == 1);
|
|
|
|
ptr = ecs_get(world, child, Counter);
|
|
test_assert(ptr != NULL);
|
|
test_assert(ptr->value == 1);
|
|
|
|
ecs_delete(world, parent);
|
|
|
|
test_int(update_counter_invoked, 4);
|
|
test_int(remove_counter_invoked, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_suspend_resume(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, TagA);
|
|
ECS_TAG(world, TagB);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_add(world, e, TagA);
|
|
test_assert(!ecs_has(world, e, TagA));
|
|
|
|
ecs_defer_suspend(world);
|
|
ecs_add(world, e, TagB);
|
|
test_assert(!ecs_has(world, e, TagA));
|
|
test_assert(ecs_has(world, e, TagB));
|
|
ecs_defer_resume(world);
|
|
|
|
test_assert(!ecs_has(world, e, TagA));
|
|
test_assert(ecs_has(world, e, TagB));
|
|
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, TagA));
|
|
test_assert(ecs_has(world, e, TagB));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
static
|
|
void System(ecs_iter_t *it) {
|
|
probe_system_w_ctx(it, it->ctx);
|
|
}
|
|
|
|
static int system_2_invoked = 0;
|
|
|
|
static
|
|
void System2(ecs_iter_t *it) {
|
|
probe_system_w_ctx(it, it->ctx);
|
|
system_2_invoked ++;
|
|
}
|
|
|
|
void Commands_create_observer_while_deferred(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, TagA);
|
|
|
|
ecs_defer_begin(world);
|
|
Probe ctx = {0};
|
|
ecs_entity_t observer = ecs_observer_init(world, &(ecs_observer_desc_t){
|
|
.filter.terms = {{ .id = TagA }},
|
|
.events = {EcsOnAdd},
|
|
.callback = System,
|
|
.ctx = &ctx
|
|
});
|
|
ecs_defer_end(world);
|
|
test_assert(observer != 0);
|
|
test_int(ctx.invoked, 0);
|
|
|
|
ecs_new(world, TagA);
|
|
test_int(ctx.invoked, 1);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_create_query_while_deferred(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, TagA);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_query_t *query = ecs_query_init(world, &(ecs_query_desc_t){
|
|
.filter.terms = {{ .id = TagA }}
|
|
});
|
|
ecs_defer_end(world);
|
|
test_assert(query != 0);
|
|
|
|
ecs_entity_t e = ecs_new(world, TagA);
|
|
|
|
ecs_iter_t it = ecs_query_iter(world, query);
|
|
test_bool(true, ecs_query_next(&it));
|
|
test_int(1, it.count);
|
|
test_uint(e, it.entities[0]);
|
|
test_bool(false, ecs_query_next(&it));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_update_observer_while_deferred(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, TagA);
|
|
|
|
ecs_defer_begin(world);
|
|
Probe ctx = {0};
|
|
ecs_entity_t observer = ecs_observer_init(world, &(ecs_observer_desc_t){
|
|
.filter.terms = {{ .id = TagA }},
|
|
.events = {EcsOnAdd},
|
|
.callback = System,
|
|
.ctx = &ctx
|
|
});
|
|
ecs_defer_end(world);
|
|
test_assert(observer != 0);
|
|
test_int(ctx.invoked, 0);
|
|
|
|
ecs_new(world, TagA);
|
|
test_int(ctx.invoked, 1);
|
|
|
|
test_int(system_2_invoked, 0);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_observer_init(world, &(ecs_observer_desc_t){
|
|
.entity = observer,
|
|
.callback = System2
|
|
});
|
|
ecs_defer_end(world);
|
|
|
|
ecs_new(world, TagA);
|
|
test_int(ctx.invoked, 2);
|
|
test_int(system_2_invoked, 1);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
typedef struct {
|
|
int16_t arr[8096];
|
|
} LargeComponent;
|
|
|
|
void Commands_defer_set_large_component(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, LargeComponent);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_defer_begin(world);
|
|
LargeComponent *ptr = ecs_get_mut(world, e, LargeComponent);
|
|
test_assert(ptr != NULL);
|
|
for (int i = 0; i < 8096; i ++) {
|
|
ptr->arr[i] = i;
|
|
}
|
|
test_assert(!ecs_has(world, e, LargeComponent));
|
|
ecs_defer_end(world);
|
|
|
|
ptr = ecs_get_mut(world, e, LargeComponent);
|
|
test_assert(ptr != NULL);
|
|
for (int i = 0; i < 8096; i ++) {
|
|
test_int(ptr->arr[i], i);
|
|
}
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
static ECS_COMPONENT_DECLARE(Position);
|
|
|
|
static void CreatePosition(ecs_iter_t *it) {
|
|
ecs_entity_t e = ecs_new_id(it->world);
|
|
ecs_set(it->world, e, Position, {999, 1000});
|
|
}
|
|
|
|
void Commands_defer_while_suspend_readonly(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT_DEFINE(world, Position);
|
|
|
|
/* Create observer on EcsComponent which will defer a command while readonly
|
|
* mode is suspended */
|
|
ecs_observer_init(world, &(ecs_observer_desc_t){
|
|
.filter.terms[0].id = ecs_id(EcsComponent),
|
|
.events = { EcsOnAdd },
|
|
.callback = CreatePosition
|
|
});
|
|
|
|
ecs_world_t *s = ecs_get_stage(world, 0);
|
|
|
|
ecs_readonly_begin(world);
|
|
|
|
/* Component creation suspends readonly mode so that they can be used right
|
|
* after they have been registered */
|
|
ECS_COMPONENT(s, Velocity);
|
|
|
|
ecs_entity_t e =
|
|
ecs_set(s, 0, Position, {10, 20});
|
|
ecs_set(s, e, Velocity, {1, 2});
|
|
test_assert(!ecs_has(s, e, Position));
|
|
test_assert(!ecs_has(s, e, Velocity));
|
|
|
|
ecs_readonly_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
|
|
const Velocity *v = ecs_get(world, e, Velocity);
|
|
test_assert(v != NULL);
|
|
test_int(v->x, 1);
|
|
test_int(v->y, 2);
|
|
|
|
test_int(2, ecs_count(world, Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_while_suspend_readonly_w_existing_commands(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT_DEFINE(world, Position);
|
|
|
|
/* Create observer on EcsComponent which will defer a command while readonly
|
|
* mode is suspended */
|
|
ecs_observer_init(world, &(ecs_observer_desc_t){
|
|
.filter.terms[0].id = ecs_id(EcsComponent),
|
|
.events = { EcsOnAdd },
|
|
.callback = CreatePosition
|
|
});
|
|
|
|
ecs_world_t *s = ecs_get_stage(world, 0);
|
|
|
|
ecs_readonly_begin(world);
|
|
|
|
ecs_entity_t e1 = ecs_set(s, 0, Position, {10, 20});
|
|
test_assert(!ecs_has(s, e1, Position));
|
|
|
|
/* Component creation suspends readonly mode so that they can be used right
|
|
* after they have been registered */
|
|
ECS_COMPONENT(s, Velocity);
|
|
|
|
ecs_entity_t e2 =
|
|
ecs_set(s, 0, Position, {20, 30});
|
|
ecs_set(s, e2, Velocity, {1, 2});
|
|
test_assert(!ecs_has(s, e2, Position));
|
|
test_assert(!ecs_has(s, e2, Velocity));
|
|
|
|
ecs_readonly_end(world);
|
|
|
|
test_assert(ecs_has(world, e1, Position));
|
|
test_assert(ecs_has(world, e2, Position));
|
|
test_assert(ecs_has(world, e2, Velocity));
|
|
|
|
const Position *p = ecs_get(world, e1, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
|
|
p = ecs_get(world, e2, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 20);
|
|
test_int(p->y, 30);
|
|
|
|
const Velocity *v = ecs_get(world, e2, Velocity);
|
|
test_assert(v != NULL);
|
|
test_int(v->x, 1);
|
|
test_int(v->y, 2);
|
|
|
|
test_int(3, ecs_count(world, Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_union_relationship(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_ENTITY(world, Rel, Union);
|
|
ECS_TAG(world, Tgt);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
ecs_defer_begin(world);
|
|
ecs_add_pair(world, e, Rel, Tgt);
|
|
test_assert(!ecs_has_pair(world, e, Rel, Tgt));
|
|
ecs_defer_end(world);
|
|
test_assert(ecs_has_pair(world, e, Rel, Tgt));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_existing_union_relationship(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_ENTITY(world, Rel, Union);
|
|
ECS_TAG(world, TgtA);
|
|
ECS_TAG(world, TgtB);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
ecs_add_pair(world, e, Rel, TgtA);
|
|
test_assert(ecs_has_pair(world, e, Rel, TgtA));
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_add_pair(world, e, Rel, TgtB);
|
|
test_assert(ecs_has_pair(world, e, Rel, TgtA));
|
|
test_assert(!ecs_has_pair(world, e, Rel, TgtB));
|
|
ecs_defer_end(world);
|
|
test_assert(!ecs_has_pair(world, e, Rel, TgtA));
|
|
test_assert(ecs_has_pair(world, e, Rel, TgtB));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_union_relationship_2_ops(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_ENTITY(world, Rel, Union);
|
|
ECS_TAG(world, Tgt);
|
|
ECS_TAG(world, Tag);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
ecs_defer_begin(world);
|
|
ecs_add_pair(world, e, Rel, Tgt);
|
|
ecs_add(world, e, Tag);
|
|
test_assert(!ecs_has_pair(world, e, Rel, Tgt));
|
|
test_assert(!ecs_has(world, e, Tag));
|
|
ecs_defer_end(world);
|
|
test_assert(ecs_has_pair(world, e, Rel, Tgt));
|
|
test_assert(ecs_has(world, e, Tag));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_existing_union_relationship_2_ops(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_ENTITY(world, Rel, Union);
|
|
ECS_TAG(world, TgtA);
|
|
ECS_TAG(world, TgtB);
|
|
ECS_TAG(world, Tag);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
ecs_add_pair(world, e, Rel, TgtA);
|
|
test_assert(ecs_has_pair(world, e, Rel, TgtA));
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_add_pair(world, e, Rel, TgtB);
|
|
ecs_add(world, e, Tag);
|
|
test_assert(ecs_has_pair(world, e, Rel, TgtA));
|
|
test_assert(!ecs_has_pair(world, e, Rel, TgtB));
|
|
test_assert(!ecs_has(world, e, Tag));
|
|
ecs_defer_end(world);
|
|
test_assert(!ecs_has_pair(world, e, Rel, TgtA));
|
|
test_assert(ecs_has_pair(world, e, Rel, TgtB));
|
|
test_assert(ecs_has(world, e, Tag));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_remove_after_set(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_set(world, e, Position, {10, 20});
|
|
test_assert(!ecs_has(world, e, Position));
|
|
ecs_remove(world, e, Position);
|
|
test_assert(!ecs_has(world, e, Position));
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
static int position_observer_invoked = 0;
|
|
|
|
static
|
|
void PositionObserver(ecs_iter_t *it) {
|
|
position_observer_invoked ++;
|
|
}
|
|
|
|
void Commands_defer_remove_after_set_w_observer(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_OBSERVER(world, PositionObserver, EcsOnSet, Position);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_set(world, e, Position, {10, 20});
|
|
test_assert(!ecs_has(world, e, Position));
|
|
ecs_remove(world, e, Position);
|
|
test_assert(!ecs_has(world, e, Position));
|
|
ecs_defer_end(world);
|
|
|
|
test_int(position_observer_invoked, 0);
|
|
test_assert(!ecs_has(world, e, Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_override_after_remove(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t base = ecs_set(world, 0, Position, {10, 20});
|
|
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
|
|
ecs_set(world, inst, Position, {20, 30});
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_remove(world, inst, Position);
|
|
ecs_add(world, inst, Position);
|
|
ecs_defer_end(world);
|
|
|
|
const Position *p = ecs_get(world, inst, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
|
|
test_assert(p != ecs_get(world, base, Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_override_after_remove_3_ops(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_TAG(world, Tag);
|
|
|
|
ecs_entity_t base = ecs_set(world, 0, Position, {10, 20});
|
|
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
|
|
ecs_set(world, inst, Position, {20, 30});
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_remove(world, inst, Position);
|
|
ecs_add(world, inst, Position);
|
|
ecs_defer_end(world);
|
|
|
|
const Position *p = ecs_get(world, inst, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
|
|
test_assert(p != ecs_get(world, base, Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_flush_stage_to_deferred_world(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, Tag);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_world_t *async = ecs_async_stage_new(world);
|
|
ecs_add(async, e, Tag);
|
|
test_assert(!ecs_has(world, e, Tag));
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_merge(async);
|
|
test_assert(!ecs_has(world, e, Tag));
|
|
ecs_defer_end(world);
|
|
test_assert(ecs_has(world, e, Tag));
|
|
|
|
ecs_async_stage_free(async);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
static
|
|
void AddPosition(ecs_iter_t *it) {
|
|
test_int(it->count, 1);
|
|
ecs_set(it->world, it->entities[0], Position, {10, 20});
|
|
}
|
|
|
|
void Commands_add_in_observer_during_merge(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT_DEFINE(world, Position);
|
|
ECS_TAG(world, TagA);
|
|
|
|
ECS_OBSERVER(world, AddPosition, EcsOnAdd, TagA);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_add(world, e, TagA);
|
|
test_assert(!ecs_has(world, e, TagA));
|
|
test_assert(!ecs_has(world, e, Position));
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, TagA));
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
const Position *ptr = ecs_get(world, e, Position);
|
|
test_assert(ptr != NULL);
|
|
test_int(ptr->x, 10);
|
|
test_int(ptr->y, 20);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_add_in_observer_during_merge_2_commands(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT_DEFINE(world, Position);
|
|
ECS_TAG(world, TagA);
|
|
ECS_TAG(world, TagB);
|
|
|
|
ECS_OBSERVER(world, AddPosition, EcsOnAdd, TagB);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_log_set_level(0);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_add(world, e, TagA);
|
|
ecs_add(world, e, TagB);
|
|
test_assert(!ecs_has(world, e, TagA));
|
|
test_assert(!ecs_has(world, e, TagB));
|
|
test_assert(!ecs_has(world, e, Position));
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, TagA));
|
|
test_assert(ecs_has(world, e, TagB));
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
const Position *ptr = ecs_get(world, e, Position);
|
|
test_assert(ptr != NULL);
|
|
test_int(ptr->x, 10);
|
|
test_int(ptr->y, 20);
|
|
|
|
ecs_log_set_level(-1);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
static ECS_DECLARE(TagB);
|
|
static ECS_DECLARE(TagC);
|
|
|
|
static
|
|
void AddTwoTags(ecs_iter_t *it) {
|
|
test_int(it->count, 1);
|
|
ecs_add(it->world, it->entities[0], TagB);
|
|
ecs_add(it->world, it->entities[0], TagC);
|
|
}
|
|
|
|
void Commands_add_2_in_observer_while_on_remove_for_delete(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, TagA);
|
|
ECS_TAG_DEFINE(world, TagB);
|
|
ECS_TAG_DEFINE(world, TagC);
|
|
|
|
ECS_OBSERVER(world, AddTwoTags, EcsOnRemove, TagA);
|
|
|
|
ecs_entity_t e = ecs_new(world, TagA);
|
|
ecs_delete(world, e);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_add_2_in_observer_while_on_remove_for_delete_child(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, TagA);
|
|
ECS_TAG_DEFINE(world, TagB);
|
|
ECS_TAG_DEFINE(world, TagC);
|
|
|
|
ECS_OBSERVER(world, AddTwoTags, EcsOnRemove, TagA);
|
|
|
|
ecs_entity_t parent = ecs_new_id(world);
|
|
ecs_entity_t e = ecs_new(world, TagA);
|
|
ecs_add_pair(world, e, EcsChildOf, parent);
|
|
ecs_delete(world, e);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_add_2_in_observer_while_on_remove_for_delete_recycled_id(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, TagA);
|
|
ECS_TAG_DEFINE(world, TagB);
|
|
ECS_TAG_DEFINE(world, TagC);
|
|
|
|
ECS_OBSERVER(world, AddTwoTags, EcsOnRemove, TagA);
|
|
|
|
ecs_delete(world, ecs_new_id(world));
|
|
|
|
ecs_entity_t e = ecs_new(world, TagA);
|
|
ecs_delete(world, e);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_add_2_in_observer_while_on_remove_for_deferred_delete_recycled_id(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, TagA);
|
|
ECS_TAG_DEFINE(world, TagB);
|
|
ECS_TAG_DEFINE(world, TagC);
|
|
|
|
ECS_OBSERVER(world, AddTwoTags, EcsOnRemove, TagA);
|
|
|
|
ecs_delete(world, ecs_new_id(world));
|
|
|
|
ecs_entity_t e = ecs_new(world, TagA);
|
|
ecs_defer_begin(world);
|
|
ecs_delete(world, e);
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, e));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_add_after_clear(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_TAG(world, Tag);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_clear(world, e);
|
|
ecs_add(world, e, Position);
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_cmd_after_modified(void) {
|
|
ecs_world_t *world = ecs_init();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e1 = ecs_new_id(world);
|
|
ecs_entity_t e2 = ecs_new_id(world);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_set(world, e1, Position, {10, 20});
|
|
ecs_modified(world, e2, Position);
|
|
ecs_set(world, e2, Position, {20, 30});
|
|
|
|
test_assert(!ecs_has(world, e1, Position));
|
|
test_assert(!ecs_has(world, e2, Position));
|
|
ecs_defer_end(world);
|
|
test_assert(ecs_has(world, e1, Position));
|
|
test_assert(ecs_has(world, e2, Position));
|
|
|
|
const Position *p = ecs_get(world, e1, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
|
|
p = ecs_get(world, e2, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 20);
|
|
test_int(p->y, 30);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_remove_after_emplace_different_id(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_TAG(world, Tag);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
ecs_add(world, e, Tag);
|
|
|
|
ecs_defer_begin(world);
|
|
Position *p = ecs_emplace(world, e, Position);
|
|
p->x = 10;
|
|
p->y = 20;
|
|
ecs_remove(world, e, Tag);
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Tag));
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Tag));
|
|
|
|
const Position *ptr = ecs_get(world, e, Position);
|
|
test_assert(ptr != NULL);
|
|
test_int(ptr->x, 10);
|
|
test_int(ptr->y, 20);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_remove_after_set_and_emplace_different_id(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
ECS_TAG(world, Tag);
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
ecs_add(world, e, Tag);
|
|
|
|
ecs_defer_begin(world);
|
|
Position *p = ecs_emplace(world, e, Position);
|
|
p->x = 10;
|
|
p->y = 20;
|
|
ecs_set(world, e, Velocity, {1, 2});
|
|
ecs_remove(world, e, Tag);
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
test_assert(ecs_has(world, e, Tag));
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
test_assert(!ecs_has(world, e, Tag));
|
|
|
|
const Position *ptr = ecs_get(world, e, Position);
|
|
test_assert(ptr != NULL);
|
|
test_int(ptr->x, 10);
|
|
test_int(ptr->y, 20);
|
|
|
|
const Velocity *v = ecs_get(world, e, Velocity);
|
|
test_assert(v != NULL);
|
|
test_int(v->x, 1);
|
|
test_int(v->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_clear_after_add_to_nonempty(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, TagA);
|
|
ECS_TAG(world, TagB);
|
|
|
|
ecs_entity_t e = ecs_new(world, TagA);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_add(world, e, TagB);
|
|
ecs_clear(world, e);
|
|
|
|
test_assert(ecs_has(world, e, TagA));
|
|
test_assert(!ecs_has(world, e, TagB));
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, TagA));
|
|
test_assert(!ecs_has(world, e, TagB));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_remove_after_add_to_nonempty(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, TagA);
|
|
ECS_TAG(world, TagB);
|
|
|
|
ecs_entity_t e = ecs_new(world, TagA);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_add(world, e, TagB);
|
|
ecs_remove(world, e, TagA);
|
|
ecs_remove(world, e, TagB);
|
|
|
|
test_assert(ecs_has(world, e, TagA));
|
|
test_assert(!ecs_has(world, e, TagB));
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, TagA));
|
|
test_assert(!ecs_has(world, e, TagB));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_register_while_deferred_with_n_stages(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ecs_set_stage_count(world, 2);
|
|
|
|
ecs_defer_begin(world);
|
|
ECS_COMPONENT(world, Position);
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_id(Position));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
static int position_velocity_observer_invoked = 0;
|
|
|
|
static
|
|
void PositionVelocityObserver(ecs_iter_t *it) {
|
|
position_velocity_observer_invoked ++;
|
|
test_int(it->count, 1);
|
|
|
|
Position *p = ecs_field(it, Position, 1);
|
|
Velocity *v = ecs_field(it, Velocity, 2);
|
|
|
|
test_assert(p != NULL);
|
|
test_assert(v != NULL);
|
|
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
|
|
test_int(v->x, 1);
|
|
test_int(v->y, 2);
|
|
}
|
|
|
|
void Commands_defer_2_sets_w_multi_observer(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_observer(world, {
|
|
.filter.terms = {{ ecs_id(Position) }, { ecs_id(Velocity) }},
|
|
.callback = PositionVelocityObserver,
|
|
.events = { EcsOnSet }
|
|
});
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_set(world, e, Position, {10, 20});
|
|
ecs_set(world, e, Velocity, {1, 2});
|
|
ecs_defer_end(world);
|
|
|
|
test_int(position_velocity_observer_invoked, 2);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
const Velocity *v = ecs_get(world, e, Velocity);
|
|
test_int(v->x, 1);
|
|
test_int(v->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_2_get_muts_w_multi_observer(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_observer(world, {
|
|
.filter.terms = {{ ecs_id(Position) }, { ecs_id(Velocity) }},
|
|
.callback = PositionVelocityObserver,
|
|
.events = { EcsOnSet }
|
|
});
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_defer_begin(world);
|
|
{
|
|
Position *p = ecs_get_mut(world, e, Position);
|
|
p->x = 10;
|
|
p->y = 20;
|
|
ecs_modified(world, e, Position);
|
|
Velocity *v = ecs_get_mut(world, e, Velocity);
|
|
v->x = 1;
|
|
v->y = 2;
|
|
ecs_modified(world, e, Velocity);
|
|
}
|
|
ecs_defer_end(world);
|
|
|
|
test_int(position_velocity_observer_invoked, 2);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
const Velocity *v = ecs_get(world, e, Velocity);
|
|
test_int(v->x, 1);
|
|
test_int(v->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_2_get_muts_no_modified_w_multi_observer(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_observer(world, {
|
|
.filter.terms = {{ ecs_id(Position) }, { ecs_id(Velocity) }},
|
|
.callback = PositionVelocityObserver,
|
|
.events = { EcsOnSet }
|
|
});
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
|
|
ecs_defer_begin(world);
|
|
{
|
|
Position *p = ecs_get_mut(world, e, Position);
|
|
p->x = 10;
|
|
p->y = 20;
|
|
Velocity *v = ecs_get_mut(world, e, Velocity);
|
|
v->x = 1;
|
|
v->y = 2;
|
|
}
|
|
ecs_defer_end(world);
|
|
|
|
test_int(position_velocity_observer_invoked, 0);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
const Velocity *v = ecs_get(world, e, Velocity);
|
|
test_int(v->x, 1);
|
|
test_int(v->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_exists_remove_set(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
ecs_set(world, e, Position, {1, 2});
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_remove(world, e, Position);
|
|
ecs_set(world, e, Position, {5, 6});
|
|
ecs_defer_end(world);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 5);
|
|
test_int(p->y, 6);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_absent_remove_set(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_remove(world, e, Position);
|
|
ecs_set(world, e, Position, {5, 6});
|
|
ecs_defer_end(world);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 5);
|
|
test_int(p->y, 6);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_exists_set_remove(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
ecs_set(world, e, Position, {1, 2});
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_set(world, e, Position, {5, 6});
|
|
ecs_remove(world, e, Position);
|
|
ecs_defer_end(world);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p == NULL);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_absent_set_remove(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_set(world, e, Position, {5, 6});
|
|
ecs_remove(world, e, Position);
|
|
ecs_defer_end(world);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p == NULL);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_exists_set_w_get_mut(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
ecs_set(world, e, Position, {1, 2});
|
|
|
|
ecs_defer_begin(world);
|
|
{
|
|
ecs_set(world, e, Position, {5, 6});
|
|
Position *p = ecs_get_mut(world, e, Position);
|
|
p->x = 11;
|
|
}
|
|
ecs_defer_end(world);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 11);
|
|
test_int(p->y, 6);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_exists_remove_get_mut(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
ecs_set(world, e, Position, {1, 2});
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_remove(world, e, Position);
|
|
{
|
|
Position *p = ecs_get_mut(world, e, Position);
|
|
test_assert(p != NULL);
|
|
p->x = 5;
|
|
p->y = 6;
|
|
}
|
|
ecs_defer_end(world);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 5);
|
|
test_int(p->y, 6);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_absent_remove_get_mut(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_remove(world, e, Position);
|
|
{
|
|
Position *p = ecs_get_mut(world, e, Position);
|
|
test_assert(p != NULL);
|
|
p->x = 5;
|
|
p->y = 6;
|
|
}
|
|
test_assert(!ecs_has(world, e, Position));
|
|
ecs_defer_end(world);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 5);
|
|
test_int(p->y, 6);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_exists_get_mut_remove(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
ecs_set(world, e, Position, {1, 2});
|
|
|
|
ecs_defer_begin(world);
|
|
{
|
|
Position *p = ecs_get_mut(world, e, Position);
|
|
test_assert(p != NULL);
|
|
p->x = 5;
|
|
p->y = 6;
|
|
}
|
|
ecs_remove(world, e, Position);
|
|
ecs_defer_end(world);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p == NULL);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_absent_get_mut_remove(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
|
|
ecs_defer_begin(world);
|
|
{
|
|
Position *p = ecs_get_mut(world, e, Position);
|
|
test_assert(p != NULL);
|
|
p->x = 5;
|
|
p->y = 6;
|
|
}
|
|
test_assert(!ecs_has(world, e, Position));
|
|
ecs_remove(world, e, Position);
|
|
ecs_defer_end(world);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p == NULL);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_absent_set_invoke_on_set(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
on_set_invoked = 0;
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_OBSERVER(world, OnSetTestInvoked, EcsOnSet, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
|
|
/* create the component */
|
|
ecs_defer_begin(world);
|
|
ecs_set(world, e, Position, {1, 2});
|
|
|
|
/* OnSet should not be run until defer has completed */
|
|
test_int(on_set_invoked, 0);
|
|
ecs_defer_end(world);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_int(on_set_invoked, 1);
|
|
test_int(p->x, 1);
|
|
test_int(p->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_exists_set_invoke_on_set(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_OBSERVER(world, OnSetTestInvoked, EcsOnSet, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
ecs_set(world, e, Position, {1, 2});
|
|
on_set_invoked = 0;
|
|
|
|
/* create the component */
|
|
ecs_defer_begin(world);
|
|
ecs_set(world, e, Position, {5, 6});
|
|
|
|
/* OnSet should not be run until defer has completed */
|
|
test_int(on_set_invoked, 0);
|
|
ecs_defer_end(world);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_int(on_set_invoked, 1);
|
|
test_int(p->x, 5);
|
|
test_int(p->y, 6);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_get_mut_no_on_set(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
on_set_invoked = 0;
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_OBSERVER(world, OnSetTestInvoked, EcsOnSet, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, 0);
|
|
|
|
/* create the component */
|
|
ecs_defer_begin(world);
|
|
{
|
|
Position *p = ecs_get_mut(world, e, Position);
|
|
p->x = 1;
|
|
p->y = 2;
|
|
}
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_int(on_set_invoked, 0);
|
|
ecs_defer_end(world);
|
|
test_int(on_set_invoked, 0);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_int(p->x, 1);
|
|
test_int(p->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_existing_get_mut_no_on_set(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
on_set_invoked = 0;
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_OBSERVER(world, OnSetTestInvoked, EcsOnSet, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
/* create the component */
|
|
ecs_defer_begin(world);
|
|
{
|
|
Position *p = ecs_get_mut(world, e, Position);
|
|
p->x = 1;
|
|
p->y = 2;
|
|
}
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_int(on_set_invoked, 0);
|
|
ecs_defer_end(world);
|
|
test_int(on_set_invoked, 0);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_int(p->x, 1);
|
|
test_int(p->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_get_mut_override(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t base = ecs_set(world, 0, Position, {1, 2});
|
|
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
|
|
|
|
ecs_defer_begin(world);
|
|
{
|
|
Position *p = ecs_get_mut(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 1);
|
|
test_int(p->y, 2);
|
|
p->x = 5;
|
|
p->y = 6;
|
|
}
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(!ecs_owns(world, e, Position));
|
|
ecs_defer_end(world);
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_owns(world, e, Position));
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_int(p->x, 5);
|
|
test_int(p->y, 6);
|
|
|
|
const Position *bp = ecs_get(world, base, Position);
|
|
test_assert(p != bp);
|
|
test_int(bp->x, 1);
|
|
test_int(bp->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_set_override(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t base = ecs_set(world, 0, Position, {1, 2});
|
|
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
|
|
|
|
ecs_defer_begin(world);
|
|
{
|
|
ecs_set(world, e, Position, {5, 6});
|
|
}
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(!ecs_owns(world, e, Position));
|
|
ecs_defer_end(world);
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_owns(world, e, Position));
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_int(p->x, 5);
|
|
test_int(p->y, 6);
|
|
|
|
const Position *bp = ecs_get(world, base, Position);
|
|
test_assert(p != bp);
|
|
test_int(bp->x, 1);
|
|
test_int(bp->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_absent_get_mut_for_entity_w_tag(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, Tag);
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_entity_t e = ecs_new(world, Tag);
|
|
test_assert(e != 0);
|
|
|
|
ecs_defer_begin(world);
|
|
{
|
|
Position *p = ecs_get_mut(world, e, Position);
|
|
test_assert(p != NULL);
|
|
p->x = 10;
|
|
p->y = 20;
|
|
}
|
|
ecs_defer_end(world);
|
|
|
|
{
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
}
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
static int set_position_invoked = 0;
|
|
static int set_velocity_invoked = 0;
|
|
static int add_tag_invoked = 0;
|
|
|
|
static void set_position_hook(ecs_iter_t *it) {
|
|
set_position_invoked ++;
|
|
}
|
|
|
|
static void set_velocity_hook(ecs_iter_t *it) {
|
|
set_velocity_invoked ++;
|
|
}
|
|
|
|
static void add_tag(ecs_iter_t *it) {
|
|
test_int(set_position_invoked, 1);
|
|
add_tag_invoked ++;
|
|
}
|
|
|
|
void Commands_on_set_hook_before_on_add_for_existing_component(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_TAG(world, TagA);
|
|
ECS_TAG(world, TagB);
|
|
|
|
ecs_set_hooks(world, Position, {
|
|
.on_set = set_position_hook
|
|
});
|
|
|
|
ecs_observer(world, {
|
|
.filter.terms[0].id = TagA,
|
|
.events = { EcsOnAdd },
|
|
.callback = add_tag
|
|
});
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_add(world, e, TagB); /* 2 add commands, to trigger batching */
|
|
ecs_modified(world, e, Position);
|
|
ecs_add(world, e, TagA);
|
|
|
|
test_int(set_position_invoked, 0);
|
|
test_int(add_tag_invoked, 0);
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(set_position_invoked != 0);
|
|
test_int(add_tag_invoked, 1);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_2_sets_w_observer_same_component(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
|
|
ecs_observer(world, {
|
|
.filter.terms[0].id = ecs_id(Position),
|
|
.events = { EcsOnSet },
|
|
.callback = set_position_hook
|
|
});
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_set(world, e, Position, {10, 20});
|
|
ecs_set(world, e, Position, {20, 30});
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(set_position_invoked != 0);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 20);
|
|
test_int(p->y, 30);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_defer_2_sets_w_observer_other_component(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
|
|
ecs_observer(world, {
|
|
.filter.terms[0].id = ecs_id(Position),
|
|
.events = { EcsOnSet },
|
|
.callback = set_position_hook
|
|
});
|
|
|
|
ecs_observer(world, {
|
|
.filter.terms[0].id = ecs_id(Velocity),
|
|
.events = { EcsOnSet },
|
|
.callback = set_velocity_hook
|
|
});
|
|
|
|
ecs_entity_t e = ecs_new(world, Position);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_set(world, e, Position, {10, 20});
|
|
ecs_set(world, e, Velocity, {1, 2});
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(set_position_invoked != 0);
|
|
test_assert(set_velocity_invoked != 0);
|
|
|
|
const Position *p = ecs_get(world, e, Position);
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
|
|
const Velocity *v = ecs_get(world, e, Velocity);
|
|
test_assert(v != NULL);
|
|
test_int(v->x, 1);
|
|
test_int(v->y, 2);
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
static int remove_tag_invoked = 0;
|
|
static void remove_tag(ecs_iter_t *it) {
|
|
remove_tag_invoked ++;
|
|
}
|
|
|
|
void Commands_on_remove_after_deferred_clear_and_add(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, TagA);
|
|
ECS_TAG(world, TagB);
|
|
ECS_TAG(world, TagC);
|
|
|
|
ecs_observer(world, {
|
|
.filter.terms[0].id = TagA,
|
|
.events = { EcsOnRemove },
|
|
.callback = remove_tag
|
|
});
|
|
|
|
ecs_entity_t e = ecs_new_id(world);
|
|
ecs_add(world, e, TagA);
|
|
ecs_add(world, e, TagB);
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_clear(world, e);
|
|
ecs_add(world, e, TagC);
|
|
test_int(remove_tag_invoked, 0);
|
|
ecs_defer_end(world);
|
|
test_int(remove_tag_invoked, 1);
|
|
|
|
test_assert(!ecs_has(world, e, TagA));
|
|
test_assert(!ecs_has(world, e, TagB));
|
|
test_assert(ecs_has(world, e, TagC));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
static void Recycle(ecs_iter_t *it) {
|
|
ecs_new_id(it->world);
|
|
*(ecs_entity_t*)it->ctx = ecs_new_id(it->world);
|
|
}
|
|
|
|
void Commands_defer_delete_recycle_same_id(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_TAG(world, Foo);
|
|
ECS_TAG(world, Bar);
|
|
|
|
ecs_entity_t parent = ecs_new_id(world);
|
|
ecs_entity_t e1 = ecs_new_w_pair(world, EcsChildOf, parent);
|
|
ecs_entity_t e2 = ecs_new_id(world);
|
|
|
|
ecs_observer(world, {
|
|
.filter.terms = {
|
|
{ .id = ecs_id(Foo) }
|
|
},
|
|
.events = { EcsOnAdd },
|
|
.callback = Recycle,
|
|
.ctx = &e1
|
|
});
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_delete(world, parent);
|
|
ecs_add(world, e2, Foo);
|
|
ecs_add(world, e1, Bar);
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_is_alive(world, parent));
|
|
test_assert(ecs_is_alive(world, e2));
|
|
test_assert(ecs_is_alive(world, e1));
|
|
test_assert((uint32_t)e1 != e1);
|
|
test_assert(ecs_has(world, e2, Foo));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
static ECS_COMPONENT_DECLARE(Velocity);
|
|
|
|
static
|
|
void AddWhileSuspended(ecs_iter_t *it) {
|
|
for (int i = 0; i < it->count; i ++) {
|
|
ecs_add(it->world, it->entities[i], Velocity);
|
|
}
|
|
}
|
|
|
|
void Commands_observer_while_defer_suspended(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT_DEFINE(world, Velocity);
|
|
|
|
ecs_observer(world, {
|
|
.filter.terms = {
|
|
{ .id = ecs_id(Position) }
|
|
},
|
|
.events = { EcsOnAdd },
|
|
.callback = AddWhileSuspended,
|
|
});
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_defer_suspend(world);
|
|
|
|
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_defer_resume(world);
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_on_add_hook_while_defer_suspended(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT_DEFINE(world, Velocity);
|
|
|
|
ecs_set_hooks(world, Position, {
|
|
.on_add = AddWhileSuspended
|
|
});
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_defer_suspend(world);
|
|
|
|
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_defer_resume(world);
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_on_set_hook_while_defer_suspended(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT_DEFINE(world, Velocity);
|
|
|
|
ecs_set_hooks(world, Position, {
|
|
.on_set = AddWhileSuspended
|
|
});
|
|
|
|
ecs_defer_begin(world);
|
|
ecs_defer_suspend(world);
|
|
|
|
ecs_entity_t e = ecs_set(world, 0, Position, {10, 20});
|
|
test_assert(e != 0);
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
|
|
ecs_defer_resume(world);
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
ecs_fini(world);
|
|
}
|
|
|
|
void Commands_on_remove_hook_while_defer_suspended(void) {
|
|
ecs_world_t *world = ecs_mini();
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT_DEFINE(world, Velocity);
|
|
|
|
ecs_set_hooks(world, Position, {
|
|
.on_remove = AddWhileSuspended
|
|
});
|
|
|
|
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_defer_begin(world);
|
|
ecs_defer_suspend(world);
|
|
|
|
test_assert(ecs_has(world, e, Position));
|
|
ecs_remove(world, e, Position);
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_assert(!ecs_has(world, e, Velocity));
|
|
|
|
ecs_defer_resume(world);
|
|
ecs_defer_end(world);
|
|
|
|
test_assert(!ecs_has(world, e, Position));
|
|
test_assert(ecs_has(world, e, Velocity));
|
|
|
|
ecs_fini(world);
|
|
}
|