2366 lines
54 KiB
C++
2366 lines
54 KiB
C++
#include <cpp_api.h>
|
|
|
|
struct Pair {
|
|
float value;
|
|
};
|
|
|
|
void Query_action(void) {
|
|
flecs::world world;
|
|
|
|
world.component<Position>();
|
|
world.component<Velocity>();
|
|
|
|
auto entity = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto q = world.query<Position, Velocity>();
|
|
|
|
q.iter([](flecs::iter& it, Position *p, Velocity *v) {
|
|
for (auto i : it) {
|
|
p[i].x += v[i].x;
|
|
p[i].y += v[i].y;
|
|
}
|
|
});
|
|
|
|
const Position *p = entity.get<Position>();
|
|
test_int(p->x, 11);
|
|
test_int(p->y, 22);
|
|
}
|
|
|
|
void Query_action_const(void) {
|
|
flecs::world world;
|
|
|
|
world.component<Position>();
|
|
world.component<Velocity>();
|
|
|
|
auto entity = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto q = world.query<Position, const Velocity>();
|
|
|
|
q.iter([](flecs::iter& it, Position *p, const Velocity *v) {
|
|
for (auto i : it) {
|
|
p[i].x += v[i].x;
|
|
p[i].y += v[i].y;
|
|
}
|
|
});
|
|
|
|
const Position *p = entity.get<Position>();
|
|
test_int(p->x, 11);
|
|
test_int(p->y, 22);
|
|
}
|
|
|
|
void Query_action_shared(void) {
|
|
flecs::world world;
|
|
|
|
world.component<Position>();
|
|
world.component<Velocity>();
|
|
|
|
auto base = flecs::entity(world)
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto e1 = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.add(flecs::IsA, base);
|
|
|
|
auto e2 = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({3, 4});
|
|
|
|
auto q = world.query_builder<Position>()
|
|
.expr("Velocity(self|up)")
|
|
.build();
|
|
|
|
q.iter([](flecs::iter&it, Position *p) {
|
|
auto v = it.field<const Velocity>(2);
|
|
|
|
if (!it.is_self(2)) {
|
|
for (auto i : it) {
|
|
p[i].x += v->x;
|
|
p[i].y += v->y;
|
|
}
|
|
} else {
|
|
for (auto i : it) {
|
|
p[i].x += v[i].x;
|
|
p[i].y += v[i].y;
|
|
}
|
|
}
|
|
});
|
|
|
|
const Position *p = e1.get<Position>();
|
|
test_int(p->x, 11);
|
|
test_int(p->y, 22);
|
|
|
|
p = e2.get<Position>();
|
|
test_int(p->x, 13);
|
|
test_int(p->y, 24);
|
|
}
|
|
|
|
void Query_action_optional(void) {
|
|
flecs::world world;
|
|
|
|
world.component<Position>();
|
|
world.component<Velocity>();
|
|
flecs::component<Mass>(world, "Mass");
|
|
|
|
auto e1 = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2})
|
|
.set<Mass>({1});
|
|
|
|
auto e2 = flecs::entity(world)
|
|
.set<Position>({30, 40})
|
|
.set<Velocity>({3, 4})
|
|
.set<Mass>({1});
|
|
|
|
auto e3 = flecs::entity(world)
|
|
.set<Position>({50, 60});
|
|
|
|
auto e4 = flecs::entity(world)
|
|
.set<Position>({70, 80});
|
|
|
|
auto q = world.query<Position, Velocity*, Mass*>();
|
|
|
|
q.iter([](flecs::iter& it, Position *p, Velocity *v, Mass *m) {
|
|
if (it.is_set(2) && it.is_set(3)) {
|
|
for (auto i : it) {
|
|
p[i].x += v[i].x * m[i].value;
|
|
p[i].y += v[i].y * m[i].value;
|
|
}
|
|
} else {
|
|
for (auto i : it) {
|
|
p[i].x ++;
|
|
p[i].y ++;
|
|
}
|
|
}
|
|
});
|
|
|
|
const Position *p = e1.get<Position>();
|
|
test_int(p->x, 11);
|
|
test_int(p->y, 22);
|
|
|
|
p = e2.get<Position>();
|
|
test_int(p->x, 33);
|
|
test_int(p->y, 44);
|
|
|
|
p = e3.get<Position>();
|
|
test_int(p->x, 51);
|
|
test_int(p->y, 61);
|
|
|
|
p = e4.get<Position>();
|
|
test_int(p->x, 71);
|
|
test_int(p->y, 81);
|
|
}
|
|
|
|
void Query_each(void) {
|
|
flecs::world world;
|
|
|
|
world.component<Position>();
|
|
world.component<Velocity>();
|
|
|
|
auto entity = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto q = world.query<Position, Velocity>();
|
|
|
|
q.each([](flecs::entity e, Position& p, Velocity& v) {
|
|
p.x += v.x;
|
|
p.y += v.y;
|
|
});
|
|
|
|
const Position *p = entity.get<Position>();
|
|
test_int(p->x, 11);
|
|
test_int(p->y, 22);
|
|
}
|
|
|
|
void Query_each_const(void) {
|
|
flecs::world world;
|
|
|
|
world.component<Position>();
|
|
world.component<Velocity>();
|
|
|
|
auto entity = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto q = world.query<Position, const Velocity>();
|
|
|
|
q.each([](flecs::entity e, Position& p, const Velocity& v) {
|
|
p.x += v.x;
|
|
p.y += v.y;
|
|
});
|
|
|
|
const Position *p = entity.get<Position>();
|
|
test_int(p->x, 11);
|
|
test_int(p->y, 22);
|
|
}
|
|
|
|
void Query_each_shared(void) {
|
|
flecs::world world;
|
|
|
|
world.component<Position>();
|
|
world.component<Velocity>();
|
|
|
|
auto base = flecs::entity(world)
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto e1 = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.add(flecs::IsA, base);
|
|
|
|
auto e2 = flecs::entity(world)
|
|
.set<Position>({20, 30})
|
|
.add(flecs::IsA, base);
|
|
|
|
auto e3 = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({3, 4});
|
|
|
|
auto q = world.query<Position, const Velocity>();
|
|
|
|
q.each([](flecs::entity e, Position& p, const Velocity& v) {
|
|
p.x += v.x;
|
|
p.y += v.y;
|
|
});
|
|
|
|
const Position *p = e1.get<Position>();
|
|
test_int(p->x, 11);
|
|
test_int(p->y, 22);
|
|
|
|
p = e2.get<Position>();
|
|
test_int(p->x, 21);
|
|
test_int(p->y, 32);
|
|
|
|
p = e3.get<Position>();
|
|
test_int(p->x, 13);
|
|
test_int(p->y, 24);
|
|
}
|
|
|
|
void Query_each_optional(void) {
|
|
flecs::world world;
|
|
|
|
world.component<Position>();
|
|
world.component<Velocity>();
|
|
flecs::component<Mass>(world, "Mass");
|
|
|
|
auto e1 = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2})
|
|
.set<Mass>({1});
|
|
|
|
auto e2 = flecs::entity(world)
|
|
.set<Position>({30, 40})
|
|
.set<Velocity>({3, 4})
|
|
.set<Mass>({1});
|
|
|
|
auto e3 = flecs::entity(world)
|
|
.set<Position>({50, 60});
|
|
|
|
auto e4 = flecs::entity(world)
|
|
.set<Position>({70, 80});
|
|
|
|
auto q = world.query<Position, Velocity*, Mass*>();
|
|
|
|
q.each([](flecs::entity e, Position& p, Velocity* v, Mass *m) {
|
|
if (v && m) {
|
|
p.x += v->x * m->value;
|
|
p.y += v->y * m->value;
|
|
} else {
|
|
p.x ++;
|
|
p.y ++;
|
|
}
|
|
});
|
|
|
|
const Position *p = e1.get<Position>();
|
|
test_int(p->x, 11);
|
|
test_int(p->y, 22);
|
|
|
|
p = e2.get<Position>();
|
|
test_int(p->x, 33);
|
|
test_int(p->y, 44);
|
|
|
|
p = e3.get<Position>();
|
|
test_int(p->x, 51);
|
|
test_int(p->y, 61);
|
|
|
|
p = e4.get<Position>();
|
|
test_int(p->x, 71);
|
|
test_int(p->y, 81);
|
|
}
|
|
|
|
void Query_signature(void) {
|
|
flecs::world world;
|
|
|
|
world.component<Position>();
|
|
world.component<Velocity>();
|
|
|
|
auto entity = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto q = world.query_builder<>().expr("Position, Velocity").build();
|
|
|
|
q.iter([](flecs::iter& it) {
|
|
auto p = it.field<Position>(1);
|
|
auto v = it.field<Velocity>(2);
|
|
|
|
for (auto i : it) {
|
|
p[i].x += v[i].x;
|
|
p[i].y += v[i].y;
|
|
}
|
|
});
|
|
|
|
const Position *p = entity.get<Position>();
|
|
test_int(p->x, 11);
|
|
test_int(p->y, 22);
|
|
}
|
|
|
|
void Query_signature_const(void) {
|
|
flecs::world world;
|
|
|
|
world.component<Position>();
|
|
world.component<Velocity>();
|
|
|
|
auto entity = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto q = world.query_builder<>().expr("Position, [in] Velocity").build();
|
|
|
|
q.iter([](flecs::iter& it) {
|
|
auto p = it.field<Position>(1);
|
|
auto v = it.field<const Velocity>(2);
|
|
|
|
for (auto i : it) {
|
|
p[i].x += v[i].x;
|
|
p[i].y += v[i].y;
|
|
}
|
|
});
|
|
|
|
const Position *p = entity.get<Position>();
|
|
test_int(p->x, 11);
|
|
test_int(p->y, 22);
|
|
}
|
|
|
|
void Query_signature_shared(void) {
|
|
flecs::world world;
|
|
|
|
world.component<Position>();
|
|
world.component<Velocity>();
|
|
|
|
auto base = flecs::entity(world)
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto e1 = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.add(flecs::IsA, base);
|
|
|
|
auto e2 = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({3, 4});
|
|
|
|
auto q = world.query_builder<>()
|
|
.expr("Position, [in] Velocity(self|up)")
|
|
.build();
|
|
|
|
q.iter([](flecs::iter&it) {
|
|
auto p = it.field<Position>(1);
|
|
auto v = it.field<const Velocity>(2);
|
|
|
|
if (!it.is_self(2)) {
|
|
for (auto i : it) {
|
|
p[i].x += v->x;
|
|
p[i].y += v->y;
|
|
}
|
|
} else {
|
|
for (auto i : it) {
|
|
p[i].x += v[i].x;
|
|
p[i].y += v[i].y;
|
|
}
|
|
}
|
|
});
|
|
|
|
const Position *p = e1.get<Position>();
|
|
test_int(p->x, 11);
|
|
test_int(p->y, 22);
|
|
|
|
p = e2.get<Position>();
|
|
test_int(p->x, 13);
|
|
test_int(p->y, 24);
|
|
}
|
|
|
|
void Query_signature_optional(void) {
|
|
flecs::world world;
|
|
|
|
world.component<Position>();
|
|
world.component<Velocity>();
|
|
flecs::component<Mass>(world, "Mass");
|
|
|
|
auto e1 = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2})
|
|
.set<Mass>({1});
|
|
|
|
auto e2 = flecs::entity(world)
|
|
.set<Position>({30, 40})
|
|
.set<Velocity>({3, 4})
|
|
.set<Mass>({1});
|
|
|
|
auto e3 = flecs::entity(world)
|
|
.set<Position>({50, 60});
|
|
|
|
auto e4 = flecs::entity(world)
|
|
.set<Position>({70, 80});
|
|
|
|
auto q = world.query_builder<>().expr("Position, ?Velocity, ?Mass").build();
|
|
|
|
q.iter([](flecs::iter& it) {
|
|
auto p = it.field<Position>(1);
|
|
auto v = it.field<const Velocity>(2);
|
|
auto m = it.field<const Mass>(3);
|
|
|
|
if (it.is_set(2) && it.is_set(3)) {
|
|
for (auto i : it) {
|
|
p[i].x += v[i].x * m[i].value;
|
|
p[i].y += v[i].y * m[i].value;
|
|
}
|
|
} else {
|
|
for (auto i : it) {
|
|
p[i].x ++;
|
|
p[i].y ++;
|
|
}
|
|
}
|
|
});
|
|
|
|
const Position *p = e1.get<Position>();
|
|
test_int(p->x, 11);
|
|
test_int(p->y, 22);
|
|
|
|
p = e2.get<Position>();
|
|
test_int(p->x, 33);
|
|
test_int(p->y, 44);
|
|
|
|
p = e3.get<Position>();
|
|
test_int(p->x, 51);
|
|
test_int(p->y, 61);
|
|
|
|
p = e4.get<Position>();
|
|
test_int(p->x, 71);
|
|
test_int(p->y, 81);
|
|
}
|
|
|
|
void Query_subquery(void) {
|
|
flecs::world world;
|
|
|
|
auto e1 = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto e2 = flecs::entity(world)
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto q = world.query<Position>();
|
|
auto sq = world.query_builder<Velocity>().observable(q).build();
|
|
|
|
sq.each([](flecs::entity e, Velocity& v) {
|
|
v.x ++;
|
|
v.y ++;
|
|
});
|
|
|
|
const Velocity *v = e1.get<Velocity>();
|
|
test_int(v->x, 2);
|
|
test_int(v->y, 3);
|
|
|
|
v = e2.get<Velocity>();
|
|
test_int(v->x, 1);
|
|
test_int(v->y, 2);
|
|
}
|
|
|
|
void Query_subquery_w_expr(void) {
|
|
flecs::world world;
|
|
|
|
auto e1 = flecs::entity(world)
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto e2 = flecs::entity(world)
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto q = world.query<Position>();
|
|
auto sq = world.query_builder<>().observable(q).expr("Velocity").build();
|
|
|
|
sq.iter([](flecs::iter it) {
|
|
auto v = it.field<Velocity>(1);
|
|
|
|
for (auto i : it) {
|
|
v[i].x ++;
|
|
v[i].y ++;
|
|
}
|
|
});
|
|
|
|
const Velocity *v = e1.get<Velocity>();
|
|
test_int(v->x, 2);
|
|
test_int(v->y, 3);
|
|
|
|
v = e2.get<Velocity>();
|
|
test_int(v->x, 1);
|
|
test_int(v->y, 2);
|
|
}
|
|
|
|
void Query_query_single_pair(void) {
|
|
flecs::world world;
|
|
|
|
flecs::entity(world).add<Pair, Position>();
|
|
auto e2 = flecs::entity(world).add<Pair, Velocity>();
|
|
|
|
auto q = world.query_builder<>()
|
|
.expr("(Pair, Velocity)")
|
|
.build();
|
|
|
|
int32_t table_count = 0;
|
|
int32_t entity_count = 0;
|
|
|
|
q.iter([&](flecs::iter it) {
|
|
table_count ++;
|
|
for (auto i : it) {
|
|
test_assert(it.entity(i) == e2);
|
|
entity_count ++;
|
|
}
|
|
});
|
|
|
|
test_int(table_count, 1);
|
|
test_int(entity_count, 1);
|
|
}
|
|
|
|
void Query_tag_w_each(void) {
|
|
flecs::world world;
|
|
|
|
auto q = world.query<Tag>();
|
|
|
|
auto e = world.entity()
|
|
.add<Tag>();
|
|
|
|
q.each([&](flecs::entity qe, Tag) {
|
|
test_assert(qe == e);
|
|
});
|
|
}
|
|
|
|
void Query_shared_tag_w_each(void) {
|
|
flecs::world world;
|
|
|
|
auto q = world.query<Tag>();
|
|
|
|
auto base = world.prefab()
|
|
.add<Tag>();
|
|
|
|
auto e = world.entity()
|
|
.add(flecs::IsA, base);
|
|
|
|
q.each([&](flecs::entity qe, Tag) {
|
|
test_assert(qe == e);
|
|
});
|
|
}
|
|
|
|
static
|
|
int compare_position(
|
|
flecs::entity_t e1,
|
|
const Position *p1,
|
|
flecs::entity_t e2,
|
|
const Position *p2)
|
|
{
|
|
return (p1->x > p2->x) - (p1->x < p2->x);
|
|
}
|
|
|
|
void Query_sort_by(void) {
|
|
flecs::world world;
|
|
|
|
world.entity().set<Position>({1, 0});
|
|
world.entity().set<Position>({6, 0});
|
|
world.entity().set<Position>({2, 0});
|
|
world.entity().set<Position>({5, 0});
|
|
world.entity().set<Position>({4, 0});
|
|
|
|
auto q = world.query_builder<Position>()
|
|
.order_by(compare_position)
|
|
.build();
|
|
|
|
q.iter([](flecs::iter it, Position *p) {
|
|
test_int(it.count(), 5);
|
|
test_int(p[0].x, 1);
|
|
test_int(p[1].x, 2);
|
|
test_int(p[2].x, 4);
|
|
test_int(p[3].x, 5);
|
|
test_int(p[4].x, 6);
|
|
});
|
|
}
|
|
|
|
void Query_changed(void) {
|
|
flecs::world world;
|
|
|
|
auto e = world.entity().set<Position>({1, 0});
|
|
|
|
auto q = world.query<const Position>();
|
|
auto q_w = world.query<Position>();
|
|
|
|
test_bool(q.changed(), true);
|
|
|
|
q.each([](const Position& p) { });
|
|
test_bool(q.changed(), false);
|
|
|
|
e.set<Position>({2, 0});
|
|
test_bool(q.changed(), true);
|
|
|
|
q.each([](const Position& p) { });
|
|
test_bool(q.changed(), false); // Reset state
|
|
|
|
q_w.each([](Position& p) { }); // Query has out term
|
|
test_bool(q.changed(), true);
|
|
}
|
|
|
|
void Query_orphaned(void) {
|
|
flecs::world world;
|
|
|
|
auto q = world.query<Position>();
|
|
auto sq = world.query_builder<Position>().observable(q).build();
|
|
|
|
test_assert(!q.orphaned());
|
|
test_assert(!sq.orphaned());
|
|
|
|
q.destruct();
|
|
|
|
test_assert(sq.orphaned());
|
|
}
|
|
|
|
void Query_default_ctor(void) {
|
|
flecs::world world;
|
|
|
|
flecs::query<Position> q_var;
|
|
|
|
int count = 0;
|
|
auto q = world.query<Position>();
|
|
|
|
world.entity().set<Position>({10, 20});
|
|
|
|
q_var = q;
|
|
|
|
q_var.each([&](flecs::entity e, Position& p) {
|
|
test_int(p.x, 10);
|
|
test_int(p.y, 20);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void Query_expr_w_template(void) {
|
|
flecs::world world;
|
|
|
|
auto comp = world.component<Template<int>>();
|
|
test_str(comp.name(), "Template<int>");
|
|
|
|
int count = 0;
|
|
auto q = world.query_builder<Position>().expr("Template<int>").build();
|
|
|
|
world.entity()
|
|
.set<Position>({10, 20})
|
|
.set<Template<int>>({30, 40});
|
|
|
|
q.each([&](flecs::entity e, Position& p) {
|
|
test_int(p.x, 10);
|
|
test_int(p.y, 20);
|
|
|
|
const Template<int> *t = e.get<Template<int>>();
|
|
test_int(t->x, 30);
|
|
test_int(t->y, 40);
|
|
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void Query_query_type_w_template(void) {
|
|
flecs::world world;
|
|
|
|
auto comp = world.component<Template<int>>();
|
|
test_str(comp.name(), "Template<int>");
|
|
|
|
int count = 0;
|
|
auto q = world.query<Position, Template<int>>();
|
|
|
|
world.entity()
|
|
.set<Position>({10, 20})
|
|
.set<Template<int>>({30, 40});
|
|
|
|
q.each([&](flecs::entity e, Position& p, Template<int>& t) {
|
|
test_int(p.x, 10);
|
|
test_int(p.y, 20);
|
|
|
|
test_int(t.x, 30);
|
|
test_int(t.y, 40);
|
|
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void Query_compare_term_id(void) {
|
|
flecs::world world;
|
|
|
|
int count = 0;
|
|
auto e = world.entity().add<Tag>();
|
|
|
|
auto q = world.query_builder<>()
|
|
.term<Tag>()
|
|
.build();
|
|
|
|
q.iter([&](flecs::iter& it) {
|
|
test_assert(it.id(1) == it.world().id<Tag>());
|
|
test_assert(it.entity(0) == e);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void Query_test_no_defer_each(void) {
|
|
install_test_abort();
|
|
|
|
flecs::world world;
|
|
|
|
struct Value { int value; };
|
|
|
|
world.entity().add<Tag>().set<Value>({10});
|
|
|
|
auto q = world.query_builder<Value>().term<Tag>().build();
|
|
|
|
q.each([](flecs::entity e, Value& v) {
|
|
test_expect_abort();
|
|
e.remove<Tag>();
|
|
});
|
|
|
|
test_assert(false); // Should never get here
|
|
}
|
|
|
|
void Query_test_no_defer_iter(void) {
|
|
install_test_abort();
|
|
|
|
flecs::world world;
|
|
|
|
struct Value { int value; };
|
|
|
|
world.entity().add<Tag>().set<Value>({10});
|
|
|
|
auto q = world.query_builder<Value>().term<Tag>().build();
|
|
|
|
q.iter([](flecs::iter& it, Value *v) {
|
|
for (auto i : it) {
|
|
test_expect_abort();
|
|
it.entity(i).remove<Tag>();
|
|
}
|
|
});
|
|
|
|
test_assert(false); // Should never get here
|
|
}
|
|
|
|
void Query_inspect_terms(void) {
|
|
flecs::world world;
|
|
|
|
auto p = world.entity();
|
|
|
|
auto q = world.query_builder<Position>()
|
|
.term<Velocity>()
|
|
.term(flecs::ChildOf, p)
|
|
.build();
|
|
|
|
test_int(3, q.field_count());
|
|
|
|
auto t = q.term(0);
|
|
test_int(t.id(), world.id<Position>());
|
|
test_int(t.oper(), flecs::And);
|
|
test_int(t.inout(), flecs::InOutDefault);
|
|
|
|
t = q.term(1);
|
|
test_int(t.id(), world.id<Velocity>());
|
|
test_int(t.oper(), flecs::And);
|
|
test_int(t.inout(), flecs::InOutDefault);
|
|
|
|
t = q.term(2);
|
|
test_int(t.id(), world.pair(flecs::ChildOf, p));
|
|
test_int(t.oper(), flecs::And);
|
|
test_int(t.inout(), flecs::InOutDefault);
|
|
test_assert(t.id().second() == p);
|
|
}
|
|
|
|
void Query_inspect_terms_w_each(void) {
|
|
flecs::world world;
|
|
|
|
auto p = world.entity();
|
|
|
|
auto q = world.query_builder<Position>()
|
|
.term<Velocity>()
|
|
.term(flecs::ChildOf, p)
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
q.each_term([&](flecs::term& t) {
|
|
if (count == 0) {
|
|
test_int(t.id(), world.id<Position>());
|
|
} else if (count == 1) {
|
|
test_int(t.id(), world.id<Velocity>());
|
|
} else if (count == 2) {
|
|
test_int(t.id(), world.pair(flecs::ChildOf, p));
|
|
test_assert(t.id().second() == p);
|
|
} else {
|
|
test_assert(false);
|
|
}
|
|
|
|
test_int(t.oper(), flecs::And);
|
|
test_int(t.inout(), flecs::InOutDefault);
|
|
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void Query_inspect_terms_w_expr(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::query<> f = ecs.query_builder()
|
|
.expr("(ChildOf,0)")
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
f.each_term([&](flecs::term &term) {
|
|
test_assert(term.id().is_pair());
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void Query_comp_to_str(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Position>()
|
|
.term<Velocity>()
|
|
.build();
|
|
test_str(q.str(), "Position, Velocity");
|
|
}
|
|
|
|
struct Eats { int amount; };
|
|
struct Apples { };
|
|
struct Pears { };
|
|
|
|
void Query_pair_to_str(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Position>()
|
|
.term<Velocity>()
|
|
.term<Eats, Apples>()
|
|
.build();
|
|
test_str(q.str(), "Position, Velocity, (Eats,Apples)");
|
|
}
|
|
|
|
void Query_oper_not_to_str(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Position>()
|
|
.term<Velocity>().oper(flecs::Not)
|
|
.build();
|
|
test_str(q.str(), "Position, !Velocity");
|
|
}
|
|
|
|
void Query_oper_optional_to_str(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Position>()
|
|
.term<Velocity>().oper(flecs::Optional)
|
|
.build();
|
|
test_str(q.str(), "Position, ?Velocity");
|
|
}
|
|
|
|
void Query_oper_or_to_str(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term<Position>().oper(flecs::Or)
|
|
.term<Velocity>()
|
|
.build();
|
|
test_str(q.str(), "Position || Velocity");
|
|
}
|
|
|
|
using EatsApples = flecs::pair<Eats, Apples>;
|
|
using EatsPears = flecs::pair<Eats, Pears>;
|
|
|
|
void Query_each_pair_type(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e1 = ecs.entity()
|
|
.set<EatsApples>({10});
|
|
|
|
ecs.entity()
|
|
.set<EatsPears>({20});
|
|
|
|
auto q = ecs.query<EatsApples>();
|
|
|
|
int count = 0;
|
|
q.each([&](flecs::entity e, EatsApples&& a) {
|
|
test_int(a->amount, 10);
|
|
test_assert(e == e1);
|
|
a->amount ++;
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
|
|
auto v = e1.get<EatsApples>();
|
|
test_assert(v != NULL);
|
|
test_int(v->amount, 11);
|
|
}
|
|
|
|
void Query_iter_pair_type(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e1 = ecs.entity()
|
|
.set<EatsApples>({10});
|
|
|
|
ecs.entity()
|
|
.set<EatsPears>({20});
|
|
|
|
auto q = ecs.query<EatsApples>();
|
|
|
|
int count = 0;
|
|
q.iter([&](flecs::iter& it, Eats* a) {
|
|
test_int(it.count(), 1);
|
|
|
|
test_int(a->amount, 10);
|
|
test_assert(it.entity(0) == e1);
|
|
|
|
a->amount ++;
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
|
|
auto v = e1.get<EatsApples>();
|
|
test_assert(v != NULL);
|
|
test_int(v->amount, 11);
|
|
}
|
|
|
|
void Query_term_pair_type(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e1 = ecs.entity()
|
|
.set<EatsApples>({10});
|
|
|
|
ecs.entity()
|
|
.set<EatsPears>({20});
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term<EatsApples>()
|
|
.build();
|
|
|
|
int count = 0;
|
|
q.iter([&](flecs::iter& it) {
|
|
test_int(it.count(), 1);
|
|
|
|
auto a = it.field<EatsApples>(1);
|
|
|
|
test_int(a->amount, 10);
|
|
test_assert(it.entity(0) == e1);
|
|
|
|
a->amount ++;
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
|
|
auto v = e1.get<EatsApples>();
|
|
test_assert(v != NULL);
|
|
test_int(v->amount, 11);
|
|
}
|
|
|
|
void Query_each_no_entity_1_comp(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity()
|
|
.set(Position{1, 2});
|
|
|
|
auto q = ecs.query<Position>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](Position& p) {
|
|
test_int(p.x, 1);
|
|
test_int(p.y, 2);
|
|
p.x += 1;
|
|
p.y += 2;
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
|
|
auto pos = e.get<Position>();
|
|
test_int(pos->x, 2);
|
|
test_int(pos->y, 4);
|
|
}
|
|
|
|
void Query_each_no_entity_2_comps(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity()
|
|
.set(Position{1, 2})
|
|
.set(Velocity{10, 20});
|
|
|
|
auto q = ecs.query<Position, Velocity>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](Position& p, Velocity& v) {
|
|
test_int(p.x, 1);
|
|
test_int(p.y, 2);
|
|
test_int(v.x, 10);
|
|
test_int(v.y, 20);
|
|
|
|
p.x += 1;
|
|
p.y += 2;
|
|
v.x += 1;
|
|
v.y += 2;
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
|
|
test_bool(e.get([](const Position& p, const Velocity& v) {
|
|
test_int(p.x, 2);
|
|
test_int(p.y, 4);
|
|
|
|
test_int(v.x, 11);
|
|
test_int(v.y, 22);
|
|
}), true);
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void Query_iter_no_comps_1_comp(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.entity().add<Position>();
|
|
ecs.entity().add<Position>();
|
|
ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Velocity>();
|
|
|
|
auto q = ecs.query<Position>();
|
|
|
|
int32_t count = 0;
|
|
q.iter([&](flecs::iter& it) {
|
|
count += it.count();
|
|
});
|
|
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void Query_iter_no_comps_2_comps(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.entity().add<Velocity>();
|
|
ecs.entity().add<Position>();
|
|
ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Position>().add<Velocity>();
|
|
|
|
auto q = ecs.query<Position, Velocity>();
|
|
|
|
int32_t count = 0;
|
|
q.iter([&](flecs::iter& it) {
|
|
|
|
count += it.count();
|
|
});
|
|
|
|
test_int(count, 2);
|
|
}
|
|
|
|
void Query_iter_no_comps_no_comps(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.entity().add<Velocity>();
|
|
ecs.entity().add<Position>();
|
|
ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Position>().add<Velocity>();
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term<Position>()
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
q.iter([&](flecs::iter& it) {
|
|
count += it.count();
|
|
});
|
|
|
|
test_int(count, 3);
|
|
}
|
|
|
|
#include <iostream>
|
|
|
|
struct Event {
|
|
const char *value;
|
|
};
|
|
|
|
struct Begin { };
|
|
struct End { };
|
|
|
|
using BeginEvent = flecs::pair<Begin, Event>;
|
|
using EndEvent = flecs::pair<End, Event>;
|
|
|
|
void Query_each_pair_object(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e1 = ecs.entity()
|
|
.set_second<Begin, Event>({"Big Bang"})
|
|
.set<EndEvent>({"Heat Death"});
|
|
|
|
auto q = ecs.query<BeginEvent, EndEvent>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, BeginEvent b_e, EndEvent e_e) {
|
|
test_assert(e == e1);
|
|
test_str(b_e->value, "Big Bang");
|
|
test_str(e_e->value, "Heat Death");
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void Query_iter_pair_object(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e1 = ecs.entity()
|
|
.set_second<Begin, Event>({"Big Bang"})
|
|
.set<EndEvent>({"Heat Death"});
|
|
|
|
auto q = ecs.query<BeginEvent, EndEvent>();
|
|
|
|
int32_t count = 0;
|
|
q.iter([&](flecs::iter it, Event *b_e, Event *e_e) {
|
|
for (auto i : it) {
|
|
test_assert(it.entity(i) == e1);
|
|
test_str(b_e[i].value, "Big Bang");
|
|
test_str(e_e[i].value, "Heat Death");
|
|
count ++;
|
|
}
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void Query_iter_query_in_system(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.entity().add<Position>().add<Velocity>();
|
|
|
|
auto q = ecs.query<Velocity>();
|
|
|
|
int32_t count = 0;
|
|
ecs.system<Position>()
|
|
.each([&](flecs::entity e1, Position&) {
|
|
q.each([&](flecs::entity e2, Velocity&) {
|
|
count ++;
|
|
});
|
|
});
|
|
|
|
ecs.progress();
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void Query_iter_type(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.entity().add<Position>();
|
|
ecs.entity().add<Position>().add<Velocity>();
|
|
|
|
auto q = ecs.query<Position>();
|
|
|
|
q.iter([&](flecs::iter it) {
|
|
test_assert(it.type().count() >= 1);
|
|
test_assert(it.table().has<Position>());
|
|
});
|
|
}
|
|
|
|
void Query_instanced_query_w_singleton_each(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.set<Velocity>({1, 2});
|
|
|
|
auto e1 = ecs.entity().set<Position>({10, 20}); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity().set<Position>({20, 30}); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity().set<Position>({30, 40}); e3.set<Self>({e3});
|
|
auto e4 = ecs.entity().set<Position>({40, 50}); e4.set<Self>({e4});
|
|
auto e5 = ecs.entity().set<Position>({50, 60}); e5.set<Self>({e5});
|
|
|
|
e4.add<Tag>();
|
|
e5.add<Tag>();
|
|
|
|
auto q = ecs.query_builder<Self, Position, const Velocity>()
|
|
.arg(3).singleton()
|
|
.instanced()
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Self& s, Position&p, const Velocity& v) {
|
|
test_assert(e == s.value);
|
|
p.x += v.x;
|
|
p.y += v.y;
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 5);
|
|
|
|
test_assert(e1.get([](const Position& p) {
|
|
test_int(p.x, 11);
|
|
test_int(p.y, 22);
|
|
}));
|
|
|
|
test_assert(e2.get([](const Position& p) {
|
|
test_int(p.x, 21);
|
|
test_int(p.y, 32);
|
|
}));
|
|
|
|
test_assert(e3.get([](const Position& p) {
|
|
test_int(p.x, 31);
|
|
test_int(p.y, 42);
|
|
}));
|
|
|
|
test_assert(e4.get([](const Position& p) {
|
|
test_int(p.x, 41);
|
|
test_int(p.y, 52);
|
|
}));
|
|
|
|
test_assert(e5.get([](const Position& p) {
|
|
test_int(p.x, 51);
|
|
test_int(p.y, 62);
|
|
}));
|
|
}
|
|
|
|
void Query_instanced_query_w_base_each(void) {
|
|
flecs::world ecs;
|
|
|
|
auto base = ecs.entity().set<Velocity>({1, 2});
|
|
|
|
auto e1 = ecs.entity().is_a(base).set<Position>({10, 20}); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity().is_a(base).set<Position>({20, 30}); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity().is_a(base).set<Position>({30, 40}); e3.set<Self>({e3});
|
|
auto e4 = ecs.entity().is_a(base).set<Position>({40, 50}).add<Tag>(); e4.set<Self>({e4});
|
|
auto e5 = ecs.entity().is_a(base).set<Position>({50, 60}).add<Tag>(); e5.set<Self>({e5});
|
|
auto e6 = ecs.entity().set<Position>({60, 70}).set<Velocity>({2, 3}); e6.set<Self>({e6});
|
|
auto e7 = ecs.entity().set<Position>({70, 80}).set<Velocity>({4, 5}); e7.set<Self>({e7});
|
|
|
|
auto q = ecs.query_builder<Self, Position, const Velocity>()
|
|
.instanced()
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Self& s, Position&p, const Velocity& v) {
|
|
test_assert(e == s.value);
|
|
p.x += v.x;
|
|
p.y += v.y;
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 7);
|
|
|
|
test_assert(e1.get([](const Position& p) {
|
|
test_int(p.x, 11);
|
|
test_int(p.y, 22);
|
|
}));
|
|
|
|
test_assert(e2.get([](const Position& p) {
|
|
test_int(p.x, 21);
|
|
test_int(p.y, 32);
|
|
}));
|
|
|
|
test_assert(e3.get([](const Position& p) {
|
|
test_int(p.x, 31);
|
|
test_int(p.y, 42);
|
|
}));
|
|
|
|
test_assert(e4.get([](const Position& p) {
|
|
test_int(p.x, 41);
|
|
test_int(p.y, 52);
|
|
}));
|
|
|
|
test_assert(e5.get([](const Position& p) {
|
|
test_int(p.x, 51);
|
|
test_int(p.y, 62);
|
|
}));
|
|
|
|
test_assert(e6.get([](const Position& p) {
|
|
test_int(p.x, 62);
|
|
test_int(p.y, 73);
|
|
}));
|
|
|
|
test_assert(e7.get([](const Position& p) {
|
|
test_int(p.x, 74);
|
|
test_int(p.y, 85);
|
|
}));
|
|
}
|
|
|
|
void Query_un_instanced_query_w_singleton_each(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.set<Velocity>({1, 2});
|
|
|
|
auto e1 = ecs.entity().set<Position>({10, 20}); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity().set<Position>({20, 30}); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity().set<Position>({30, 40}); e3.set<Self>({e3});
|
|
auto e4 = ecs.entity().set<Position>({40, 50}); e4.set<Self>({e4});
|
|
auto e5 = ecs.entity().set<Position>({50, 60}); e5.set<Self>({e5});
|
|
|
|
e4.add<Tag>();
|
|
e5.add<Tag>();
|
|
|
|
auto q = ecs.query_builder<Self, Position, const Velocity>()
|
|
.arg(3).singleton()
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Self& s, Position&p, const Velocity& v) {
|
|
test_assert(e == s.value);
|
|
p.x += v.x;
|
|
p.y += v.y;
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 5);
|
|
|
|
test_assert(e1.get([](const Position& p) {
|
|
test_int(p.x, 11);
|
|
test_int(p.y, 22);
|
|
}));
|
|
|
|
test_assert(e2.get([](const Position& p) {
|
|
test_int(p.x, 21);
|
|
test_int(p.y, 32);
|
|
}));
|
|
|
|
test_assert(e3.get([](const Position& p) {
|
|
test_int(p.x, 31);
|
|
test_int(p.y, 42);
|
|
}));
|
|
|
|
test_assert(e4.get([](const Position& p) {
|
|
test_int(p.x, 41);
|
|
test_int(p.y, 52);
|
|
}));
|
|
|
|
test_assert(e5.get([](const Position& p) {
|
|
test_int(p.x, 51);
|
|
test_int(p.y, 62);
|
|
}));
|
|
}
|
|
|
|
void Query_un_instanced_query_w_base_each(void) {
|
|
flecs::world ecs;
|
|
|
|
auto base = ecs.entity().set<Velocity>({1, 2});
|
|
|
|
auto e1 = ecs.entity().is_a(base).set<Position>({10, 20}); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity().is_a(base).set<Position>({20, 30}); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity().is_a(base).set<Position>({30, 40}); e3.set<Self>({e3});
|
|
auto e4 = ecs.entity().is_a(base).set<Position>({40, 50}).add<Tag>(); e4.set<Self>({e4});
|
|
auto e5 = ecs.entity().is_a(base).set<Position>({50, 60}).add<Tag>(); e5.set<Self>({e5});
|
|
auto e6 = ecs.entity().set<Position>({60, 70}).set<Velocity>({2, 3}); e6.set<Self>({e6});
|
|
auto e7 = ecs.entity().set<Position>({70, 80}).set<Velocity>({4, 5}); e7.set<Self>({e7});
|
|
|
|
auto q = ecs.query_builder<Self, Position, const Velocity>()
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Self& s, Position&p, const Velocity& v) {
|
|
test_assert(e == s.value);
|
|
p.x += v.x;
|
|
p.y += v.y;
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 7);
|
|
|
|
test_assert(e1.get([](const Position& p) {
|
|
test_int(p.x, 11);
|
|
test_int(p.y, 22);
|
|
}));
|
|
|
|
test_assert(e2.get([](const Position& p) {
|
|
test_int(p.x, 21);
|
|
test_int(p.y, 32);
|
|
}));
|
|
|
|
test_assert(e3.get([](const Position& p) {
|
|
test_int(p.x, 31);
|
|
test_int(p.y, 42);
|
|
}));
|
|
|
|
test_assert(e4.get([](const Position& p) {
|
|
test_int(p.x, 41);
|
|
test_int(p.y, 52);
|
|
}));
|
|
|
|
test_assert(e5.get([](const Position& p) {
|
|
test_int(p.x, 51);
|
|
test_int(p.y, 62);
|
|
}));
|
|
|
|
test_assert(e6.get([](const Position& p) {
|
|
test_int(p.x, 62);
|
|
test_int(p.y, 73);
|
|
}));
|
|
|
|
test_assert(e7.get([](const Position& p) {
|
|
test_int(p.x, 74);
|
|
test_int(p.y, 85);
|
|
}));
|
|
}
|
|
|
|
void Query_instanced_query_w_singleton_iter(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.set<Velocity>({1, 2});
|
|
|
|
auto e1 = ecs.entity().set<Position>({10, 20}); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity().set<Position>({20, 30}); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity().set<Position>({30, 40}); e3.set<Self>({e3});
|
|
auto e4 = ecs.entity().set<Position>({40, 50}); e4.set<Self>({e4});
|
|
auto e5 = ecs.entity().set<Position>({50, 60}); e5.set<Self>({e5});
|
|
|
|
e4.add<Tag>();
|
|
e5.add<Tag>();
|
|
|
|
auto q = ecs.query_builder<Self, Position, const Velocity>()
|
|
.arg(3).singleton()
|
|
.instanced()
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
q.iter([&](flecs::iter it, Self* s, Position* p, const Velocity* v) {
|
|
test_assert(it.count() > 1);
|
|
|
|
for (auto i : it) {
|
|
p[i].x += v->x;
|
|
p[i].y += v->y;
|
|
test_assert(it.entity(i) == s[i].value);
|
|
count ++;
|
|
}
|
|
});
|
|
|
|
test_int(count, 5);
|
|
|
|
test_assert(e1.get([](const Position& p) {
|
|
test_int(p.x, 11);
|
|
test_int(p.y, 22);
|
|
}));
|
|
|
|
test_assert(e2.get([](const Position& p) {
|
|
test_int(p.x, 21);
|
|
test_int(p.y, 32);
|
|
}));
|
|
|
|
test_assert(e3.get([](const Position& p) {
|
|
test_int(p.x, 31);
|
|
test_int(p.y, 42);
|
|
}));
|
|
|
|
test_assert(e4.get([](const Position& p) {
|
|
test_int(p.x, 41);
|
|
test_int(p.y, 52);
|
|
}));
|
|
|
|
test_assert(e5.get([](const Position& p) {
|
|
test_int(p.x, 51);
|
|
test_int(p.y, 62);
|
|
}));
|
|
}
|
|
|
|
void Query_instanced_query_w_base_iter(void) {
|
|
flecs::world ecs;
|
|
|
|
auto base = ecs.entity().set<Velocity>({1, 2});
|
|
|
|
auto e1 = ecs.entity().is_a(base).set<Position>({10, 20}); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity().is_a(base).set<Position>({20, 30}); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity().is_a(base).set<Position>({30, 40}); e3.set<Self>({e3});
|
|
auto e4 = ecs.entity().is_a(base).set<Position>({40, 50}).add<Tag>(); e4.set<Self>({e4});
|
|
auto e5 = ecs.entity().is_a(base).set<Position>({50, 60}).add<Tag>(); e5.set<Self>({e5});
|
|
auto e6 = ecs.entity().set<Position>({60, 70}).set<Velocity>({2, 3}); e6.set<Self>({e6});
|
|
auto e7 = ecs.entity().set<Position>({70, 80}).set<Velocity>({4, 5}); e7.set<Self>({e7});
|
|
|
|
auto q = ecs.query_builder<Self, Position, const Velocity>()
|
|
.instanced()
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
q.iter([&](flecs::iter it, Self* s, Position* p, const Velocity* v) {
|
|
test_assert(it.count() > 1);
|
|
|
|
for (auto i : it) {
|
|
if (it.is_self(3)) {
|
|
p[i].x += v[i].x;
|
|
p[i].y += v[i].y;
|
|
} else {
|
|
p[i].x += v->x;
|
|
p[i].y += v->y;
|
|
}
|
|
|
|
test_assert(it.entity(i) == s[i].value);
|
|
count ++;
|
|
}
|
|
});
|
|
|
|
test_int(count, 7);
|
|
|
|
test_assert(e1.get([](const Position& p) {
|
|
test_int(p.x, 11);
|
|
test_int(p.y, 22);
|
|
}));
|
|
|
|
test_assert(e2.get([](const Position& p) {
|
|
test_int(p.x, 21);
|
|
test_int(p.y, 32);
|
|
}));
|
|
|
|
test_assert(e3.get([](const Position& p) {
|
|
test_int(p.x, 31);
|
|
test_int(p.y, 42);
|
|
}));
|
|
|
|
test_assert(e4.get([](const Position& p) {
|
|
test_int(p.x, 41);
|
|
test_int(p.y, 52);
|
|
}));
|
|
|
|
test_assert(e5.get([](const Position& p) {
|
|
test_int(p.x, 51);
|
|
test_int(p.y, 62);
|
|
}));
|
|
|
|
test_assert(e6.get([](const Position& p) {
|
|
test_int(p.x, 62);
|
|
test_int(p.y, 73);
|
|
}));
|
|
|
|
test_assert(e7.get([](const Position& p) {
|
|
test_int(p.x, 74);
|
|
test_int(p.y, 85);
|
|
}));
|
|
}
|
|
|
|
void Query_un_instanced_query_w_singleton_iter(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.set<Velocity>({1, 2});
|
|
|
|
auto e1 = ecs.entity().set<Position>({10, 20}); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity().set<Position>({20, 30}); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity().set<Position>({30, 40}); e3.set<Self>({e3});
|
|
auto e4 = ecs.entity().set<Position>({40, 50}); e4.set<Self>({e4});
|
|
auto e5 = ecs.entity().set<Position>({50, 60}); e5.set<Self>({e5});
|
|
|
|
e4.add<Tag>();
|
|
e5.add<Tag>();
|
|
|
|
auto q = ecs.query_builder<Self, Position, const Velocity>()
|
|
.arg(3).singleton()
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
q.iter([&](flecs::iter it, Self* s, Position* p, const Velocity* v) {
|
|
test_assert(it.count() == 1);
|
|
|
|
for (auto i : it) {
|
|
p[i].x += v[i].x;
|
|
p[i].y += v[i].y;
|
|
test_assert(it.entity(i) == s[i].value);
|
|
count ++;
|
|
}
|
|
});
|
|
|
|
test_int(count, 5);
|
|
|
|
test_assert(e1.get([](const Position& p) {
|
|
test_int(p.x, 11);
|
|
test_int(p.y, 22);
|
|
}));
|
|
|
|
test_assert(e2.get([](const Position& p) {
|
|
test_int(p.x, 21);
|
|
test_int(p.y, 32);
|
|
}));
|
|
|
|
test_assert(e3.get([](const Position& p) {
|
|
test_int(p.x, 31);
|
|
test_int(p.y, 42);
|
|
}));
|
|
|
|
test_assert(e4.get([](const Position& p) {
|
|
test_int(p.x, 41);
|
|
test_int(p.y, 52);
|
|
}));
|
|
|
|
test_assert(e5.get([](const Position& p) {
|
|
test_int(p.x, 51);
|
|
test_int(p.y, 62);
|
|
}));
|
|
}
|
|
|
|
void Query_un_instanced_query_w_base_iter(void) {
|
|
flecs::world ecs;
|
|
|
|
auto base = ecs.entity().set<Velocity>({1, 2});
|
|
|
|
auto e1 = ecs.entity().is_a(base).set<Position>({10, 20}); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity().is_a(base).set<Position>({20, 30}); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity().is_a(base).set<Position>({30, 40}); e3.set<Self>({e3});
|
|
auto e4 = ecs.entity().is_a(base).set<Position>({40, 50}).add<Tag>(); e4.set<Self>({e4});
|
|
auto e5 = ecs.entity().is_a(base).set<Position>({50, 60}).add<Tag>(); e5.set<Self>({e5});
|
|
auto e6 = ecs.entity().set<Position>({60, 70}).set<Velocity>({2, 3}); e6.set<Self>({e6});
|
|
auto e7 = ecs.entity().set<Position>({70, 80}).set<Velocity>({4, 5}); e7.set<Self>({e7});
|
|
|
|
auto q = ecs.query_builder<Self, Position, const Velocity>()
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
q.iter([&](flecs::iter it, Self* s, Position* p, const Velocity* v) {
|
|
for (auto i : it) {
|
|
p[i].x += v[i].x;
|
|
p[i].y += v[i].y;
|
|
test_assert(it.entity(i) == s[i].value);
|
|
count ++;
|
|
}
|
|
});
|
|
|
|
test_int(count, 7);
|
|
|
|
test_assert(e1.get([](const Position& p) {
|
|
test_int(p.x, 11);
|
|
test_int(p.y, 22);
|
|
}));
|
|
|
|
test_assert(e2.get([](const Position& p) {
|
|
test_int(p.x, 21);
|
|
test_int(p.y, 32);
|
|
}));
|
|
|
|
test_assert(e3.get([](const Position& p) {
|
|
test_int(p.x, 31);
|
|
test_int(p.y, 42);
|
|
}));
|
|
|
|
test_assert(e4.get([](const Position& p) {
|
|
test_int(p.x, 41);
|
|
test_int(p.y, 52);
|
|
}));
|
|
|
|
test_assert(e5.get([](const Position& p) {
|
|
test_int(p.x, 51);
|
|
test_int(p.y, 62);
|
|
}));
|
|
|
|
test_assert(e6.get([](const Position& p) {
|
|
test_int(p.x, 62);
|
|
test_int(p.y, 73);
|
|
}));
|
|
|
|
test_assert(e7.get([](const Position& p) {
|
|
test_int(p.x, 74);
|
|
test_int(p.y, 85);
|
|
}));
|
|
}
|
|
|
|
void Query_default_ctor_no_assign(void) {
|
|
flecs::query<> q;
|
|
|
|
// Make sure code compiles & works
|
|
test_assert(true);
|
|
}
|
|
|
|
void Query_query_each_from_component(void) {
|
|
flecs::world w;
|
|
|
|
w.entity().set<Position>({}).set<Velocity>({});
|
|
w.entity().set<Position>({}).set<Velocity>({});
|
|
|
|
struct QueryComponent {
|
|
flecs::query<Position, Velocity> q;
|
|
};
|
|
|
|
auto q = w.query<Position, Velocity>();
|
|
auto e = w.entity().set<QueryComponent>({ q });
|
|
|
|
const QueryComponent *qc = e.get<QueryComponent>();
|
|
test_assert(qc != nullptr);
|
|
|
|
int count = 0;
|
|
qc->q.each([&](Position&, Velocity&) { // Ensure we can iterate const query
|
|
count ++;
|
|
});
|
|
test_int(count, 2);
|
|
}
|
|
|
|
void Query_query_iter_from_component(void) {
|
|
flecs::world w;
|
|
|
|
w.entity().set<Position>({}).set<Velocity>({});
|
|
w.entity().set<Position>({}).set<Velocity>({});
|
|
|
|
struct QueryComponent {
|
|
flecs::query<Position, Velocity> q;
|
|
};
|
|
|
|
auto q = w.query<Position, Velocity>();
|
|
auto e = w.entity().set<QueryComponent>({ q });
|
|
|
|
const QueryComponent *qc = e.get<QueryComponent>();
|
|
test_assert(qc != nullptr);
|
|
|
|
int count = 0;
|
|
qc->q.iter([&](flecs::iter& it) { // Ensure we can iterate const query
|
|
count += it.count();
|
|
});
|
|
test_int(count, 2);
|
|
}
|
|
|
|
static int invoked_count = 0;
|
|
|
|
void EachFunc(flecs::entity e, Position& p) {
|
|
invoked_count ++;
|
|
p.x ++;
|
|
p.y ++;
|
|
}
|
|
|
|
void IterFunc(flecs::iter& it, Position* p) {
|
|
test_int(it.count(), 1);
|
|
invoked_count ++;
|
|
p->x ++;
|
|
p->y ++;
|
|
}
|
|
|
|
void Query_query_each_w_func_ptr(void) {
|
|
flecs::world w;
|
|
|
|
auto e = w.entity().set<Position>({10, 20});
|
|
|
|
auto q = w.query<Position>();
|
|
|
|
q.each(&EachFunc);
|
|
|
|
test_int(invoked_count, 1);
|
|
|
|
const Position *ptr = e.get<Position>();
|
|
test_int(ptr->x, 11);
|
|
test_int(ptr->y, 21);
|
|
}
|
|
|
|
void Query_query_iter_w_func_ptr(void) {
|
|
flecs::world w;
|
|
|
|
auto e = w.entity().set<Position>({10, 20});
|
|
|
|
auto q = w.query<Position>();
|
|
|
|
q.iter(&IterFunc);
|
|
|
|
test_int(invoked_count, 1);
|
|
|
|
const Position *ptr = e.get<Position>();
|
|
test_int(ptr->x, 11);
|
|
test_int(ptr->y, 21);
|
|
}
|
|
|
|
void Query_query_each_w_func_no_ptr(void) {
|
|
flecs::world w;
|
|
|
|
auto e = w.entity().set<Position>({10, 20});
|
|
|
|
auto q = w.query<Position>();
|
|
|
|
q.each(EachFunc);
|
|
|
|
test_int(invoked_count, 1);
|
|
|
|
const Position *ptr = e.get<Position>();
|
|
test_int(ptr->x, 11);
|
|
test_int(ptr->y, 21);
|
|
}
|
|
|
|
void Query_query_iter_w_func_no_ptr(void) {
|
|
flecs::world w;
|
|
|
|
auto e = w.entity().set<Position>({10, 20});
|
|
|
|
auto q = w.query<Position>();
|
|
|
|
q.iter(IterFunc);
|
|
|
|
test_int(invoked_count, 1);
|
|
|
|
const Position *ptr = e.get<Position>();
|
|
test_int(ptr->x, 11);
|
|
test_int(ptr->y, 21);
|
|
}
|
|
|
|
void Query_query_each_w_iter(void) {
|
|
flecs::world w;
|
|
|
|
auto e1 = w.entity(); e1.set<Self>({e1});
|
|
e1.set<Position>({10, 20});
|
|
auto e2 = w.entity(); e2.set<Self>({e2});
|
|
e2.set<Position>({20, 30});
|
|
|
|
auto q = w.query<Self, Position>();
|
|
|
|
int32_t invoked = 0;
|
|
q.each([&](flecs::iter& it, int32_t i, Self& s, Position& p) {
|
|
test_int(it.count(), 2);
|
|
test_int(it.entity(i), s.value);
|
|
p.x ++;
|
|
p.y ++;
|
|
invoked ++;
|
|
});
|
|
|
|
test_int(invoked, 2);
|
|
|
|
const Position *ptr = e1.get<Position>();
|
|
test_int(ptr->x, 11);
|
|
test_int(ptr->y, 21);
|
|
|
|
ptr = e2.get<Position>();
|
|
test_int(ptr->x, 21);
|
|
test_int(ptr->y, 31);
|
|
}
|
|
|
|
void Query_change_tracking(void) {
|
|
flecs::world w;
|
|
|
|
auto qw = w.query<Position>();
|
|
auto qr = w.query<const Position>();
|
|
|
|
auto e1 = w.entity().add<Tag>().set<Position>({10, 20});
|
|
w.entity().set<Position>({20, 30});
|
|
|
|
test_bool(qr.changed(), true);
|
|
qr.iter([](flecs::iter&) { });
|
|
test_bool(qr.changed(), false);
|
|
|
|
int32_t count = 0, change_count = 0;
|
|
|
|
qw.iter([&](flecs::iter& it, Position* p) {
|
|
test_int(it.count(), 1);
|
|
|
|
count ++;
|
|
|
|
if (it.entity(0) == e1) {
|
|
it.skip();
|
|
return;
|
|
}
|
|
|
|
change_count ++;
|
|
});
|
|
|
|
test_int(count, 2);
|
|
test_int(change_count, 1);
|
|
|
|
count = 0;
|
|
change_count = 0;
|
|
|
|
test_bool(qr.changed(), true);
|
|
|
|
qr.iter([&](flecs::iter& it, const Position* p) {
|
|
test_int(it.count(), 1);
|
|
|
|
count ++;
|
|
|
|
if (it.entity(0) == e1) {
|
|
test_bool(it.changed(), false);
|
|
} else {
|
|
test_bool(it.changed(), true);
|
|
change_count ++;
|
|
}
|
|
});
|
|
|
|
test_int(count, 2);
|
|
test_int(change_count, 1);
|
|
}
|
|
|
|
void Query_not_w_write(void) {
|
|
flecs::world ecs;
|
|
|
|
struct A {};
|
|
struct B {};
|
|
|
|
auto q = ecs.query_builder()
|
|
.term<A>()
|
|
.term<B>().oper(flecs::Not).write()
|
|
.build();
|
|
|
|
auto e = ecs.entity().add<A>();
|
|
|
|
int32_t count = 0;
|
|
ecs.defer([&] {
|
|
q.each([&](flecs::entity e) {
|
|
e.add<B>();
|
|
count ++;
|
|
});
|
|
});
|
|
|
|
test_int(1, count);
|
|
test_assert(e.has<B>());
|
|
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
});
|
|
|
|
test_int(1, count);
|
|
}
|
|
|
|
void Query_get_first(void) {
|
|
flecs::world ecs;
|
|
|
|
struct A {};
|
|
|
|
auto e1 = ecs.entity().add<A>();
|
|
ecs.entity().add<A>();
|
|
ecs.entity().add<A>();
|
|
|
|
auto q = ecs.query<A>();
|
|
|
|
auto first = q.iter().first();
|
|
test_assert(first != 0);
|
|
test_assert(first == e1);
|
|
}
|
|
|
|
void Query_get_first_direct(void) {
|
|
flecs::world ecs;
|
|
|
|
struct A {};
|
|
|
|
auto e1 = ecs.entity().add<A>();
|
|
ecs.entity().add<A>();
|
|
ecs.entity().add<A>();
|
|
|
|
auto q = ecs.query<A>();
|
|
|
|
auto first = q.first();
|
|
test_assert(first != 0);
|
|
test_assert(first == e1);
|
|
}
|
|
|
|
void Query_get_count_direct(void) {
|
|
flecs::world ecs;
|
|
|
|
struct A {};
|
|
|
|
ecs.entity().add<A>();
|
|
ecs.entity().add<A>();
|
|
ecs.entity().add<A>();
|
|
|
|
auto q = ecs.query<A>();
|
|
|
|
test_int(3, q.count());
|
|
}
|
|
|
|
void Query_get_is_true_direct(void) {
|
|
flecs::world ecs;
|
|
|
|
struct A {};
|
|
struct B {};
|
|
|
|
ecs.entity().add<A>();
|
|
ecs.entity().add<A>();
|
|
ecs.entity().add<A>();
|
|
|
|
auto q_1 = ecs.query<A>();
|
|
auto q_2 = ecs.query<B>();
|
|
|
|
test_bool(true, q_1.is_true());
|
|
test_bool(false, q_2.is_true());
|
|
}
|
|
|
|
void Query_each_w_no_this(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity()
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto q = ecs.query_builder<Position, Velocity>()
|
|
.arg(1).src(e)
|
|
.arg(2).src(e)
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](Position& p, Velocity& v) {
|
|
count ++;
|
|
test_int(p.x, 10);
|
|
test_int(p.y, 20);
|
|
test_int(v.x, 1);
|
|
test_int(v.y, 2);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void Query_each_w_iter_no_this(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity()
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto q = ecs.query_builder<Position, Velocity>()
|
|
.arg(1).src(e)
|
|
.arg(2).src(e)
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::iter& it, size_t index, Position& p, Velocity& v) {
|
|
count ++;
|
|
test_int(p.x, 10);
|
|
test_int(p.y, 20);
|
|
test_int(v.x, 1);
|
|
test_int(v.y, 2);
|
|
test_int(index, 0);
|
|
test_int(it.count(), 0);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void Query_invalid_each_w_no_this(void) {
|
|
install_test_abort();
|
|
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity()
|
|
.set<Position>({10, 20})
|
|
.set<Velocity>({1, 2});
|
|
|
|
auto q = ecs.query_builder<Position, Velocity>()
|
|
.arg(1).src(e)
|
|
.arg(2).src(e)
|
|
.build();
|
|
|
|
test_expect_abort();
|
|
|
|
q.each([&](flecs::entity e, Position& p, Velocity& v) { });
|
|
}
|
|
|
|
void Query_named_query(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
auto e2 = ecs.entity().add<Position>();
|
|
|
|
auto q = ecs.query<Position>("my_query");
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Position&) {
|
|
test_assert(e == e1 || e == e2);
|
|
count ++;
|
|
});
|
|
test_int(count, 2);
|
|
|
|
flecs::entity qe = q.entity();
|
|
test_assert(qe != 0);
|
|
test_str(qe.name(), "my_query");
|
|
}
|
|
|
|
void Query_named_scoped_query(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
auto e2 = ecs.entity().add<Position>();
|
|
|
|
auto q = ecs.query<Position>("my::query");
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Position&) {
|
|
test_assert(e == e1 || e == e2);
|
|
count ++;
|
|
});
|
|
test_int(count, 2);
|
|
|
|
flecs::entity qe = q.entity();
|
|
test_assert(qe != 0);
|
|
test_str(qe.name(), "query");
|
|
test_str(qe.path(), "::my::query");
|
|
}
|
|
|
|
void Query_instanced_nested_query_w_iter(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::query<> q1 = ecs.query_builder()
|
|
.term<Position>()
|
|
.term<Mass>().singleton()
|
|
.build();
|
|
|
|
flecs::query<> q2 = ecs.query_builder()
|
|
.term<Velocity>()
|
|
.build();
|
|
|
|
ecs.add<Mass>();
|
|
ecs.entity().add<Velocity>();
|
|
ecs.entity().add<Position>();
|
|
ecs.entity().add<Position>();
|
|
|
|
int32_t count = 0;
|
|
|
|
q2.iter([&](flecs::iter& it_2) {
|
|
q1.iter(it_2, [&](flecs::iter& it_1) {
|
|
test_int(it_1.count(), 1);
|
|
count += it_1.count();
|
|
});
|
|
});
|
|
|
|
test_int(count, 2);
|
|
}
|
|
|
|
void Query_instanced_nested_query_w_entity(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::query<> q1 = ecs.query_builder()
|
|
.term<Position>()
|
|
.term<Mass>().singleton()
|
|
.build();
|
|
|
|
flecs::query<> q2 = ecs.query_builder()
|
|
.term<Velocity>()
|
|
.build();
|
|
|
|
ecs.add<Mass>();
|
|
ecs.entity().add<Velocity>();
|
|
ecs.entity().add<Position>();
|
|
ecs.entity().add<Position>();
|
|
|
|
int32_t count = 0;
|
|
|
|
q2.each([&](flecs::entity e_2) {
|
|
q1.iter(e_2, [&](flecs::iter& it_1) {
|
|
test_int(it_1.count(), 1);
|
|
count += it_1.count();
|
|
});
|
|
});
|
|
|
|
test_int(count, 2);
|
|
}
|
|
|
|
void Query_instanced_nested_query_w_world(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::query<> q1 = ecs.query_builder()
|
|
.term<Position>()
|
|
.term<Mass>().singleton()
|
|
.build();
|
|
|
|
flecs::query<> q2 = ecs.query_builder()
|
|
.term<Velocity>()
|
|
.build();
|
|
|
|
ecs.add<Mass>();
|
|
ecs.entity().add<Velocity>();
|
|
ecs.entity().add<Position>();
|
|
ecs.entity().add<Position>();
|
|
|
|
int32_t count = 0;
|
|
|
|
q2.iter([&](flecs::iter& it_2) {
|
|
q1.iter(it_2.world(), [&](flecs::iter& it_1) {
|
|
test_int(it_1.count(), 1);
|
|
count += it_1.count();
|
|
});
|
|
});
|
|
|
|
test_int(count, 2);
|
|
}
|
|
|
|
void Query_captured_query(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::query<Position> q = ecs.query<Position>();
|
|
flecs::entity e_1 = ecs.entity().set<Position>({10, 20});
|
|
|
|
[=]() {
|
|
int count = 0;
|
|
q.each([&](flecs::entity e, Position& p) {
|
|
test_assert(e == e_1);
|
|
test_int(p.x, 10);
|
|
test_int(p.y, 20);
|
|
count ++;
|
|
});
|
|
test_int(count, 1);
|
|
}();
|
|
}
|
|
|
|
void Query_page_iter_captured_query(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::query<Position> q = ecs.query<Position>();
|
|
/* flecs::entity e_1 = */ ecs.entity().set<Position>({10, 20});
|
|
flecs::entity e_2 = ecs.entity().set<Position>({20, 30});
|
|
/* flecs::entity e_3 = */ ecs.entity().set<Position>({10, 20});
|
|
|
|
[=]() {
|
|
int count = 0;
|
|
q.iter().page(1, 1).each([&](flecs::entity e, Position& p) {
|
|
test_assert(e == e_2);
|
|
test_int(p.x, 20);
|
|
test_int(p.y, 30);
|
|
count ++;
|
|
});
|
|
test_int(count, 1);
|
|
}();
|
|
}
|
|
|
|
void Query_worker_iter_captured_query(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::query<Position> q = ecs.query<Position>();
|
|
/* flecs::entity e_1 = */ ecs.entity().set<Position>({10, 20});
|
|
flecs::entity e_2 = ecs.entity().set<Position>({20, 30});
|
|
/* flecs::entity e_3 = */ ecs.entity().set<Position>({10, 20});
|
|
|
|
[=]() {
|
|
int count = 0;
|
|
q.iter().worker(1, 3).each([&](flecs::entity e, Position& p) {
|
|
test_assert(e == e_2);
|
|
test_int(p.x, 20);
|
|
test_int(p.y, 30);
|
|
count ++;
|
|
});
|
|
test_int(count, 1);
|
|
}();
|
|
}
|
|
|
|
void Query_iter_entities(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e1 = ecs.entity().set<Position>({10, 20});
|
|
auto e2 = ecs.entity().set<Position>({10, 20});
|
|
auto e3 = ecs.entity().set<Position>({10, 20});
|
|
|
|
ecs.query<Position>()
|
|
.iter([&](flecs::iter& it) {
|
|
test_int(it.count(), 3);
|
|
|
|
auto entities = it.entities();
|
|
test_assert(entities[0] == e1);
|
|
test_assert(entities[1] == e2);
|
|
test_assert(entities[2] == e3);
|
|
});
|
|
}
|
|
|
|
void Query_iter_get_pair_w_id(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::entity Rel = ecs.entity();
|
|
flecs::entity Tgt = ecs.entity();
|
|
flecs::entity e = ecs.entity().add(Rel, Tgt);
|
|
|
|
flecs::query<> q = ecs.query_builder()
|
|
.with(Rel, flecs::Wildcard)
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::iter& it, size_t i) {
|
|
test_bool(true, it.id(1).is_pair());
|
|
test_assert(it.id(1).first() == Rel);
|
|
test_assert(it.id(1).second() == Tgt);
|
|
test_assert(e == it.entity(i));
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void Query_find(void) {
|
|
flecs::world ecs;
|
|
|
|
/* auto e1 = */ ecs.entity().set<Position>({10, 20});
|
|
auto e2 = ecs.entity().set<Position>({20, 30});
|
|
|
|
auto q = ecs.query<Position>();
|
|
|
|
auto r = q.find([](Position& p) {
|
|
return p.x == 20;
|
|
});
|
|
|
|
test_assert(r == e2);
|
|
}
|
|
|
|
void Query_find_not_found(void) {
|
|
flecs::world ecs;
|
|
|
|
/* auto e1 = */ ecs.entity().set<Position>({10, 20});
|
|
/* auto e2 = */ ecs.entity().set<Position>({20, 30});
|
|
|
|
auto q = ecs.query<Position>();
|
|
|
|
auto r = q.find([](Position& p) {
|
|
return p.x == 30;
|
|
});
|
|
|
|
test_assert(!r);
|
|
}
|
|
|
|
void Query_find_w_entity(void) {
|
|
flecs::world ecs;
|
|
|
|
/* auto e1 = */ ecs.entity().set<Position>({10, 20}).set<Velocity>({20, 30});
|
|
auto e2 = ecs.entity().set<Position>({20, 30}).set<Velocity>({20, 30});
|
|
|
|
auto q = ecs.query<Position>();
|
|
|
|
auto r = q.find([](flecs::entity e, Position& p) {
|
|
return p.x == e.get<Velocity>()->x &&
|
|
p.y == e.get<Velocity>()->y;
|
|
});
|
|
|
|
test_assert(r == e2);
|
|
}
|
|
|
|
void Query_optional_pair_term(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.entity()
|
|
.add<TagA>()
|
|
.emplace<Position, Tag>(1.0f, 2.0f);
|
|
ecs.entity()
|
|
.add<TagA>();
|
|
|
|
int32_t with_pair = 0, without_pair = 0;
|
|
|
|
auto f = ecs.query_builder<flecs::pair<Position, Tag>*>()
|
|
.with<TagA>()
|
|
.build();
|
|
|
|
f.each([&](flecs::entity e, Position* p) {
|
|
if (p) {
|
|
with_pair++;
|
|
test_flt(1.0f, p->x);
|
|
test_flt(2.0f, p->y);
|
|
} else {
|
|
without_pair++;
|
|
}
|
|
});
|
|
|
|
ecs.progress(1.0);
|
|
|
|
test_int(1, with_pair);
|
|
test_int(1, without_pair);
|
|
}
|