2090 lines
48 KiB
C++
2090 lines
48 KiB
C++
#include <cpp_api.h>
|
|
|
|
struct Other {
|
|
int32_t value;
|
|
};
|
|
|
|
void QueryBuilder_builder_assign_same_type(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::query<Position, Velocity> q =
|
|
ecs.query_builder<Position, Velocity>().build();
|
|
|
|
auto e1 = ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Position>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Position& p, Velocity& v) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_builder_assign_to_empty(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::query<> q = ecs.query_builder<Position, Velocity>().build();
|
|
|
|
auto e1 = ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Position>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_builder_assign_from_empty(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::query<> q = ecs.query_builder<>()
|
|
.term<Position>()
|
|
.term<Velocity>()
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Position>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_builder_build(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::query<Position, Velocity> q =
|
|
ecs.query_builder<Position, Velocity>().build();
|
|
|
|
auto e1 = ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Position>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Position& p, Velocity& v) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_builder_build_to_auto(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Position, Velocity>().build();
|
|
|
|
auto e1 = ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Position>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Position& p, Velocity& v) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_builder_build_n_statements(void) {
|
|
flecs::world ecs;
|
|
|
|
auto qb = ecs.query_builder<>();
|
|
qb.term<Position>();
|
|
qb.term<Velocity>();
|
|
auto q = qb.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Position>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_1_type(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Position>().build();
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
ecs.entity().add<Velocity>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Position& p) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_add_1_type(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term<Position>()
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
ecs.entity().add<Velocity>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_add_2_types(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term<Position>()
|
|
.term<Velocity>()
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Velocity>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_add_1_type_w_1_type(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Position>()
|
|
.term<Velocity>()
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Velocity>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Position& p) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_add_2_types_w_1_type(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Position>()
|
|
.term<Velocity>()
|
|
.term<Mass>()
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>().add<Velocity>().add<Mass>();
|
|
ecs.entity().add<Velocity>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Position& p) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_add_pair(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Likes = ecs.entity();
|
|
auto Bob = ecs.entity();
|
|
auto Alice = ecs.entity();
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term(Likes, Bob)
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add(Likes, Bob);
|
|
ecs.entity().add(Likes, Alice);
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_add_not(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Position>()
|
|
.term<Velocity>().oper(flecs::Not)
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
ecs.entity().add<Position>().add<Velocity>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Position& p) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_add_or(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term<Position>().oper(flecs::Or)
|
|
.term<Velocity>()
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
auto e2 = ecs.entity().add<Velocity>();
|
|
ecs.entity().add<Mass>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1 || e == e2);
|
|
});
|
|
|
|
test_int(count, 2);
|
|
}
|
|
|
|
void QueryBuilder_add_optional(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term<Position>()
|
|
.term<Velocity>().oper(flecs::Optional)
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
auto e2 = ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Velocity>().add<Mass>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1 || e == e2);
|
|
});
|
|
|
|
test_int(count, 2);
|
|
}
|
|
|
|
void QueryBuilder_ptr_type(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Position, Velocity*>().build();
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
auto e2 = ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Velocity>().add<Mass>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Position& p, Velocity* v) {
|
|
count ++;
|
|
test_assert(e == e1 || e == e2);
|
|
});
|
|
|
|
test_int(count, 2);
|
|
}
|
|
|
|
void QueryBuilder_const_type(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<const Position>().build();
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
ecs.entity().add<Velocity>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, const Position& p) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_string_term(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.component<Position>();
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.expr("Position")
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
ecs.entity().add<Velocity>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_singleton_term(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.set<Other>({10});
|
|
|
|
auto q = ecs.query_builder<Self>()
|
|
.term<Other>().singleton()
|
|
.build();
|
|
|
|
auto
|
|
e = ecs.entity(); e.set<Self>({e});
|
|
e = ecs.entity(); e.set<Self>({e});
|
|
e = ecs.entity(); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.iter([&](flecs::iter& it, Self *s) {
|
|
auto o = it.field<const Other>(2);
|
|
test_assert(!it.is_self(2));
|
|
test_int(o->value, 10);
|
|
|
|
const Other& o_ref = *o;
|
|
test_int(o_ref.value, 10);
|
|
|
|
for (auto i : it) {
|
|
test_assert(it.entity(i) == s[i].value);
|
|
count ++;
|
|
}
|
|
});
|
|
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void QueryBuilder_isa_superset_term(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Self>()
|
|
.term<Other>().src().up()
|
|
.build();
|
|
|
|
auto base = ecs.entity().set<Other>({10});
|
|
|
|
auto
|
|
e = ecs.entity().add(flecs::IsA, base); e.set<Self>({e});
|
|
e = ecs.entity().add(flecs::IsA, base); e.set<Self>({e});
|
|
e = ecs.entity().add(flecs::IsA, base); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.iter([&](flecs::iter& it, Self *s) {
|
|
auto o = it.field<const Other>(2);
|
|
test_assert(!it.is_self(2));
|
|
test_int(o->value, 10);
|
|
|
|
for (auto i : it) {
|
|
test_assert(it.entity(i) == s[i].value);
|
|
count ++;
|
|
}
|
|
});
|
|
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void QueryBuilder_isa_self_superset_term(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Self>()
|
|
.term<Other>().src().self().up()
|
|
.build();
|
|
|
|
auto base = ecs.entity().set<Other>({10});
|
|
|
|
auto
|
|
e = ecs.entity().add(flecs::IsA, base); e.set<Self>({e});
|
|
e = ecs.entity().add(flecs::IsA, base); e.set<Self>({e});
|
|
e = ecs.entity().add(flecs::IsA, base); e.set<Self>({e});
|
|
e = ecs.entity().set<Other>({20}); e.set<Self>({e});
|
|
e = ecs.entity().set<Other>({20}); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
int32_t owned_count = 0;
|
|
|
|
q.iter([&](flecs::iter& it, Self *s) {
|
|
auto o = it.field<const Other>(2);
|
|
|
|
if (!it.is_self(2)) {
|
|
test_int(o->value, 10);
|
|
} else {
|
|
for (auto i : it) {
|
|
test_int(o[i].value, 20);
|
|
owned_count ++;
|
|
}
|
|
}
|
|
|
|
for (auto i : it) {
|
|
test_assert(it.entity(i) == s[i].value);
|
|
count ++;
|
|
}
|
|
});
|
|
|
|
test_int(count, 5);
|
|
test_int(owned_count, 2);
|
|
}
|
|
|
|
void QueryBuilder_childof_superset_term(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Self>()
|
|
.term<Other>().src().up(flecs::ChildOf)
|
|
.build();
|
|
|
|
auto base = ecs.entity().set<Other>({10});
|
|
|
|
auto
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.iter([&](flecs::iter& it, Self *s) {
|
|
auto o = it.field<const Other>(2);
|
|
test_assert(!it.is_self(2));
|
|
test_int(o->value, 10);
|
|
|
|
for (auto i : it) {
|
|
test_assert(it.entity(i) == s[i].value);
|
|
count ++;
|
|
}
|
|
});
|
|
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void QueryBuilder_childof_self_superset_term(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Self>()
|
|
.term<Other>().src().self().up(flecs::ChildOf)
|
|
.build();
|
|
|
|
auto base = ecs.entity().set<Other>({10});
|
|
|
|
auto
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().set<Other>({20}); e.set<Self>({e});
|
|
e = ecs.entity().set<Other>({20}); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
int32_t owned_count = 0;
|
|
|
|
q.iter([&](flecs::iter& it, Self *s) {
|
|
auto o = it.field<const Other>(2);
|
|
|
|
if (!it.is_self(2)) {
|
|
test_int(o->value, 10);
|
|
} else {
|
|
for (auto i : it) {
|
|
test_int(o[i].value, 20);
|
|
owned_count ++;
|
|
}
|
|
}
|
|
|
|
for (auto i : it) {
|
|
test_assert(it.entity(i) == s[i].value);
|
|
count ++;
|
|
}
|
|
});
|
|
|
|
test_int(count, 5);
|
|
test_int(owned_count, 2);
|
|
}
|
|
|
|
void QueryBuilder_isa_superset_term_w_each(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Self, Other>()
|
|
.arg(2).src().up()
|
|
.build();
|
|
|
|
auto base = ecs.entity().set<Other>({10});
|
|
|
|
auto
|
|
e = ecs.entity().add(flecs::IsA, base); e.set<Self>({e});
|
|
e = ecs.entity().add(flecs::IsA, base); e.set<Self>({e});
|
|
e = ecs.entity().add(flecs::IsA, base); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e, Self& s, Other& o) {
|
|
test_assert(e == s.value);
|
|
test_int(o.value, 10);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void QueryBuilder_isa_self_superset_term_w_each(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Self, Other>()
|
|
.arg(2).src().self().up()
|
|
.build();
|
|
|
|
auto base = ecs.entity().set<Other>({10});
|
|
|
|
auto
|
|
e = ecs.entity().add(flecs::IsA, base); e.set<Self>({e});
|
|
e = ecs.entity().add(flecs::IsA, base); e.set<Self>({e});
|
|
e = ecs.entity().add(flecs::IsA, base); e.set<Self>({e});
|
|
e = ecs.entity().set<Other>({10}); e.set<Self>({e});
|
|
e = ecs.entity().set<Other>({10}); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e, Self& s, Other& o) {
|
|
test_assert(e == s.value);
|
|
test_int(o.value, 10);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 5);
|
|
}
|
|
|
|
void QueryBuilder_childof_superset_term_w_each(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Self, Other>()
|
|
.arg(2).src().up(flecs::ChildOf)
|
|
.build();
|
|
|
|
auto base = ecs.entity().set<Other>({10});
|
|
|
|
auto
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e, Self& s, Other& o) {
|
|
test_assert(e == s.value);
|
|
test_int(o.value, 10);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void QueryBuilder_childof_self_superset_term_w_each(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Self, Other>()
|
|
.arg(2).src().self().up(flecs::ChildOf)
|
|
.build();
|
|
|
|
auto base = ecs.entity().set<Other>({10});
|
|
|
|
auto
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().set<Other>({10}); e.set<Self>({e});
|
|
e = ecs.entity().set<Other>({10}); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e, Self& s, Other& o) {
|
|
test_assert(e == s.value);
|
|
test_int(o.value, 10);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 5);
|
|
}
|
|
|
|
void QueryBuilder_isa_superset_shortcut(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Self, Other>()
|
|
.arg(2).up()
|
|
.build();
|
|
|
|
auto base = ecs.entity().set<Other>({10});
|
|
|
|
auto
|
|
e = ecs.entity().is_a(base); e.set<Self>({e});
|
|
e = ecs.entity().is_a(base); e.set<Self>({e});
|
|
e = ecs.entity().is_a(base); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e, Self& s, Other& o) {
|
|
test_assert(e == s.value);
|
|
test_int(o.value, 10);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void QueryBuilder_isa_superset_shortcut_w_self(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Self, Other>()
|
|
.arg(2).self().up(flecs::IsA)
|
|
.build();
|
|
|
|
auto base = ecs.entity().set<Other>({10});
|
|
|
|
auto
|
|
e = ecs.entity().is_a(base); e.set<Self>({e});
|
|
e = ecs.entity().is_a(base); e.set<Self>({e});
|
|
e = ecs.entity().is_a(base); e.set<Self>({e});
|
|
e = ecs.entity().set<Other>({10}); e.set<Self>({e});
|
|
e = ecs.entity().set<Other>({10}); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e, Self& s, Other& o) {
|
|
test_assert(e == s.value);
|
|
test_int(o.value, 10);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 5);
|
|
}
|
|
|
|
void QueryBuilder_childof_superset_shortcut(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Self, Other>()
|
|
.arg(2).up(flecs::ChildOf)
|
|
.build();
|
|
|
|
auto base = ecs.entity().set<Other>({10});
|
|
|
|
auto
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e, Self& s, Other& o) {
|
|
test_assert(e == s.value);
|
|
test_int(o.value, 10);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void QueryBuilder_childof_superset_shortcut_w_self(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Self, Other>()
|
|
.arg(2).self().up(flecs::ChildOf)
|
|
.build();
|
|
|
|
auto base = ecs.entity().set<Other>({10});
|
|
|
|
auto
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().child_of(base); e.set<Self>({e});
|
|
e = ecs.entity().set<Other>({10}); e.set<Self>({e});
|
|
e = ecs.entity().set<Other>({10}); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e, Self& s, Other& o) {
|
|
test_assert(e == s.value);
|
|
test_int(o.value, 10);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 5);
|
|
}
|
|
|
|
void QueryBuilder_relation(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Likes = ecs.entity();
|
|
auto Bob = ecs.entity();
|
|
auto Alice = ecs.entity();
|
|
|
|
auto q = ecs.query_builder<Self>()
|
|
.term(Likes, Bob)
|
|
.build();
|
|
|
|
auto
|
|
e = ecs.entity().add(Likes, Bob); e.set<Self>({e});
|
|
e = ecs.entity().add(Likes, Bob); e.set<Self>({e});
|
|
|
|
e = ecs.entity().add(Likes, Alice); e.set<Self>({0});
|
|
e = ecs.entity().add(Likes, Alice); e.set<Self>({0});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e, Self& s) {
|
|
test_assert(e == s.value);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 2);
|
|
}
|
|
|
|
void QueryBuilder_relation_w_object_wildcard(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Likes = ecs.entity();
|
|
auto Bob = ecs.entity();
|
|
auto Alice = ecs.entity();
|
|
|
|
auto q = ecs.query_builder<Self>()
|
|
.term(Likes, flecs::Wildcard)
|
|
.build();
|
|
|
|
auto
|
|
e = ecs.entity().add(Likes, Bob); e.set<Self>({e});
|
|
e = ecs.entity().add(Likes, Bob); e.set<Self>({e});
|
|
|
|
e = ecs.entity().add(Likes, Alice); e.set<Self>({e});
|
|
e = ecs.entity().add(Likes, Alice); e.set<Self>({e});
|
|
|
|
e = ecs.entity(); e.set<Self>({0});
|
|
e = ecs.entity(); e.set<Self>({0});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e, Self& s) {
|
|
test_assert(e == s.value);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 4);
|
|
}
|
|
|
|
void QueryBuilder_relation_w_predicate_wildcard(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Likes = ecs.entity();
|
|
auto Dislikes = ecs.entity();
|
|
auto Bob = ecs.entity();
|
|
auto Alice = ecs.entity();
|
|
|
|
auto q = ecs.query_builder<Self>()
|
|
.term(flecs::Wildcard, Alice)
|
|
.build();
|
|
|
|
auto
|
|
e = ecs.entity().add(Likes, Alice); e.set<Self>({e});
|
|
e = ecs.entity().add(Dislikes, Alice); e.set<Self>({e});
|
|
|
|
e = ecs.entity().add(Likes, Bob); e.set<Self>({0});
|
|
e = ecs.entity().add(Dislikes, Bob); e.set<Self>({0});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e, Self& s) {
|
|
test_assert(e == s.value);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 2);
|
|
}
|
|
|
|
void QueryBuilder_add_pair_w_rel_type(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Likes { };
|
|
|
|
auto Dislikes = ecs.entity();
|
|
auto Bob = ecs.entity();
|
|
auto Alice = ecs.entity();
|
|
|
|
auto q = ecs.query_builder<Self>()
|
|
.term<Likes>(flecs::Wildcard)
|
|
.build();
|
|
|
|
auto
|
|
e = ecs.entity().add<Likes>(Alice); e.set<Self>({e});
|
|
e = ecs.entity().add(Dislikes, Alice); e.set<Self>({0});
|
|
|
|
e = ecs.entity().add<Likes>(Bob); e.set<Self>({e});
|
|
e = ecs.entity().add(Dislikes, Bob); e.set<Self>({0});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e, Self& s) {
|
|
test_assert(e == s.value);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 2);
|
|
}
|
|
|
|
void QueryBuilder_template_term(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Position>()
|
|
.term<Template<int>>()
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>().add<Template<int>>();
|
|
ecs.entity().add<Position>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Position& p) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_explicit_subject_w_id(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<Position>()
|
|
.term<Position>().id(flecs::This)
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>().add<Velocity>();
|
|
ecs.entity().add<Velocity>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Position& p) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_explicit_subject_w_type(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.set<Position>({10, 20});
|
|
|
|
auto q = ecs.query_builder<Position>()
|
|
.term<Position>().src<Position>()
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e, Position& p) {
|
|
test_int(p.x, 10);
|
|
test_int(p.y, 20);
|
|
count ++;
|
|
test_assert(e == ecs.singleton<Position>());
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_explicit_object_w_id(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Likes = ecs.entity();
|
|
auto Alice = ecs.entity();
|
|
auto Bob = ecs.entity();
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term(Likes).second(Alice)
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add(Likes, Alice);
|
|
ecs.entity().add(Likes, Bob);
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_explicit_object_w_type(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Likes = ecs.entity();
|
|
struct Alice { };
|
|
auto Bob = ecs.entity();
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term(Likes).second<Alice>()
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add(Likes, ecs.id<Alice>());
|
|
ecs.entity().add(Likes, Bob);
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_explicit_term(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term(ecs.term(ecs.id<Position>()))
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
ecs.entity().add<Velocity>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_explicit_term_w_type(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term(ecs.term<Position>())
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
ecs.entity().add<Velocity>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_explicit_term_w_pair_type(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Likes { };
|
|
struct Alice { };
|
|
struct Bob { };
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term(ecs.term<Likes, Alice>())
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add<Likes, Alice>();
|
|
ecs.entity().add<Likes, Bob>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_explicit_term_w_id(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Apples = ecs.entity();
|
|
auto Pears = ecs.entity();
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term(ecs.term(Apples))
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add(Apples);
|
|
ecs.entity().add(Pears);
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_explicit_term_w_pair_id(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Likes = ecs.entity();
|
|
auto Apples = ecs.entity();
|
|
auto Pears = ecs.entity();
|
|
|
|
auto q = ecs.query_builder<>()
|
|
.term(ecs.term(Likes, Apples))
|
|
.build();
|
|
|
|
auto e1 = ecs.entity().add(Likes, Apples);
|
|
ecs.entity().add(Likes, Pears);
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_1_term_to_empty(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Likes = ecs.entity();
|
|
auto Apples = ecs.entity();
|
|
|
|
auto qb = ecs.query_builder<>()
|
|
.term<Position>();
|
|
|
|
qb.term(Likes, Apples);
|
|
|
|
auto q = qb.build();
|
|
|
|
test_int(q.field_count(), 2);
|
|
test_int(q.term(0).id(), ecs.id<Position>());
|
|
test_int(q.term(1).id(), ecs.pair(Likes, Apples));
|
|
}
|
|
|
|
void QueryBuilder_2_subsequent_args(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Rel { int foo; };
|
|
|
|
int32_t count = 0;
|
|
|
|
auto s = ecs.system<Rel, const Velocity>()
|
|
.arg(1).second(flecs::Wildcard)
|
|
.arg(2).singleton()
|
|
.iter([&](flecs::iter it){
|
|
count += it.count();
|
|
});
|
|
|
|
ecs.entity().add<Rel, Tag>();
|
|
ecs.set<Velocity>({});
|
|
|
|
s.run();
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_optional_tag_is_set(void) {
|
|
flecs::world ecs;
|
|
|
|
struct TagA { };
|
|
struct TagB { };
|
|
|
|
auto q = ecs.query_builder()
|
|
.term<TagA>()
|
|
.term<TagB>().oper(flecs::Optional)
|
|
.build();
|
|
|
|
auto e_1 = ecs.entity().add<TagA>().add<TagB>();
|
|
auto e_2 = ecs.entity().add<TagA>();
|
|
|
|
int count = 0;
|
|
|
|
q.iter([&](flecs::iter& it) {
|
|
test_int(it.count(), 1);
|
|
|
|
count += it.count();
|
|
|
|
if (it.entity(0) == e_1) {
|
|
test_bool(it.is_set(1), true);
|
|
test_bool(it.is_set(2), true);
|
|
} else {
|
|
test_assert(it.entity(0) == e_2);
|
|
test_bool(it.is_set(1), true);
|
|
test_bool(it.is_set(2), false);
|
|
}
|
|
});
|
|
|
|
test_int(count, 2);
|
|
}
|
|
|
|
void QueryBuilder_10_terms(void) {
|
|
flecs::world ecs;
|
|
|
|
auto f = ecs.query_builder<>()
|
|
.term<TagA>()
|
|
.term<TagB>()
|
|
.term<TagC>()
|
|
.term<TagD>()
|
|
.term<TagE>()
|
|
.term<TagF>()
|
|
.term<TagG>()
|
|
.term<TagH>()
|
|
.term<TagI>()
|
|
.term<TagJ>()
|
|
.build();
|
|
|
|
test_int(f.field_count(), 10);
|
|
|
|
auto e = ecs.entity()
|
|
.add<TagA>()
|
|
.add<TagB>()
|
|
.add<TagC>()
|
|
.add<TagD>()
|
|
.add<TagE>()
|
|
.add<TagF>()
|
|
.add<TagG>()
|
|
.add<TagH>()
|
|
.add<TagI>()
|
|
.add<TagJ>();
|
|
|
|
int count = 0;
|
|
f.iter([&](flecs::iter& it) {
|
|
test_int(it.count(), 1);
|
|
test_assert(it.entity(0) == e);
|
|
test_int(it.field_count(), 10);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_20_terms(void) {
|
|
flecs::world ecs;
|
|
|
|
auto f = ecs.query_builder<>()
|
|
.term<TagA>()
|
|
.term<TagB>()
|
|
.term<TagC>()
|
|
.term<TagD>()
|
|
.term<TagE>()
|
|
.term<TagF>()
|
|
.term<TagG>()
|
|
.term<TagH>()
|
|
.term<TagI>()
|
|
.term<TagJ>()
|
|
.term<TagK>()
|
|
.term<TagL>()
|
|
.term<TagM>()
|
|
.term<TagN>()
|
|
.term<TagO>()
|
|
.term<TagP>()
|
|
.term<TagQ>()
|
|
.term<TagR>()
|
|
.term<TagS>()
|
|
.term<TagT>()
|
|
.build();
|
|
|
|
test_int(f.field_count(), 20);
|
|
|
|
auto e = ecs.entity()
|
|
.add<TagA>()
|
|
.add<TagB>()
|
|
.add<TagC>()
|
|
.add<TagD>()
|
|
.add<TagE>()
|
|
.add<TagF>()
|
|
.add<TagG>()
|
|
.add<TagH>()
|
|
.add<TagI>()
|
|
.add<TagJ>()
|
|
.add<TagK>()
|
|
.add<TagL>()
|
|
.add<TagM>()
|
|
.add<TagN>()
|
|
.add<TagO>()
|
|
.add<TagP>()
|
|
.add<TagQ>()
|
|
.add<TagR>()
|
|
.add<TagS>()
|
|
.add<TagT>();
|
|
|
|
int count = 0;
|
|
f.iter([&](flecs::iter& it) {
|
|
test_int(it.count(), 1);
|
|
test_assert(it.entity(0) == e);
|
|
test_int(it.field_count(), 20);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
uint64_t group_by_first_id(
|
|
flecs::world_t *m_world,
|
|
flecs::table_t *m_table,
|
|
flecs::entity_t id,
|
|
void *ctx)
|
|
{
|
|
const flecs::type_t *type = ecs_table_get_type(m_table);
|
|
return type->array[0];
|
|
}
|
|
|
|
uint64_t group_by_first_id_negated(
|
|
flecs::world_t *m_world,
|
|
flecs::table_t *m_table,
|
|
flecs::entity_t id,
|
|
void *ctx)
|
|
{
|
|
return ~group_by_first_id(m_world, m_table, id, ctx);
|
|
}
|
|
|
|
void QueryBuilder_group_by_raw(void) {
|
|
flecs::world ecs;
|
|
|
|
struct TagA { };
|
|
struct TagB { };
|
|
struct TagC { };
|
|
struct TagX { };
|
|
|
|
ecs.component<TagA>();
|
|
ecs.component<TagB>();
|
|
ecs.component<TagC>();
|
|
ecs.component<TagX>();
|
|
|
|
auto q = ecs.query_builder()
|
|
.term<TagX>()
|
|
.group_by(flecs::type_id<TagX>(), group_by_first_id)
|
|
.build();
|
|
|
|
auto q_reverse = ecs.query_builder()
|
|
.term<TagX>()
|
|
.group_by(flecs::type_id<TagX>(), group_by_first_id_negated)
|
|
.build();
|
|
|
|
auto e3 = ecs.entity().add<TagX>().add<TagC>();
|
|
auto e2 = ecs.entity().add<TagX>().add<TagB>();
|
|
auto e1 = ecs.entity().add<TagX>().add<TagA>();
|
|
|
|
int count = 0;
|
|
|
|
q.iter([&](flecs::iter& it){
|
|
test_int(it.count(), 1);
|
|
if(count == 0){
|
|
test_bool(it.entity(0) == e1, true);
|
|
}else if(count == 1){
|
|
test_bool(it.entity(0) == e2, true);
|
|
}else if(count == 2){
|
|
test_bool(it.entity(0) == e3, true);
|
|
}else{
|
|
test_assert(false);
|
|
}
|
|
count++;
|
|
});
|
|
test_int(count, 3);
|
|
|
|
count = 0;
|
|
q_reverse.iter([&](flecs::iter& it){
|
|
test_int(it.count(), 1);
|
|
if(count == 0){
|
|
test_bool(it.entity(0) == e3, true);
|
|
}else if(count == 1){
|
|
test_bool(it.entity(0) == e2, true);
|
|
}else if(count == 2){
|
|
test_bool(it.entity(0) == e1, true);
|
|
}else{
|
|
test_assert(false);
|
|
}
|
|
count++;
|
|
});
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void QueryBuilder_group_by_template(void) {
|
|
flecs::world ecs;
|
|
|
|
struct TagA { };
|
|
struct TagB { };
|
|
struct TagC { };
|
|
struct TagX { };
|
|
|
|
ecs.component<TagA>();
|
|
ecs.component<TagB>();
|
|
ecs.component<TagC>();
|
|
ecs.component<TagX>();
|
|
|
|
auto q = ecs.query_builder()
|
|
.term<TagX>()
|
|
.group_by<TagX>(group_by_first_id)
|
|
.build();
|
|
|
|
auto q_reverse = ecs.query_builder()
|
|
.term<TagX>()
|
|
.group_by<TagX>( group_by_first_id_negated)
|
|
.build();
|
|
|
|
auto e3 = ecs.entity().add<TagX>().add<TagC>();
|
|
auto e2 = ecs.entity().add<TagX>().add<TagB>();
|
|
auto e1 = ecs.entity().add<TagX>().add<TagA>();
|
|
|
|
int count = 0;
|
|
|
|
q.iter([&](flecs::iter& it){
|
|
test_int(it.count(), 1);
|
|
if(count == 0){
|
|
test_bool(it.entity(0) == e1, true);
|
|
}else if(count == 1){
|
|
test_bool(it.entity(0) == e2, true);
|
|
}else if(count == 2){
|
|
test_bool(it.entity(0) == e3, true);
|
|
}else{
|
|
test_assert(false);
|
|
}
|
|
count++;
|
|
});
|
|
test_int(count, 3);
|
|
|
|
count = 0;
|
|
q_reverse.iter([&](flecs::iter& it){
|
|
test_int(it.count(), 1);
|
|
if(count == 0){
|
|
test_bool(it.entity(0) == e3, true);
|
|
}else if(count == 1){
|
|
test_bool(it.entity(0) == e2, true);
|
|
}else if(count == 2){
|
|
test_bool(it.entity(0) == e1, true);
|
|
}else{
|
|
test_assert(false);
|
|
}
|
|
count++;
|
|
});
|
|
test_int(count, 3);
|
|
}
|
|
|
|
static
|
|
uint64_t group_by_rel(flecs::world_t *world, flecs::table_t *table, flecs::entity_t id, void *ctx) {
|
|
ecs_id_t match;
|
|
if (ecs_search(world, table, ecs_pair(id, EcsWildcard), &match) != -1) {
|
|
return ECS_PAIR_SECOND(match);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void QueryBuilder_group_by_iter_one(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Rel = ecs.entity();
|
|
auto TgtA = ecs.entity();
|
|
auto TgtB = ecs.entity();
|
|
auto TgtC = ecs.entity();
|
|
auto Tag = ecs.entity();
|
|
|
|
ecs.entity().add(Rel, TgtA);
|
|
auto e2 = ecs.entity().add(Rel, TgtB);
|
|
ecs.entity().add(Rel, TgtC);
|
|
|
|
ecs.entity().add(Rel, TgtA).add(Tag);
|
|
auto e5 = ecs.entity().add(Rel, TgtB).add(Tag);
|
|
ecs.entity().add(Rel, TgtC).add(Tag);
|
|
|
|
auto q = ecs.query_builder()
|
|
.term(Rel, flecs::Wildcard)
|
|
.group_by(Rel, group_by_rel)
|
|
.build();
|
|
|
|
bool e2_found = false;
|
|
bool e5_found = false;
|
|
int32_t count = 0;
|
|
|
|
q.iter().set_group(TgtB).each([&](flecs::iter& it, size_t i) {
|
|
flecs::entity e = it.entity(i);
|
|
test_assert(it.group_id() == TgtB);
|
|
|
|
if (e == e2) e2_found = true;
|
|
if (e == e5) e5_found = true;
|
|
count ++;
|
|
});
|
|
|
|
test_int(2, count);
|
|
test_bool(true, e2_found);
|
|
test_bool(true, e5_found);
|
|
}
|
|
|
|
void QueryBuilder_group_by_iter_one_template(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Rel { };
|
|
struct TgtA { };
|
|
struct TgtB { };
|
|
struct TgtC { };
|
|
struct Tag { };
|
|
|
|
ecs.entity().add<Rel, TgtA>();
|
|
auto e2 = ecs.entity().add<Rel, TgtB>();
|
|
ecs.entity().add<Rel, TgtC>();
|
|
|
|
ecs.entity().add<Rel, TgtA>().add<Tag>();
|
|
auto e5 = ecs.entity().add<Rel, TgtB>().add<Tag>();
|
|
ecs.entity().add<Rel, TgtC>().add<Tag>();
|
|
|
|
auto q = ecs.query_builder()
|
|
.term<Rel>(flecs::Wildcard)
|
|
.group_by<Rel>(group_by_rel)
|
|
.build();
|
|
|
|
bool e2_found = false;
|
|
bool e5_found = false;
|
|
int32_t count = 0;
|
|
|
|
q.iter().set_group<TgtB>().each([&](flecs::iter& it, size_t i) {
|
|
flecs::entity e = it.entity(i);
|
|
test_assert(it.group_id() == ecs.id<TgtB>());
|
|
|
|
if (e == e2) e2_found = true;
|
|
if (e == e5) e5_found = true;
|
|
count ++;
|
|
});
|
|
|
|
test_int(2, count);
|
|
test_bool(true, e2_found);
|
|
test_bool(true, e5_found);
|
|
}
|
|
|
|
void QueryBuilder_group_by_iter_one_all_groups(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Rel = ecs.entity();
|
|
auto TgtA = ecs.entity();
|
|
auto TgtB = ecs.entity();
|
|
auto TgtC = ecs.entity();
|
|
auto Tag = ecs.entity();
|
|
|
|
auto e1 = ecs.entity().add(Rel, TgtA);
|
|
auto e2 = ecs.entity().add(Rel, TgtB);
|
|
auto e3 = ecs.entity().add(Rel, TgtC);
|
|
|
|
auto e4 = ecs.entity().add(Rel, TgtA).add(Tag);
|
|
auto e5 = ecs.entity().add(Rel, TgtB).add(Tag);
|
|
auto e6 = ecs.entity().add(Rel, TgtC).add(Tag);
|
|
|
|
auto q = ecs.query_builder()
|
|
.term(Rel, flecs::Wildcard)
|
|
.group_by(Rel, group_by_rel)
|
|
.build();
|
|
|
|
int e1_found = 0;
|
|
int e2_found = 0;
|
|
int e3_found = 0;
|
|
int e4_found = 0;
|
|
int e5_found = 0;
|
|
int e6_found = 0;
|
|
int32_t count = 0;
|
|
uint64_t group_id = 0;
|
|
|
|
const auto func = [&](flecs::iter& it, size_t i) {
|
|
flecs::entity e = it.entity(i);
|
|
test_assert(it.group_id() == group_id);
|
|
if (e == e1) e1_found ++;
|
|
if (e == e2) e2_found ++;
|
|
if (e == e3) e3_found ++;
|
|
if (e == e4) e4_found ++;
|
|
if (e == e5) e5_found ++;
|
|
if (e == e6) e6_found ++;
|
|
count ++;
|
|
};
|
|
|
|
group_id = TgtB;
|
|
q.iter().set_group(TgtB).each(func);
|
|
test_int(2, count);
|
|
test_int(1, e2_found);
|
|
test_int(1, e5_found);
|
|
|
|
group_id = TgtA;
|
|
q.iter().set_group(TgtA).each(func);
|
|
test_int(4, count);
|
|
test_int(1, e1_found);
|
|
test_int(1, e4_found);
|
|
|
|
group_id = TgtC;
|
|
q.iter().set_group(TgtC).each(func);
|
|
test_int(6, count);
|
|
test_int(1, e3_found);
|
|
test_int(1, e6_found);
|
|
|
|
test_int(1, e1_found);
|
|
test_int(1, e2_found);
|
|
test_int(1, e3_found);
|
|
test_int(1, e4_found);
|
|
test_int(1, e5_found);
|
|
test_int(1, e6_found);
|
|
}
|
|
|
|
void QueryBuilder_group_by_default_func_w_id(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Rel = ecs.entity();
|
|
auto TgtA = ecs.entity();
|
|
auto TgtB = ecs.entity();
|
|
auto TgtC = ecs.entity();
|
|
|
|
auto e1 = ecs.entity().add(Rel, TgtC);
|
|
auto e2 = ecs.entity().add(Rel, TgtB);
|
|
auto e3 = ecs.entity().add(Rel, TgtA);
|
|
|
|
auto q = ecs.query_builder()
|
|
.term(Rel, flecs::Wildcard)
|
|
.group_by(Rel)
|
|
.build();
|
|
|
|
bool e1_found = false;
|
|
bool e2_found = false;
|
|
bool e3_found = false;
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::iter& it, size_t i) {
|
|
flecs::entity e = it.entity(i);
|
|
if (e == e1) {
|
|
test_assert(it.group_id() == TgtC);
|
|
test_assert(!e1_found);
|
|
test_assert(e2_found);
|
|
test_assert(e3_found);
|
|
e1_found = true;
|
|
}
|
|
if (e == e2) {
|
|
test_assert(it.group_id() == TgtB);
|
|
test_assert(!e1_found);
|
|
test_assert(!e2_found);
|
|
test_assert(e3_found);
|
|
e2_found = true;
|
|
}
|
|
if (e == e3) {
|
|
test_assert(it.group_id() == TgtA);
|
|
test_assert(!e1_found);
|
|
test_assert(!e2_found);
|
|
test_assert(!e3_found);
|
|
e3_found = true;
|
|
}
|
|
count ++;
|
|
});
|
|
|
|
test_int(3, count);
|
|
test_bool(true, e1_found);
|
|
test_bool(true, e2_found);
|
|
test_bool(true, e3_found);
|
|
}
|
|
|
|
void QueryBuilder_group_by_default_func_w_type(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Rel { };
|
|
auto TgtA = ecs.entity();
|
|
auto TgtB = ecs.entity();
|
|
auto TgtC = ecs.entity();
|
|
|
|
auto e1 = ecs.entity().add<Rel>(TgtC);
|
|
auto e2 = ecs.entity().add<Rel>(TgtB);
|
|
auto e3 = ecs.entity().add<Rel>(TgtA);
|
|
|
|
auto q = ecs.query_builder()
|
|
.term<Rel>(flecs::Wildcard)
|
|
.group_by<Rel>()
|
|
.build();
|
|
|
|
bool e1_found = false;
|
|
bool e2_found = false;
|
|
bool e3_found = false;
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::iter& it, size_t i) {
|
|
flecs::entity e = it.entity(i);
|
|
if (e == e1) {
|
|
test_assert(it.group_id() == TgtC);
|
|
test_assert(!e1_found);
|
|
test_assert(e2_found);
|
|
test_assert(e3_found);
|
|
e1_found = true;
|
|
}
|
|
if (e == e2) {
|
|
test_assert(it.group_id() == TgtB);
|
|
test_assert(!e1_found);
|
|
test_assert(!e2_found);
|
|
test_assert(e3_found);
|
|
e2_found = true;
|
|
}
|
|
if (e == e3) {
|
|
test_assert(it.group_id() == TgtA);
|
|
test_assert(!e1_found);
|
|
test_assert(!e2_found);
|
|
test_assert(!e3_found);
|
|
e3_found = true;
|
|
}
|
|
count ++;
|
|
});
|
|
|
|
test_int(3, count);
|
|
test_bool(true, e1_found);
|
|
test_bool(true, e2_found);
|
|
test_bool(true, e3_found);
|
|
}
|
|
|
|
static int group_by_ctx = 0;
|
|
|
|
void QueryBuilder_group_by_callbacks(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Rel { };
|
|
auto TgtA = ecs.entity();
|
|
auto TgtB = ecs.entity();
|
|
auto TgtC = ecs.entity();
|
|
|
|
auto e1 = ecs.entity().add<Rel>(TgtC);
|
|
auto e2 = ecs.entity().add<Rel>(TgtB);
|
|
auto e3 = ecs.entity().add<Rel>(TgtA);
|
|
|
|
auto q = ecs.query_builder()
|
|
.term<Rel>(flecs::Wildcard)
|
|
.group_by<Rel>()
|
|
.group_by_ctx(&group_by_ctx)
|
|
.on_group_create(
|
|
[](flecs::world_t *world, uint64_t id, void *group_by_arg) {
|
|
test_assert(world != nullptr);
|
|
test_assert(id != 0);
|
|
test_assert(group_by_arg != nullptr);
|
|
test_assert(group_by_arg == &group_by_ctx);
|
|
uint64_t *ctx = ecs_os_malloc_t(uint64_t);
|
|
*ctx = id;
|
|
return (void*)ctx;
|
|
})
|
|
.on_group_delete(
|
|
[](flecs::world_t *world, uint64_t id, void *ctx, void *group_by_arg) {
|
|
test_assert(world != nullptr);
|
|
test_assert(id != 0);
|
|
test_assert(group_by_arg != nullptr);
|
|
test_assert(group_by_arg == &group_by_ctx);
|
|
test_assert(ctx != NULL);
|
|
test_uint(*(uint64_t*)ctx, id);
|
|
ecs_os_free(ctx);
|
|
})
|
|
.build();
|
|
|
|
bool e1_found = false;
|
|
bool e2_found = false;
|
|
bool e3_found = false;
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::iter& it, size_t i) {
|
|
flecs::entity e = it.entity(i);
|
|
if (e == e1) {
|
|
test_assert(it.group_id() == TgtC);
|
|
test_assert(!e1_found);
|
|
test_assert(e2_found);
|
|
test_assert(e3_found);
|
|
e1_found = true;
|
|
uint64_t *ctx = (uint64_t*)q.group_ctx(it.group_id());
|
|
test_uint(*ctx, it.group_id());
|
|
}
|
|
if (e == e2) {
|
|
test_assert(it.group_id() == TgtB);
|
|
test_assert(!e1_found);
|
|
test_assert(!e2_found);
|
|
test_assert(e3_found);
|
|
e2_found = true;
|
|
uint64_t *ctx = (uint64_t*)q.group_ctx(it.group_id());
|
|
test_uint(*ctx, it.group_id());
|
|
}
|
|
if (e == e3) {
|
|
test_assert(it.group_id() == TgtA);
|
|
test_assert(!e1_found);
|
|
test_assert(!e2_found);
|
|
test_assert(!e3_found);
|
|
e3_found = true;
|
|
uint64_t *ctx = (uint64_t*)q.group_ctx(it.group_id());
|
|
test_uint(*ctx, it.group_id());
|
|
}
|
|
count ++;
|
|
});
|
|
|
|
test_int(3, count);
|
|
test_bool(true, e1_found);
|
|
test_bool(true, e2_found);
|
|
test_bool(true, e3_found);
|
|
}
|
|
|
|
void QueryBuilder_create_w_no_template_args(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder().term<Position>().build();
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_any_wildcard(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Likes = ecs.entity();
|
|
auto Apple = ecs.entity();
|
|
auto Mango = ecs.entity();
|
|
|
|
auto e1 = ecs.entity()
|
|
.add(Likes, Apple)
|
|
.add(Likes, Mango);
|
|
|
|
auto q = ecs.query_builder()
|
|
.term(Likes, flecs::Any)
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
test_assert(e == e1);
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|
|
|
|
void QueryBuilder_cascade(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Tag = ecs.entity();
|
|
auto Foo = ecs.entity();
|
|
auto Bar = ecs.entity();
|
|
|
|
auto e0 = ecs.entity().add(Tag);
|
|
auto e1 = ecs.entity().is_a(e0);
|
|
auto e2 = ecs.entity().is_a(e1);
|
|
auto e3 = ecs.entity().is_a(e2);
|
|
|
|
auto q = ecs.query_builder()
|
|
.term(Tag).cascade()
|
|
.build();
|
|
|
|
e1.add(Bar);
|
|
e2.add(Foo);
|
|
|
|
bool e1_found = false;
|
|
bool e2_found = false;
|
|
bool e3_found = false;
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
|
|
if (e == e1) {
|
|
test_bool(e1_found, false);
|
|
test_bool(e2_found, false);
|
|
test_bool(e3_found, false);
|
|
e1_found = true;
|
|
}
|
|
if (e == e2) {
|
|
test_bool(e1_found, true);
|
|
test_bool(e2_found, false);
|
|
test_bool(e3_found, false);
|
|
e2_found = true;
|
|
}
|
|
if (e == e3) {
|
|
test_bool(e1_found, true);
|
|
test_bool(e2_found, true);
|
|
test_bool(e3_found, false);
|
|
e3_found = true;
|
|
}
|
|
});
|
|
|
|
test_bool(e1_found, true);
|
|
test_bool(e2_found, true);
|
|
test_bool(e3_found, true);
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void QueryBuilder_cascade_desc(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Tag = ecs.entity();
|
|
auto Foo = ecs.entity();
|
|
auto Bar = ecs.entity();
|
|
|
|
auto e0 = ecs.entity().add(Tag);
|
|
auto e1 = ecs.entity().is_a(e0);
|
|
auto e2 = ecs.entity().is_a(e1);
|
|
auto e3 = ecs.entity().is_a(e2);
|
|
|
|
auto q = ecs.query_builder()
|
|
.term(Tag).cascade().desc()
|
|
.build();
|
|
|
|
e1.add(Bar);
|
|
e2.add(Foo);
|
|
|
|
bool e1_found = false;
|
|
bool e2_found = false;
|
|
bool e3_found = false;
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
|
|
if (e == e1) {
|
|
test_bool(e1_found, false);
|
|
test_bool(e2_found, true);
|
|
test_bool(e3_found, true);
|
|
e1_found = true;
|
|
}
|
|
if (e == e2) {
|
|
test_bool(e1_found, false);
|
|
test_bool(e2_found, false);
|
|
test_bool(e3_found, true);
|
|
e2_found = true;
|
|
}
|
|
if (e == e3) {
|
|
test_bool(e1_found, false);
|
|
test_bool(e2_found, false);
|
|
test_bool(e3_found, false);
|
|
e3_found = true;
|
|
}
|
|
});
|
|
|
|
test_bool(e1_found, true);
|
|
test_bool(e2_found, true);
|
|
test_bool(e3_found, true);
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void QueryBuilder_cascade_w_relationship(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Tag = ecs.entity();
|
|
auto Foo = ecs.entity();
|
|
auto Bar = ecs.entity();
|
|
|
|
auto e0 = ecs.entity().add(Tag);
|
|
auto e1 = ecs.entity().child_of(e0);
|
|
auto e2 = ecs.entity().child_of(e1);
|
|
auto e3 = ecs.entity().child_of(e2);
|
|
|
|
auto q = ecs.query_builder()
|
|
.term(Tag).cascade(flecs::ChildOf)
|
|
.build();
|
|
|
|
e1.add(Bar);
|
|
e2.add(Foo);
|
|
|
|
bool e1_found = false;
|
|
bool e2_found = false;
|
|
bool e3_found = false;
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
|
|
if (e == e1) {
|
|
test_bool(e1_found, false);
|
|
test_bool(e2_found, false);
|
|
test_bool(e3_found, false);
|
|
e1_found = true;
|
|
}
|
|
if (e == e2) {
|
|
test_bool(e1_found, true);
|
|
test_bool(e2_found, false);
|
|
test_bool(e3_found, false);
|
|
e2_found = true;
|
|
}
|
|
if (e == e3) {
|
|
test_bool(e1_found, true);
|
|
test_bool(e2_found, true);
|
|
test_bool(e3_found, false);
|
|
e3_found = true;
|
|
}
|
|
});
|
|
|
|
test_bool(e1_found, true);
|
|
test_bool(e2_found, true);
|
|
test_bool(e3_found, true);
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void QueryBuilder_up_w_type(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Rel { };
|
|
|
|
ecs.component<Rel>().add(flecs::Traversable);
|
|
|
|
auto q = ecs.query_builder<Self>()
|
|
.term<Other>().src().up<Rel>()
|
|
.build();
|
|
|
|
auto base = ecs.entity().set<Other>({10});
|
|
|
|
auto
|
|
e = ecs.entity().add<Rel>(base); e.set<Self>({e});
|
|
e = ecs.entity().add<Rel>(base); e.set<Self>({e});
|
|
e = ecs.entity().add<Rel>(base); e.set<Self>({e});
|
|
|
|
int32_t count = 0;
|
|
|
|
q.iter([&](flecs::iter& it, Self *s) {
|
|
auto o = it.field<const Other>(2);
|
|
test_assert(!it.is_self(2));
|
|
test_int(o->value, 10);
|
|
|
|
for (auto i : it) {
|
|
test_assert(it.entity(i) == s[i].value);
|
|
count ++;
|
|
}
|
|
});
|
|
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void QueryBuilder_cascade_w_type(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Rel { };
|
|
|
|
ecs.component<Rel>().add(flecs::Traversable);
|
|
|
|
auto Tag = ecs.entity();
|
|
auto Foo = ecs.entity();
|
|
auto Bar = ecs.entity();
|
|
|
|
auto e0 = ecs.entity().add(Tag);
|
|
auto e1 = ecs.entity().add<Rel>(e0);
|
|
auto e2 = ecs.entity().add<Rel>(e1);
|
|
auto e3 = ecs.entity().add<Rel>(e2);
|
|
|
|
auto q = ecs.query_builder()
|
|
.term(Tag).cascade<Rel>()
|
|
.build();
|
|
|
|
e1.add(Bar);
|
|
e2.add(Foo);
|
|
|
|
bool e1_found = false;
|
|
bool e2_found = false;
|
|
bool e3_found = false;
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
count ++;
|
|
|
|
if (e == e1) {
|
|
test_bool(e1_found, false);
|
|
test_bool(e2_found, false);
|
|
test_bool(e3_found, false);
|
|
e1_found = true;
|
|
}
|
|
if (e == e2) {
|
|
test_bool(e1_found, true);
|
|
test_bool(e2_found, false);
|
|
test_bool(e3_found, false);
|
|
e2_found = true;
|
|
}
|
|
if (e == e3) {
|
|
test_bool(e1_found, true);
|
|
test_bool(e2_found, true);
|
|
test_bool(e3_found, false);
|
|
e3_found = true;
|
|
}
|
|
});
|
|
|
|
test_bool(e1_found, true);
|
|
test_bool(e2_found, true);
|
|
test_bool(e3_found, true);
|
|
test_int(count, 3);
|
|
}
|
|
|
|
void QueryBuilder_named_query(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
auto e2 = ecs.entity().add<Position>();
|
|
|
|
auto q = ecs.query_builder("my_query")
|
|
.term<Position>()
|
|
.build();
|
|
|
|
int32_t count = 0;
|
|
q.each([&](flecs::entity e) {
|
|
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 QueryBuilder_term_w_write(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder()
|
|
.term<Position>()
|
|
.term<Position>().write()
|
|
.build();
|
|
|
|
auto f = q.filter();
|
|
test_assert(f.term(0).inout() == flecs::InOutDefault);
|
|
test_assert(f.term(0).get_src() == flecs::This);
|
|
test_assert(f.term(1).inout() == flecs::Out);
|
|
test_assert(f.term(1).get_src() == 0);
|
|
}
|
|
|
|
void QueryBuilder_term_w_read(void) {
|
|
flecs::world ecs;
|
|
|
|
auto q = ecs.query_builder()
|
|
.term<Position>()
|
|
.term<Position>().read()
|
|
.build();
|
|
|
|
auto f = q.filter();
|
|
test_assert(f.term(0).inout() == flecs::InOutDefault);
|
|
test_assert(f.term(0).get_src() == flecs::This);
|
|
test_assert(f.term(1).inout() == flecs::In);
|
|
test_assert(f.term(1).get_src() == 0);
|
|
}
|
|
|
|
void QueryBuilder_iter_w_stage(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.set_stage_count(2);
|
|
flecs::world stage = ecs.get_stage(1);
|
|
|
|
auto e1 = ecs.entity().add<Position>();
|
|
|
|
auto q = ecs.query<Position>();
|
|
|
|
int32_t count = 0;
|
|
q.each(stage, [&](flecs::iter& it, size_t i, Position&) {
|
|
test_assert(it.world() == stage);
|
|
test_assert(it.entity(i) == e1);
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 1);
|
|
}
|