#include void RuleBuilder_1_type(void) { flecs::world ecs; auto e1 = ecs.entity() .set({10, 20}); ecs.entity().set({10, 20}); auto r = ecs.rule(); int count = 0; r.each([&](flecs::entity e, Position& p) { count ++; test_assert(e == e1); test_int(p.x, 10); test_int(p.y, 20); }); test_int(count, 1); r.destruct(); } void RuleBuilder_2_types(void) { flecs::world ecs; auto e1 = ecs.entity() .set({10, 20}) .set({1, 2}); ecs.entity().set({10, 20}); auto r = ecs.rule(); int count = 0; r.each([&](flecs::entity e, Position& p, const Velocity& v) { count ++; test_assert(e == e1); test_int(p.x, 10); test_int(p.y, 20); test_int(v.x, 1); test_int(v.y, 2); }); test_int(count, 1); r.destruct(); } void RuleBuilder_id_term(void) { flecs::world ecs; auto Tag = ecs.entity(); auto e1 = ecs.entity() .add(Tag); ecs.entity().set({10, 20}); auto r = ecs.rule_builder() .term(Tag) .build(); int count = 0; r.each([&](flecs::entity e) { count ++; test_assert(e == e1); }); test_int(count, 1); r.destruct(); } void RuleBuilder_type_term(void) { flecs::world ecs; auto e1 = ecs.entity() .set({10, 20}); ecs.entity().set({10, 20}); auto r = ecs.rule_builder() .term() .build(); int count = 0; r.each([&](flecs::entity e) { count ++; test_assert(e == e1); }); test_int(count, 1); r.destruct(); } void RuleBuilder_id_pair_term(void) { flecs::world ecs; auto Likes = ecs.entity(); auto Apples = ecs.entity(); auto Pears = ecs.entity(); auto e1 = ecs.entity() .add(Likes, Apples); ecs.entity() .add(Likes, Pears); auto r = ecs.rule_builder() .term(Likes, Apples) .build(); int count = 0; r.each([&](flecs::entity e) { count ++; test_assert(e == e1); }); test_int(count, 1); r.destruct(); } void RuleBuilder_id_pair_wildcard_term(void) { flecs::world ecs; auto Likes = ecs.entity(); auto Apples = ecs.entity(); auto Pears = ecs.entity(); auto e1 = ecs.entity() .add(Likes, Apples); auto e2 = ecs.entity() .add(Likes, Pears); auto r = ecs.rule_builder() .term(Likes, flecs::Wildcard) .build(); int count = 0; r.each([&](flecs::iter& it, size_t index) { if (it.entity(index) == e1) { test_assert(it.id(1) == ecs.pair(Likes, Apples)); count ++; } if (it.entity(index) == e2) { test_assert(it.id(1) == ecs.pair(Likes, Pears)); count ++; } }); test_int(count, 2); r.destruct(); } void RuleBuilder_type_pair_term(void) { flecs::world ecs; struct Likes { }; struct Apples { }; struct Pears { }; auto e1 = ecs.entity() .add(); auto e2 = ecs.entity() .add(); auto r = ecs.rule_builder() .term(flecs::Wildcard) .build(); int count = 0; r.each([&](flecs::iter& it, size_t index) { if (it.entity(index) == e1) { test_assert((it.id(1) == ecs.pair())); count ++; } if (it.entity(index) == e2) { test_assert((it.id(1) == ecs.pair())); count ++; } }); test_int(count, 2); r.destruct(); } void RuleBuilder_pair_term_w_var(void) { flecs::world ecs; struct Likes { }; struct Apples { }; struct Pears { }; auto e1 = ecs.entity() .add(); auto e2 = ecs.entity() .add(); auto r = ecs.rule_builder() .term().second().var("Food") .build(); int food_var = r.find_var("Food"); int count = 0; r.each([&](flecs::iter& it, size_t index) { if (it.entity(index) == e1) { test_assert((it.id(1) == ecs.pair())); test_assert(it.get_var("Food") == ecs.id()); test_assert(it.get_var(food_var) == ecs.id()); count ++; } if (it.entity(index) == e2) { test_assert((it.id(1) == ecs.pair())); test_assert(it.get_var("Food") == ecs.id()); test_assert(it.get_var(food_var) == ecs.id()); count ++; } }); test_int(count, 2); r.destruct(); } void RuleBuilder_2_pair_terms_w_var(void) { flecs::world ecs; struct Likes { }; struct Eats { }; struct Apples { }; struct Pears { }; auto Bob = ecs.entity() .add(); auto Alice = ecs.entity() .add() .add(Bob); Bob.add(Alice); auto r = ecs.rule_builder() .term().second().var("Food") .term().second().var("Person") .build(); int food_var = r.find_var("Food"); int person_var = r.find_var("Person"); int count = 0; r.each([&](flecs::iter& it, size_t index) { if (it.entity(index) == Bob) { test_assert((it.id(1) == ecs.pair())); test_assert(it.get_var("Food") == ecs.id()); test_assert(it.get_var(food_var) == ecs.id()); test_assert((it.id(2) == ecs.pair(Alice))); test_assert(it.get_var("Person") == Alice); test_assert(it.get_var(person_var) == Alice); count ++; } if (it.entity(index) == Alice) { test_assert((it.id(1) == ecs.pair())); test_assert(it.get_var("Food") == ecs.id()); test_assert(it.get_var(food_var) == ecs.id()); test_assert((it.id(2) == ecs.pair(Bob))); test_assert(it.get_var("Person") == Bob); test_assert(it.get_var(person_var) == Bob); count ++; } }); test_int(count, 2); r.destruct(); } void RuleBuilder_set_var(void) { flecs::world ecs; struct Likes { }; auto Apples = ecs.entity(); auto Pears = ecs.entity(); ecs.entity() .add(Apples); auto e2 = ecs.entity() .add(Pears); auto r = ecs.rule_builder() .term().second().var("Food") .build(); int food_var = r.find_var("Food"); int count = 0; r.iter() .set_var(food_var, Pears) .each([&](flecs::iter& it, size_t index) { test_assert(it.entity(index) == e2); test_assert((it.id(1) == ecs.pair(Pears))); test_assert(it.get_var("Food") == Pears); test_assert(it.get_var(food_var) == Pears); count ++; }); test_int(count, 1); r.destruct(); } void RuleBuilder_set_2_vars(void) { flecs::world ecs; struct Likes { }; struct Eats { }; auto Apples = ecs.entity(); auto Pears = ecs.entity(); auto Bob = ecs.entity() .add(Apples); auto Alice = ecs.entity() .add(Pears) .add(Bob); Bob.add(Alice); auto r = ecs.rule_builder() .term().second().var("Food") .term().second().var("Person") .build(); int food_var = r.find_var("Food"); int person_var = r.find_var("Person"); int count = 0; r.iter() .set_var(food_var, Pears) .set_var(person_var, Bob) .each([&](flecs::iter& it, size_t index) { test_assert(it.entity(index) == Alice); test_assert((it.id(1) == ecs.pair(Pears))); test_assert((it.id(2) == ecs.pair(Bob))); test_assert(it.get_var("Food") == Pears); test_assert(it.get_var(food_var) == Pears); test_assert(it.get_var("Person") == Bob); test_assert(it.get_var(person_var) == Bob); count ++; }); test_int(count, 1); r.destruct(); } void RuleBuilder_set_var_by_name(void) { flecs::world ecs; struct Likes { }; auto Apples = ecs.entity(); auto Pears = ecs.entity(); ecs.entity() .add(Apples); auto e2 = ecs.entity() .add(Pears); auto r = ecs.rule_builder() .term().second().var("Food") .build(); int count = 0; r.iter() .set_var("Food", Pears) .each([&](flecs::iter& it, size_t index) { test_assert(it.entity(index) == e2); test_assert((it.id(1) == ecs.pair(Pears))); count ++; }); test_int(count, 1); r.destruct(); } void RuleBuilder_set_2_vars_by_name(void) { flecs::world ecs; struct Likes { }; struct Eats { }; auto Apples = ecs.entity(); auto Pears = ecs.entity(); auto Bob = ecs.entity() .add(Apples); auto Alice = ecs.entity() .add(Pears) .add(Bob); Bob.add(Alice); auto r = ecs.rule_builder() .term().second().var("Food") .term().second().var("Person") .build(); int food_var = r.find_var("Food"); int person_var = r.find_var("Person"); int count = 0; r.iter() .set_var("Food", Pears) .set_var("Person", Bob) .each([&](flecs::iter& it, size_t index) { test_assert(it.entity(index) == Alice); test_assert((it.id(1) == ecs.pair(Pears))); test_assert((it.id(2) == ecs.pair(Bob))); test_assert(it.get_var("Food") == Pears); test_assert(it.get_var(food_var) == Pears); test_assert(it.get_var("Person") == Bob); test_assert(it.get_var(person_var) == Bob); count ++; }); test_int(count, 1); r.destruct(); } void RuleBuilder_expr_w_var(void) { flecs::world ecs; auto rel = ecs.entity("Rel"); auto obj = ecs.entity(); auto e = ecs.entity().add(rel, obj); auto r = ecs.rule_builder() .expr("(Rel, $X)") .build(); int x_var = r.find_var("X"); test_assert(x_var != -1); int32_t count = 0; r.each([&](flecs::iter& it, size_t index) { test_assert(it.entity(index) == e); test_assert(it.pair(1).second() == obj); count ++; }); test_int(count, 1); r.destruct(); } void RuleBuilder_get_first(void) { flecs::world ecs; struct A {}; auto e1 = ecs.entity().add(); ecs.entity().add(); ecs.entity().add(); auto q = ecs.rule(); auto first = q.iter().first(); test_assert(first != 0); test_assert(first == e1); q.destruct(); } void RuleBuilder_get_count_direct(void) { flecs::world ecs; struct A {}; ecs.entity().add(); ecs.entity().add(); ecs.entity().add(); auto q = ecs.rule(); test_int(3, q.count()); q.destruct(); } void RuleBuilder_get_is_true_direct(void) { flecs::world ecs; struct A {}; struct B {}; ecs.entity().add(); ecs.entity().add(); ecs.entity().add(); auto q_1 = ecs.rule(); auto q_2 = ecs.rule(); test_bool(true, q_1.is_true()); test_bool(false, q_2.is_true()); q_1.destruct(); q_2.destruct(); } void RuleBuilder_get_first_direct(void) { flecs::world ecs; struct A {}; auto e1 = ecs.entity().add(); ecs.entity().add(); ecs.entity().add(); auto q = ecs.rule(); auto first = q.first(); test_assert(first != 0); test_assert(first == e1); q.destruct(); } void RuleBuilder_var_src_w_prefixed_name(void) { flecs::world ecs; struct Foo { }; auto r = ecs.rule_builder() .term().src("$Var") .build(); auto e = ecs.entity().add(); int32_t count = 0; r.iter([&](flecs::iter& it) { test_assert(it.get_var("Var") == e); count ++; }); test_int(count, 1); r.destruct(); } void RuleBuilder_var_first_w_prefixed_name(void) { flecs::world ecs; struct Foo { }; auto r = ecs.rule_builder() .term() .term().first("$Var") .build(); auto e = ecs.entity().add(); int32_t count = 0; r.iter([&](flecs::iter& it) { test_int(it.count(), 1); test_uint(it.entity(0), e); test_assert(it.get_var("Var") == ecs.id()); count ++; }); test_int(count, 1); r.destruct(); } void RuleBuilder_var_second_w_prefixed_name(void) { flecs::world ecs; struct Foo { }; auto r = ecs.rule_builder() .term().second("$Var") .build(); auto t = ecs.entity(); auto e = ecs.entity().add(t); int32_t count = 0; r.iter([&](flecs::iter& it) { test_int(it.count(), 1); test_uint(it.entity(0), e); test_assert(it.get_var("Var") == t); count ++; }); test_int(count, 1); r.destruct(); } void RuleBuilder_term_w_second_var_string(void) { flecs::world ecs; flecs::entity Foo = ecs.entity(); auto r = ecs.rule_builder() .term(Foo, "$Var") .build(); auto t = ecs.entity(); auto e = ecs.entity().add(Foo, t); int32_t count = 0; r.iter([&](flecs::iter& it) { test_int(it.count(), 1); test_uint(it.entity(0), e); test_assert(it.get_var("Var") == t); count ++; }); test_int(count, 1); r.destruct(); } void RuleBuilder_term_type_w_second_var_string(void) { flecs::world ecs; struct Foo { }; auto r = ecs.rule_builder() .term("$Var") .build(); auto t = ecs.entity(); auto e = ecs.entity().add(t); int32_t count = 0; r.iter([&](flecs::iter& it) { test_int(it.count(), 1); test_uint(it.entity(0), e); test_assert(it.get_var("Var") == t); count ++; }); test_int(count, 1); r.destruct(); } void RuleBuilder_named_rule(void) { flecs::world ecs; auto e1 = ecs.entity().add(); auto e2 = ecs.entity().add(); auto q = ecs.rule("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"); q.destruct(); } void RuleBuilder_named_scoped_rule(void) { flecs::world ecs; auto e1 = ecs.entity().add(); auto e2 = ecs.entity().add(); auto q = ecs.rule("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"); q.destruct(); } void RuleBuilder_is_valid(void) { flecs::world ecs; auto q_1 = ecs.rule(); test_assert(q_1.is_valid()); flecs::log::set_level(-4); auto q_2 = ecs.rule_builder().expr("foo").build(); test_assert(!q_2.is_valid()); q_1.destruct(); } void RuleBuilder_unresolved_by_name(void) { flecs::world ecs; auto q = ecs.rule_builder() .filter_flags(EcsFilterUnresolvedByName) .expr("$this == Foo") .build(); test_assert(q.is_valid()); test_false(q.iter().is_true()); ecs.entity("Foo"); test_true(q.iter().is_true()); q.destruct(); } void RuleBuilder_scope(void) { flecs::world ecs; flecs::entity Root = ecs.entity(); flecs::entity TagA = ecs.entity(); flecs::entity TagB = ecs.entity(); ecs.entity() .add(Root) .add(TagA) .add(TagB); auto e2 = ecs.entity() .add(Root) .add(TagA); ecs.entity() .add(Root) .add(TagB); ecs.entity() .add(Root); auto r = ecs.rule_builder() .with(Root) .scope_open().not_() .with(TagA) .without(TagB) .scope_close() .build(); int32_t count = 0; r.each([&](flecs::entity e) { test_assert(e != e2); count ++; }); test_int(count, 3); r.destruct(); } void RuleBuilder_iter_w_stage(void) { flecs::world ecs; ecs.set_stage_count(2); flecs::world stage = ecs.get_stage(1); auto e1 = ecs.entity().add(); auto q = ecs.rule(); 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); q.destruct(); } void RuleBuilder_inspect_terms_w_expr(void) { flecs::world ecs; flecs::rule<> f = ecs.rule_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); f.destruct(); } void RuleBuilder_find(void) { flecs::world ecs; /* auto e1 = */ ecs.entity().set({10, 20}); auto e2 = ecs.entity().set({20, 30}); auto q = ecs.rule(); auto r = q.find([](Position& p) { return p.x == 20; }); test_assert(r == e2); q.destruct(); } void RuleBuilder_find_not_found(void) { flecs::world ecs; /* auto e1 = */ ecs.entity().set({10, 20}); /* auto e2 = */ ecs.entity().set({20, 30}); auto q = ecs.rule(); auto r = q.find([](Position& p) { return p.x == 30; }); test_assert(!r); q.destruct(); } void RuleBuilder_find_w_entity(void) { flecs::world ecs; /* auto e1 = */ ecs.entity().set({10, 20}).set({20, 30}); auto e2 = ecs.entity().set({20, 30}).set({20, 30}); auto q = ecs.rule(); auto r = q.find([](flecs::entity e, Position& p) { return p.x == e.get()->x && p.y == e.get()->y; }); test_assert(r == e2); q.destruct(); }