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

4326 lines
126 KiB
C

#include <api.h>
static ecs_id_t NamePair;
void Prefab_setup(void) {
NamePair = ecs_pair(ecs_id(EcsIdentifier), EcsName);
}
static
void Iter(ecs_iter_t *it) {
Mass *m_ptr = ecs_field(it, Mass, 1);
bool shared = !ecs_field_is_self(it, 1);
Position *p = ecs_field(it, Position, 2);
Velocity *v = NULL;
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 Prefab_new_w_prefab(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {10, 20});
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(e1 != 0);
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has_pair(world, e1, EcsIsA, Prefab));
/* These components should never be inherited from prefabs */
test_assert( !ecs_has_id(world, e1, EcsPrefab));
test_assert( !ecs_has_id(world, e1, NamePair));
test_assert( !ecs_get_id(world, e1, NamePair));
ecs_add(world, e1, Velocity);
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has(world, e1, Velocity));
test_assert( ecs_has_pair(world, e1, EcsIsA, Prefab));
test_assert( !ecs_has_id(world, e1, EcsPrefab));
test_assert( !ecs_has_id(world, e1, NamePair));
test_assert( !ecs_get_id(world, e1, NamePair));
ecs_entity_t e2 = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert( ecs_has(world, e2, Position));
test_assert( ecs_has_pair(world, e2, EcsIsA, Prefab));
test_assert( !ecs_has_id(world, e2, EcsPrefab));
test_assert( !ecs_has_id(world, e2, NamePair));
test_assert( !ecs_get_id(world, e2, NamePair));
ecs_add(world, e2, Velocity);
test_assert( ecs_has(world, e2, Position));
test_assert( ecs_has(world, e2, Velocity));
test_assert( ecs_has_pair(world, e2, EcsIsA, Prefab));
test_assert( !ecs_has_id(world, e2, EcsPrefab));
test_assert( !ecs_has_id(world, e2, NamePair));
test_assert( !ecs_get_id(world, e2, NamePair));
const Position *p_1 = ecs_get(world, e1, Position);
const Position *p_2 = ecs_get(world, e2, Position);
test_assert(p_1 != NULL);
test_assert(p_2 != NULL);
test_assert(p_1 == p_2);
test_int(p_1->x, 10);
test_int(p_1->y, 20);
const Velocity *v_1 = ecs_get(world, e1, Velocity);
const Velocity *v_2 = ecs_get(world, e2, Velocity);
test_assert(v_1 != NULL);
test_assert(v_2 != NULL);
test_assert(v_1 != v_2);
ecs_fini(world);
}
void Prefab_new_w_count_prefab(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {10, 20});
const ecs_entity_t *ids = ecs_bulk_new_w_id(world, ecs_pair(EcsIsA, Prefab), 10);
test_assert(ids != NULL);
ecs_entity_t i;
const Position *p_prev = NULL;
for (i = 0; i < 10; i ++) {
ecs_entity_t e = ids[i];
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
if (p_prev) test_ptr(p, p_prev);
test_int(p->x, 10);
test_int(p->y, 20);
p_prev = p;
}
ecs_fini(world);
}
void Prefab_new_w_type_w_prefab(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Position, OVERRIDE | Velocity);
ecs_set(world, Prefab, Position, {10, 20});
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(e1 != 0);
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has_pair(world, e1, EcsIsA, Prefab));
/* These components should never be inherited from prefabs */
test_assert( !ecs_has_id(world, e1, EcsPrefab));
test_assert( !ecs_has_id(world, e1, NamePair));
ecs_entity_t e2 = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert( ecs_has(world, e2, Position));
test_assert( ecs_has_pair(world, e2, EcsIsA, Prefab));
test_assert( !ecs_has_id(world, e2, EcsPrefab));
test_assert( !ecs_has_id(world, e2, NamePair));
const Position *p_1 = ecs_get(world, e1, Position);
const Position *p_2 = ecs_get(world, e2, Position);
const Position *p_prefab = ecs_get(world, Prefab, Position);
test_assert(p_1 != NULL);
test_assert(p_2 != NULL);
test_assert(p_1 == p_2);
test_assert(p_1 == p_prefab);
test_int(p_1->x, 10);
test_int(p_1->y, 20);
const Velocity *v_1 = ecs_get(world, e1, Velocity);
const Velocity *v_2 = ecs_get(world, e2, Velocity);
test_assert(v_1 != NULL);
test_assert(v_2 != NULL);
test_assert(v_1 != v_2);
ecs_fini(world);
}
void Prefab_add_prefab(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {10, 20});
ecs_entity_t e1 = ecs_new(world, Velocity);
test_assert(e1 != 0);
ecs_add_pair(world, e1, EcsIsA, Prefab);
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has_pair(world, e1, EcsIsA, Prefab));
/* These components should never be inherited from prefabs */
test_assert( !ecs_has_id(world, e1, EcsPrefab));
test_assert( !ecs_has_id(world, e1, NamePair));
ecs_entity_t e2 = ecs_new(world, Velocity);
test_assert(e2 != 0);
ecs_add_pair(world, e2, EcsIsA, Prefab);
test_assert( ecs_has(world, e2, Position));
test_assert( ecs_has_pair(world, e2, EcsIsA, Prefab));
test_assert( !ecs_has_id(world, e2, EcsPrefab));
test_assert( !ecs_has_id(world, e2, NamePair));
const Position *p_1 = ecs_get(world, e1, Position);
const Position *p_2 = ecs_get(world, e2, Position);
const Position *p_prefab = ecs_get(world, Prefab, Position);
test_assert(p_1 != NULL);
test_assert(p_2 != NULL);
test_assert(p_1 == p_2);
test_assert(p_prefab == p_1);
test_int(p_1->x, 10);
test_int(p_1->y, 20);
const Velocity *v_1 = ecs_get(world, e1, Velocity);
const Velocity *v_2 = ecs_get(world, e2, Velocity);
test_assert(v_1 != NULL);
test_assert(v_2 != NULL);
test_assert(v_1 != v_2);
ecs_fini(world);
}
void Prefab_remove_prefab_after_new(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {10, 20});
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(e1 != 0);
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has_pair(world, e1, EcsIsA, Prefab));
/* These components should never be inherited from prefabs */
test_assert( !ecs_has_id(world, e1, EcsPrefab));
test_assert( !ecs_has_id(world, e1, NamePair));
test_assert( !ecs_get_id(world, e1, NamePair));
ecs_remove_pair(world, e1, EcsIsA, Prefab);
test_assert( !ecs_has(world, e1, Position));
test_assert( !ecs_has_pair(world, e1, EcsIsA, Prefab));
/* These components should never be inherited from prefabs */
test_assert( !ecs_has_id(world, e1, EcsPrefab));
test_assert( !ecs_has_id(world, e1, NamePair));
test_assert( !ecs_get_id(world, e1, NamePair));
ecs_fini(world);
}
void Prefab_remove_prefab_after_add(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {10, 20});
ecs_entity_t e1 = ecs_new(world, 0);
test_assert(e1 != 0);
ecs_add_pair(world, e1, EcsIsA, Prefab);
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has_pair(world, e1, EcsIsA, Prefab));
/* These components should never be inherited from prefabs */
test_assert( !ecs_has_id(world, e1, EcsPrefab));
test_assert( !ecs_has_id(world, e1, NamePair));
test_assert( !ecs_get_id(world, e1, NamePair));
ecs_remove_pair(world, e1, EcsIsA, Prefab);
test_assert( !ecs_has(world, e1, Position));
test_assert( !ecs_has_pair(world, e1, EcsIsA, Prefab));
/* These components should never be inherited from prefabs */
test_assert( !ecs_has_id(world, e1, EcsPrefab));
test_assert( !ecs_has_id(world, e1, NamePair));
test_assert( !ecs_get_id(world, e1, NamePair));
ecs_fini(world);
}
void Prefab_override_component(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {10, 20});
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(e1 != 0);
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has_pair(world, e1, EcsIsA, Prefab));
/* These components should never be inherited from prefabs */
test_assert( !ecs_has_id(world, e1, EcsPrefab));
test_assert( !ecs_has_id(world, e1, NamePair));
test_assert( !ecs_get_id(world, e1, NamePair));
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_set(world, e1, Position, {20, 30});
p = ecs_get(world, e1, Position);
test_int(p->x, 20);
test_int(p->y, 30);
const Position *p_prefab = ecs_get(world, Prefab, Position);
test_assert(p != p_prefab);
test_int(p_prefab->x, 10);
test_int(p_prefab->y, 20);
ecs_fini(world);
}
void Prefab_override_remove_component(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {10, 20});
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(e1 != 0);
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has_pair(world, e1, EcsIsA, Prefab));
/* These components should never be inherited from prefabs */
test_assert( !ecs_has_id(world, e1, EcsPrefab));
test_assert( !ecs_has_id(world, e1, NamePair));
test_assert( !ecs_get_id(world, e1, NamePair));
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_set(world, e1, Position, {20, 30});
p = ecs_get(world, e1, Position);
test_int(p->x, 20);
test_int(p->y, 30);
const Position *p_prefab = ecs_get(world, Prefab, Position);
test_assert(p_prefab != NULL);
test_assert(p != p_prefab);
test_int(p_prefab->x, 10);
test_int(p_prefab->y, 20);
ecs_remove(world, e1, Position);
p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_assert(p == p_prefab);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_fini(world);
}
void Prefab_override_2_of_3_components_1_self(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_COMPONENT(world, Rotation);
ECS_PREFAB(world, Prefab, Position, Velocity, Mass);
ecs_set(world, Prefab, Position, {10, 20});
ecs_set(world, Prefab, Velocity, {30, 40});
ecs_set(world, Prefab, Mass, {50});
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(e1 != 0);
ecs_set(world, e1, Rotation, {60});
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has(world, e1, Velocity));
test_assert( ecs_has(world, e1, Mass));
test_assert( ecs_has(world, e1, Rotation));
test_assert( ecs_has_pair(world, e1, EcsIsA, Prefab));
/* These components should never be inherited from prefabs */
test_assert( !ecs_has_id(world, e1, EcsPrefab));
test_assert( !ecs_has_id(world, e1, NamePair));
test_assert( !ecs_get_id(world, e1, NamePair));
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
ecs_set(world, e1, Position, {20, 30});
p = ecs_get(world, e1, Position);
test_int(p->x, 20);
test_int(p->y, 30);
const Position *p_prefab = ecs_get(world, Prefab, Position);
test_assert(p != p_prefab);
test_int(p_prefab->x, 10);
test_int(p_prefab->y, 20);
const Velocity *v = ecs_get(world, e1, Velocity);
test_assert(v != NULL);
test_int(v->x, 30);
test_int(v->y, 40);
ecs_set(world, e1, Velocity, {40, 50});
v = ecs_get(world, e1, Velocity);
test_int(v->x, 40);
test_int(v->y, 50);
const Velocity *v_prefab = ecs_get(world, Prefab, Velocity);
test_assert(v != v_prefab);
test_int(v_prefab->x, 30);
test_int(v_prefab->y, 40);
const Mass *m = ecs_get(world, e1, Mass);
test_assert(m != NULL);
test_int(*m, 50);
const Mass *m_prefab = ecs_get(world, Prefab, Mass);
test_assert(m_prefab != NULL);
test_ptr(m_prefab, m);
const Rotation *r = ecs_get(world, e1, Rotation);
test_assert(r != NULL);
test_int(*r, 60);
ecs_fini(world);
}
void Prefab_new_type_w_1_override(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Position, Velocity, OVERRIDE | Position);
ecs_set(world, Prefab, Position, {10, 20});
ecs_set(world, Prefab, Velocity, {30, 40});
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(e1 != 0);
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has(world, e1, Velocity));
test_assert( ecs_has_pair(world, e1, EcsIsA, Prefab));
/* These components should never be inherited from prefabs */
test_assert( !ecs_has_id(world, e1, EcsPrefab));
test_assert( !ecs_has_id(world, e1, NamePair));
test_assert( !ecs_get_id(world, e1, NamePair));
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
const Position *p_prefab = ecs_get(world, Prefab, Position);
test_assert(p_prefab != NULL);
test_assert(p != p_prefab);
test_int(p_prefab->x, 10);
test_int(p_prefab->y, 20);
const Velocity *v = ecs_get(world, e1, Velocity);
test_assert(v != NULL);
test_int(v->x, 30);
test_int(v->y, 40);
const Velocity *v_prefab = ecs_get(world, Prefab, Velocity);
test_assert(v_prefab != NULL);
test_assert(v == v_prefab);
test_int(v_prefab->x, 30);
test_int(v_prefab->y, 40);
ecs_fini(world);
}
void Prefab_new_type_w_2_overrides(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Position, Velocity, OVERRIDE | Position, OVERRIDE | Velocity);
ecs_set(world, Prefab, Position, {10, 20});
ecs_set(world, Prefab, Velocity, {30, 40});
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(e1 != 0);
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has(world, e1, Velocity));
test_assert( ecs_has_pair(world, e1, EcsIsA, Prefab));
/* These components should never be inherited from prefabs */
test_assert( !ecs_has_id(world, e1, EcsPrefab));
test_assert( !ecs_has_id(world, e1, NamePair));
test_assert( !ecs_get_id(world, e1, NamePair));
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
const Position *p_prefab = ecs_get(world, Prefab, Position);
test_assert(p_prefab != NULL);
test_assert(p != p_prefab);
test_int(p_prefab->x, 10);
test_int(p_prefab->y, 20);
const Velocity *v = ecs_get(world, e1, Velocity);
test_assert(v != NULL);
test_int(v->x, 30);
test_int(v->y, 40);
const Velocity *v_prefab = ecs_get(world, Prefab, Velocity);
test_assert(v_prefab != NULL);
test_assert(v != v_prefab);
test_int(v_prefab->x, 30);
test_int(v_prefab->y, 40);
ecs_fini(world);
}
void Prefab_get_ptr_prefab(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {10, 20});
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(e1 != 0);
test_assert( ecs_has_pair(world, e1, EcsIsA, Prefab));
test_assert( ecs_get_id(world, e1, Prefab) == NULL);
ecs_fini(world);
}
static
void Prefab_w_shared(ecs_iter_t *it) {
Velocity *v = NULL;
if (it->field_count >= 2) {
v = ecs_field(it, Velocity, 2);
if (v) {
test_assert(!ecs_field_is_self(it, 2));
}
}
Mass *m = NULL;
if (it->field_count >= 3) {
m = ecs_field(it, Mass, 3);
}
probe_iter(it);
Position *pos = ecs_field(it, Position, 1);
for (int i = 0; i < it->count; i ++) {
Position *p = &pos[i];
p->x += v->x;
p->y += v->y;
if (m) {
p->x += *m;
p->y += *m;
}
}
}
void Prefab_iterate_w_prefab_shared(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Velocity);
ECS_SYSTEM(world, Prefab_w_shared, EcsOnUpdate, Position, Velocity(up|self));
ecs_set(world, Prefab, Velocity, {1, 2});
ECS_ENTITY(world, e1, (IsA, Prefab), Position);
test_assert(e1 != 0);
ecs_set(world, e1, Position, {0, 0});
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, Prefab_w_shared);
test_int(ctx.term_count, 2);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], Prefab);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 1);
test_int(p->y, 2);
ecs_fini(world);
}
void Prefab_match_entity_prefab_w_system_optional(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_PREFAB(world, Prefab, Velocity, Mass);
ECS_SYSTEM(world, Prefab_w_shared, EcsOnUpdate,
Position,
Velocity(self|up),
?Mass(self|up));
ecs_set(world, Prefab, Velocity, {1, 2});
ecs_set(world, Prefab, Mass, {3});
ECS_ENTITY(world, e1, (IsA, Prefab), Position);
test_assert(e1 != 0);
ecs_set(world, e1, Position, {0, 0});
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, Prefab_w_shared);
test_int(ctx.term_count, 3);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], Prefab);
test_int(ctx.c[0][2], ecs_id(Mass));
test_int(ctx.s[0][2], Prefab);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 4);
test_int(p->y, 5);
ecs_fini(world);
}
void Prefab_prefab_in_system_expr(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_PREFAB(world, Prefab1, Velocity);
ECS_PREFAB(world, Prefab2, Velocity);
ECS_SYSTEM(world, Prefab_w_shared, EcsOnUpdate, Position, Velocity(self|up), Mass, (IsA, Prefab1));
ecs_system_init(world, &(ecs_system_desc_t){
.entity = Prefab_w_shared,
.query.filter.instanced = true
});
ecs_set(world, Prefab1, Velocity, {1, 2});
ecs_set(world, Prefab2, Velocity, {1, 2});
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, Prefab1);
ecs_entity_t e2 = ecs_new_w_pair(world, EcsIsA, Prefab1);
ecs_entity_t e3 = ecs_new_w_pair(world, EcsIsA, Prefab2);
test_assert(e1 != 0);
test_assert(e2 != 0);
test_assert(e3 != 0);
ecs_set(world, e1, Position, {0, 0});
ecs_set(world, e2, Position, {0, 0});
ecs_set(world, e3, Position, {0, 0});
ecs_set(world, e1, Mass, {0});
ecs_set(world, e2, Mass, {0});
ecs_set(world, e3, Mass, {0});
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, Prefab_w_shared);
test_int(ctx.term_count, 4);
test_null(ctx.param);
test_int(ctx.e[0], e1);
test_int(ctx.e[1], e2);
test_int(ctx.c[0][0], ecs_id(Position));
test_int(ctx.s[0][0], 0);
test_int(ctx.c[0][1], ecs_id(Velocity));
test_int(ctx.s[0][1], Prefab1);
test_int(ctx.c[0][2], ecs_id(Mass));
test_int(ctx.s[0][2], 0);
test_int(ctx.c[0][3], ecs_pair(EcsIsA, Prefab1));
test_int(ctx.s[0][3], 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, 1);
test_int(p->y, 2);
ecs_fini(world);
}
static
void Dummy(ecs_iter_t *it) {
probe_iter(it);
}
void Prefab_dont_match_prefab(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, Prefab, Position);
ECS_SYSTEM(world, Dummy, EcsOnUpdate, Position);
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 0);
test_int(ctx.invoked, 0);
ecs_fini(world);
}
void Prefab_new_w_count_w_override(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Position, Velocity, OVERRIDE | Velocity);
ecs_set(world, Prefab, Position, {10, 20});
ecs_set(world, Prefab, Velocity, {30, 40});
const ecs_entity_t *ids = ecs_bulk_new_w_id(
world, ecs_pair(EcsIsA, Prefab), 100);
test_assert(ids != NULL);
const Position *prefab_p = ecs_get(world, Prefab, Position);
const Velocity *prefab_v = ecs_get(world, Prefab, Velocity);
int i;
for (i = 0; i < 100; i ++) {
ecs_entity_t e = ids[i];
test_assert( ecs_has(world, e, Position));
test_assert( ecs_has(world, e, Velocity));
test_assert( ecs_has_pair(world, e, EcsIsA, Prefab));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_assert(p == prefab_p);
test_int(p->x, 10);
test_int(p->y, 20);
const Velocity *v = ecs_get(world, e, Velocity);
test_assert(v != NULL);
test_assert(v != prefab_v);
test_int(v->x, 30);
test_int(v->y, 40);
}
ecs_fini(world);
}
void Prefab_override_2_components_different_size(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Color);
ECS_PREFAB(world, Prefab, Position, Velocity, Color, OVERRIDE | Velocity, OVERRIDE | Color);
ecs_set(world, Prefab, Position, {10, 20});
ecs_set(world, Prefab, Velocity, {30, 40});
ecs_set(world, Prefab, Color, {1, 2, 3, 4});
const ecs_entity_t *ids = ecs_bulk_new_w_id(world, ecs_pair(EcsIsA, Prefab), 100);
test_assert(ids != NULL);
const Position *prefab_p = ecs_get(world, Prefab, Position);
const Velocity *prefab_v = ecs_get(world, Prefab, Velocity);
const Color *prefab_c = ecs_get(world, Prefab, Color);
test_assert(prefab_p != NULL);
test_assert(prefab_v != NULL);
test_assert(prefab_c != NULL);
int i;
for (i = 0; i < 100; i ++) {
ecs_entity_t e = ids[i];
test_assert( ecs_has(world, e, Position));
test_assert( ecs_has(world, e, Velocity));
test_assert( ecs_has_pair(world, e, EcsIsA, Prefab));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
test_assert(p == prefab_p);
const Velocity *v = ecs_get(world, e, Velocity);
test_assert(v != NULL);
test_int(v->x, 30);
test_int(v->y, 40);
test_assert(v != prefab_v);
const Color *c = ecs_get(world, e, Color);
test_assert(c != NULL);
test_int(c->r, 1);
test_int(c->g, 2);
test_int(c->b, 3);
test_int(c->a, 4);
test_assert(c != prefab_c);
}
ecs_fini(world);
}
void Prefab_ignore_prefab_parent_component(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, parent, Prefab, Position);
ECS_ENTITY(world, child, Prefab, (ChildOf, parent), Velocity);
test_assert( ecs_has_pair(world, child, EcsChildOf, parent));
test_assert( !ecs_has(world, child, Position));
test_assert( ecs_has(world, child, Velocity));
ecs_fini(world);
}
static
void Move(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
Velocity *v = ecs_field(it, Velocity, 2);
int i;
for (i = 0; i < it->count; i ++) {
p[i].x += v[i].y;
p[i].y += v[i].y;
}
}
static
void AddVelocity(ecs_iter_t *it) {
ecs_id_t ecs_id(Velocity) = ecs_field_id(it, 2);
int i;
for (i = 0; i < it->count; i ++) {
ecs_set(it->world, it->entities[i], Velocity, {1, 1});
}
}
void Prefab_match_table_created_in_progress(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_PREFAB(world, Prefab, Mass);
ecs_set(world, Prefab, Mass, {10});
ECS_ENTITY(world, e, (IsA, Prefab), Position);
ECS_SYSTEM(world, AddVelocity, EcsOnUpdate, Position, [out] !Velocity);
ECS_SYSTEM(world, Move, EcsOnUpdate, Position, Velocity, Mass(self|up));
ecs_set(world, e, Position, {0, 0});
test_assert( ecs_has(world, e, Position));
test_assert( !ecs_has(world, e, Velocity));
test_assert( ecs_has(world, e, Mass));
ecs_progress(world, 1);
test_assert( ecs_has(world, e, Velocity));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 1);
test_int(p->y, 1);
ecs_progress(world, 1);
p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 2);
test_int(p->y, 2);
ecs_fini(world);
}
void Prefab_prefab_w_1_child(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, Parent, Position);
ecs_set(world, Parent, Position, {1, 2});
ECS_PREFAB(world, Child, (ChildOf, Parent), Position);
ecs_set(world, Child, Position, {2, 3});
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Parent);
test_assert(e != 0);
test_assert( ecs_has(world, e, Position));
const Position *p_e = ecs_get(world, e, Position);
test_assert(p_e != NULL);
test_int(p_e->x, 1);
test_int(p_e->y, 2);
ecs_entity_t e_child = ecs_lookup_child(world, e, "Child");
test_assert(e_child != 0);
test_assert(ecs_has(world, e_child, Position));
test_assert(ecs_has_pair(world, e_child, EcsChildOf, e));
const Position *p_child = ecs_get(world, e_child, Position);
test_assert(p_child != NULL);
test_int(p_child->x, 2);
test_int(p_child->y, 3);
ecs_entity_t e2 = ecs_new_w_pair(world, EcsIsA, Parent);
test_assert(e2 != 0);
test_assert( ecs_has(world, e, Position));
test_assert( ecs_get(world, e2, Position) == p_e);
ecs_entity_t e_child2 = ecs_lookup_child(world, e2, "Child");
test_assert(e_child2 != 0);
test_assert(ecs_has(world, e_child2, Position));
test_assert(ecs_has_pair(world, e_child2, EcsChildOf, e2));
test_assert( ecs_get(world, e_child2, Position) != p_child);
p_child = ecs_get(world, e_child2, Position);
test_assert(p_child != NULL);
test_int(p_child->x, 2);
test_int(p_child->y, 3);
ecs_fini(world);
}
void Prefab_prefab_w_2_children(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_ENTITY(world, Parent, Prefab, Position);
ecs_set(world, Parent, Position, {1, 2});
ECS_ENTITY(world, Child1, Prefab, (ChildOf, Parent), Position);
ecs_set(world, Child1, Position, {2, 3});
ECS_ENTITY(world, Child2, Prefab, (ChildOf, Parent), Position);
ecs_set(world, Child2, Position, {3, 4});
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Parent);
test_assert(e != 0);
test_assert( ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 1);
test_int(p->y, 2);
ecs_entity_t e_child = ecs_lookup_child(world, e, "Child1");
test_assert(e_child != 0);
test_assert(ecs_has(world, e_child, Position));
test_assert(ecs_has_pair(world, e_child, EcsChildOf, e));
p = ecs_get(world, e_child, Position);
test_assert(p != NULL);
test_int(p->x, 2);
test_int(p->y, 3);
e_child = ecs_lookup_child(world, e, "Child2");
test_assert(e_child != 0);
test_assert(ecs_has(world, e_child, Position));
test_assert(ecs_has_pair(world, e_child, EcsChildOf, e));
p = ecs_get(world, e_child, Position);
test_assert(p != NULL);
test_int(p->x, 3);
test_int(p->y, 4);
ecs_fini(world);
}
void Prefab_prefab_w_grandchild(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Rotation);
ECS_ENTITY(world, Parent, Prefab, Position);
ecs_set(world, Parent, Position, {1, 2});
ECS_ENTITY(world, Child, Prefab, (ChildOf, Parent), Position);
ecs_set(world, Child, Position, {2, 3});
ECS_ENTITY(world, GrandChild, Prefab, (ChildOf, Parent.Child), Position, Rotation);
ecs_set(world, GrandChild, Position, {3, 4});
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Parent);
test_assert(e != 0);
test_assert( ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 1);
test_int(p->y, 2);
ecs_entity_t e_child = ecs_lookup_child(world, e, "Child");
test_assert(e_child != 0);
test_assert(ecs_has(world, e_child, Position));
test_assert(ecs_has_pair(world, e_child, EcsChildOf, e));
p = ecs_get(world, e_child, Position);
test_assert(p != NULL);
test_int(p->x, 2);
test_int(p->y, 3);
ecs_entity_t e_grandchild = ecs_lookup_child(world, e_child, "GrandChild");
test_assert(e_grandchild != 0);
test_assert(ecs_has(world, e_grandchild, Position));
test_assert(ecs_has_pair(world, e_grandchild, EcsChildOf, e_child));
p = ecs_get(world, e_grandchild, Position);
test_assert(p != NULL);
test_int(p->x, 3);
test_int(p->y, 4);
ecs_fini(world);
}
void Prefab_prefab_tree_1_2_1(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Rotation);
ECS_ENTITY(world, parent, Prefab, Position);
ecs_set(world, parent, Position, {1, 2});
ECS_ENTITY(world, child_1, Prefab, (ChildOf, parent), Position);
ecs_set(world, child_1, Position, {2, 3});
ECS_ENTITY(world, child_2, Prefab, (ChildOf, parent), Position);
ecs_set(world, child_2, Position, {4, 5});
ECS_ENTITY(world, grandchild, Prefab, (ChildOf, parent.child_2), Position);
ecs_set(world, grandchild, Position, {6, 7});
test_assert(ecs_has_pair(world, child_1, EcsChildOf, parent));
test_assert(ecs_has_pair(world, child_2, EcsChildOf, parent));
test_assert(ecs_has_pair(world, grandchild, EcsChildOf, child_2));
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, parent);
test_assert(e != 0);
test_assert( ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 1);
test_int(p->y, 2);
ecs_entity_t e_child = ecs_lookup_child(world, e, "child_1");
test_assert(e_child != 0);
test_assert(ecs_has(world, e_child, Position));
test_assert(ecs_has_pair(world, e_child, EcsChildOf, e));
p = ecs_get(world, e_child, Position);
test_assert(p != NULL);
test_int(p->x, 2);
test_int(p->y, 3);
e_child = ecs_lookup_child(world, e, "child_2");
test_assert(e_child != 0);
test_assert(ecs_has(world, e_child, Position));
test_assert(ecs_has_pair(world, e_child, EcsChildOf, e));
p = ecs_get(world, e_child, Position);
test_assert(p != NULL);
test_int(p->x, 4);
test_int(p->y, 5);
ecs_entity_t e_grandchild = ecs_lookup_child(world, e_child, "grandchild");
test_assert(e_grandchild != 0);
test_assert(ecs_has(world, e_grandchild, Position));
test_assert(ecs_has_pair(world, e_grandchild, EcsChildOf, e_child));
p = ecs_get(world, e_grandchild, Position);
test_assert(p != NULL);
test_int(p->x, 6);
test_int(p->y, 7);
ecs_fini(world);
}
void Prefab_prefab_w_base_w_child(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, Base, Prefab, Velocity);
ecs_set(world, Base, Velocity, {3, 4});
ECS_ENTITY(world, Parent, Prefab, (IsA, Base), Position);
ecs_set(world, Parent, Position, {1, 2});
ECS_ENTITY(world, Child, Prefab, (ChildOf, Parent), Position);
ecs_set(world, Child, Position, {2, 3});
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Parent);
test_assert(e != 0);
test_assert( ecs_has(world, e, Position));
test_assert( ecs_has(world, e, Velocity));
const Position *p_e = ecs_get(world, e, Position);
test_assert(p_e != NULL);
test_int(p_e->x, 1);
test_int(p_e->y, 2);
const Velocity *v_e = ecs_get(world, e, Velocity);
test_assert(v_e != NULL);
test_int(v_e->x, 3);
test_int(v_e->y, 4);
ecs_entity_t e_child = ecs_lookup_child(world, e, "Child");
test_assert(e_child != 0);
test_assert(ecs_has(world, e_child, Position));
test_assert(!ecs_has(world, e_child, Velocity));
test_assert(ecs_has_pair(world, e_child, EcsChildOf, e));
const Position *p_child = ecs_get(world, e_child, Position);
test_assert(p_child != NULL);
test_int(p_child->x, 2);
test_int(p_child->y, 3);
ecs_fini(world);
}
void Prefab_prefab_w_child_w_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, Base, Prefab, Velocity);
ecs_set(world, Base, Velocity, {3, 4});
ECS_ENTITY(world, Parent, Prefab, Position);
ecs_set(world, Parent, Position, {1, 2});
ECS_ENTITY(world, Child, Prefab, (ChildOf, Parent), (IsA, Base), Position);
ecs_set(world, Child, Position, {2, 3});
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Parent);
test_assert(e != 0);
test_assert( ecs_has(world, e, Position));
const Position *p_e = ecs_get(world, e, Position);
test_assert(p_e != NULL);
test_int(p_e->x, 1);
test_int(p_e->y, 2);
ecs_entity_t e_child = ecs_lookup_child(world, e, "Child");
test_assert(e_child != 0);
test_assert(ecs_has(world, e_child, Position));
test_assert(ecs_has(world, e_child, Velocity));
test_assert(ecs_has_pair(world, e_child, EcsChildOf, e));
const Position *p_child = ecs_get(world, e_child, Position);
test_assert(p_child != NULL);
test_int(p_child->x, 2);
test_int(p_child->y, 3);
const Velocity *v_child = ecs_get(world, e_child, Velocity);
test_assert(v_child != NULL);
test_int(v_child->x, 3);
test_int(v_child->y, 4);
ecs_fini(world);
}
void Prefab_prefab_w_child_w_base_w_children(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, Base, Prefab, Velocity);
ecs_set(world, Base, Velocity, {3, 4});
ECS_ENTITY(world, BaseChild, Prefab, (ChildOf, Base), Position);
ecs_set(world, BaseChild, Position, {4, 5});
ECS_ENTITY(world, Parent, Prefab, Position);
ecs_set(world, Parent, Position, {1, 2});
ECS_ENTITY(world, Child, Prefab, (ChildOf, Parent), (IsA, Base), Position);
ecs_set(world, Child, Position, {2, 3});
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Parent);
test_assert(e != 0);
test_assert( ecs_has(world, e, Position));
const Position *p_e = ecs_get(world, e, Position);
test_assert(p_e != NULL);
test_int(p_e->x, 1);
test_int(p_e->y, 2);
ecs_entity_t e_child = ecs_lookup_child(world, e, "Child");
test_assert(e_child != 0);
test_assert(ecs_has(world, e_child, Position));
test_assert(ecs_has(world, e_child, Velocity));
test_assert(ecs_has_pair(world, e_child, EcsChildOf, e));
const Position *p_child = ecs_get(world, e_child, Position);
test_assert(p_child != NULL);
test_int(p_child->x, 2);
test_int(p_child->y, 3);
const Velocity *v_child = ecs_get(world, e_child, Velocity);
test_assert(v_child != NULL);
test_int(v_child->x, 3);
test_int(v_child->y, 4);
ecs_entity_t e_base_child = ecs_lookup_child(world, e_child, "BaseChild");
test_assert(e_base_child != 0);
test_assert(ecs_has(world, e_base_child, Position));
test_assert(!ecs_has(world, e_base_child, Velocity));
test_assert(ecs_has_pair(world, e_base_child, EcsChildOf, e_child));
const Position *p_base_child = ecs_get(world, e_base_child, Position);
test_assert(p_base_child != NULL);
test_assert(p_base_child != p_child);
test_int(p_base_child->x, 4);
test_int(p_base_child->y, 5);
ecs_fini(world);
}
void Prefab_prefab_w_child_new_w_count(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_ENTITY(world, Parent, Prefab, Position);
ecs_set(world, Parent, Position, {1, 2});
ECS_ENTITY(world, Child, Prefab, (ChildOf, Parent), Position);
ecs_set(world, Child, Position, {2, 3});
const ecs_entity_t *ids = ecs_bulk_new_w_id(world, ecs_pair(EcsIsA, Parent), 3);
test_assert(ids != NULL);
int i;
for (i = 0; i < 3; i ++) {
ecs_entity_t e = ids[i];
test_assert( ecs_has(world, e, Position));
const Position *p_e = ecs_get(world, e, Position);
test_assert(p_e != NULL);
test_int(p_e->x, 1);
test_int(p_e->y, 2);
ecs_entity_t e_child = ecs_lookup_child(world, e, "Child");
test_assert(e_child != 0);
test_assert(ecs_has(world, e_child, Position));
test_assert(ecs_has_pair(world, e_child, EcsChildOf, e));
const Position *p_child = ecs_get(world, e_child, Position);
test_assert(p_child != NULL);
test_int(p_child->x, 2);
test_int(p_child->y, 3);
}
ecs_fini(world);
}
void Prefab_prefab_auto_override_child_component(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_ENTITY(world, Parent, Prefab, Position);
ecs_set(world, Parent, Position, {1, 2});
ECS_ENTITY(world, ChildPrefab, Prefab, Position, Velocity);
ecs_set(world, ChildPrefab, Position, {2, 3});
ecs_set(world, ChildPrefab, Velocity, {4, 5});
ECS_ENTITY(world, Child, Prefab, (ChildOf, Parent), (IsA, ChildPrefab), Velocity);
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, Parent);
test_assert(e1 != 0);
test_assert( ecs_has(world, e1, Position));
ecs_entity_t e2 = ecs_new_w_pair(world, EcsIsA, Parent);
test_assert(e2 != 0);
test_assert( ecs_has(world, e2, Position));
const Position *p1 = ecs_get(world, e1, Position);
test_assert(p1 != NULL);
test_int(p1->x, 1);
test_int(p1->y, 2);
const Position *p2 = ecs_get(world, e2, Position);
test_assert(p2 != NULL);
test_int(p2->x, 1);
test_int(p2->y, 2);
test_assert(p1 == p2);
ecs_entity_t child_1 = ecs_lookup_child(world, e1, "Child");
test_assert(child_1 != 0);
test_assert( ecs_has(world, child_1, Position));
test_assert( ecs_has(world, child_1, Velocity));
ecs_entity_t child_2 = ecs_lookup_child(world, e2, "Child");
test_assert(child_2 != 0);
test_assert( ecs_has(world, child_2, Position));
test_assert( ecs_has(world, child_2, Velocity));
const Position *child_p1 = ecs_get(world, child_1, Position);
test_assert(child_p1 != NULL);
test_int(child_p1->x, 2);
test_int(child_p1->y, 3);
const Position *child_p2 = ecs_get(world, child_2, Position);
test_assert(child_p2 != NULL);
test_int(child_p2->x, 2);
test_int(child_p2->y, 3);
test_assert(child_p1 == child_p2);
const Velocity *child_v1 = ecs_get(world, child_1, Velocity);
test_assert(child_v1 != NULL);
test_int(child_v1->x, 4);
test_int(child_v1->y, 5);
const Velocity *child_v2 = ecs_get(world, child_2, Velocity);
test_assert(child_v2 != NULL);
test_int(child_v2->x, 4);
test_int(child_v2->y, 5);
test_assert(child_v1 != child_v2);
ecs_fini(world);
}
static int invoked;
void PrefabReactiveTest(ecs_iter_t *it) {
invoked ++;
}
void Prefab_ignore_on_add(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, PrefabReactiveTest, EcsOnAdd, Position);
ECS_PREFAB(world, Prefab, Position);
test_int(invoked, 0);
ecs_fini(world);
}
void Prefab_ignore_on_remove(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, PrefabReactiveTest, EcsOnRemove, Position);
ECS_PREFAB(world, Prefab, Position);
test_int(invoked, 0);
ecs_remove(world, Prefab, Position);
test_int(invoked, 0);
ecs_fini(world);
}
void Prefab_ignore_on_set(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, PrefabReactiveTest, EcsOnSet, Position);
ECS_PREFAB(world, Prefab, Position);
test_int(invoked, 0);
ecs_set(world, Prefab, Position, {0, 0});
test_int(invoked, 0);
ecs_fini(world);
}
void Prefab_on_set_on_instance(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, PrefabReactiveTest, EcsOnSet, Position(self|up));
ECS_PREFAB(world, Prefab, Position);
test_int(invoked, 0);
ecs_set(world, Prefab, Position, {1, 2});
test_int(invoked, 0);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(e != 0);
test_assert( ecs_has(world, e, Position));
test_int(invoked, 1);
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 1);
test_int(p->y, 2);
ecs_fini(world);
}
void InstantiateInProgress(ecs_iter_t *it) {
ecs_id_t Prefab = ecs_field_id(it, 2);
ecs_entity_t *ids = ecs_get_ctx(it->world);
int i;
for (i = 0; i < it->count; i ++) {
ids[i] = ecs_new_w_pair(it->world, EcsIsA, Prefab);
}
}
void Prefab_instantiate_in_progress(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Velocity);
ecs_set(world, Prefab, Velocity, {1, 2});
ECS_SYSTEM(world, InstantiateInProgress, EcsOnUpdate, Position, Prefab());
const ecs_entity_t *dummy_ids = ecs_bulk_new(world, Position, 10);
test_assert(dummy_ids != NULL);
ecs_entity_t ids[10];
ecs_set_ctx(world, ids, NULL);
ecs_progress(world, 1);
test_int(ecs_count_id(world, ecs_pair(EcsIsA, Prefab)), 10);
const Velocity *v_prefab = ecs_get(world, Prefab, Velocity);
int i;
for (i = 0; i < 10; i ++) {
const Velocity *v = ecs_get(world, ids[i], Velocity);
test_assert(v == v_prefab);
}
ecs_fini(world);
}
void NewInProgress(ecs_iter_t *it) {
ecs_id_t Prefab = ecs_field_id(it, 2);
ecs_entity_t *ids = ecs_get_ctx(it->world);
int i;
for (i = 0; i < it->count; i ++) {
ids[i] = ecs_new_w_pair(it->world, EcsIsA, Prefab);
}
}
void Prefab_copy_from_prefab_in_progress(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Velocity, OVERRIDE | Velocity);
ecs_set(world, Prefab, Velocity, {1, 2});
ECS_SYSTEM(world, NewInProgress, EcsOnUpdate, Position, Prefab());
ecs_entity_t ids[10];
ecs_set_ctx(world, ids, NULL);
const ecs_entity_t *dummy_ids = ecs_bulk_new(world, Position, 10);
test_assert(dummy_ids != NULL);
/* Create one prefab instance so table is already created (case where table
* is not created is tested in copy_from_prefab_first_instance_in_progress*/
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(e != 0);
ecs_progress(world, 1);
test_int(ecs_count_id(world, ecs_pair(EcsIsA, Prefab)), 11);
int i;
for (i = 0; i < 10; i ++) {
const Velocity *v = ecs_get(world, ids[i], Velocity);
test_int(v->x, 1);
test_int(v->y, 2);
}
ecs_fini(world);
}
void Prefab_copy_from_prefab_first_instance_in_progress(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Velocity, OVERRIDE | Velocity);
ecs_set(world, Prefab, Velocity, {1, 2});
ECS_SYSTEM(world, NewInProgress, EcsOnUpdate, Position, Prefab());
ecs_entity_t ids[10];
ecs_set_ctx(world, ids, NULL);
const ecs_entity_t *dummy_ids = ecs_bulk_new(world, Position, 10);
test_assert(dummy_ids != NULL);
ecs_progress(world, 1);
test_int(ecs_count_id(world, ecs_pair(EcsIsA, Prefab)), 10);
int i;
for (i = 0; i < 10; i ++) {
const Velocity *v = ecs_get(world, ids[i], Velocity);
test_int(v->x, 1);
test_int(v->y, 2);
}
ecs_fini(world);
}
void Prefab_ref_after_realloc(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_PREFAB(world, Prefab, Mass);
ecs_set(world, Prefab, Mass, {2});
ECS_ENTITY(world, e1, Position, Mass);
ecs_set(world, e1, Mass, {3});
ECS_ENTITY(world, e2, Position, (IsA, Prefab));
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(self|up), Position);
/* Trigger a realloc of the table in which the prefab is stored. This should
* cause systems with refs to re-resolve their cached ref ptrs */
for (int i = 0; i < 1000; i ++) {
ecs_clone(world, 0, Prefab, false);
}
ecs_progress(world, 1);
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 30);
test_int(p->y, 60);
p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
ecs_fini(world);
}
void Prefab_revalidate_ref_w_mixed_table_refs(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_PREFAB(world, Prefab, Mass);
ecs_set(world, Prefab, Mass, {1});
ECS_ENTITY(world, e1, Position, (IsA, Prefab));
ECS_ENTITY(world, e2, Position, Mass);
ecs_set(world, e2, Mass, {3});
ECS_SYSTEM(world, Iter, EcsOnUpdate, Mass(self|up), Position);
/* Trigger a realloc of the table in which the prefab is stored. This should
* cause systems with refs to re-resolve their cached ref ptrs */
for (int i = 0; i < 1000; i ++) {
ecs_clone(world, 0, Prefab, false);
}
ecs_set(world, Prefab, Mass, {2});
ecs_progress(world, 1);
const Position *p = ecs_get(world, e2, Position);
test_assert(p != NULL);
test_int(p->x, 30);
test_int(p->y, 60);
p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 20);
test_int(p->y, 40);
ecs_fini(world);
}
void Prefab_no_overwrite_on_2nd_add(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_PREFAB(world, Prefab, Mass);
ecs_set(world, Prefab, Mass, {1});
ECS_ENTITY(world, e1, Position, (IsA, Prefab));
ecs_add(world, e1, Mass);
test_int( *ecs_get(world, e1, Mass), 1);
ecs_set(world, e1, Mass, {2});
test_int( *ecs_get(world, e1, Mass), 2);
ecs_add(world, e1, Mass);
test_int( *ecs_get(world, e1, Mass), 2);
ecs_fini(world);
}
void AddPrefab(ecs_iter_t *it) {
ecs_id_t Prefab = ecs_field_id(it, 2);
int i;
for (i = 0; i < it->count; i ++) {
ecs_add_pair(it->world, it->entities[i], EcsIsA, Prefab);
}
}
void Prefab_no_overwrite_on_2nd_add_in_progress(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_PREFAB(world, Prefab, Mass);
ecs_set(world, Prefab, Mass, {1});
ECS_SYSTEM(world, AddPrefab, EcsOnUpdate, Position, Prefab());
ECS_ENTITY(world, e1, Position, (IsA, Prefab));
ecs_add(world, e1, Mass);
test_int( *ecs_get(world, e1, Mass), 1);
ecs_set(world, e1, Mass, {2});
test_int( *ecs_get(world, e1, Mass), 2);
ecs_progress(world, 1);
test_int( *ecs_get(world, e1, Mass), 2);
ecs_fini(world);
}
void Prefab_no_instantiate_on_2nd_add(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {1, 2});
ECS_PREFAB(world, ChildPrefab, (ChildOf, Prefab), Velocity);
ecs_set(world, ChildPrefab, Velocity, {3, 4});
ECS_SYSTEM(world, AddPrefab, EcsOnUpdate, Position, Prefab());
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert( ecs_has_pair(world, e, EcsIsA, Prefab));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 1);
test_int(p->y, 2);
ecs_entity_t e_child = ecs_lookup_child(world, e, "ChildPrefab");
test_assert(e_child != 0);
const Velocity *v = ecs_get(world, e_child, Velocity);
test_assert(v != NULL);
test_int(v->x, 3);
test_int(v->y, 4);
ecs_set(world, e_child, Velocity, {4, 5});
v = ecs_get(world, e_child, Velocity);
test_assert(v != NULL);
test_int(v->x, 4);
test_int(v->y, 5);
ecs_add_pair(world, e, EcsIsA, Prefab);
ecs_entity_t e_child_2 = ecs_lookup_child(world, e, "ChildPrefab");
test_assert(e_child == e_child_2);
v = ecs_get(world, e_child, Velocity);
test_assert(v != NULL);
test_int(v->x, 4);
test_int(v->y, 5);
ecs_fini(world);
}
void Prefab_no_instantiate_on_2nd_add_in_progress(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {1, 2});
ECS_PREFAB(world, ChildPrefab, (ChildOf, Prefab), Velocity);
ecs_set(world, ChildPrefab, Velocity, {3, 4});
ECS_SYSTEM(world, AddPrefab, EcsOnUpdate, Position, Prefab());
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert( ecs_has_pair(world, e, EcsIsA, Prefab));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 1);
test_int(p->y, 2);
ecs_entity_t e_child = ecs_lookup_child(world, e, "ChildPrefab");
test_assert(e_child != 0);
const Velocity *v = ecs_get(world, e_child, Velocity);
test_assert(v != NULL);
test_int(v->x, 3);
test_int(v->y, 4);
ecs_set(world, e_child, Velocity, {4, 5});
v = ecs_get(world, e_child, Velocity);
test_assert(v != NULL);
test_int(v->x, 4);
test_int(v->y, 5);
ecs_progress(world, 1);
ecs_entity_t e_child_2 = ecs_lookup_child(world, e, "ChildPrefab");
test_assert(e_child == e_child_2);
v = ecs_get(world, e_child, Velocity);
test_assert(v != NULL);
test_int(v->x, 4);
test_int(v->y, 5);
ecs_fini(world);
}
void NewPrefab_w_count(ecs_iter_t *it) {
ecs_entity_t *ids = ecs_get_ctx(it->world);
ecs_id_t Prefab = ecs_field_id(it, 1);
const ecs_entity_t *new_ids = ecs_bulk_new_w_id(it->world, ecs_pair(EcsIsA, Prefab), 3);
test_assert(new_ids != NULL);
memcpy(ids, new_ids, sizeof(ecs_entity_t) * 3);
}
void Prefab_nested_prefab_in_progress_w_count(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {1, 2});
ECS_PREFAB(world, ChildPrefab, (ChildOf, Prefab), Velocity);
ecs_set(world, ChildPrefab, Velocity, {3, 4});
ECS_SYSTEM(world, NewPrefab_w_count, EcsOnUpdate, Prefab());
ecs_entity_t ids[3] = {0};
ecs_set_ctx(world, ids, NULL);
ecs_progress(world, 1);
int i;
for (i = 0; i < 3; i ++) {
ecs_has_pair(world, ids[i], EcsIsA, Prefab);
const Position *p = ecs_get(world, ids[i], Position);
test_assert(p != NULL);
test_int(p->x, 1);
test_int(p->y, 2);
ecs_entity_t child = ecs_lookup_child(world, ids[i], "ChildPrefab");
test_assert(child != 0);
const Velocity *v = ecs_get(world, child, Velocity);
test_assert(v != NULL);
test_int(v->x, 3);
test_int(v->y, 4);
}
ecs_fini(world);
}
static int on_set_velocity_invoked;
static
void OnSetVelocity(ecs_iter_t *it) {
Velocity *v = ecs_field(it, Velocity, 1);
ecs_id_t ecs_id(Velocity) = ecs_field_id(it, 1);
on_set_velocity_invoked ++;
int i;
for (i = 0; i < it->count; i ++) {
ecs_add(it->world, it->entities[i], Velocity);
if (ecs_field_is_self(it, 1)) {
v[i].x ++;
v[i].y ++;
}
}
}
void Prefab_nested_prefab_in_progress_w_count_set_after_override(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {1, 2});
ECS_PREFAB(world, ChildPrefab, (ChildOf, Prefab), Velocity);
ecs_set(world, ChildPrefab, Velocity, {3, 4});
ECS_SYSTEM(world, NewPrefab_w_count, EcsOnUpdate, Prefab());
ECS_OBSERVER(world, OnSetVelocity, EcsOnSet, Velocity);
test_int(on_set_velocity_invoked, 0);
ecs_entity_t ids[3] = {0};
ecs_set_ctx(world, ids, NULL);
ecs_progress(world, 1);
test_assert(ids != NULL);
test_int(on_set_velocity_invoked, 3);
int i;
for (i = 0; i < 3; i ++) {
ecs_has_pair(world, ids[i], EcsIsA, Prefab);
const Position *p = ecs_get(world, ids[i], Position);
test_assert(p != NULL);
test_int(p->x, 1);
test_int(p->y, 2);
ecs_entity_t child = ecs_lookup_child(world, ids[i], "ChildPrefab");
test_assert(child != 0);
const Velocity *v = ecs_get(world, child, Velocity);
test_assert(v != NULL);
test_int(v->x, 3 + 1);
test_int(v->y, 4 + 1);
}
ecs_fini(world);
}
void AddPrefabInProgress(ecs_iter_t *it) {
ecs_id_t Prefab = ecs_field_id(it, 2);
ecs_id_t ecs_id(Velocity) = ecs_field_id(it, 3);
int i;
for (i = 0; i < it->count; i ++) {
ecs_add_pair(it->world, it->entities[i], EcsIsA, Prefab);
test_assert( ecs_has_id(it->world, it->entities[i], Prefab));
test_assert( ecs_has(it->world, it->entities[i], Velocity));
const Velocity *v = ecs_get(it->world, it->entities[i], Velocity);
test_assert(v != NULL);
test_int(v->x, 1);
test_int(v->y, 2);
test_assert( ecs_get(it->world, Prefab, Velocity) == v);
}
}
void Prefab_get_ptr_from_prefab_from_new_table_in_progress(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Velocity);
ecs_set(world, Prefab, Velocity, {1, 2});
ECS_SYSTEM(world, AddPrefabInProgress, EcsOnUpdate, Position, Prefab(), Velocity());
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab);
ecs_progress(world, 1);
test_assert( ecs_has_pair(world, e, EcsIsA, Prefab));
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);
test_assert( ecs_get(world, Prefab, Velocity) == v);
ecs_fini(world);
}
void TestBase(ecs_iter_t *it) {
Position *p = ecs_field(it, Position, 1);
Velocity *v = ecs_field(it, Velocity, 2);
test_assert(!ecs_field_is_self(it, 2));
test_assert(p != NULL);
test_assert(v != NULL);
test_int(it->count, 1);
}
void Prefab_match_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Base, Velocity);
ecs_set(world, Base, Velocity, {1, 2});
ECS_PREFAB(world, Child, (IsA, Base));
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Child);
ecs_add(world, e, Position);
ECS_SYSTEM(world, TestBase, EcsOnUpdate, Position, Velocity(self|up));
ecs_progress(world, 1);
ecs_fini(world);
}
static
void AddMass(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_add(it->world, it->entities[i], Mass);
}
}
void Prefab_match_base_after_add_in_prev_phase(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_PREFAB(world, Base, Velocity);
ecs_set(world, Base, Velocity, {1, 2});
ECS_PREFAB(world, Child, (IsA, Base));
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Child);
ecs_add(world, e, Position);
ECS_SYSTEM(world, AddMass, EcsPreUpdate, Position, !Mass);
ECS_SYSTEM(world, TestBase, EcsOnUpdate, Position, Velocity(self|up));
ecs_progress(world, 1);
ecs_fini(world);
}
void Prefab_override_watched_prefab(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
/* Create a system that listens for Position */
ECS_SYSTEM(world, Dummy, EcsOnUpdate, Position(self|up));
/* Create a prefab with Position */
ECS_PREFAB(world, Prefab, Position);
/* Create an instance of Prefab, this will cause Prefab to be watched since
* it will be matched as reference with the system */
ECS_ENTITY(world, Entity1, (IsA, Prefab));
/* Another instance of Prefab is created, prefab data is resolved to check
* if components need to be overridden. Index will be negative, so code
* needs to flip sign on the index, or this will fail. */
ECS_ENTITY(world, Entity2, (IsA, Prefab), Position);
const Position *p1 = ecs_get(world, Prefab, Position);
const Position *p2 = ecs_get(world, Entity1, Position);
const Position *p3 = ecs_get(world, Entity2, Position);
test_assert(p1 == p2);
test_assert(p2 != p3);
ecs_fini(world);
}
void Prefab_rematch_twice(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_SYSTEM(world, Dummy, EcsOnUpdate, Position(self|up), Velocity(self|up), Mass(self|up));
ECS_PREFAB(world, Prefab, Position);
ECS_ENTITY(world, Entity, (IsA, Prefab));
Probe ctx = {0};
ecs_set_ctx(world, &ctx, NULL);
ecs_progress(world, 1);
test_int(ctx.count, 0);
ctx.count = 0;
ecs_add(world, Prefab, Velocity);
ecs_progress(world, 1);
test_int(ctx.count, 0);
ctx.count = 0;
ecs_add(world, Prefab, Mass);
ecs_progress(world, 1);
test_int(ctx.count, 1);
ecs_fini(world);
}
static
void AddPosition(ecs_iter_t *it) {
ecs_id_t ecs_id(Position) = ecs_field_id(it, 1);
ecs_entity_t *base = ecs_get_ctx(it->world);
ecs_add(it->world, *base, Position);
}
void Prefab_add_to_empty_base_in_system(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_new(world, 0);
ecs_entity_t e1 = ecs_new(world, Position);
ecs_add_pair(world, e1, EcsIsA, base);
ECS_SYSTEM(world, AddPosition, EcsOnUpdate, Position());
ecs_set_ctx(world, &base, NULL);
ecs_progress(world, 1);
test_assert( ecs_has(world, base, Position));
ecs_fini(world);
}
void Prefab_inherit_disabled(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_entity_t e1 = ecs_new(world, Position);
ecs_entity_t e2 = ecs_new(world, Velocity);
ecs_add_id(world, e2, EcsDisabled);
ecs_add_pair(world, e1, EcsIsA, e2);
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has(world, e1, Velocity));
test_assert( ecs_has_id(world, e1, EcsDisabled));
test_assert( ecs_has_pair(world, e1, EcsIsA, e2));
test_assert( !ecs_has(world, e2, Position));
test_assert( ecs_has(world, e2, Velocity));
test_assert( ecs_has_id(world, e2, EcsDisabled));
ecs_fini(world);
}
static bool has_cloned = false;
static
void CloneInOnAdd(ecs_iter_t *it)
{
Position *p = ecs_field(it, Position, 1);
int i;
for (i = 0; i < it->count; i ++) {
bool has_cloned_test = has_cloned;
/* Prevent recursive OnAdd calls */
has_cloned = true;
p[i].x = 10;
p[i].y = 20;
if (!has_cloned_test) {
ecs_entity_t e = it->entities[i];
ecs_entity_t clone = ecs_clone(it->world, 0, e, true);
ecs_add_pair(it->world, e, EcsIsA, clone);
}
}
}
void Prefab_clone_after_inherit_in_on_add(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_OBSERVER(world, CloneInOnAdd, EcsOnAdd, Position);
ecs_entity_t e = ecs_new(world, Position);
test_assert(e != 0);
const Position *p = ecs_get(world, e, Position);
test_int(p->x, 10);
test_int(p->y, 20);
test_assert(has_cloned == true);
ecs_fini(world);
}
void Prefab_override_from_nested(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, BasePrefab, Position);
ecs_set(world, BasePrefab, Position, {10, 20});
ECS_PREFAB(world, SubPrefab, (IsA, BasePrefab), Velocity, OVERRIDE | Position, OVERRIDE | Velocity);
ecs_set(world, SubPrefab, Velocity, {30, 40});
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, SubPrefab);
test_assert(e1 != 0);
test_assert( ecs_owns(world, e1, Position));
test_assert( ecs_owns(world, e1, Velocity));
test_assert( ecs_owns(world, e1, Position));
test_assert( ecs_owns(world, e1, Velocity));
test_assert( ecs_has_pair(world, e1, EcsIsA, SubPrefab));
test_assert( ecs_has_pair(world, e1, EcsIsA, BasePrefab));
const Position *p = ecs_get(world, e1, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
const Velocity *v = ecs_get(world, e1, Velocity);
test_assert(v != NULL);
test_int(v->x, 30);
test_int(v->y, 40);
ecs_fini(world);
}
static
void OnAddEntity(ecs_iter_t *it) {
ecs_entity_t *e = ecs_field(it, ecs_entity_t, 1);
int i;
for (i = 0; i < it->count; i ++) {
e[i] = it->entities[i];
}
}
void Prefab_create_multiple_nested_w_on_set(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_COMPONENT(world, ecs_entity_t);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {1, 2});
ECS_PREFAB(world, Child, (ChildOf, Prefab), Velocity, ecs_entity_t);
ecs_set(world, Child, Velocity, {3, 4});
ECS_OBSERVER(world, OnAddEntity, EcsOnSet, ecs_entity_t);
ECS_OBSERVER(world, OnSetVelocity, EcsOnSet, Velocity);
test_int(on_set_velocity_invoked, 0);
/* Create two entities with separate calls */
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, Prefab);
ecs_entity_t e2 = ecs_new_w_pair(world, EcsIsA, Prefab);
test_int(on_set_velocity_invoked, 2);
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has(world, e2, Position));
ecs_entity_t child1 = ecs_lookup_child(world, e1, "Child");
test_assert(child1 != 0);
ecs_entity_t child2 = ecs_lookup_child(world, e2, "Child");
test_assert(child2 != 0);
test_assert(child1 != child2);
const ecs_entity_t *self1 = ecs_get(world, child1, ecs_entity_t);
test_assert(self1 != NULL);
test_assert(*self1 == child1);
const ecs_entity_t *self2 = ecs_get(world, child2, ecs_entity_t);
test_assert(self2 != NULL);
test_assert(self1 != self2);
test_assert(*self2 == child2);
test_assert( ecs_has(world, child1, Velocity));
test_assert( ecs_has(world, child2, Velocity));
test_assert( ecs_owns(world, child1, Velocity));
test_assert( ecs_owns(world, child2, Velocity));
const Velocity *v1 = ecs_get(world, child1, Velocity);
test_assert(v1 != NULL);
test_int(v1->x, 4);
test_int(v1->y, 5);
const Velocity *v2 = ecs_get(world, child2, Velocity);
test_assert(v2 != NULL);
test_assert(v1 != v2);
test_int(v2->x, 4);
test_int(v2->y, 5);
ecs_fini(world);
}
static ecs_entity_t new_instance_1, new_instance_2;
static
void CreateInstances(ecs_iter_t *it) {
ecs_id_t Prefab = ecs_field_id(it, 1);
new_instance_1 = ecs_new_w_pair(it->world, EcsIsA, Prefab);
new_instance_2 = ecs_new_w_pair(it->world, EcsIsA, Prefab);
}
void Prefab_create_multiple_nested_w_on_set_in_progress(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_COMPONENT(world, ecs_entity_t);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {1, 2});
ECS_PREFAB(world, ChildPrefab, Velocity);
ecs_set(world, ChildPrefab, Velocity, {3, 4});
ECS_PREFAB(world, Child, (ChildOf, Prefab), (IsA, ChildPrefab), ecs_entity_t);
ECS_SYSTEM(world, CreateInstances, EcsOnUpdate, Prefab());
ECS_OBSERVER(world, OnAddEntity, EcsOnSet, ecs_entity_t);
ECS_OBSERVER(world, OnSetVelocity, EcsOnSet, Velocity(self|up));
ecs_progress(world, 1);
test_int(on_set_velocity_invoked, 2);
ecs_entity_t e1 = new_instance_1;
ecs_entity_t e2 = new_instance_2;
test_assert( ecs_has(world, e1, Position));
test_assert( ecs_has(world, e2, Position));
ecs_entity_t child1 = ecs_lookup_child(world, e1, "Child");
test_assert(child1 != 0);
ecs_entity_t child2 = ecs_lookup_child(world, e2, "Child");
test_assert(child2 != 0);
test_assert(child1 != child2);
const ecs_entity_t *self1 = ecs_get(world, child1, ecs_entity_t);
test_assert(self1 != NULL);
test_assert(*self1 == child1);
const ecs_entity_t *self2 = ecs_get(world, child2, ecs_entity_t);
test_assert(self2 != NULL);
test_assert(self1 != self2);
test_assert(*self2 == child2);
test_assert( ecs_has(world, child1, Velocity));
test_assert( ecs_has(world, child2, Velocity));
test_assert( ecs_owns(world, child1, Velocity));
test_assert( ecs_owns(world, child2, Velocity));
const Velocity *v1 = ecs_get(world, child1, Velocity);
test_assert(v1 != NULL);
test_int(v1->x, 3);
test_int(v1->y, 4);
const Velocity *v2 = ecs_get(world, child2, Velocity);
test_assert(v2 != NULL);
test_assert(v1 != v2);
test_int(v2->x, 3);
test_int(v2->y, 4);
ecs_fini(world);
}
void Prefab_single_on_set_on_child_w_override(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_COMPONENT(world, Mass);
ECS_COMPONENT(world, ecs_entity_t);
ECS_PREFAB(world, Prefab, Position);
ecs_set(world, Prefab, Position, {1, 2});
ECS_PREFAB(world, ChildPrefab, Velocity);
ecs_set(world, ChildPrefab, Velocity, {3, 4});
ECS_PREFAB(world, Child, (ChildOf, Prefab), (IsA, ChildPrefab), Velocity);
ECS_OBSERVER(world, OnSetVelocity, EcsOnSet, Velocity);
test_int(on_set_velocity_invoked, 0);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab);
/* Make sure OnSet is invoked only once, even though Child overrides a
* component from a ChildPrefab. Velocity is already overridden for Child,
* and while it would technically not be incorrect to issue an OnSet for the
* override, we don't want to spam the application with redundant triggers. */
test_int(on_set_velocity_invoked, 1);
test_assert( ecs_has(world, e, Position));
ecs_entity_t child = ecs_lookup_child(world, e, "Child");
test_assert(child != 0);
test_assert( ecs_has(world, child, Velocity));
test_assert( ecs_owns(world, child, Velocity));
const Velocity *v = ecs_get(world, child, Velocity);
test_assert(v != NULL);
test_int(v->x, 4);
test_int(v->y, 5);
ecs_fini(world);
}
void Prefab_auto_override(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Position, Velocity, OVERRIDE | Position);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_owns(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
test_assert(!ecs_owns(world, e, Velocity));
ecs_fini(world);
}
void Prefab_auto_override_2(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Position, Velocity, OVERRIDE | Position, OVERRIDE | Velocity);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_owns(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
test_assert(ecs_owns(world, e, Velocity));
ecs_fini(world);
}
void Prefab_auto_override_nested(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Prefab, Position, Velocity, OVERRIDE | Position);
ECS_PREFAB(world, Prefab_2, (IsA, Prefab));
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab_2);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_owns(world, e, Position));
test_assert(ecs_has(world, e, Velocity));
test_assert(!ecs_owns(world, e, Velocity));
ecs_fini(world);
}
void Prefab_auto_override_pair(void) {
ecs_world_t *world = ecs_init();
ECS_TAG(world, TgtA);
ECS_TAG(world, TgtB);
ECS_TAG(world, Rel);
ecs_entity_t base = ecs_new_id(world);
ecs_add_id(world, base, ECS_OVERRIDE | ecs_pair(Rel, TgtA));
test_assert(!ecs_has_pair(world, base, Rel, TgtA));
test_assert(!ecs_has_pair(world, base, Rel, TgtB));
test_assert(ecs_has_id(world, base, ECS_OVERRIDE | ecs_pair(Rel, TgtA)));
ecs_add_pair(world, base, Rel, TgtA);
ecs_add_pair(world, base, Rel, TgtB);
test_assert(ecs_has_pair(world, base, Rel, TgtA));
test_assert(ecs_has_pair(world, base, Rel, TgtB));
test_assert(ecs_has_id(world, base, ECS_OVERRIDE | ecs_pair(Rel, TgtA)));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(ecs_has_pair(world, inst, Rel, TgtA));
test_assert(ecs_has_pair(world, inst, Rel, TgtB));
test_assert(ecs_owns_pair(world, inst, Rel, TgtA));
test_assert(!ecs_owns_pair(world, inst, Rel, TgtB));
ecs_fini(world);
}
void Prefab_auto_override_pair_w_component(void) {
ecs_world_t *world = ecs_init();
ECS_TAG(world, TgtA);
ECS_TAG(world, TgtB);
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_new_id(world);
ecs_add_id(world, base, ECS_OVERRIDE | ecs_pair(ecs_id(Position), TgtA));
test_assert(ecs_get_pair(world, base, Position, TgtA) == NULL);
ecs_set_pair(world, base, Position, TgtA, {10, 20});
ecs_set_pair(world, base, Position, TgtB, {20, 30});
const Position *pa = ecs_get_pair(world, base, Position, TgtA);
const Position *pb = ecs_get_pair(world, base, Position, TgtB);
test_assert(pa != NULL);
test_assert(pb != NULL);
test_int(pa->x, 10);
test_int(pa->y, 20);
test_int(pb->x, 20);
test_int(pb->y, 30);
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
const Position *pia = ecs_get_pair(world, inst, Position, TgtA);
const Position *pib = ecs_get_pair(world, inst, Position, TgtB);
test_assert(pia != pa);
test_assert(pib == pb);
test_int(pia->x, 10);
test_int(pia->y, 20);
test_assert(ecs_owns_pair(world, inst, ecs_id(Position), TgtA));
test_assert(!ecs_owns_pair(world, inst, ecs_id(Position), TgtB));
ecs_fini(world);
}
void Prefab_auto_override_2_pairs(void) {
ecs_world_t *world = ecs_init();
ECS_TAG(world, TgtA);
ECS_TAG(world, TgtB);
ECS_TAG(world, Rel);
ecs_entity_t base = ecs_new_id(world);
ecs_add_id(world, base, ECS_OVERRIDE | ecs_pair(Rel, TgtA));
ecs_add_id(world, base, ECS_OVERRIDE | ecs_pair(Rel, TgtB));
test_assert(!ecs_has_pair(world, base, Rel, TgtA));
test_assert(!ecs_has_pair(world, base, Rel, TgtB));
test_assert(ecs_has_id(world, base, ECS_OVERRIDE | ecs_pair(Rel, TgtA)));
test_assert(ecs_has_id(world, base, ECS_OVERRIDE | ecs_pair(Rel, TgtB)));
ecs_add_pair(world, base, Rel, TgtA);
ecs_add_pair(world, base, Rel, TgtB);
test_assert(ecs_has_pair(world, base, Rel, TgtA));
test_assert(ecs_has_pair(world, base, Rel, TgtB));
test_assert(ecs_has_id(world, base, ECS_OVERRIDE | ecs_pair(Rel, TgtA)));
test_assert(ecs_has_id(world, base, ECS_OVERRIDE | ecs_pair(Rel, TgtB)));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(ecs_has_pair(world, inst, Rel, TgtA));
test_assert(ecs_has_pair(world, inst, Rel, TgtB));
test_assert(ecs_owns_pair(world, inst, Rel, TgtA));
test_assert(ecs_owns_pair(world, inst, Rel, TgtB));
ecs_fini(world);
}
void Prefab_auto_override_2_pairs_w_component(void) {
ecs_world_t *world = ecs_init();
ECS_TAG(world, TgtA);
ECS_TAG(world, TgtB);
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_new_id(world);
ecs_add_id(world, base, ECS_OVERRIDE | ecs_pair(ecs_id(Position), TgtA));
ecs_add_id(world, base, ECS_OVERRIDE | ecs_pair(ecs_id(Position), TgtB));
test_assert(ecs_get_pair(world, base, Position, TgtA) == NULL);
test_assert(ecs_get_pair(world, base, Position, TgtB) == NULL);
ecs_set_pair(world, base, Position, TgtA, {10, 20});
ecs_set_pair(world, base, Position, TgtB, {20, 30});
const Position *pa = ecs_get_pair(world, base, Position, TgtA);
const Position *pb = ecs_get_pair(world, base, Position, TgtB);
test_assert(pa != NULL);
test_assert(pb != NULL);
test_int(pa->x, 10);
test_int(pa->y, 20);
test_int(pb->x, 20);
test_int(pb->y, 30);
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
const Position *pia = ecs_get_pair(world, inst, Position, TgtA);
const Position *pib = ecs_get_pair(world, inst, Position, TgtB);
test_assert(pia != pa);
test_assert(pib != pb);
test_int(pia->x, 10);
test_int(pia->y, 20);
test_int(pib->x, 20);
test_int(pib->y, 30);
test_assert(ecs_owns_pair(world, inst, ecs_id(Position), TgtA));
test_assert(ecs_owns_pair(world, inst, ecs_id(Position), TgtB));
ecs_fini(world);
}
void Prefab_auto_override_2_pairs_same_obj(void) {
ecs_world_t *world = ecs_init();
ECS_TAG(world, Tgt);
ECS_TAG(world, RelA);
ECS_TAG(world, RelB);
ecs_entity_t base = ecs_new_id(world);
ecs_add_id(world, base, ECS_OVERRIDE | ecs_pair(RelA, Tgt));
ecs_add_id(world, base, ECS_OVERRIDE | ecs_pair(RelB, Tgt));
test_assert(!ecs_has_pair(world, base, RelA, Tgt));
test_assert(!ecs_has_pair(world, base, RelB, Tgt));
test_assert(ecs_has_id(world, base, ECS_OVERRIDE | ecs_pair(RelA, Tgt)));
test_assert(ecs_has_id(world, base, ECS_OVERRIDE | ecs_pair(RelB, Tgt)));
ecs_add_pair(world, base, RelA, Tgt);
ecs_add_pair(world, base, RelB, Tgt);
test_assert(ecs_has_pair(world, base, RelA, Tgt));
test_assert(ecs_has_pair(world, base, RelB, Tgt));
test_assert(ecs_has_id(world, base, ECS_OVERRIDE | ecs_pair(RelA, Tgt)));
test_assert(ecs_has_id(world, base, ECS_OVERRIDE | ecs_pair(RelB, Tgt)));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(ecs_has_pair(world, inst, RelA, Tgt));
test_assert(ecs_has_pair(world, inst, RelB, Tgt));
test_assert(ecs_owns_pair(world, inst, RelA, Tgt));
test_assert(ecs_owns_pair(world, inst, RelB, Tgt));
ecs_fini(world);
}
void Prefab_prefab_instanceof_hierarchy(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, Base, Position);
ECS_PREFAB(world, BaseChild, Position, (ChildOf, Base));
ECS_PREFAB(world, ThePrefab, (IsA, Base));
/* Ensure that child has not been instantiated by making
* sure there are no matching entities for Position up to this point */
ecs_query_t *q = ecs_query_new(world, "Position(self|up)");
ecs_iter_t qit = ecs_query_iter(world, q);
test_assert(!ecs_query_next(&qit));
/* Instantiate the prefab */
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, ThePrefab);
test_assert(e != 0);
ecs_entity_t child = ecs_lookup_child(world, e, "BaseChild");
test_assert(child != 0);
qit = ecs_query_iter(world, q);
test_assert(ecs_query_next(&qit) == true);
test_int(qit.count, 1);
test_assert(ecs_query_next(&qit) == true);
test_int(qit.count, 1);
test_assert(ecs_query_next(&qit) == false);
ecs_fini(world);
}
void Prefab_override_tag(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tag);
ecs_entity_t base = ecs_new(world, Tag);
ecs_set(world, base, Position, {10, 20});
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has(world, e, Tag));
ecs_add(world, e, Tag);
test_assert(ecs_has(world, e, Tag));
test_assert(ecs_owns(world, e, Tag));
ecs_fini(world);
}
void Prefab_empty_prefab(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_new(world, 0);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
ecs_add(world, e, Position);
test_assert(ecs_has(world, e, Position));
test_assert(ecs_has_pair(world, e, EcsIsA, base));
ecs_fini(world);
}
void Prefab_instanceof_0(void) {
install_test_abort();
ecs_world_t *world = ecs_mini();
test_expect_abort();
/* Not allowed */
ecs_new_w_pair(world, EcsIsA, 0);
ecs_fini(world);
}
void Prefab_instantiate_empty_child_table(void) {
ecs_world_t *world = ecs_init();
ECS_PREFAB(world, Prefab, 0);
/* Forces creation of child table without children */
ecs_table_t *table = ecs_table_add_id(world, 0, ecs_childof(Prefab));
test_assert(table != NULL);
/* Main goal of this test is to ensure this doesn't crash */
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(e != 0);
test_assert(ecs_has_pair(world, e, EcsIsA, Prefab));
/* This shouldn't crash either */
ecs_delete(world, Prefab);
test_assert(!ecs_is_alive(world, Prefab));
ecs_fini(world);
}
void Prefab_instantiate_emptied_child_table(void) {
ecs_world_t *world = ecs_init();
ECS_PREFAB(world, Prefab, 0);
/* Create & remove prefab child */
ecs_entity_t child = ecs_new_w_pair(world, EcsChildOf, Prefab);
test_assert(child != 0);
/* Deleting the child will leave an initialized but empty table */
ecs_delete(world, child);
test_assert(!ecs_is_alive(world, child));
/* Main goal of this test is to ensure this doesn't crash */
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Prefab);
test_assert(e != 0);
test_assert(ecs_has_pair(world, e, EcsIsA, Prefab));
/* This shouldn't crash either */
ecs_delete(world, Prefab);
test_assert(!ecs_is_alive(world, Prefab));
ecs_fini(world);
}
void Prefab_override_2_prefabs(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ECS_PREFAB(world, PrefabA, Position);
ECS_PREFAB(world, PrefabB, Velocity);
ecs_set(world, PrefabA, Position, {10, 20});
ecs_set(world, PrefabB, Velocity, {1, 2});
ecs_entity_t e = ecs_new(world, 0);
ecs_add_pair(world, e, EcsIsA, PrefabA);
ecs_add_pair(world, e, EcsIsA, PrefabB);
ecs_add(world, e, Position);
ecs_add(world, e, Velocity);
test_assert(ecs_owns(world, e, Position));
test_assert(ecs_owns(world, e, Velocity));
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 Prefab_rematch_after_add_instanceof_to_parent(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_query_t *q = ecs_query_new(world, "Position(parent)");
test_assert(q != NULL);
ecs_entity_t base = ecs_set(world, 0, Position, {10, 20});
ecs_entity_t parent = ecs_new(world, 0);
ecs_entity_t child = ecs_new_w_pair(world, EcsChildOf, parent);
test_assert(base != 0);
test_assert(parent != 0);
test_assert(child != 0);
ecs_add_pair(world, parent, EcsIsA, base);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
test_int(it.entities[0], child);
Position *p = ecs_field(&it, Position, 1);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Prefab_child_of_instance(void) {
install_test_abort();
ecs_world_t *world = ecs_init();
ecs_entity_t base = ecs_new_w_id(world, EcsPrefab);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, EcsChildOf, base);
test_expect_abort();
/* Should trigger an assert */
ecs_add_pair(world, e, EcsIsA, base);
ecs_fini(world);
}
void Prefab_rematch_after_prefab_delete(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_set(world, 0, Position, {10, 20});
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
ecs_query_t *q = ecs_query_new(world, "Position(up)");
ecs_iter_t it = ecs_query_iter(world, q);
test_assert(ecs_query_next(&it));
test_int(it.count, 1);
test_int(it.entities[0], e);
Position *p = ecs_field(&it, Position, 1);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
test_assert(!ecs_query_next(&it));
ecs_delete(world, base);
it = ecs_query_iter(world, q);
test_assert(!ecs_query_next(&it));
ecs_fini(world);
}
void Prefab_add_tag_w_low_id_to_instance(void) {
ecs_world_t *world = ecs_init();
ecs_entity_t Tag = ecs_new_low_id(world);
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_set(world, 0, Position, {10, 20});
ecs_add_id(world, base, Tag);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
ecs_add(world, e, Position);
ecs_add_id(world, e, Tag);
test_assert(ecs_has_id(world, e, Tag));
ecs_fini(world);
}
void Prefab_get_type_after_base_add(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_new(world, Position);
test_assert(base != 0);
test_assert( ecs_get_type(world, base) != NULL);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
test_assert(e != 0);
test_assert( ecs_get_type(world, base) != NULL);
ecs_fini(world);
}
void Prefab_get_type_after_recycled_base_add(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_new(world, 0);
test_assert(base != 0);
test_assert( ecs_get_type(world, base) == NULL);
ecs_delete(world, base);
test_assert( !ecs_is_alive(world, base));
base = ecs_new(world, Position);
test_assert(base != 0);
test_assert(ecs_entity_t_lo(base) != base); // Ensure recycled
test_assert( ecs_get_type(world, base) != NULL);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
test_assert(e != 0);
test_assert( ecs_get_type(world, base) != NULL);
ecs_fini(world);
}
void Prefab_new_w_recycled_base(void) {
ecs_world_t *world = ecs_init();
ecs_entity_t base = ecs_new(world, 0);
test_assert(base != 0);
ecs_delete(world, base);
test_assert( !ecs_is_alive(world, base));
base = ecs_new(world, 0);
test_assert(base != 0);
test_assert(ecs_entity_t_lo(base) != base); // Ensure recycled
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
test_assert(e != 0);
test_assert( ecs_has_pair(world, e, EcsIsA, base));
ecs_fini(world);
}
void Prefab_add_recycled_base(void) {
ecs_world_t *world = ecs_init();
ecs_entity_t base = ecs_new(world, 0);
test_assert(base != 0);
ecs_delete(world, base);
test_assert( !ecs_is_alive(world, base));
base = ecs_new(world, 0);
test_assert(base != 0);
test_assert(ecs_entity_t_lo(base) != base); // Ensure recycled
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_add_pair(world, e, EcsIsA, base);
test_assert( ecs_has_pair(world, e, EcsIsA, base));
ecs_fini(world);
}
void Prefab_remove_recycled_base(void) {
ecs_world_t *world = ecs_init();
ecs_entity_t base = ecs_new(world, 0);
test_assert(base != 0);
ecs_delete(world, base);
test_assert( !ecs_is_alive(world, base));
base = ecs_new(world, 0);
test_assert(base != 0);
test_assert(ecs_entity_t_lo(base) != base); // Ensure recycled
ecs_entity_t e = ecs_new(world, 0);
test_assert(e != 0);
ecs_add_pair(world, e, EcsIsA, base);
test_assert( ecs_has_pair(world, e, EcsIsA, base));
ecs_remove_pair(world, e, EcsIsA, base);
test_assert( !ecs_has_pair(world, e, EcsIsA, base));
ecs_fini(world);
}
void Prefab_get_from_recycled_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_new(world, 0);
test_assert(base != 0);
ecs_delete(world, base);
test_assert( !ecs_is_alive(world, base));
base = ecs_set(world, 0, Position, {10, 20});
test_assert(base != 0);
test_assert(ecs_entity_t_lo(base) != base); // Ensure recycled
test_assert( ecs_get_type(world, base) != NULL);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
test_assert(e != 0);
test_assert( ecs_has_pair(world, e, EcsIsA, base));
test_assert( ecs_has(world, e, Position));
test_assert( !ecs_owns(world, e, Position));
const Position *p = ecs_get(world, e, 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 Prefab_override_from_recycled_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_new(world, 0);
test_assert(base != 0);
ecs_delete(world, base);
test_assert( !ecs_is_alive(world, base));
base = ecs_set(world, 0, Position, {10, 20});
test_assert(base != 0);
test_assert(ecs_entity_t_lo(base) != base); // Ensure recycled
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
test_assert(e != 0);
test_assert( ecs_has_pair(world, e, EcsIsA, base));
test_assert( ecs_has(world, e, Position));
test_assert( !ecs_owns(world, e, Position));
ecs_add(world, e, Position);
test_assert( ecs_has(world, e, Position));
test_assert( ecs_owns(world, e, 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 Prefab_remove_override_from_recycled_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_new(world, 0);
test_assert(base != 0);
ecs_delete(world, base);
test_assert( !ecs_is_alive(world, base));
base = ecs_set(world, 0, Position, {10, 20});
test_assert(base != 0);
test_assert(ecs_entity_t_lo(base) != base); // Ensure recycled
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
test_assert(e != 0);
test_assert( ecs_has_pair(world, e, EcsIsA, base));
test_assert( ecs_has(world, e, Position));
test_assert( !ecs_owns(world, e, Position));
ecs_add(world, e, Position);
test_assert( ecs_has(world, e, Position));
test_assert( ecs_owns(world, e, Position));
ecs_remove(world, e, Position);
test_assert( ecs_has(world, e, Position));
test_assert( !ecs_owns(world, e, Position));
ecs_fini(world);
}
void Prefab_instantiate_tree_from_recycled_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_new_w_id(world, EcsPrefab);
test_assert(base != 0);
ecs_delete(world, base);
test_assert( !ecs_is_alive(world, base));
base = ecs_set(world, 0, Position, {10, 20});
test_assert(base != 0);
ecs_add_id(world, base, EcsPrefab);
ecs_entity_t base_child = ecs_new_w_pair(world, EcsChildOf, base);
test_assert(base_child != 0);
ecs_set_name(world, base_child, "Child");
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
test_assert(e != 0);
test_assert( ecs_has_pair(world, e, EcsIsA, base));
test_assert( ecs_has(world, e, Position));
test_assert( !ecs_owns(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
test_assert(p == ecs_get(world, base, Position));
ecs_entity_t instance_child = ecs_lookup_child(world, e, "Child");
test_assert(instance_child != 0);
test_assert( ecs_has_pair(world, instance_child, EcsChildOf, e));
ecs_fini(world);
}
void Prefab_rematch_after_add_to_recycled_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Tag);
ecs_query_t *q = ecs_query_new(world, "Tag, Position(up)");
ecs_entity_t base = ecs_new(world, 0);
test_assert(base != 0);
ecs_delete(world, base);
test_assert( !ecs_is_alive(world, base));
base = ecs_new(world, 0);
test_assert(base != 0);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base);
test_assert(e != 0);
test_assert( ecs_has_pair(world, e, EcsIsA, base));
ecs_add(world, e, Tag);
ecs_iter_t it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), false);
ecs_set(world, base, Position, {10, 20});
ecs_progress(world, 0);
it = ecs_query_iter(world, q);
test_bool(ecs_query_next(&it), true);
test_int(it.count, 1);
const Position *p = ecs_field(&it, Position, 2);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
test_assert(ecs_field_src(&it, 2) == base);
test_bool(ecs_query_next(&it), false);
ecs_fini(world);
}
void Prefab_get_tag_from_2nd_base(void) {
ecs_world_t *world = ecs_init();
ECS_TAG(world, Tag);
ecs_entity_t base_1 = ecs_new_id(world);
ecs_entity_t base_2 = ecs_new_w_id(world, Tag);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, EcsIsA, base_1);
ecs_add_pair(world, e, EcsIsA, base_2);
test_assert(ecs_has_pair(world, e, EcsIsA, base_1));
test_assert(ecs_has_pair(world, e, EcsIsA, base_2));
test_assert(ecs_has_id(world, e, Tag));
ecs_fini(world);
}
void Prefab_get_component_from_2nd_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t base_1 = ecs_new_id(world);
ecs_entity_t base_2 = ecs_new(world, Position);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, EcsIsA, base_1);
ecs_add_pair(world, e, EcsIsA, base_2);
test_assert(ecs_has_pair(world, e, EcsIsA, base_1));
test_assert(ecs_has_pair(world, e, EcsIsA, base_2));
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_assert(p == ecs_get(world, base_2, Position));
ecs_fini(world);
}
void Prefab_get_component_from_1st_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t base_1 = ecs_new(world, Position);
ecs_entity_t base_2 = ecs_new(world, Position);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, EcsIsA, base_1);
ecs_add_pair(world, e, EcsIsA, base_2);
test_assert(ecs_has_pair(world, e, EcsIsA, base_1));
test_assert(ecs_has_pair(world, e, EcsIsA, base_2));
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_assert(p == ecs_get(world, base_1, Position));
ecs_fini(world);
}
void Prefab_get_component_from_2nd_base_of_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t base_1 = ecs_new_id(world);
ecs_entity_t base_2 = ecs_new(world, Position);
ecs_entity_t base_3 = ecs_new_id(world);
ecs_add_pair(world, base_3, EcsIsA, base_1);
ecs_add_pair(world, base_3, EcsIsA, base_2);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base_3);
test_assert(ecs_has_pair(world, e, EcsIsA, base_1));
test_assert(ecs_has_pair(world, e, EcsIsA, base_2));
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_assert(p == ecs_get(world, base_2, Position));
ecs_fini(world);
}
void Prefab_get_component_from_1st_base_of_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ecs_entity_t base_1 = ecs_new(world, Position);
ecs_entity_t base_2 = ecs_new(world, Position);
ecs_entity_t base_3 = ecs_new_id(world);
ecs_add_pair(world, base_3, EcsIsA, base_1);
ecs_add_pair(world, base_3, EcsIsA, base_2);
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base_3);
test_assert(ecs_has_pair(world, e, EcsIsA, base_1));
test_assert(ecs_has_pair(world, e, EcsIsA, base_2));
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_assert(p == ecs_get(world, base_1, Position));
ecs_fini(world);
}
void Prefab_get_component_from_2nd_base_prefab_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, base_1, 0);
ECS_PREFAB(world, base_2, Position);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, EcsIsA, base_1);
ecs_add_pair(world, e, EcsIsA, base_2);
test_assert(ecs_has_pair(world, e, EcsIsA, base_1));
test_assert(ecs_has_pair(world, e, EcsIsA, base_2));
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_assert(p == ecs_get(world, base_2, Position));
ecs_fini(world);
}
void Prefab_get_component_from_1st_base_prefab_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, base_1, Position);
ECS_PREFAB(world, base_2, Position);
ecs_entity_t e = ecs_new_id(world);
ecs_add_pair(world, e, EcsIsA, base_1);
ecs_add_pair(world, e, EcsIsA, base_2);
test_assert(ecs_has_pair(world, e, EcsIsA, base_1));
test_assert(ecs_has_pair(world, e, EcsIsA, base_2));
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_assert(p == ecs_get(world, base_1, Position));
ecs_fini(world);
}
void Prefab_get_component_from_2nd_base_of_base_prefab_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, base_1, 0);
ECS_PREFAB(world, base_2, Position);
ECS_PREFAB(world, base_3, (IsA, base_1), (IsA, base_2));
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base_3);
test_assert(ecs_has_pair(world, e, EcsIsA, base_1));
test_assert(ecs_has_pair(world, e, EcsIsA, base_2));
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_assert(p == ecs_get(world, base_2, Position));
ecs_fini(world);
}
void Prefab_get_component_from_1st_base_of_base_prefab_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_PREFAB(world, base_1, Position);
ECS_PREFAB(world, base_2, Position);
ECS_PREFAB(world, base_3, (IsA, base_1), (IsA, base_2));
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, base_3);
test_assert(ecs_has_pair(world, e, EcsIsA, base_1));
test_assert(ecs_has_pair(world, e, EcsIsA, base_2));
test_assert(ecs_has(world, e, Position));
const Position *p = ecs_get(world, e, Position);
test_assert(p != NULL);
test_assert(p == ecs_get(world, base_1, Position));
ecs_fini(world);
}
void Prefab_fail_on_override_final(void) {
install_test_abort();
ecs_world_t *world = ecs_init();
ecs_entity_t base = ecs_new_w_id(world, EcsFinal);
test_expect_abort();
ecs_new_w_pair(world, EcsIsA, base);
ecs_fini(world);
}
static
int child_count(ecs_world_t *world, ecs_entity_t e) {
int32_t count = 0;
ecs_iter_t it = ecs_term_iter(world, &(ecs_term_t){
ecs_pair(EcsChildOf, e
)});
while (ecs_term_next(&it)) {
count += it.count;
}
return count;
}
void Prefab_instantiate_tree_once(void) {
ecs_world_t *world = ecs_init();
ECS_PREFAB(world, Cannon, 0);
ECS_PREFAB(world, Turret, 0);
ECS_PREFAB(world, CannonA, (IsA, Cannon), (ChildOf, Turret));
ECS_PREFAB(world, CannonB, (IsA, Cannon), (ChildOf, Turret));
ECS_PREFAB(world, SpaceShip, 0);
ECS_PREFAB(world, TurretA, (IsA, Turret), (ChildOf, SpaceShip));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, SpaceShip);
test_assert(inst != 0);
test_int(1, child_count(world, inst));
ecs_entity_t turret_a = ecs_lookup_child(world, inst, "TurretA");
test_assert(turret_a != 0);
test_int(2, child_count(world, turret_a));
ecs_fini(world);
}
void Prefab_nested_prefab_w_named_children(void) {
ecs_world_t *world = ecs_init();
ECS_PREFAB(world, Cannon, 0);
ECS_PREFAB(world, Turret, 0);
ecs_set_scope(world, Turret);
ECS_ENTITY(world, CannonA, (IsA, Cannon));
ecs_set_scope(world, 0);
ECS_PREFAB(world, SpaceShip, 0);
ecs_set_scope(world, SpaceShip);
ECS_PREFAB(world, TurretA, (IsA, Turret));
ecs_set_scope(world, 0);
test_assert( ecs_has_pair(world, CannonA, EcsChildOf, Turret));
test_assert( ecs_has_pair(world, CannonA, EcsIsA, Cannon));
test_str("CannonA", ecs_get_name(world, CannonA));
test_assert( ecs_has_pair(world, TurretA, EcsChildOf, SpaceShip));
test_assert( ecs_has_pair(world, TurretA, EcsIsA, Turret));
test_str("TurretA", ecs_get_name(world, TurretA));
ecs_fini(world);
}
void Prefab_dont_copy_children_for_non_prefab_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_ENTITY(world, Base, Position);
ECS_ENTITY(world, Child, (ChildOf, Base));
ecs_entity_t e = ecs_new_w_pair(world, EcsIsA, Base);
test_assert(e != 0);
test_assert(ecs_get(world, e, Position) != NULL);
test_assert(ecs_lookup_child(world, e, "Child") == 0);
ecs_fini(world);
}
void Prefab_get_component_pair_from_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Obj);
ecs_entity_t base = ecs_set_pair(world, 0, Position, Obj, {10, 20});
test_assert(ecs_has_pair(world, base, ecs_id(Position), Obj));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(ecs_has_pair(world, inst, ecs_id(Position), Obj));
const Position *p = ecs_get_pair(world, inst, Position, Obj);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
test_assert(p == ecs_get_pair(world, base, Position, Obj));
ecs_fini(world);
}
void Prefab_get_component_pair_from_prefab_base(void) {
ecs_world_t *world = ecs_init();
ECS_COMPONENT(world, Position);
ECS_TAG(world, Obj);
ecs_entity_t base = ecs_new_w_id(world, EcsPrefab);
ecs_set_pair(world, base, Position, Obj, {10, 20});
test_assert(ecs_has_pair(world, base, ecs_id(Position), Obj));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(ecs_has_pair(world, inst, ecs_id(Position), Obj));
const Position *p = ecs_get_pair(world, inst, Position, Obj);
test_assert(p != NULL);
test_int(p->x, 10);
test_int(p->y, 20);
test_assert(p == ecs_get_pair(world, base, Position, Obj));
ecs_fini(world);
}
void Prefab_override_dont_inherit(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_add_id(world, ecs_id(Position), EcsDontInherit);
ecs_set_hooks(world, Position, {
.ctor = ecs_default_ctor
});
ecs_entity_t base = ecs_set(world, 0, Position, {10, 20});
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert( !ecs_has(world, inst, Position));
ecs_add(world, inst, Position);
test_assert( ecs_has(world, inst, Position));
const Position *p = ecs_get(world, inst, Position);
test_int(p->x, 0);
test_int(p->y, 0);
ecs_fini(world);
}
void Prefab_prefab_w_switch(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Movement, Union);
ECS_TAG(world, Walking);
ECS_TAG(world, Running);
ecs_entity_t p = ecs_new_w_pair(world, Movement, Running);
test_assert( ecs_has_pair(world, p, Movement, Running));
ecs_entity_t i = ecs_new_w_pair(world, EcsIsA, p);
test_assert( ecs_has_pair(world, i, Movement, Running));
test_assert( !ecs_has_pair(world, i, Movement, Walking));
ecs_fini(world);
}
void Prefab_prefab_child_w_dont_inherit_component(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, TagA, DontInherit);
ECS_TAG(world, TagB);
ecs_entity_t base = ecs_new_prefab(world, "Base");
ecs_entity_t base_child = ecs_new_prefab(world, "Base.Child");
ecs_add(world, base_child, TagA);
ecs_add(world, base_child, TagB);
test_assert(base != 0);
test_assert(base_child != 0);
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(inst != 0);
ecs_entity_t inst_child = ecs_lookup_child(world, inst, "Child");
test_assert(inst_child != 0);
test_assert(!ecs_has(world, inst_child, TagA));
test_assert(ecs_has(world, inst_child, TagB));
ecs_fini(world);
}
void Prefab_prefab_child_override(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, Foo);
ECS_TAG(world, Bar);
ecs_entity_t turret = ecs_new_prefab(world, "Turret");
ecs_entity_t turret_head = ecs_new_prefab(world, "Turret.Head");
ecs_add(world, turret_head, Foo);
ecs_entity_t railgun = ecs_new_prefab(world, "Railgun");
ecs_add_pair(world, railgun, EcsIsA, turret);
ecs_entity_t railgun_head = ecs_new_prefab(world, "Railgun.Head");
ecs_add(world, railgun_head, Bar);
ecs_entity_t inst = ecs_new_entity(world, "inst");
ecs_add_pair(world, inst, EcsIsA, railgun);
ecs_entity_t head = ecs_lookup_child(world, inst, "Head");
test_assert(head != 0);
test_assert(ecs_has(world, head, Foo));
test_assert(ecs_has(world, head, Bar));
ecs_fini(world);
}
void Prefab_prefab_child_override_w_exclusive_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Rel, Exclusive);
ECS_TAG(world, ObjA);
ECS_TAG(world, ObjB);
ecs_entity_t turret = ecs_new_prefab(world, "Turret");
ecs_entity_t turret_head = ecs_new_prefab(world, "Turret.Head");
ecs_add_pair(world, turret_head, Rel, ObjA);
test_assert(ecs_has_pair(world, turret_head, Rel, ObjA));
ecs_entity_t railgun = ecs_new_prefab(world, "Railgun");
ecs_add_pair(world, railgun, EcsIsA, turret);
ecs_entity_t railgun_head = ecs_new_prefab(world, "Railgun.Head");
ecs_add_pair(world, railgun_head, Rel, ObjB);
test_assert(!ecs_has_pair(world, railgun_head, Rel, ObjA));
test_assert(ecs_has_pair(world, railgun_head, Rel, ObjB));
ecs_entity_t inst = ecs_new_entity(world, "inst");
ecs_add_pair(world, inst, EcsIsA, railgun);
ecs_entity_t head = ecs_lookup_child(world, inst, "Head");
test_assert(head != 0);
test_assert(!ecs_has_pair(world, head, Rel, ObjA));
test_assert(ecs_has_pair(world, head, Rel, ObjB));
ecs_fini(world);
}
void Prefab_prefab_1_slot(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t base = ecs_new_prefab(world, "Base");
ecs_entity_t base_slot = ecs_new_prefab(world, "Base.Slot");
ecs_add_pair(world, base_slot, EcsSlotOf, base);
test_assert(ecs_has_pair(world, base_slot, EcsChildOf, base));
test_assert(ecs_has_pair(world, base_slot, EcsSlotOf, base));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(inst != 0);
ecs_entity_t inst_slot = ecs_get_target(world, inst, base_slot, 0);
test_assert(inst_slot != 0);
test_str(ecs_get_name(world, inst_slot), "Slot");
test_assert(!ecs_has_pair(world, inst_slot, EcsSlotOf, EcsWildcard));
test_assert(ecs_has_pair(world, inst_slot, EcsChildOf, inst));
ecs_fini(world);
}
void Prefab_prefab_2_slots(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t base = ecs_new_prefab(world, "Base");
ecs_entity_t base_slot_a = ecs_new_prefab(world, "Base.SlotA");
ecs_entity_t base_slot_b = ecs_new_prefab(world, "Base.SlotB");
ecs_add_pair(world, base_slot_a, EcsSlotOf, base);
ecs_add_pair(world, base_slot_b, EcsSlotOf, base);
test_assert(ecs_has_pair(world, base_slot_a, EcsChildOf, base));
test_assert(ecs_has_pair(world, base_slot_a, EcsSlotOf, base));
test_assert(ecs_has_pair(world, base_slot_b, EcsChildOf, base));
test_assert(ecs_has_pair(world, base_slot_b, EcsSlotOf, base));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(inst != 0);
ecs_entity_t inst_slot_a = ecs_get_target(world, inst, base_slot_a, 0);
test_assert(inst_slot_a != 0);
test_str(ecs_get_name(world, inst_slot_a), "SlotA");
test_assert(!ecs_has_pair(world, inst_slot_a, EcsSlotOf, EcsWildcard));
test_assert(ecs_has_pair(world, inst_slot_a, EcsChildOf, inst));
ecs_entity_t inst_slot_b = ecs_get_target(world, inst, base_slot_b, 0);
test_assert(inst_slot_b != 0);
test_str(ecs_get_name(world, inst_slot_b), "SlotB");
test_assert(!ecs_has_pair(world, inst_slot_b, EcsSlotOf, EcsWildcard));
test_assert(ecs_has_pair(world, inst_slot_b, EcsChildOf, inst));
ecs_fini(world);
}
void Prefab_prefab_w_nested_slot(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t base = ecs_new_prefab(world, "Base");
ecs_entity_t base_slot = ecs_new_prefab(world, "Base.Slot");
ecs_entity_t base_slot_slot = ecs_new_prefab(world, "Base.Slot.Slot");
ecs_add_pair(world, base_slot, EcsSlotOf, base);
ecs_add_pair(world, base_slot_slot, EcsSlotOf, base);
test_assert(ecs_has_pair(world, base_slot, EcsChildOf, base));
test_assert(ecs_has_pair(world, base_slot, EcsSlotOf, base));
test_assert(ecs_has_pair(world, base_slot_slot, EcsChildOf, base_slot));
test_assert(ecs_has_pair(world, base_slot_slot, EcsSlotOf, base));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(inst != 0);
ecs_entity_t inst_slot = ecs_get_target(world, inst, base_slot, 0);
test_assert(inst_slot != 0);
test_str(ecs_get_name(world, inst_slot), "Slot");
test_assert(!ecs_has_pair(world, inst_slot, EcsSlotOf, EcsWildcard));
test_assert(ecs_has_pair(world, inst_slot, EcsChildOf, inst));
ecs_entity_t inst_slot_slot = ecs_get_target(world, inst, base_slot_slot, 0);
test_assert(inst_slot_slot != 0);
test_assert(inst_slot_slot != inst_slot);
test_str(ecs_get_name(world, inst_slot_slot), "Slot");
test_assert(!ecs_has_pair(world, inst_slot_slot, EcsSlotOf, EcsWildcard));
test_assert(ecs_has_pair(world, inst_slot_slot, EcsChildOf, inst_slot));
ecs_fini(world);
}
void Prefab_prefab_w_mixed_slots(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t base = ecs_new_prefab(world, "Base");
ecs_entity_t base_slot = ecs_new_prefab(world, "Base.Slot");
ecs_entity_t base_slot_slot = ecs_new_prefab(world, "Base.Slot.Slot");
ecs_add_pair(world, base_slot, EcsSlotOf, base);
ecs_add_pair(world, base_slot_slot, EcsSlotOf, base_slot);
test_assert(ecs_has_pair(world, base_slot, EcsChildOf, base));
test_assert(ecs_has_pair(world, base_slot, EcsSlotOf, base));
test_assert(ecs_has_pair(world, base_slot_slot, EcsChildOf, base_slot));
test_assert(ecs_has_pair(world, base_slot_slot, EcsSlotOf, base_slot));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(inst != 0);
ecs_entity_t inst_slot = ecs_get_target(world, inst, base_slot, 0);
test_assert(inst_slot != 0);
test_str(ecs_get_name(world, inst_slot), "Slot");
test_assert(!ecs_has_pair(world, inst_slot, EcsSlotOf, EcsWildcard));
test_assert(ecs_has_pair(world, inst_slot, EcsChildOf, inst));
ecs_entity_t inst_slot_slot = ecs_get_target(world, inst, base_slot_slot, 0);
test_assert(inst_slot_slot == 0);
inst_slot_slot = ecs_get_target(world, inst_slot, base_slot_slot, 0);
test_assert(inst_slot_slot != 0);
test_assert(inst_slot_slot != inst_slot);
test_str(ecs_get_name(world, inst_slot_slot), "Slot");
test_assert(!ecs_has_pair(world, inst_slot_slot, EcsSlotOf, EcsWildcard));
test_assert(ecs_has_pair(world, inst_slot_slot, EcsChildOf, inst_slot));
ecs_fini(world);
}
void Prefab_prefab_variant_w_slot(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t base = ecs_new_prefab(world, "Base");
ecs_entity_t variant = ecs_new_prefab(world, "Variant");
ecs_entity_t variant_slot = ecs_new_prefab(world, "Variant.Slot");
ecs_add_pair(world, variant, EcsIsA, base);
ecs_add_pair(world, variant_slot, EcsSlotOf, variant);
test_assert(ecs_has_pair(world, variant_slot, EcsChildOf, variant));
test_assert(ecs_has_pair(world, variant_slot, EcsSlotOf, variant));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, variant);
test_assert(inst != 0);
ecs_entity_t inst_slot = ecs_get_target(world, inst, variant_slot, 0);
test_assert(inst_slot != 0);
test_str(ecs_get_name(world, inst_slot), "Slot");
test_assert(!ecs_has_pair(world, inst_slot, EcsSlotOf, EcsWildcard));
test_assert(ecs_has_pair(world, inst_slot, EcsChildOf, inst));
ecs_fini(world);
}
void Prefab_prefab_variant_w_base_slot(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t base = ecs_new_prefab(world, "Base");
ecs_entity_t base_slot = ecs_new_prefab(world, "Base.Slot");
ecs_add_pair(world, base_slot, EcsSlotOf, base);
test_assert(ecs_has_pair(world, base_slot, EcsChildOf, base));
test_assert(ecs_has_pair(world, base_slot, EcsSlotOf, base));
ecs_entity_t variant = ecs_new_prefab(world, "Variant");
ecs_add_pair(world, variant, EcsIsA, base);
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, variant);
test_assert(inst != 0);
ecs_entity_t inst_slot = ecs_get_target(world, inst, base_slot, 0);
test_assert(inst_slot != 0);
test_str(ecs_get_name(world, inst_slot), "Slot");
test_assert(!ecs_has_pair(world, inst_slot, EcsSlotOf, EcsWildcard));
test_assert(ecs_has_pair(world, inst_slot, EcsChildOf, inst));
ecs_fini(world);
}
void Prefab_prefab_variant_w_mixed_slots(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t base = ecs_new_prefab(world, "Base");
ecs_entity_t base_slot = ecs_new_prefab(world, "Base.BaseSlot");
ecs_add_pair(world, base_slot, EcsSlotOf, base);
test_assert(ecs_has_pair(world, base_slot, EcsChildOf, base));
test_assert(ecs_has_pair(world, base_slot, EcsSlotOf, base));
ecs_entity_t variant = ecs_new_prefab(world, "Variant");
ecs_add_pair(world, variant, EcsIsA, base);
ecs_entity_t variant_slot = ecs_new_prefab(world, "Variant.VariantSlot");
ecs_add_pair(world, variant, EcsIsA, base);
ecs_add_pair(world, variant_slot, EcsSlotOf, variant);
test_assert(ecs_has_pair(world, variant_slot, EcsChildOf, variant));
test_assert(ecs_has_pair(world, variant_slot, EcsSlotOf, variant));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, variant);
test_assert(inst != 0);
ecs_entity_t inst_base_slot = ecs_get_target(world, inst, base_slot, 0);
test_assert(inst_base_slot != 0);
test_str(ecs_get_name(world, inst_base_slot), "BaseSlot");
test_assert(!ecs_has_pair(world, inst_base_slot, EcsSlotOf, EcsWildcard));
test_assert(ecs_has_pair(world, inst_base_slot, EcsChildOf, inst));
ecs_entity_t inst_variant_slot = ecs_get_target(world, inst, variant_slot, 0);
test_assert(inst_variant_slot != 0);
test_assert(inst_variant_slot != inst_base_slot);
test_str(ecs_get_name(world, inst_variant_slot), "VariantSlot");
test_assert(!ecs_has_pair(world, inst_variant_slot, EcsSlotOf, EcsWildcard));
test_assert(ecs_has_pair(world, inst_variant_slot, EcsChildOf, inst));
ecs_fini(world);
}
void Prefab_override_slot(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t base = ecs_new_prefab(world, "Base");
ecs_entity_t base_slot = ecs_new_prefab(world, "Base.Slot");
ecs_add_pair(world, base_slot, EcsSlotOf, base);
test_assert(ecs_has_pair(world, base_slot, EcsChildOf, base));
test_assert(ecs_has_pair(world, base_slot, EcsSlotOf, base));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(inst != 0);
ecs_entity_t inst_slot = ecs_get_target(world, inst, base_slot, 0);
test_assert(inst_slot != 0);
test_str(ecs_get_name(world, inst_slot), "Slot");
test_assert(!ecs_has_pair(world, inst_slot, EcsSlotOf, EcsWildcard));
test_assert(ecs_has_pair(world, inst_slot, EcsChildOf, inst));
ecs_entity_t slot_override = ecs_new_id(world);
ecs_add_pair(world, inst, base_slot, slot_override);
test_assert(ecs_has_pair(world, inst, base_slot, slot_override));
test_assert(!ecs_has_pair(world, inst, base_slot, inst_slot));
ecs_fini(world);
}
void Prefab_2_instances_w_slots_same_table(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t base = ecs_new_prefab(world, "Base");
ecs_entity_t base_slot = ecs_new_prefab(world, "Base.Slot");
ecs_add_pair(world, base_slot, EcsSlotOf, base);
test_assert(ecs_has_pair(world, base_slot, EcsChildOf, base));
test_assert(ecs_has_pair(world, base_slot, EcsSlotOf, base));
ecs_entity_t inst_1 = ecs_new_w_pair(world, EcsIsA, base);
test_assert(inst_1 != 0);
ecs_entity_t inst_2 = ecs_new_w_pair(world, EcsIsA, base);
test_assert(inst_2 != 0);
ecs_entity_t slot_1 = ecs_get_target(world, inst_1, base_slot, 0);
test_assert(slot_1 != 0);
ecs_entity_t slot_2 = ecs_get_target(world, inst_2, base_slot, 0);
test_assert(slot_2 != 0);
test_assert(slot_1 != slot_2);
/* Make sure slots don't fragment */
test_assert(ecs_get_table(world, inst_1) == ecs_get_table(world, inst_2));
ecs_fini(world);
}
void Prefab_slot_has_union(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t base = ecs_new_prefab(world, "Base");
ecs_entity_t base_slot = ecs_new_prefab(world, "Base.Slot");
ecs_add_pair(world, base_slot, EcsSlotOf, base);
test_assert(ecs_has_pair(world, base_slot, EcsChildOf, base));
test_assert(ecs_has_pair(world, base_slot, EcsSlotOf, base));
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(inst != 0);
ecs_entity_t inst_slot = ecs_get_target(world, inst, base_slot, 0);
test_assert(inst_slot != 0);
test_assert(base_slot != 0);
test_assert( ecs_has_id(world, base_slot, EcsUnion));
test_assert( !ecs_has_id(world, inst_slot, EcsUnion));
ecs_fini(world);
}
void Prefab_slot_override(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t turret = ecs_new_prefab(world, "Turret");
ecs_entity_t turret_base = ecs_new_prefab(world, "Turret.Base");
ecs_add_pair(world, turret_base, EcsSlotOf, turret);
ecs_entity_t turret_head = ecs_new_prefab(world, "Turret.Head");
ecs_add_pair(world, turret_head, EcsSlotOf, turret);
ecs_entity_t railgun = ecs_new_prefab(world, "Railgun");
ecs_add_pair(world, railgun, EcsIsA, turret);
ecs_entity_t railgun_head = ecs_new_prefab(world, "Railgun.Head");
test_assert(ecs_has_pair(world, railgun_head, EcsSlotOf, turret));
ecs_add_pair(world, railgun_head, EcsSlotOf, railgun);
test_assert(ecs_has_pair(world, railgun_head, EcsSlotOf, railgun));
test_assert(!ecs_has_pair(world, railgun_head, EcsSlotOf, turret));
ecs_entity_t railgun_beam = ecs_new_prefab(world, "Railgun.Beam");
ecs_add_pair(world, railgun_beam, EcsSlotOf, railgun);
ecs_entity_t inst = ecs_new_entity(world, "inst");
ecs_add_pair(world, inst, EcsIsA, railgun);
ecs_entity_t head = ecs_get_target(world, inst, turret_head, 0);
ecs_entity_t head_r = ecs_get_target(world, inst, railgun_head, 0);
ecs_entity_t base = ecs_get_target(world, inst, turret_base, 0);
ecs_entity_t beam = ecs_get_target(world, inst, railgun_beam, 0);
test_assert(head == 0);
test_assert(head_r != 0);
test_assert(base != 0);
test_assert(beam != 0);
char *path = ecs_get_fullpath(world, head_r);
test_str(path, "inst.Head");
ecs_os_free(path);
path = ecs_get_fullpath(world, base);
test_str(path, "inst.Base");
ecs_os_free(path);
path = ecs_get_fullpath(world, beam);
test_str(path, "inst.Beam");
ecs_os_free(path);
ecs_fini(world);
}
void Prefab_base_slot_override(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t turret = ecs_new_prefab(world, "Turret");
ecs_entity_t turret_base = ecs_new_prefab(world, "Turret.Base");
ecs_add_pair(world, turret_base, EcsSlotOf, turret);
ecs_entity_t turret_head = ecs_new_prefab(world, "Turret.Head");
ecs_add_pair(world, turret_head, EcsSlotOf, turret);
ecs_entity_t railgun = ecs_new_prefab(world, "Railgun");
ecs_add_pair(world, railgun, EcsIsA, turret);
ecs_entity_t railgun_head = ecs_new_prefab(world, "Railgun.Head");
test_assert(ecs_has_pair(world, railgun_head, EcsSlotOf, turret));
ecs_entity_t railgun_beam = ecs_new_prefab(world, "Railgun.Beam");
ecs_add_pair(world, railgun_beam, EcsSlotOf, railgun);
ecs_entity_t inst = ecs_new_entity(world, "inst");
ecs_add_pair(world, inst, EcsIsA, railgun);
ecs_entity_t head = ecs_get_target(world, inst, turret_head, 0);
ecs_entity_t head_r = ecs_get_target(world, inst, railgun_head, 0);
ecs_entity_t base = ecs_get_target(world, inst, turret_base, 0);
ecs_entity_t beam = ecs_get_target(world, inst, railgun_beam, 0);
test_assert(head != 0);
test_assert(head_r == 0);
test_assert(base != 0);
test_assert(beam != 0);
char *path = ecs_get_fullpath(world, head);
test_str(path, "inst.Head");
ecs_os_free(path);
path = ecs_get_fullpath(world, base);
test_str(path, "inst.Base");
ecs_os_free(path);
path = ecs_get_fullpath(world, beam);
test_str(path, "inst.Beam");
ecs_os_free(path);
ecs_fini(world);
}
void Prefab_prefab_child_w_union(void) {
ecs_world_t *world = ecs_mini();
ECS_ENTITY(world, Rel, Union);
ECS_TAG(world, TgtA);
ECS_TAG(world, TgtB);
ECS_TAG(world, TgtC);
ecs_entity_t base = ecs_new_prefab(world, "Base");
ecs_entity_t base_child_a = ecs_new_prefab(world, "Base.ChildA");
ecs_entity_t base_child_b = ecs_new_prefab(world, "Base.ChildB");
ecs_entity_t base_child_c = ecs_new_prefab(world, "Base.ChildC");
ecs_add_pair(world, base_child_a, Rel, TgtA);
ecs_add_pair(world, base_child_b, Rel, TgtB);
ecs_add_pair(world, base_child_c, Rel, TgtC);
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
test_assert(inst != 0);
ecs_entity_t child_a = ecs_lookup_child(world, inst, "ChildA");
ecs_entity_t child_b = ecs_lookup_child(world, inst, "ChildB");
ecs_entity_t child_c = ecs_lookup_child(world, inst, "ChildC");
test_assert(child_a != 0);
test_assert(child_b != 0);
test_assert(child_c != 0);
test_assert(ecs_has_pair(world, child_a, Rel, TgtA));
test_assert(ecs_has_pair(world, child_b, Rel, TgtB));
test_assert(ecs_has_pair(world, child_c, Rel, TgtC));
ecs_fini(world);
}
void Prefab_override_twice_w_add(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_new_id(world);
ecs_set(world, base, Position, {10});
ecs_override(world, base, Position);
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, base);
ecs_set(world, e1, Position, { 20 });
ecs_entity_t e2 = ecs_new_w_pair(world, EcsIsA, base);
ecs_add(world, e2, Position);
const Position *ptr = ecs_get(world, e1, Position);
test_assert(ptr != NULL);
test_int(ptr->x, 20);
ptr = ecs_get(world, e2, Position);
test_assert(ptr != NULL);
test_int(ptr->x, 10);
ecs_fini(world);
}
void Prefab_override_twice_w_set(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_entity_t base = ecs_new_id(world);
ecs_set(world, base, Position, {10});
ecs_override(world, base, Position);
ecs_entity_t e1 = ecs_new_w_pair(world, EcsIsA, base);
ecs_set(world, e1, Position, { 20 });
ecs_entity_t e2 = ecs_new_w_pair(world, EcsIsA, base);
ecs_set(world, e2, Position, {30});
const Position *ptr = ecs_get(world, e1, Position);
test_assert(ptr != NULL);
test_int(ptr->x, 20);
ptr = ecs_get(world, e2, Position);
test_assert(ptr != NULL);
test_int(ptr->x, 30);
ecs_fini(world);
}
static int position_copy_invoked = 0;
static ECS_COPY(Position, dst, src, {
dst->x = src->x;
dst->y = src->y;
position_copy_invoked ++;
})
void Prefab_auto_override_copy_once(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ecs_set_hooks(world, Position, {
.copy = ecs_copy(Position)
});
ecs_entity_t base = ecs_new_id(world);
ecs_set(world, base, Position, {10, 20});
ecs_override(world, base, Position);
test_int(position_copy_invoked, 1);
position_copy_invoked = 0;
ecs_entity_t inst = ecs_new_w_pair(world, EcsIsA, base);
const Position *ptr = ecs_get(world, inst, Position);
test_assert(ptr != NULL);
test_int(ptr->x, 10);
test_int(ptr->y, 20);
test_int(position_copy_invoked, 1);
ecs_fini(world);
}
void Prefab_always_override(void) {
ecs_world_t *world = ecs_mini();
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_add_id(world, ecs_id(Position), EcsAlwaysOverride);
ecs_entity_t b = ecs_new_id(world);
ecs_set(world, b, Position, {10, 20});
ecs_set(world, b, Velocity, {1, 2});
ecs_entity_t i = ecs_new_w_pair(world, EcsIsA, b);
test_assert(ecs_has(world, i, Position));
test_assert(ecs_has(world, i, Velocity));
test_assert(ecs_owns(world, i, Position));
test_assert(!ecs_owns(world, i, Velocity));
{
const Position *ptr = ecs_get(world, i, Position);
test_assert(ptr != NULL);
test_int(ptr->x, 10);
test_int(ptr->y, 20);
}
{
const Velocity *ptr = ecs_get(world, i, Velocity);
test_assert(ptr != NULL);
test_int(ptr->x, 1);
test_int(ptr->y, 2);
}
ecs_fini(world);
}
void Prefab_always_override_pair(void) {
ecs_world_t *world = ecs_mini();
ECS_TAG(world, RelA);
ECS_TAG(world, RelB);
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
ecs_add_id(world, RelA, EcsAlwaysOverride);
ecs_entity_t b = ecs_new_id(world);
ecs_set_pair_second(world, b, RelA, Position, {10, 20});
ecs_set_pair_second(world, b, RelB, Velocity, {1, 2});
ecs_entity_t i = ecs_new_w_pair(world, EcsIsA, b);
test_assert(ecs_has_pair(world, i, RelA, ecs_id(Position)));
test_assert(ecs_has_pair(world, i, RelB, ecs_id(Velocity)));
test_assert(ecs_owns_pair(world, i, RelA, ecs_id(Position)));
test_assert(!ecs_owns_pair(world, i, RelB, ecs_id(Velocity)));
{
const Position *ptr = ecs_get_pair_second(world, i, RelA, Position);
test_assert(ptr != NULL);
test_int(ptr->x, 10);
test_int(ptr->y, 20);
}
{
const Velocity *ptr = ecs_get_pair_second(world, i, RelB, Velocity);
test_assert(ptr != NULL);
test_int(ptr->x, 1);
test_int(ptr->y, 2);
}
ecs_fini(world);
}
void Prefab_child_of_prefab_is_prefab(void) {
ecs_world_t *world = ecs_mini();
ecs_entity_t base = ecs_new_w_id(world, EcsPrefab);
ecs_entity_t inst = ecs_new_w_pair(world, EcsChildOf, base);
test_assert(ecs_has_id(world, inst, EcsPrefab));
ecs_entity_t inst_child = ecs_new_w_pair(world, EcsChildOf, inst);
test_assert(ecs_has_id(world, inst_child, EcsPrefab));
ecs_fini(world);
}
void Prefab_override_exclusive(void) {
ecs_world_t* ecs = ecs_mini();
ECS_ENTITY(ecs, Rel, Exclusive);
ecs_entity_t t1 = ecs_new_id(ecs);
ecs_entity_t t2 = ecs_new_id(ecs);
ecs_entity_t e = ecs_new_id(ecs);
ecs_add_pair(ecs, e, Rel, t1);
ecs_entity_t p = ecs_new_id(ecs);
ecs_override_pair(ecs, p, Rel, t2);
ecs_add_pair(ecs, e, EcsIsA, p);
test_assert(ecs_has_pair(ecs, e, Rel, t2));
test_assert(!ecs_has_pair(ecs, e, Rel, t1));
ecs_fini(ecs);
}
void Prefab_override_exclusive_2_lvls(void) {
ecs_world_t* ecs = ecs_mini();
ECS_ENTITY(ecs, Rel, Exclusive);
ecs_entity_t t1 = ecs_new_id(ecs);
ecs_entity_t t2 = ecs_new_id(ecs);
ecs_entity_t t3 = ecs_new_id(ecs);
ecs_entity_t e = ecs_new_id(ecs);
ecs_add_pair(ecs, e, Rel, t1);
ecs_entity_t p = ecs_new_id(ecs);
ecs_override_pair(ecs, p, Rel, t2);
ecs_entity_t p2 = ecs_new_id(ecs);
ecs_override_pair(ecs, p2, Rel, t3);
ecs_add_pair(ecs, p2, EcsIsA, p);
ecs_add_pair(ecs, e, EcsIsA, p2);
test_assert(ecs_has_pair(ecs, e, Rel, t2));
test_assert(!ecs_has_pair(ecs, e, Rel, t1));
test_assert(!ecs_has_pair(ecs, e, Rel, t3));
ecs_fini(ecs);
}
static
ecs_entity_t make_prefabs(ecs_world_t *ecs) {
ecs_entity_t root = ecs_new_w_id(ecs, EcsPrefab);
ecs_entity_t parent = ecs_new_w_pair(ecs, EcsChildOf, root);
ecs_new_w_pair(ecs, EcsChildOf, parent);
return root;
}
void Prefab_hierarchy_w_recycled_id(void) {
ecs_world_t* ecs = ecs_mini();
{
ecs_entity_t p = make_prefabs(ecs);
test_assert(p != 0);
ecs_entity_t i = ecs_new_w_pair(ecs, EcsIsA, p);
test_assert(i != 0);
ecs_delete(ecs, i);
}
{
ecs_entity_t p = make_prefabs(ecs);
test_assert(p != 0);
ecs_entity_t i = ecs_new_w_pair(ecs, EcsIsA, p);
test_assert(i != 0);
}
ecs_fini(ecs);
}