Files
PixelDefense/engine/libs/flecs/test/cpp_api/src/Observer.cpp

819 lines
17 KiB
C++

#include <cpp_api.h>
void Observer_2_terms_on_add(void) {
flecs::world ecs;
int32_t count = 0;
ecs.observer<Position, Velocity>()
.event(flecs::OnAdd)
.each([&](Position& p, Velocity& v) {
count ++;
});
auto e = ecs.entity();
test_int(count, 0);
e.set<Position>({10, 20});
test_int(count, 0);
e.set<Velocity>({1, 2});
test_int(count, 1);
}
void Observer_2_terms_on_remove(void) {
flecs::world ecs;
int32_t count = 0;
ecs.observer<Position, Velocity>()
.event(flecs::OnRemove)
.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);
});
auto e = ecs.entity();
test_int(count, 0);
e.set<Position>({10, 20});
test_int(count, 0);
e.set<Velocity>({1, 2});
test_int(count, 0);
e.remove<Velocity>();
test_int(count, 1);
e.remove<Position>();
test_int(count, 1);
}
void Observer_2_terms_on_set(void) {
flecs::world ecs;
int32_t count = 0;
ecs.observer<Position, Velocity>()
.event(flecs::OnSet)
.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);
});
auto e = ecs.entity();
test_int(count, 0);
e.set<Position>({10, 20});
test_int(count, 0);
e.set<Velocity>({1, 2});
test_int(count, 1);
}
void Observer_2_terms_un_set(void) {
flecs::world ecs;
int32_t count = 0;
ecs.observer<Position, Velocity>()
.event(flecs::UnSet)
.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);
});
auto e = ecs.entity();
test_int(count, 0);
e.set<Position>({10, 20});
test_int(count, 0);
e.set<Velocity>({1, 2});
test_int(count, 0);
e.remove<Velocity>();
test_int(count, 1);
e.remove<Position>();
test_int(count, 1);
}
void Observer_10_terms(void) {
flecs::world ecs;
int count = 0;
auto e = ecs.entity();
ecs.observer<>()
.event(flecs::OnAdd)
.term<TagA>()
.term<TagB>()
.term<TagC>()
.term<TagD>()
.term<TagE>()
.term<TagF>()
.term<TagG>()
.term<TagH>()
.term<TagI>()
.term<TagJ>()
.iter([&](flecs::iter& it) {
test_int(it.count(), 1);
test_assert(it.entity(0) == e);
test_int(it.field_count(), 10);
count ++;
});
e.add<TagA>()
.add<TagB>()
.add<TagC>()
.add<TagD>()
.add<TagE>()
.add<TagF>()
.add<TagG>()
.add<TagH>()
.add<TagI>()
.add<TagJ>();
test_int(count, 1);
}
void Observer_20_terms(void) {
flecs::world ecs;
int count = 0;
auto e = ecs.entity();
ecs.observer<>()
.event(flecs::OnAdd)
.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>()
.iter([&](flecs::iter& it) {
test_int(it.count(), 1);
test_assert(it.entity(0) == e);
test_int(it.field_count(), 20);
count ++;
});
e.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>();
test_int(count, 1);
}
void Observer_2_entities_iter(void) {
flecs::world ecs;
auto e1 = ecs.entity();
auto e2 = ecs.entity();
int32_t count = 0;
flecs::entity last;
ecs.observer<const Position>()
.event(flecs::OnSet)
.iter([&](flecs::iter& it, const Position *p) {
for (auto i : it) {
count ++;
if (it.entity(i) == e1) {
test_int(p[i].x, 10);
test_int(p[i].y, 20);
} else if (it.entity(i) == e2) {
test_int(p[i].x, 30);
test_int(p[i].y, 40);
} else {
test_assert(false);
}
last = it.entity(i);
}
});
e1.set<Position>({ 10, 20 });
test_int(count, 1);
test_assert(last == e1);
e2.set<Position>({ 30, 40 });
test_int(count, 2);
test_assert(last == e2);
}
void Observer_2_entities_table_column(void) {
flecs::world ecs;
auto e1 = ecs.entity();
auto e2 = ecs.entity();
int32_t count = 0;
flecs::entity last;
ecs.observer<const Position>()
.event(flecs::OnSet)
.iter([&](flecs::iter& it) {
auto p = it.range().get<Position>();
for (auto i : it) {
count ++;
if (it.entity(i) == e1) {
test_int(p[i].x, 10);
test_int(p[i].y, 20);
} else if (it.entity(i) == e2) {
test_int(p[i].x, 30);
test_int(p[i].y, 40);
} else {
test_assert(false);
}
last = it.entity(i);
}
});
e1.set<Position>({ 10, 20 });
test_int(count, 1);
test_assert(last == e1);
e2.set<Position>({ 30, 40 });
test_int(count, 2);
test_assert(last == e2);
}
void Observer_2_entities_each(void) {
flecs::world ecs;
auto e1 = ecs.entity();
auto e2 = ecs.entity();
int32_t count = 0;
flecs::entity last;
ecs.observer<const Position>()
.event(flecs::OnSet)
.each([&](flecs::entity e, const Position& p) {
count ++;
if (e == e1) {
test_int(p.x, 10);
test_int(p.y, 20);
} else if (e == e2) {
test_int(p.x, 30);
test_int(p.y, 40);
} else {
test_assert(false);
}
last = e;
});
e1.set<Position>({ 10, 20 });
test_int(count, 1);
test_assert(last == e1);
e2.set<Position>({ 30, 40 });
test_int(count, 2);
test_assert(last == e2);
}
void Observer_create_w_no_template_args(void) {
flecs::world ecs;
auto e1 = ecs.entity();
int32_t count = 0;
ecs.observer()
.term<Position>()
.event(flecs::OnAdd)
.each([&](flecs::entity e) {
test_assert(e == e1);
count ++;
});
e1.set<Position>({10, 20});
test_int(count, 1);
}
void Observer_yield_existing(void) {
flecs::world world;
struct TagA { };
struct TagB { };
auto e1 = world.entity().add<TagA>();
auto e2 = world.entity().add<TagA>();
auto e3 = world.entity().add<TagA>().add<TagB>();
int32_t count = 0;
world.observer<TagA>()
.event(flecs::OnAdd)
.yield_existing()
.each([&](flecs::entity e, TagA) {
if (e == e1) count ++;
if (e == e2) count += 2;
if (e == e3) count += 3;
});
test_int(count, 6);
}
void Observer_yield_existing_2_terms(void) {
flecs::world world;
struct TagA { };
struct TagB { };
auto e1 = world.entity().add<TagA>().add<TagB>();
auto e2 = world.entity().add<TagA>().add<TagB>();
auto e3 = world.entity().add<TagA>().add<TagB>().add<TagC>();
world.entity().add<TagA>();
world.entity().add<TagB>();
int32_t count = 0;
world.observer<TagA, TagB>()
.event(flecs::OnAdd)
.yield_existing()
.each([&](flecs::entity e, TagA, TagB) {
if (e == e1) count ++;
if (e == e2) count += 2;
if (e == e3) count += 3;
});
test_int(count, 6);
}
void Observer_default_ctor(void) {
flecs::world world;
struct TagA { };
flecs::observer o;
test_assert(o == 0);
int32_t count = 0;
o = world.observer<TagA>()
.event(flecs::OnAdd)
.each([&](flecs::entity e, TagA) {
count ++;
});
world.entity().add<TagA>();
test_int(count, 1);
}
void Observer_entity_ctor(void) {
flecs::world world;
struct TagA { };
flecs::observer o = world.observer<TagA>()
.event(flecs::OnAdd)
.each([&](flecs::entity e, TagA) { });
flecs::entity oe = o;
flecs::observer eo = world.observer(oe);
test_assert(eo == o);
}
void Observer_on_add(void) {
flecs::world world;
int invoked = 0;
world.observer<Position>()
.event(flecs::OnAdd)
.each([&](flecs::entity e, Position& p) {
invoked ++;
});
world.entity()
.add<Position>();
test_int(invoked, 1);
}
void Observer_on_remove(void) {
flecs::world world;
int invoked = 0;
world.observer<Position>()
.event(flecs::OnRemove)
.each([&](flecs::entity e, Position& p) {
invoked ++;
});
auto e = world.entity()
.add<Position>();
test_int(invoked, 0);
e.remove<Position>();
test_int(invoked, 1);
}
struct MyTag { };
void Observer_on_add_tag_action(void) {
flecs::world world;
int invoked = 0;
world.observer<MyTag>()
.event(flecs::OnAdd)
.iter([&](flecs::iter it, MyTag*) {
invoked ++;
});
world.entity()
.add<MyTag>();
test_int(invoked, 1);
}
void Observer_on_add_tag_iter(void) {
flecs::world world;
int invoked = 0;
world.observer<MyTag>()
.event(flecs::OnAdd)
.iter([&](flecs::iter it, MyTag*) {
invoked ++;
});
world.entity()
.add<MyTag>();
test_int(invoked, 1);
}
void Observer_on_add_tag_each(void) {
flecs::world world;
int invoked = 0;
world.observer<MyTag>()
.event(flecs::OnAdd)
.each([&](flecs::entity e, MyTag) {
invoked ++;
});
world.entity()
.add<MyTag>();
test_int(invoked, 1);
}
void Observer_on_add_expr(void) {
flecs::world world;
int invoked = 0;
world.component<Tag>();
world.observer<>().expr("Tag")
.event(flecs::OnAdd)
.each([&](flecs::entity e) {
invoked ++;
});
auto e = world.entity().add<Tag>();
test_int(invoked, 1);
e.remove<Tag>();
test_int(invoked, 1);
}
void Observer_observer_w_filter_term(void) {
flecs::world world;
flecs::entity TagA = world.entity();
flecs::entity TagB = world.entity();
int invoked = 0;
world.observer()
.term(TagA)
.term(TagB).filter()
.event(flecs::OnAdd)
.each([&](flecs::entity e) {
invoked ++;
});
flecs::entity e = world.entity();
test_int(invoked, 0);
e.add(TagB);
test_int(invoked, 0);
e.add(TagA);
test_int(invoked, 1);
e.remove(TagB);
test_int(invoked, 1);
e.add(TagB);
test_int(invoked, 1);
e.clear();
test_int(invoked, 1);
e.add(TagA);
test_int(invoked, 1);
}
void Observer_run_callback(void) {
flecs::world ecs;
int32_t count = 0;
ecs.observer<Position>()
.event(flecs::OnAdd)
.run([](flecs::iter_t *it) {
while (ecs_iter_next(it)) {
it->callback(it);
}
})
.each([&](Position& p) {
count ++;
});
auto e = ecs.entity();
test_int(count, 0);
e.set<Position>({10, 20});
test_int(count, 1);
}
void Observer_get_query(void) {
flecs::world world;
world.entity().set<Position>({0, 0});
world.entity().set<Position>({1, 0});
world.entity().set<Position>({2, 0});
int32_t count = 0;
auto sys = world.observer<const Position>()
.event(flecs::OnSet)
.each([&](flecs::entity e, const Position& p) {
// Not used
});
auto q = sys.query();
q.iter([&](flecs::iter &it) {
auto pos = it.field<const Position>(1);
for (auto i : it) {
test_int(i, pos[i].x);
count ++;
}
});
test_int(count, 3);
}
void Observer_on_set_w_set(void) {
flecs::world world;
int32_t count = 0;
world.observer<Position>()
.event(flecs::OnSet)
.each([&](flecs::entity e, Position& p) {
count ++;
});
flecs::entity e = world.entity();
test_int(count, 0);
e.set<Position>({10, 20});
test_int(count, 1);
}
void Observer_on_set_w_defer_set(void) {
flecs::world world;
int32_t count = 0;
world.observer<Position>()
.event(flecs::OnSet)
.each([&](flecs::entity e, Position& p) {
count ++;
});
flecs::entity e = world.entity();
test_int(count, 0);
world.defer_begin();
e.set<Position>({10, 20});
test_int(count, 0);
world.defer_end();
test_int(count, 1);
}
#include <iostream>
void Observer_on_add_singleton(void) {
flecs::world world;
int32_t count = 0;
world.observer<Position>()
.term_at(1).singleton()
.event(flecs::OnSet)
.each([&](Position& p) {
test_int(p.x, 10);
test_int(p.y, 20);
count ++;
});
world.set<Position>({10, 20});
test_int(count, 1);
}
void Observer_on_add_pair_singleton(void) {
flecs::world world;
int32_t count = 0;
flecs::entity tgt = world.entity();
world.observer<Position>()
.term_at(1).second(tgt).singleton()
.event(flecs::OnSet)
.each([&](Position& p) {
test_int(p.x, 10);
test_int(p.y, 20);
count ++;
});
world.set<Position>(tgt, {10, 20});
test_int(count, 1);
}
void Observer_on_add_pair_wildcard_singleton(void) {
flecs::world world;
int32_t count = 0;
flecs::entity tgt_1 = world.entity();
flecs::entity tgt_2 = world.entity();
world.observer<Position>()
.term_at(1).second(flecs::Wildcard).singleton()
.event(flecs::OnSet)
.each([&](Position& p) {
test_int(p.x, 10);
test_int(p.y, 20);
count ++;
});
world.set<Position>(tgt_1, {10, 20});
test_int(count, 1);
world.set<Position>(tgt_2, {10, 20});
test_int(count, 2);
}
void Observer_on_add_with_pair_singleton(void) {
flecs::world world;
int32_t count = 0;
flecs::entity tgt = world.entity();
world.observer()
.with<Position>(tgt).singleton()
.event(flecs::OnSet)
.each([&](flecs::entity) {
count ++;
});
world.set<Position>(tgt, {10, 20});
test_int(count, 1);
}
void Observer_add_in_yield_existing(void) {
flecs::world world;
flecs::entity e1 = world.entity().set<Position>({});
flecs::entity e2 = world.entity().set<Position>({});
flecs::entity e3 = world.entity().set<Position>({});
world.observer()
.with<Position>()
.event(flecs::OnAdd)
.yield_existing()
.each([](flecs::entity e) {
e.add<Velocity>();
});
test_assert(e1.has<Position>());
test_assert(e1.has<Velocity>());
test_assert(e2.has<Position>());
test_assert(e2.has<Velocity>());
test_assert(e3.has<Position>());
test_assert(e3.has<Velocity>());
}
void Observer_add_in_yield_existing_multi(void) {
flecs::world world;
flecs::entity e1 = world.entity().set<Position>({}).set<Mass>({});
flecs::entity e2 = world.entity().set<Position>({}).set<Mass>({});
flecs::entity e3 = world.entity().set<Position>({}).set<Mass>({});
world.observer()
.with<Position>()
.with<Mass>()
.event(flecs::OnAdd)
.yield_existing()
.each([](flecs::entity e) {
e.add<Velocity>();
});
test_assert(e1.has<Position>());
test_assert(e1.has<Mass>());
test_assert(e1.has<Velocity>());
test_assert(e2.has<Position>());
test_assert(e2.has<Mass>());
test_assert(e2.has<Velocity>());
test_assert(e3.has<Position>());
test_assert(e3.has<Mass>());
test_assert(e3.has<Velocity>());
}
void Observer_name_from_root(void) {
flecs::world ecs;
flecs::entity sys = ecs.observer<Position>("::ns::MySystem")
.event(flecs::OnSet)
.each([](Position& p) { });
test_str(sys.name(), "MySystem");
flecs::entity ns = ecs.entity("::ns");
test_assert(ns == sys.parent());
}