Files
PixelDefense/engine/libs/flecs/test/addons/src/System_w_FromParent.c

1295 lines
33 KiB
C

#include <addons.h>
void System_w_FromParent_setup(void) {
ecs_log_set_level(-3);
}
static
void Iter(ecs_iter_t *it) {
Mass *m_ptr = ecs_field(it, Mass, 1);
bool shared = false;
if (m_ptr) {
shared = !ecs_field_is_self(it, 1);
}
Position *p = NULL;
Velocity *v = NULL;
if (it->field_count >= 2) {
p = ecs_field(it, Position, 2);
}
if (it->field_count >= 3) {
v = ecs_field(it, Velocity, 3);
}
probe_iter(it);
int i;
for (i = 0; i < it->count; i ++) {
Mass m = 1;
if (m_ptr) {
if (shared) {
m = *m_ptr;
} else {
m = m_ptr[i];
}
}
p[i].x = 10 * m;
p[i].y = 20 * m;
if (v) {
v[i].x = 30 * m;
v[i].y = 40 * m;
}
}
}
void System_w_FromParent_1_column_from_container(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_ENTITY(world, e3, Position);
ECS_ENTITY(world, e4, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ecs_entity_t parent = ecs_set(world, 0, Mass, {2});
ecs_add_pair(world, e1, EcsChildOf, parent);
ecs_add_pair(world, e2, EcsChildOf, parent);
ecs_add_pair(world, e3, EcsChildOf, parent);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 3);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.e[2], e3);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
p = ecs_get(world, e3, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
ecs_fini(world);
}
void System_w_FromParent_2_column_1_from_container(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position, Velocity);
ECS_ENTITY(world, e2, Position, Velocity);
ECS_ENTITY(world, e3, Position, Velocity);
ECS_ENTITY(world, e4, Position, Velocity);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(parent), Position, Velocity);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ecs_entity_t parent = ecs_set(world, 0, Mass, {2});
ecs_add_pair(world, e1, EcsChildOf, parent);
ecs_add_pair(world, e2, EcsChildOf, parent);
ecs_add_pair(world, e3, EcsChildOf, parent);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 3);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 3);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.e[2], e3);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
test_int(ctx.c[0][2], ecs_id(Velocity));
test_int(ctx.s[0][2], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
p = ecs_get(world, e3, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
const Velocity *v = ecs_get(world, e1, Velocity);
test_assert(v != NULL);
test_int(v->x, 60);
test_int(v->y, 80);
v = ecs_get(world, e2, Velocity);
test_assert(v != NULL);
test_int(v->x, 60);
test_int(v->y, 80);
v = ecs_get(world, e3, Velocity);
test_assert(v != NULL);
test_int(v->x, 60);
test_int(v->y, 80);
ecs_fini(world);
}
static
void Iter_2_shared(ecs_iter_t *it) {
Mass *m_ptr = ecs_field(it, Mass, 1);
Rotation *r_ptr = NULL;
Position *p = NULL;
Velocity *v = NULL;
if (it->field_count >= 2) {
r_ptr = ecs_field(it, Rotation, 2);
}
if (it->field_count >= 3) {
p = ecs_field(it, Position, 3);
}
if (it->field_count >= 4) {
v = ecs_field(it, Velocity, 4);
}
probe_iter(it);
Mass m = 1;
if (m_ptr) {
m = *m_ptr;
}
Rotation r = 0;
if (r_ptr) {
r = *r_ptr;
}
int i;
for (i = 0; i < it->count; i ++) {
if (p) {
p[i].x = 10 * m + r;
p[i].y = 20 * m + r;
}
if (v) {
v[i].x = 30 * m + r;
v[i].y = 40 * m + r;
}
}
}
void System_w_FromParent_3_column_2_from_container(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Rotation);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_ENTITY(world, e3, Position);
ECS_ENTITY(world, e4, Position);
ECS_SYSTEM(world, Iter_2_shared, EcsOnUpdate, Mass(parent), Rotation(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter_2_shared,
.query.filter.instanced = true
});
ecs_entity_t parent = ecs_set(world, 0, Mass, {2});
ecs_set(world, parent, Rotation, {3});
ecs_add_pair(world, e1, EcsChildOf, parent);
ecs_add_pair(world, e2, EcsChildOf, parent);
ecs_add_pair(world, e4, EcsChildOf, parent);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 3);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter_2_shared);
test_int(ctx.term_count, 3);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.e[2], e4);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], parent);
test_int(ctx.c[0][1], ecs_id(Rotation));
test_int(ctx.s[0][1], parent);
test_int(ctx.c[0][2], ecs_id(Position));
test_int(ctx.s[0][2], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 23);
test_int(p->y, 43);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 23);
test_int(p->y, 43);
p = ecs_get(world, e4, Position);
test_assert(p != NULL);
test_int(p->x, 23);
test_int(p->y, 43);
ecs_fini(world);
}
void System_w_FromParent_2_column_1_from_container_w_not(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Rotation);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_ENTITY(world, e3, Position);
ECS_ENTITY(world, e4, Position);
ECS_ENTITY(world, e5, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, !Mass(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ecs_entity_t parent_1 = ecs_set(world, 0, Mass, {2});
ecs_entity_t parent_2 = ecs_set(world, 0, Rotation, {3});
ecs_add_pair(world, e1, EcsChildOf, parent_2);
ecs_add_pair(world, e2, EcsChildOf, parent_2);
ecs_add_pair(world, e3, EcsChildOf, parent_2);
ecs_add_pair(world, e4, EcsChildOf, parent_1);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 4);
test_int(ctx.invoked, 2);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e5);
test_int(ctx.e[1], e1);
test_int(ctx.e[2], e2);
test_int(ctx.e[3], e3);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
test_int(ctx.c[1][0], ecs_id(Mass));
test_int(ctx.s[1][0], 0);
test_int(ctx.c[1][1], ecs_id(Position));
test_int(ctx.s[1][1], 0);
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, 10);
test_int(p->y, 20);
p = ecs_get(world, e3, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
p = ecs_get(world, e5, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void System_w_FromParent_3_column_1_from_comtainer_1_from_container_w_not(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Rotation);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_ENTITY(world, e3, Position);
ECS_ENTITY(world, e4, Position);
ECS_ENTITY(world, e5, Position);
ECS_ENTITY(world, e6, Position);
ECS_SYSTEM(world, Iter_2_shared, EcsOnUpdate, !Mass(parent), Rotation(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter_2_shared,
.query.filter.instanced = true
});
ecs_entity_t parent_1 = ecs_set(world, 0, Mass, {2});
ecs_entity_t parent_2 = ecs_set(world, 0, Rotation, {3});
ecs_entity_t parent_3 = ecs_set(world, 0, Mass, {4});
ecs_set(world, parent_3, Rotation, {5});
ecs_add_pair(world, e1, EcsChildOf, parent_2);
ecs_add_pair(world, e2, EcsChildOf, parent_2);
ecs_add_pair(world, e3, EcsChildOf, parent_2);
ecs_add_pair(world, e4, EcsChildOf, parent_1);
ecs_add_pair(world, e5, EcsChildOf, parent_3);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 3);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter_2_shared);
test_int(ctx.term_count, 3);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.e[2], e3);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Rotation));
test_int(ctx.s[0][1], parent_2);
test_int(ctx.c[0][2], ecs_id(Position));
test_int(ctx.s[0][2], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 13);
test_int(p->y, 23);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 13);
test_int(p->y, 23);
p = ecs_get(world, e3, Position);
test_assert(p != NULL);
test_int(p->x, 13);
test_int(p->y, 23);
ecs_fini(world);
}
void System_w_FromParent_2_column_1_from_container_w_not_prefab(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Rotation);
ECS_COMPONENT(world, Mass);
ECS_PREFAB(world, Prefab, Rotation);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, !Mass(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ecs_entity_t parent_1 = ecs_set(world, 0, Mass, {2});
ecs_add_pair(world, e1, EcsIsA, Prefab);
ecs_add_pair(world, e1, EcsChildOf, parent_1);
ecs_set(world, e1, Position, {1, 2});
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e2);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 1);
test_int(p->y, 2);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void System_w_FromParent_2_column_1_from_container_w_or(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Rotation);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_ENTITY(world, e3, Position);
ECS_ENTITY(world, e4, Position);
ECS_ENTITY(world, e5, Position);
ECS_ENTITY(world, e6, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(parent) || Rotation(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ecs_entity_t parent_1 = ecs_set(world, 0, Mass, {2});
ecs_entity_t parent_2 = ecs_set(world, 0, Rotation, {3});
ecs_entity_t parent_3 = ecs_set(world, 0, Rotation, {4});
ecs_set(world, parent_3, Mass, {5});
ecs_entity_t parent_4 = ecs_set(world, 0, Velocity, {10, 20});
ecs_add_pair(world, e1, EcsChildOf, parent_1);
ecs_add_pair(world, e2, EcsChildOf, parent_2);
ecs_add_pair(world, e3, EcsChildOf, parent_3);
ecs_add_pair(world, e4, EcsChildOf, parent_4);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 3);
test_int(ctx.invoked, 3);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.e[2], e3);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], parent_1);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
test_int(ctx.c[1][0], ecs_id(Rotation));
test_int(ctx.s[1][0], parent_2);
test_int(ctx.c[1][1], ecs_id(Position));
test_int(ctx.s[2][1], 0);
test_int(ctx.c[2][0], ecs_id(Mass));
test_int(ctx.s[2][0], parent_3);
test_int(ctx.c[2][1], ecs_id(Position));
test_int(ctx.s[2][1], 0);
ecs_fini(world);
}
static
void Dummy(ecs_iter_t *it) {
Mass *m_ptr = ecs_field(it, Mass, 1);
Position *p = ecs_field(it, Position, 2);
test_assert(!m_ptr || !ecs_field_is_self(it, 1));
probe_iter(it);
Mass m = 1;
if (m_ptr) {
m = *m_ptr;
}
int i;
for (i = 0; i < it->count; i ++) {
p[i].x += m;
p[i].y += m;
}
}
void System_w_FromParent_add_component_after_match(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_ENTITY(world, e3, Position);
ECS_ENTITY(world, e4, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ecs_entity_t parent = ecs_new(world, 0);
ecs_add_pair(world, e1, EcsChildOf, parent);
ecs_add_pair(world, e2, EcsChildOf, parent);
ecs_set(world, parent, Mass, {2});
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 2);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
ecs_fini(world);
}
void System_w_FromParent_add_component_after_match_and_rematch(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_ENTITY(world, e3, Position);
ECS_ENTITY(world, e4, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ecs_entity_t parent = ecs_new(world, 0);
ecs_add_pair(world, e1, EcsChildOf, parent);
ecs_add_pair(world, e2, EcsChildOf, parent);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
/* This will rematch tables, but not match Iter with e1 and e2 because the
* parent does not have Mass yet */
ecs_progress(world, 1);
test_int(ctx.count, 0);
ecs_set(world, parent, Mass, {2});
/* Now a rematch of tables need to happen again, since parent has changed */
ecs_os_zeromem(&ctx);
ecs_progress(world, 1);
test_int(ctx.count, 2);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
ecs_fini(world);
}
void System_w_FromParent_add_component_after_match_and_rematch_w_entity_type_expr(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e3, Position);
ECS_ENTITY(world, e4, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ECS_ENTITY(world, Parent, 0);
ECS_ENTITY(world, e1, Position, (ChildOf, Parent));
ECS_ENTITY(world, e2, Position, (ChildOf, Parent));
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
/* This will rematch tables, but not match Iter with e1 and e2 because the
* Parent does not have Mass yet */
ecs_progress(world, 1);
test_int(ctx.count, 0);
ecs_set(world, Parent, Mass, {2});
/* Now a rematch of tables need to happen again, since parent has changed */
ecs_os_zeromem(&ctx);
ecs_progress(world, 1);
test_int(ctx.count, 2);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], Parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
ecs_fini(world);
}
static
void SetMass(ecs_iter_t *it) {
ecs_id_t ecs_id(Mass) = ecs_field_id(it, 2);
int i;
for (i = 0; i < it->count; i ++) {
ecs_set(it->world, it->entities[i], Mass, {2});
}
}
void System_w_FromParent_add_component_after_match_and_rematch_w_entity_type_expr_in_progress(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e3, Position);
ECS_ENTITY(world, e4, Position);
ECS_SYSTEM(world, SetMass, EcsOnUpdate, Velocity, Mass());
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ECS_ENTITY(world, Parent, Velocity);
ECS_ENTITY(world, e1, Position, (ChildOf, Parent));
ECS_ENTITY(world, e2, Position, (ChildOf, Parent));
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_os_zeromem(&ctx);
ecs_progress(world, 1);
test_int(ctx.count, 2);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], Parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
ecs_fini(world);
}
void System_w_FromParent_add_component_after_match_unmatch(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_ENTITY(world, e3, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, !Mass(parent), Position);
ecs_entity_t parent = ecs_new(world, 0);
ecs_add_pair(world, e1, EcsChildOf, parent);
ecs_add_pair(world, e2, EcsChildOf, parent);
ecs_set(world, parent, Mass, {2});
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e3);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e3, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void System_w_FromParent_add_component_after_match_unmatch_match(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ECS_SYSTEM(world, Dummy, EcsOnUpdate, !Mass(parent), Position);
ecs_entity_t parent = ecs_new(world, 0);
ecs_add_pair(world, e1, EcsChildOf, parent);
ecs_add_pair(world, e2, EcsChildOf, parent);
ecs_set(world, parent, Mass, {2});
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 2);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
ecs_fini(world);
}
void System_w_FromParent_add_component_after_match_2_systems(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_ENTITY(world, e3, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ECS_SYSTEM(world, Dummy, EcsOnUpdate, Mass(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Dummy,
.query.filter.instanced = true
});
ecs_entity_t parent = ecs_new(world, 0);
ecs_add_pair(world, e1, EcsChildOf, parent);
ecs_add_pair(world, e2, EcsChildOf, parent);
ecs_set(world, parent, Mass, {2});
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 4);
test_int(ctx.invoked, 2);
test_int(ctx.system, Dummy);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.e[2], e1);
test_int(ctx.e[3], e2);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 22);
test_int(p->y, 42);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 22);
test_int(p->y, 42);
ecs_fini(world);
}
static
void AddMass(ecs_iter_t *it) {
test_assert(it->ctx != NULL);
ecs_entity_t ecs_id(Mass) = *(ecs_entity_t*)it->ctx;
int i;
for (i = 0; i < it->count; i ++) {
ecs_set(it->world, it->entities[i], Mass, {2});
}
}
void System_w_FromParent_add_component_in_progress_after_match(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, Tag, 0);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_ENTITY(world, e3, Position);
ECS_ENTITY(world, e4, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ECS_OBSERVER(world, AddMass, EcsOnAdd, Tag);
ecs_observer_init(world, &(ecs_observer_desc_t){
.entity = AddMass,
.ctx = &ecs_id(Mass)
});
ecs_entity_t parent = ecs_new(world, 0);
ecs_add_pair(world, e1, EcsChildOf, parent);
ecs_add_pair(world, e2, EcsChildOf, parent);
ecs_add_id(world, parent, Tag);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 2);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
ecs_fini(world);
}
void System_w_FromParent_adopt_after_match(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_ENTITY(world, e3, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ecs_entity_t parent = ecs_new(world, Mass);
ecs_add_pair(world, e1, EcsChildOf, parent);
ecs_add_pair(world, e2, EcsChildOf, parent);
ecs_set(world, parent, Mass, {2});
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 2);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
ecs_fini(world);
}
void System_w_FromParent_new_child_after_match(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e3, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Iter,
.query.filter.instanced = true
});
ECS_ENTITY(world, parent, Mass);
ECS_ENTITY(world, e1, (ChildOf, parent), Position);
ECS_ENTITY(world, e2, (ChildOf, parent), Position);
ecs_set(world, parent, Mass, {2});
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 2);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
ecs_fini(world);
}
void IterSame(ecs_iter_t *it) {
Position *p_parent = ecs_field(it, Position, 1);
Position *p = ecs_field(it, Position, 2);
test_assert(!ecs_field_is_self(it, 1));
probe_iter(it);
int i;
for (i = 0; i < it->count; i ++) {
p[i].x += p_parent->x;
p[i].y += p_parent->y;
}
}
void System_w_FromParent_select_same_from_container(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position);
ECS_ENTITY(world, e2, Position);
ECS_ENTITY(world, e3, Position);
ECS_ENTITY(world, e4, Position);
ECS_SYSTEM(world, IterSame, EcsOnUpdate, Position(parent), Position);
ecs_system_init(world, &(ecs_system_desc_t){
.entity = IterSame,
.query.filter.instanced = true
});
ecs_entity_t parent = ecs_set(world, 0, Position, {1, 2});
ecs_add_pair(world, e1, EcsChildOf, parent);
ecs_add_pair(world, e2, EcsChildOf, parent);
ecs_add_pair(world, e3, EcsChildOf, parent);
ecs_set(world, e1, Position, {10, 20});
ecs_set(world, e2, Position, {20, 40});
ecs_set(world, e3, Position, {30, 60});
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 3);
test_int(ctx.invoked, 1);
test_int(ctx.system, IterSame);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.e[2], e3);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 11);
test_int(p->y, 22);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 21);
test_int(p->y, 42);
p = ecs_get(world, e3, Position);
test_assert(p != NULL);
test_int(p->x, 31);
test_int(p->y, 62);
ecs_fini(world);
}
void System_w_FromParent_realloc_after_match(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Mass);
ECS_ENTITY(world, e1, Position);
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(parent), Position);
ecs_entity_t parent = ecs_set(world, 0, Mass, {2});
ecs_add_pair(world, e1, EcsChildOf, parent);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
/* Add 1000 entities to table of container, which will trigger realloc */
for (int i = 0; i < 1000; i ++) {
ecs_clone(world, 0, parent, false);
}
/* Change value of parent Mass. This will update the value in the new table.
* If the realloc would not be properly handled, the code could either crash
* or reference freed memory and use the old value. */
ecs_set(world, parent, Mass, {3});
ecs_os_zeromem(&ctx);
ecs_progress(world, 1);
test_int(ctx.count, 1);
test_int(ctx.invoked, 1);
test_int(ctx.system, Iter);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.c[0][0], ecs_id(Mass));
test_int(ctx.s[0][0], parent);
test_int(ctx.c[0][1], ecs_id(Position));
test_int(ctx.s[0][1], 0);
p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 30);
test_int(p->y, 60);
ecs_fini(world);
}