1844 lines
42 KiB
C++
1844 lines
42 KiB
C++
#include <cpp_api.h>
|
|
|
|
void World_multi_world_empty(void) {
|
|
flecs::world *w1 = new flecs::world();
|
|
delete w1;
|
|
flecs::world *w2 = new flecs::world();
|
|
delete w2;
|
|
|
|
test_assert(true);
|
|
}
|
|
|
|
class FooModule {
|
|
public:
|
|
FooModule(flecs::world& world) {
|
|
world.module<FooModule>();
|
|
}
|
|
};
|
|
|
|
typedef struct TestInteropModule {
|
|
int dummy;
|
|
} TestInteropModule;
|
|
|
|
static
|
|
void TestInteropModuleImport(ecs_world_t *world) {
|
|
ECS_MODULE(world, TestInteropModule);
|
|
|
|
ECS_COMPONENT(world, Position);
|
|
ECS_COMPONENT(world, Velocity);
|
|
}
|
|
|
|
namespace test {
|
|
namespace interop {
|
|
|
|
class module : TestInteropModule {
|
|
public:
|
|
struct Velocity : ::Velocity { };
|
|
|
|
module(flecs::world& ecs) {
|
|
TestInteropModuleImport(ecs);
|
|
|
|
ecs.module<test::interop::module>();
|
|
ecs.component<Position>("::test::interop::module::Position");
|
|
ecs.component<Velocity>("::test::interop::module::Velocity");
|
|
}
|
|
};
|
|
|
|
}
|
|
}
|
|
|
|
namespace ns {
|
|
struct FooComp {
|
|
int value;
|
|
};
|
|
|
|
struct namespace_module {
|
|
namespace_module(flecs::world& ecs) {
|
|
ecs.module<namespace_module>();
|
|
|
|
ecs.component<FooComp>();
|
|
|
|
import_count ++;
|
|
|
|
ecs.system<FooComp>()
|
|
.kind(flecs::OnUpdate)
|
|
.each([](flecs::entity entity, FooComp &sc) {
|
|
namespace_module::system_invoke_count ++;
|
|
});
|
|
}
|
|
|
|
static int import_count;
|
|
static int system_invoke_count;
|
|
};
|
|
|
|
int namespace_module::import_count = 0;
|
|
int namespace_module::system_invoke_count = 0;
|
|
}
|
|
|
|
void World_builtin_components(void) {
|
|
flecs::world ecs;
|
|
|
|
test_assert(ecs.component<flecs::Component>() == ecs_id(EcsComponent));
|
|
test_assert(ecs.component<flecs::Identifier>() == ecs_id(EcsIdentifier));
|
|
test_assert(ecs.component<flecs::Poly>() == ecs_id(EcsPoly));
|
|
test_assert(ecs.component<flecs::Target>() == ecs_id(EcsTarget));
|
|
test_assert(ecs.component<flecs::RateFilter>() == ecs_id(EcsRateFilter));
|
|
test_assert(ecs.component<flecs::TickSource>() == ecs_id(EcsTickSource));
|
|
test_assert(flecs::Name == EcsName);
|
|
test_assert(flecs::Symbol == EcsSymbol);
|
|
test_assert(flecs::System == EcsSystem);
|
|
test_assert(flecs::Observer == EcsObserver);
|
|
test_assert(flecs::Query == EcsQuery);
|
|
}
|
|
|
|
void World_multi_world_component(void) {
|
|
flecs::world w1;
|
|
flecs::world w2;
|
|
|
|
auto p_1 = w1.component<Position>();
|
|
auto v_1 = w1.component<Velocity>();
|
|
auto v_2 = w2.component<Velocity>();
|
|
auto m_2 = w2.component<Mass>();
|
|
|
|
test_assert(v_1.id() == v_2.id());
|
|
test_assert(p_1.id() != m_2.id());
|
|
test_assert(m_2.id() > v_2.id());
|
|
|
|
auto m_1 = w2.component<Mass>();
|
|
test_assert(m_1.id() == m_2.id());
|
|
}
|
|
|
|
namespace A {
|
|
struct Comp {
|
|
float x;
|
|
float y;
|
|
};
|
|
}
|
|
|
|
void World_multi_world_component_namespace(void) {
|
|
flecs::world *w = new flecs::world();
|
|
auto c = w->component<A::Comp>();
|
|
auto id_1 = c.id();
|
|
delete w;
|
|
|
|
w = new flecs::world();
|
|
c = w->component<A::Comp>();
|
|
auto id_2 = c.id();
|
|
|
|
test_assert(id_1 == id_2);
|
|
|
|
delete w;
|
|
}
|
|
|
|
void World_multi_world_module(void) {
|
|
flecs::world world1;
|
|
world1.import<ns::namespace_module>();
|
|
|
|
flecs::world world2;
|
|
world2.import<ns::namespace_module>();
|
|
|
|
world1.entity().add<ns::FooComp>();
|
|
world2.entity().add<ns::FooComp>();
|
|
|
|
world1.progress();
|
|
test_int(ns::namespace_module::system_invoke_count, 1);
|
|
|
|
world2.progress();
|
|
test_int(ns::namespace_module::system_invoke_count, 2);
|
|
}
|
|
|
|
void World_multi_world_recycled_component(void) {
|
|
flecs::entity c;
|
|
{
|
|
flecs::world ecs;
|
|
for (int i = 0; i < FLECS_HI_COMPONENT_ID; i ++) {
|
|
ecs_new_low_id(ecs);
|
|
}
|
|
|
|
ecs.entity().destruct();
|
|
c = ecs.component<Position>();
|
|
}
|
|
{
|
|
flecs::world ecs;
|
|
test_assert((c == ecs.component<Position>()));
|
|
}
|
|
}
|
|
|
|
void World_multi_world_recycled_component_different_generation(void) {
|
|
flecs::entity c;
|
|
{
|
|
flecs::world ecs;
|
|
for (int i = 0; i < FLECS_HI_COMPONENT_ID; i ++) {
|
|
ecs_new_low_id(ecs);
|
|
}
|
|
|
|
ecs.entity().destruct();
|
|
c = ecs.component<Position>();
|
|
}
|
|
{
|
|
flecs::world ecs;
|
|
for (int i = 0; i < FLECS_HI_COMPONENT_ID; i ++) {
|
|
ecs_new_low_id(ecs);
|
|
}
|
|
|
|
ecs.entity().destruct();
|
|
test_assert((c == ecs.component<Position>()));
|
|
}
|
|
}
|
|
|
|
void World_type_id(void) {
|
|
flecs::world ecs;
|
|
|
|
auto p = ecs.component<Position>();
|
|
|
|
test_assert(p.id() == flecs::type_id<Position>());
|
|
}
|
|
|
|
void World_different_comp_same_name(void) {
|
|
install_test_abort();
|
|
|
|
flecs::world ecs;
|
|
|
|
test_expect_abort();
|
|
|
|
ecs.component<Position>("Position");
|
|
ecs.component<Velocity>("Position");
|
|
}
|
|
|
|
void World_reregister_after_reset(void) {
|
|
flecs::world ecs;
|
|
|
|
auto p1 = ecs.component<Position>("Position");
|
|
|
|
// Simulate different binary
|
|
flecs::_::cpp_type<Position>::reset();
|
|
|
|
auto p2 = ecs.component<Position>("Position");
|
|
|
|
test_assert(p1.id() == p2.id());
|
|
}
|
|
|
|
void World_implicit_reregister_after_reset(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.entity().add<Position>();
|
|
|
|
flecs::entity_t p_id_1 = flecs::type_id<Position>();
|
|
|
|
// Simulate different binary
|
|
flecs::_::cpp_type<Position>::reset();
|
|
|
|
ecs.entity().add<Position>();
|
|
|
|
flecs::entity_t p_id_2 = flecs::type_id<Position>();
|
|
|
|
test_assert(p_id_1 == p_id_2);
|
|
}
|
|
|
|
void World_reregister_after_reset_w_namespace(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.component<ns::FooComp>();
|
|
|
|
flecs::entity_t p_id_1 = flecs::type_id<ns::FooComp>();
|
|
|
|
// Simulate different binary
|
|
flecs::_::cpp_type<ns::FooComp>::reset();
|
|
|
|
ecs.component<ns::FooComp>();
|
|
|
|
flecs::entity_t p_id_2 = flecs::type_id<ns::FooComp>();
|
|
|
|
test_assert(p_id_1 == p_id_2);
|
|
}
|
|
|
|
void World_reregister_namespace(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.component<ns::FooComp>();
|
|
|
|
flecs::entity_t p_id_1 = flecs::type_id<ns::FooComp>();
|
|
|
|
ecs.component<ns::FooComp>();
|
|
|
|
flecs::entity_t p_id_2 = flecs::type_id<ns::FooComp>();
|
|
|
|
test_assert(p_id_1 == p_id_2);
|
|
}
|
|
|
|
void World_reregister_after_reset_different_name(void) {
|
|
install_test_abort();
|
|
|
|
flecs::world ecs;
|
|
|
|
test_expect_abort();
|
|
|
|
ecs.component<Position>("Position");
|
|
|
|
// Simulate different binary
|
|
flecs::_::cpp_type<Position>::reset();
|
|
|
|
ecs.component<Position>("Velocity");
|
|
}
|
|
|
|
void World_register_component_w_reset_in_multithreaded(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.set_threads(2);
|
|
|
|
flecs::entity pos = ecs.component<Position>();
|
|
flecs::entity e = ecs.entity();
|
|
|
|
flecs::_::cpp_type<Position>::reset();
|
|
|
|
ecs.readonly_begin();
|
|
e.set<Position>({10, 20});
|
|
ecs.readonly_end();
|
|
|
|
test_assert(e.has<Position>());
|
|
test_assert(e.has(pos));
|
|
const Position *p = e.get<Position>();
|
|
test_assert(p != nullptr);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
}
|
|
|
|
struct Module { };
|
|
|
|
void World_register_component_w_core_name(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::entity c = ecs.component<Module>();
|
|
test_assert(c != 0);
|
|
test_str(c.path().c_str(), "::Module");
|
|
}
|
|
|
|
template <typename T>
|
|
struct Tmp { int32_t v; };
|
|
struct Test { };
|
|
|
|
void World_register_short_template(void) {
|
|
flecs::world ecs;
|
|
|
|
auto c = ecs.component<Tmp<Test>>();
|
|
test_assert(c != 0);
|
|
test_str(c.name(), "Tmp<Test>");
|
|
|
|
const EcsComponent *ptr = c.get<flecs::Component>();
|
|
test_assert(ptr != NULL);
|
|
test_int(ptr->size, 4);
|
|
test_int(ptr->alignment, 4);
|
|
}
|
|
|
|
void World_reimport(void) {
|
|
flecs::world ecs;
|
|
|
|
auto m1 = ecs.import<FooModule>();
|
|
|
|
auto m2 = ecs.import<FooModule>();
|
|
|
|
test_assert(m1.id() == m2.id());
|
|
}
|
|
|
|
void World_reimport_module_after_reset(void) {
|
|
flecs::world ecs;
|
|
|
|
auto m1 = ecs.import<FooModule>();
|
|
|
|
// Simulate different binary
|
|
flecs::_::cpp_type<FooModule>::reset();
|
|
|
|
auto m2 = ecs.import<FooModule>();
|
|
|
|
test_assert(m1.id() == m2.id());
|
|
}
|
|
|
|
void World_reimport_module_new_world(void) {
|
|
flecs::entity e1;
|
|
{
|
|
flecs::world ecs;
|
|
|
|
e1 = ecs.import<FooModule>();
|
|
}
|
|
|
|
{
|
|
flecs::world ecs;
|
|
|
|
auto e2 = ecs.import<FooModule>();
|
|
|
|
test_assert(e1.id() == e2.id());
|
|
}
|
|
}
|
|
|
|
void World_reimport_namespaced_module(void) {
|
|
flecs::world ecs;
|
|
|
|
test_int(ns::namespace_module::import_count, 0);
|
|
|
|
// Import first time, should call module constructor.
|
|
ecs.import<ns::namespace_module>();
|
|
|
|
test_int(ns::namespace_module::import_count, 1);
|
|
|
|
// Import second time, should not call constructor.
|
|
ecs.import<ns::namespace_module>();
|
|
|
|
test_int(ns::namespace_module::import_count, 1);
|
|
}
|
|
|
|
|
|
void World_c_interop_module(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.import<test::interop::module>();
|
|
|
|
auto e_pos = ecs.lookup("test::interop::module::Position");
|
|
test_assert(e_pos.id() != 0);
|
|
}
|
|
|
|
void World_c_interop_after_reset(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.import<test::interop::module>();
|
|
|
|
auto e_pos = ecs.lookup("test::interop::module::Position");
|
|
test_assert(e_pos.id() != 0);
|
|
|
|
flecs::_::cpp_type<test::interop::module>::reset();
|
|
|
|
ecs.import<test::interop::module>();
|
|
}
|
|
|
|
void World_implicit_register_w_new_world(void) {
|
|
{
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity().set<Position>({10, 20});
|
|
test_assert(e.has<Position>());
|
|
auto *p = e.get<Position>();
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
}
|
|
|
|
{
|
|
/* Recreate world, does not reset static state */
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity().set<Position>({10, 20});
|
|
test_assert(e.has<Position>());
|
|
auto *p = e.get<Position>();
|
|
test_assert(p != NULL);
|
|
test_int(p->x, 10);
|
|
test_int(p->y, 20);
|
|
}
|
|
}
|
|
|
|
void World_implicit_register_after_reset_register_w_custom_name(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::entity c = ecs.component<Position>("MyPosition");
|
|
test_str(c.name(), "MyPosition");
|
|
|
|
flecs::reset(); // Simulate working across boundary
|
|
|
|
auto e = ecs.entity().add<Position>();
|
|
test_assert(e.has<Position>());
|
|
test_assert(e.has(c));
|
|
}
|
|
|
|
void World_register_after_reset_register_w_custom_name(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::entity c1 = ecs.component<Position>("MyPosition");
|
|
test_str(c1.name(), "MyPosition");
|
|
|
|
flecs::reset(); // Simulate working across boundary
|
|
|
|
flecs::entity c2 = ecs.component<Position>();
|
|
test_str(c2.name(), "MyPosition");
|
|
}
|
|
|
|
void World_register_builtin_after_reset(void) {
|
|
flecs::world ecs;
|
|
|
|
auto c1 = ecs.component<flecs::Component>();
|
|
test_assert(c1 == ecs_id(EcsComponent));
|
|
|
|
flecs::reset(); // Simulate working across boundary
|
|
|
|
auto c2 = ecs.component<flecs::Component>();
|
|
test_assert(c2 == ecs_id(EcsComponent));
|
|
test_assert(c1 == c2);
|
|
}
|
|
|
|
void World_register_meta_after_reset(void) {
|
|
flecs::world ecs;
|
|
|
|
auto c1 = ecs.component<Position>();
|
|
|
|
flecs::reset(); // Simulate working across boundary
|
|
|
|
auto c2 = ecs.component<Position>()
|
|
.member<float>("x")
|
|
.member<float>("y");
|
|
|
|
test_assert(c1 == c2);
|
|
}
|
|
|
|
void World_count(void) {
|
|
flecs::world ecs;
|
|
|
|
test_int(ecs.count<Position>(), 0);
|
|
|
|
ecs.entity().add<Position>();
|
|
ecs.entity().add<Position>();
|
|
ecs.entity().add<Position>();
|
|
ecs.entity().add<Position>().add<Mass>();
|
|
ecs.entity().add<Position>().add<Mass>();
|
|
ecs.entity().add<Position>().add<Velocity>();
|
|
|
|
test_int(ecs.count<Position>(), 6);
|
|
}
|
|
|
|
void World_count_id(void) {
|
|
flecs::world ecs;
|
|
|
|
auto ent = ecs.entity();
|
|
|
|
test_int(ecs.count(ent), 0);
|
|
|
|
ecs.entity().add(ent);
|
|
ecs.entity().add(ent);
|
|
ecs.entity().add(ent);
|
|
ecs.entity().add(ent).add<Mass>();
|
|
ecs.entity().add(ent).add<Mass>();
|
|
ecs.entity().add(ent).add<Velocity>();
|
|
|
|
test_int(ecs.count(ent), 6);
|
|
}
|
|
|
|
void World_count_pair(void) {
|
|
flecs::world ecs;
|
|
|
|
auto parent = ecs.entity();
|
|
|
|
test_int(ecs.count(flecs::ChildOf, parent), 0);
|
|
|
|
ecs.entity().add(flecs::ChildOf, parent);
|
|
ecs.entity().add(flecs::ChildOf, parent);
|
|
ecs.entity().add(flecs::ChildOf, parent);
|
|
ecs.entity().add(flecs::ChildOf, parent).add<Mass>();
|
|
ecs.entity().add(flecs::ChildOf, parent).add<Mass>();
|
|
ecs.entity().add(flecs::ChildOf, parent).add<Velocity>();
|
|
|
|
test_int(ecs.count(flecs::ChildOf, parent), 6);
|
|
}
|
|
|
|
void World_count_pair_type_id(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Rel { };
|
|
|
|
auto parent = ecs.entity();
|
|
|
|
test_int(ecs.count<Rel>(parent), 0);
|
|
|
|
ecs.entity().add<Rel>(parent);
|
|
ecs.entity().add<Rel>(parent);
|
|
ecs.entity().add<Rel>(parent);
|
|
ecs.entity().add<Rel>(parent).add<Mass>();
|
|
ecs.entity().add<Rel>(parent).add<Mass>();
|
|
ecs.entity().add<Rel>(parent).add<Velocity>();
|
|
|
|
test_int(ecs.count<Rel>(parent), 6);
|
|
}
|
|
|
|
void World_count_pair_id(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Rel { };
|
|
|
|
auto rel = ecs.entity();
|
|
auto parent = ecs.entity();
|
|
|
|
test_int(ecs.count(rel, parent), 0);
|
|
|
|
ecs.entity().add(rel, parent);
|
|
ecs.entity().add(rel, parent);
|
|
ecs.entity().add(rel, parent);
|
|
ecs.entity().add(rel, parent).add<Mass>();
|
|
ecs.entity().add(rel, parent).add<Mass>();
|
|
ecs.entity().add(rel, parent).add<Velocity>();
|
|
|
|
test_int(ecs.count(rel, parent), 6);
|
|
}
|
|
|
|
void World_staged_count(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::world stage = ecs.get_stage(0);
|
|
|
|
ecs.readonly_begin();
|
|
|
|
test_int(stage.count<Position>(), 0);
|
|
|
|
ecs.readonly_end();
|
|
|
|
ecs.readonly_begin();
|
|
|
|
stage.entity().add<Position>();
|
|
stage.entity().add<Position>();
|
|
stage.entity().add<Position>();
|
|
stage.entity().add<Position>().add<Mass>();
|
|
stage.entity().add<Position>().add<Mass>();
|
|
stage.entity().add<Position>().add<Velocity>();
|
|
|
|
test_int(stage.count<Position>(), 0);
|
|
|
|
ecs.readonly_end();
|
|
|
|
test_int(stage.count<Position>(), 6);
|
|
}
|
|
|
|
void World_async_stage_add(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.component<Position>();
|
|
|
|
auto e = ecs.entity();
|
|
|
|
flecs::world async = ecs.async_stage();
|
|
e.mut(async).add<Position>();
|
|
test_assert(!e.has<Position>());
|
|
async.merge();
|
|
test_assert(e.has<Position>());
|
|
}
|
|
|
|
void World_with_tag(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Tag = ecs.entity();
|
|
|
|
ecs.with(Tag, [&]{
|
|
auto e1 = ecs.entity(); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity(); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity(); e3.set<Self>({e3});
|
|
});
|
|
|
|
// Ensures that while Self is (implicitly) registered within the with, it
|
|
// does not get any contents from the with.
|
|
auto self = ecs.component<Self>();
|
|
test_assert(!self.has(Tag));
|
|
|
|
auto q = ecs.query_builder<>().term(Tag).build();
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e) {
|
|
test_assert(e.has(Tag));
|
|
|
|
test_bool(e.get([&](const Self& s) {
|
|
test_assert(s.value == e);
|
|
}), true);
|
|
|
|
count ++;
|
|
});
|
|
|
|
count ++;
|
|
}
|
|
|
|
void World_with_tag_type(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Tag { };
|
|
|
|
ecs.with<Tag>([&]{
|
|
auto e1 = ecs.entity(); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity(); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity(); e3.set<Self>({e3});
|
|
});
|
|
|
|
// Ensures that while Self is (implicitly) registered within the with, it
|
|
// does not get any contents from the with.
|
|
auto self = ecs.component<Self>();
|
|
test_assert(!self.has<Tag>());
|
|
|
|
auto q = ecs.query_builder<>().term<Tag>().build();
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e) {
|
|
test_assert(e.has<Tag>());
|
|
|
|
test_bool(e.get([&](const Self& s) {
|
|
test_assert(s.value == e);
|
|
}), true);
|
|
|
|
count ++;
|
|
});
|
|
|
|
count ++;
|
|
}
|
|
|
|
void World_with_relation(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Likes = ecs.entity();
|
|
auto Bob = ecs.entity();
|
|
|
|
ecs.with(Likes, Bob, [&]{
|
|
auto e1 = ecs.entity(); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity(); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity(); e3.set<Self>({e3});
|
|
});
|
|
|
|
// Ensures that while Self is (implicitly) registered within the with, it
|
|
// does not get any contents from the with.
|
|
auto self = ecs.component<Self>();
|
|
test_assert(!self.has(Likes, Bob));
|
|
|
|
auto q = ecs.query_builder<>().term(Likes, Bob).build();
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e) {
|
|
test_assert(e.has(Likes, Bob));
|
|
|
|
test_bool(e.get([&](const Self& s) {
|
|
test_assert(s.value == e);
|
|
}), true);
|
|
|
|
count ++;
|
|
});
|
|
|
|
count ++;
|
|
}
|
|
|
|
void World_with_relation_type(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Likes { };
|
|
auto Bob = ecs.entity();
|
|
|
|
ecs.with<Likes>(Bob, [&]{
|
|
auto e1 = ecs.entity(); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity(); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity(); e3.set<Self>({e3});
|
|
});
|
|
|
|
// Ensures that while Self is (implicitly) registered within the with, it
|
|
// does not get any contents from the with.
|
|
auto self = ecs.component<Self>();
|
|
test_assert(!self.has<Likes>(Bob));
|
|
|
|
auto q = ecs.query_builder<>().term<Likes>(Bob).build();
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e) {
|
|
test_assert(e.has<Likes>(Bob));
|
|
|
|
test_bool(e.get([&](const Self& s) {
|
|
test_assert(s.value == e);
|
|
}), true);
|
|
|
|
count ++;
|
|
});
|
|
|
|
count ++;
|
|
}
|
|
|
|
void World_with_relation_object_type(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Likes { };
|
|
struct Bob { };
|
|
|
|
ecs.with<Likes, Bob>([&]{
|
|
auto e1 = ecs.entity(); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity(); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity(); e3.set<Self>({e3});
|
|
});
|
|
|
|
// Ensures that while Self is (implicitly) registered within the with, it
|
|
// does not get any contents from the with.
|
|
auto self = ecs.component<Self>();
|
|
test_assert(!(self.has<Likes, Bob>()));
|
|
|
|
auto q = ecs.query_builder<>().term<Likes, Bob>().build();
|
|
|
|
int32_t count = 0;
|
|
|
|
q.each([&](flecs::entity e) {
|
|
test_assert((e.has<Likes, Bob>()));
|
|
|
|
test_bool(e.get([&](const Self& s) {
|
|
test_assert(s.value == e);
|
|
}), true);
|
|
|
|
count ++;
|
|
});
|
|
|
|
count ++;
|
|
}
|
|
|
|
void World_with_scope(void) {
|
|
flecs::world ecs;
|
|
|
|
auto parent = ecs.entity("P");
|
|
|
|
ecs.scope(parent, [&]{
|
|
auto e1 = ecs.entity("C1"); e1.set<Self>({e1});
|
|
auto e2 = ecs.entity("C2"); e2.set<Self>({e2});
|
|
auto e3 = ecs.entity("C3"); e3.set<Self>({e3});
|
|
|
|
// Ensure relative lookups work
|
|
test_assert(ecs.lookup("C1") == e1);
|
|
test_assert(ecs.lookup("C2") == e2);
|
|
test_assert(ecs.lookup("C3") == e3);
|
|
|
|
test_assert(parent.lookup("C1") == e1);
|
|
test_assert(parent.lookup("C2") == e2);
|
|
test_assert(parent.lookup("C3") == e3);
|
|
|
|
test_assert(ecs.lookup("::P::C1") == e1);
|
|
test_assert(ecs.lookup("::P::C2") == e2);
|
|
test_assert(ecs.lookup("::P::C3") == e3);
|
|
});
|
|
|
|
test_assert(parent.lookup("C1") != 0);
|
|
test_assert(parent.lookup("C2") != 0);
|
|
test_assert(parent.lookup("C3") != 0);
|
|
|
|
test_assert(ecs.lookup("P::C1") == parent.lookup("C1"));
|
|
test_assert(ecs.lookup("P::C2") == parent.lookup("C2"));
|
|
test_assert(ecs.lookup("P::C3") == parent.lookup("C3"));
|
|
|
|
// Ensures that while Self is (implicitly) registered within the with, it
|
|
// does not become a child of the parent.
|
|
auto self = ecs.component<Self>();
|
|
test_assert(!self.has(flecs::ChildOf, parent));
|
|
|
|
int count = 0;
|
|
auto q = ecs.query_builder<>().term(flecs::ChildOf, parent).build();
|
|
|
|
q.each([&](flecs::entity e) {
|
|
test_assert(e.has(flecs::ChildOf, parent));
|
|
|
|
test_bool(e.get([&](const Self& s){
|
|
test_assert(s.value == e);
|
|
}), true);
|
|
|
|
count ++;
|
|
});
|
|
|
|
test_int(count, 3);
|
|
}
|
|
|
|
struct ParentScope { };
|
|
|
|
void World_with_scope_type(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.scope<ParentScope>([&]{
|
|
ecs.entity("Child");
|
|
});
|
|
|
|
auto parent = ecs.lookup("ParentScope");
|
|
test_assert(parent != 0);
|
|
|
|
auto child = ecs.lookup("ParentScope::Child");
|
|
test_assert(child != 0);
|
|
test_assert(child == parent.lookup("Child"));
|
|
}
|
|
|
|
void World_with_scope_type_staged(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::entity e;
|
|
flecs::world stage = ecs.get_stage(0);
|
|
|
|
ecs.readonly_begin();
|
|
stage.scope<ParentScope>([&]{
|
|
e = stage.entity("Child");
|
|
});
|
|
ecs.readonly_end();
|
|
|
|
test_assert( e.has(flecs::ChildOf, ecs.id<ParentScope>()) );
|
|
|
|
auto parent = ecs.lookup("ParentScope");
|
|
test_assert(parent != 0);
|
|
|
|
auto child = ecs.lookup("ParentScope::Child");
|
|
test_assert(child != 0);
|
|
test_assert(child == parent.lookup("Child"));
|
|
}
|
|
|
|
void World_with_scope_no_lambda(void) {
|
|
flecs::world ecs;
|
|
|
|
auto parent = ecs.entity("Parent");
|
|
auto child = ecs.scope(parent).entity("Child");
|
|
|
|
test_assert(child.has(flecs::ChildOf, parent));
|
|
test_assert(ecs.get_scope() == 0);
|
|
}
|
|
|
|
void World_with_scope_type_no_lambda(void) {
|
|
flecs::world ecs;
|
|
|
|
auto child = ecs.scope<ParentScope>().entity("Child");
|
|
|
|
test_assert(child.has(flecs::ChildOf, ecs.id<ParentScope>()));
|
|
test_assert(ecs.get_scope() == 0);
|
|
}
|
|
|
|
void World_with_tag_nested(void) {
|
|
flecs::world ecs;
|
|
|
|
auto Tier1 = ecs.entity();
|
|
|
|
ecs.with(Tier1, [&]{
|
|
ecs.entity("Tier2").with([&]{
|
|
ecs.entity("Tier3");
|
|
});
|
|
});
|
|
|
|
auto Tier2 = ecs.lookup("Tier2");
|
|
test_assert(Tier2 != 0);
|
|
|
|
auto Tier3 = ecs.lookup("Tier3");
|
|
test_assert(Tier3 != 0);
|
|
|
|
test_assert(Tier2.has(Tier1));
|
|
test_assert(Tier3.has(Tier2));
|
|
}
|
|
|
|
void World_with_scope_nested(void) {
|
|
flecs::world ecs;
|
|
|
|
auto parent = ecs.entity("P");
|
|
|
|
ecs.scope(parent, [&]{
|
|
auto child = ecs.entity("C").scope([&]{
|
|
auto gchild = ecs.entity("GC");
|
|
test_assert(gchild == ecs.lookup("GC"));
|
|
test_assert(gchild == ecs.lookup("::P::C::GC"));
|
|
});
|
|
|
|
// Ensure relative lookups work
|
|
test_assert(ecs.lookup("C") == child);
|
|
test_assert(ecs.lookup("::P::C") == child);
|
|
test_assert(ecs.lookup("::P::C::GC") != 0);
|
|
});
|
|
|
|
test_assert(0 == ecs.lookup("C"));
|
|
test_assert(0 == ecs.lookup("GC"));
|
|
test_assert(0 == ecs.lookup("C::GC"));
|
|
|
|
auto child = ecs.lookup("P::C");
|
|
test_assert(0 != child);
|
|
test_assert(child.has(flecs::ChildOf, parent));
|
|
|
|
auto gchild = ecs.lookup("P::C::GC");
|
|
test_assert(0 != gchild);
|
|
test_assert(gchild.has(flecs::ChildOf, child));
|
|
}
|
|
|
|
void World_recursive_lookup(void) {
|
|
flecs::world ecs;
|
|
|
|
auto A = ecs.entity("A");
|
|
auto B = ecs.entity("B");
|
|
|
|
auto P = ecs.entity("P");
|
|
P.scope([&]{
|
|
auto CA = ecs.entity("A");
|
|
test_assert(CA != A);
|
|
|
|
test_assert(CA == ecs.lookup("A"));
|
|
test_assert(CA == ecs.lookup("P::A"));
|
|
test_assert(CA == ecs.lookup("::P::A"));
|
|
test_assert(A == ecs.lookup("::A"));
|
|
|
|
test_assert(B == ecs.lookup("B"));
|
|
test_assert(B == ecs.lookup("::B"));
|
|
});
|
|
}
|
|
|
|
void World_type_w_tag_name(void) {
|
|
flecs::world ecs;
|
|
|
|
auto c = ecs.component<Tag>();
|
|
test_assert(c != flecs::entity());
|
|
test_str(c.path().c_str(), "::Tag");
|
|
test_assert(c != flecs::Tag);
|
|
}
|
|
|
|
void World_entity_w_tag_name(void) {
|
|
flecs::world ecs;
|
|
|
|
auto c = ecs.entity("Tag");
|
|
test_assert(c != flecs::entity());
|
|
test_str(c.path().c_str(), "::Tag");
|
|
test_assert(c != flecs::Tag);
|
|
}
|
|
|
|
template <typename T>
|
|
struct TemplateType { };
|
|
|
|
void World_template_component_name(void) {
|
|
flecs::world ecs;
|
|
|
|
auto c = ecs.component<TemplateType<Position>>();
|
|
test_str(c.name().c_str(), "TemplateType<Position>");
|
|
test_str(c.path().c_str(), "::TemplateType<Position>");
|
|
}
|
|
|
|
namespace ns {
|
|
template <typename T>
|
|
struct TemplateType { };
|
|
struct foo { };
|
|
}
|
|
|
|
void World_template_component_w_namespace_name(void) {
|
|
flecs::world ecs;
|
|
|
|
auto c = ecs.component<ns::TemplateType<Position>>();
|
|
test_str(c.name().c_str(), "TemplateType<Position>");
|
|
test_str(c.path().c_str(), "::ns::TemplateType<Position>");
|
|
}
|
|
|
|
void World_template_component_w_namespace_name_and_namespaced_arg(void) {
|
|
flecs::world ecs;
|
|
|
|
auto c = ecs.component<ns::TemplateType<ns::foo>>();
|
|
test_str(c.name().c_str(), "TemplateType<ns::foo>");
|
|
test_str(c.path().c_str(), "::ns::TemplateType<ns::foo>");
|
|
}
|
|
|
|
namespace foo {
|
|
template <typename T>
|
|
struct foo { };
|
|
struct bar { };
|
|
}
|
|
|
|
void World_template_component_w_same_namespace_name(void) {
|
|
flecs::world ecs;
|
|
|
|
auto c = ecs.component<foo::foo<Position>>();
|
|
test_str(c.name().c_str(), "foo<Position>");
|
|
test_str(c.path().c_str(), "::foo::foo<Position>");
|
|
}
|
|
|
|
void World_template_component_w_same_namespace_name_and_namespaced_arg(void) {
|
|
flecs::world ecs;
|
|
|
|
auto c = ecs.component<foo::foo<foo::bar>>();
|
|
test_str(c.name().c_str(), "foo<foo::bar>");
|
|
test_str(c.path().c_str(), "::foo::foo<foo::bar>");
|
|
}
|
|
|
|
struct module_w_template_component {
|
|
struct Foo { };
|
|
struct Bar { };
|
|
|
|
template <typename T, typename U>
|
|
struct TypeWithArgs { };
|
|
|
|
module_w_template_component(flecs::world &world) {
|
|
world.module<module_w_template_component>();
|
|
world.component<TypeWithArgs<Foo, Bar>>();
|
|
};
|
|
};
|
|
|
|
|
|
void World_template_component_from_module_2_args(void) {
|
|
flecs::world ecs;
|
|
|
|
auto m = ecs.import<module_w_template_component>();
|
|
test_assert(m == ecs.lookup("module_w_template_component"));
|
|
|
|
auto tid = ecs.id<module_w_template_component::TypeWithArgs<
|
|
module_w_template_component::Foo,
|
|
module_w_template_component::Bar>>();
|
|
test_assert(tid != 0);
|
|
|
|
auto mid = m.lookup("TypeWithArgs<module_w_template_component::Foo, module_w_template_component::Bar>");
|
|
if (mid == 0) {
|
|
mid = m.lookup("TypeWithArgs<module_w_template_component::Foo,module_w_template_component::Bar>");
|
|
}
|
|
test_assert(mid != 0);
|
|
test_assert(tid == mid);
|
|
}
|
|
|
|
void World_entity_as_tag(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity<Tag>();
|
|
test_assert(e.id() != 0);
|
|
|
|
auto t = ecs.component<Tag>();
|
|
test_assert(t.id() != 0);
|
|
test_assert(e == t);
|
|
|
|
auto e2 = ecs.entity()
|
|
.add<Tag>();
|
|
|
|
test_bool(e2.has<Tag>(), true);
|
|
test_bool(e2.has(e), true);
|
|
|
|
test_str(e.name(), "Tag");
|
|
}
|
|
|
|
void World_entity_w_name_as_tag(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity<Tag>("Foo");
|
|
test_assert(e.id() != 0);
|
|
|
|
auto t = ecs.component<Tag>();
|
|
test_assert(t.id() != 0);
|
|
test_assert(e == t);
|
|
|
|
auto e2 = ecs.entity()
|
|
.add<Tag>();
|
|
|
|
test_bool(e2.has<Tag>(), true);
|
|
test_bool(e2.has(e), true);
|
|
|
|
test_str(e.name(), "Foo");
|
|
}
|
|
|
|
void World_entity_as_component(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity<Position>();
|
|
test_assert(e.id() != 0);
|
|
|
|
auto t = ecs.component<Position>();
|
|
test_assert(t.id() != 0);
|
|
test_assert(e == t);
|
|
|
|
auto e2 = ecs.entity()
|
|
.set<Position>({10, 20});
|
|
|
|
test_bool(e2.has<Position>(), true);
|
|
test_bool(e2.has(e), true);
|
|
|
|
test_str(e.name(), "Position");
|
|
}
|
|
|
|
void World_entity_w_name_as_component(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity<Position>("Foo");
|
|
test_assert(e.id() != 0);
|
|
|
|
auto t = ecs.component<Position>();
|
|
test_assert(t.id() != 0);
|
|
test_assert(e == t);
|
|
|
|
auto e2 = ecs.entity()
|
|
.set<Position>({10, 20});
|
|
|
|
test_bool(e2.has<Position>(), true);
|
|
test_bool(e2.has(e), true);
|
|
|
|
test_str(e.name(), "Foo");
|
|
}
|
|
|
|
void World_entity_as_component_2_worlds(void) {
|
|
flecs::world ecs_1;
|
|
auto e_1 = ecs_1.entity<Position>();
|
|
test_assert(e_1.id() != 0);
|
|
|
|
flecs::world ecs_2;
|
|
auto e_2 = ecs_2.entity<Position>();
|
|
test_assert(e_2.id() != 0);
|
|
|
|
test_assert(e_1 == e_2);
|
|
test_assert(e_1 == ecs_1.component<Position>());
|
|
test_assert(e_2 == ecs_2.component<Position>());
|
|
}
|
|
|
|
struct Parent {
|
|
struct Child { };
|
|
};
|
|
|
|
void World_entity_as_namespaced_component_2_worlds(void) {
|
|
flecs::world ecs_1;
|
|
auto e_1 = ecs_1.entity<Parent>();
|
|
test_assert(e_1.id() != 0);
|
|
|
|
auto e_1_1 = ecs_1.entity<Parent::Child>();
|
|
test_assert(e_1_1.id() != 0);
|
|
|
|
flecs::world ecs_2;
|
|
auto e_2 = ecs_2.entity<Parent>();
|
|
test_assert(e_2.id() != 0);
|
|
|
|
auto e_2_1 = ecs_2.entity<Parent::Child>();
|
|
test_assert(e_2_1.id() != 0);
|
|
|
|
test_assert(e_1 == e_2);
|
|
test_assert(e_1 == ecs_1.component<Parent>());
|
|
test_assert(e_2 == ecs_2.component<Parent>());
|
|
|
|
test_assert(e_1_1 == e_2_1);
|
|
test_assert(e_1_1 == ecs_1.component<Parent::Child>());
|
|
test_assert(e_2_1 == ecs_2.component<Parent::Child>());
|
|
}
|
|
|
|
void World_entity_as_component_2_worlds_implicit_namespaced(void) {
|
|
flecs::world ecs_1;
|
|
auto e_1 = ecs_1.entity<Parent>();
|
|
test_assert(e_1.id() != 0);
|
|
|
|
ecs_1.entity().add<Parent::Child>();
|
|
|
|
flecs::world ecs_2;
|
|
auto e_2 = ecs_2.entity<Parent>();
|
|
test_assert(e_2.id() != 0);
|
|
|
|
ecs_2.entity().add<Parent::Child>();
|
|
|
|
test_assert(e_1 == e_2);
|
|
test_assert(e_1 == ecs_1.component<Parent>());
|
|
test_assert(e_2 == ecs_2.component<Parent>());
|
|
|
|
test_assert(ecs_1.component<Parent::Child>() ==
|
|
ecs_2.component<Parent::Child>());
|
|
}
|
|
|
|
struct PositionDerived : Position {
|
|
PositionDerived() { }
|
|
PositionDerived(float x, float y) : Position{x, y} { }
|
|
};
|
|
|
|
void World_delete_with_id(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::id tag = ecs.entity();
|
|
auto e_1 = ecs.entity().add(tag);
|
|
auto e_2 = ecs.entity().add(tag);
|
|
auto e_3 = ecs.entity().add(tag);
|
|
|
|
ecs.delete_with(tag);
|
|
|
|
test_assert(!e_1.is_alive());
|
|
test_assert(!e_2.is_alive());
|
|
test_assert(!e_3.is_alive());
|
|
}
|
|
|
|
void World_delete_with_type(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e_1 = ecs.entity().add<Tag>();
|
|
auto e_2 = ecs.entity().add<Tag>();
|
|
auto e_3 = ecs.entity().add<Tag>();
|
|
|
|
ecs.delete_with<Tag>();
|
|
|
|
test_assert(!e_1.is_alive());
|
|
test_assert(!e_2.is_alive());
|
|
test_assert(!e_3.is_alive());
|
|
}
|
|
|
|
void World_delete_with_pair(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::id rel = ecs.entity();
|
|
flecs::id obj = ecs.entity();
|
|
auto e_1 = ecs.entity().add(rel, obj);
|
|
auto e_2 = ecs.entity().add(rel, obj);
|
|
auto e_3 = ecs.entity().add(rel, obj);
|
|
|
|
ecs.delete_with(rel, obj);
|
|
|
|
test_assert(!e_1.is_alive());
|
|
test_assert(!e_2.is_alive());
|
|
test_assert(!e_3.is_alive());
|
|
}
|
|
|
|
void World_delete_with_pair_type(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Rel { };
|
|
struct Obj { };
|
|
|
|
auto e_1 = ecs.entity().add<Rel, Obj>();
|
|
auto e_2 = ecs.entity().add<Rel, Obj>();
|
|
auto e_3 = ecs.entity().add<Rel, Obj>();
|
|
|
|
ecs.delete_with<Rel, Obj>();
|
|
|
|
test_assert(!e_1.is_alive());
|
|
test_assert(!e_2.is_alive());
|
|
test_assert(!e_3.is_alive());
|
|
}
|
|
|
|
void World_delete_with_implicit(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.delete_with<Tag>();
|
|
|
|
test_assert(true);
|
|
}
|
|
|
|
void World_delete_with_pair_implicit(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Rel { };
|
|
struct Obj { };
|
|
|
|
ecs.delete_with<Rel, Obj>();
|
|
|
|
test_assert(true);
|
|
}
|
|
|
|
void World_remove_all_id(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::id tag_a = ecs.entity();
|
|
flecs::id tag_b = ecs.entity();
|
|
auto e_1 = ecs.entity().add(tag_a);
|
|
auto e_2 = ecs.entity().add(tag_a);
|
|
auto e_3 = ecs.entity().add(tag_a).add(tag_b);
|
|
|
|
ecs.remove_all(tag_a);
|
|
|
|
test_assert(e_1.is_alive());
|
|
test_assert(e_2.is_alive());
|
|
test_assert(e_3.is_alive());
|
|
|
|
test_assert(!e_1.has(tag_a));
|
|
test_assert(!e_2.has(tag_a));
|
|
test_assert(!e_3.has(tag_a));
|
|
|
|
test_assert(e_3.has(tag_b));
|
|
}
|
|
|
|
void World_remove_all_type(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e_1 = ecs.entity().add<Position>();
|
|
auto e_2 = ecs.entity().add<Position>();
|
|
auto e_3 = ecs.entity().add<Position>().add<Velocity>();
|
|
|
|
ecs.remove_all<Position>();
|
|
|
|
test_assert(e_1.is_alive());
|
|
test_assert(e_2.is_alive());
|
|
test_assert(e_3.is_alive());
|
|
|
|
test_assert(!e_1.has<Position>());
|
|
test_assert(!e_2.has<Position>());
|
|
test_assert(!e_3.has<Position>());
|
|
|
|
test_assert(e_3.has<Velocity>());
|
|
}
|
|
|
|
void World_remove_all_pair(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::id rel = ecs.entity();
|
|
flecs::id obj_a = ecs.entity();
|
|
flecs::id obj_b = ecs.entity();
|
|
auto e_1 = ecs.entity().add(rel, obj_a);
|
|
auto e_2 = ecs.entity().add(rel, obj_a);
|
|
auto e_3 = ecs.entity().add(rel, obj_a).add(rel, obj_b);
|
|
|
|
ecs.remove_all(rel, obj_a);
|
|
|
|
test_assert(e_1.is_alive());
|
|
test_assert(e_2.is_alive());
|
|
test_assert(e_3.is_alive());
|
|
|
|
test_assert(!e_1.has(rel, obj_a));
|
|
test_assert(!e_2.has(rel, obj_a));
|
|
test_assert(!e_3.has(rel, obj_a));
|
|
|
|
test_assert(e_3.has(rel, obj_b));
|
|
}
|
|
|
|
void World_remove_all_pair_type(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Rel { };
|
|
struct ObjA { };
|
|
struct ObjB { };
|
|
|
|
auto e_1 = ecs.entity().add<Rel, ObjA>();
|
|
auto e_2 = ecs.entity().add<Rel, ObjA>();
|
|
auto e_3 = ecs.entity().add<Rel, ObjA>().add<Rel, ObjB>();
|
|
|
|
ecs.remove_all<Rel, ObjA>();
|
|
|
|
test_assert(e_1.is_alive());
|
|
test_assert(e_2.is_alive());
|
|
test_assert(e_3.is_alive());
|
|
|
|
test_assert((!e_1.has<Rel, ObjA>()));
|
|
test_assert((!e_2.has<Rel, ObjA>()));
|
|
test_assert((!e_3.has<Rel, ObjA>()));
|
|
|
|
test_assert((!e_1.has<Rel, ObjB>()));
|
|
test_assert((!e_2.has<Rel, ObjB>()));
|
|
test_assert((e_3.has<Rel, ObjB>()));
|
|
}
|
|
|
|
void World_remove_all_implicit(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.remove_all<Tag>();
|
|
|
|
test_assert(true);
|
|
}
|
|
|
|
void World_remove_all_pair_implicit(void) {
|
|
flecs::world ecs;
|
|
|
|
struct Rel { };
|
|
struct Obj { };
|
|
|
|
ecs.remove_all<Rel, Obj>();
|
|
|
|
test_assert(true);
|
|
}
|
|
|
|
void World_get_scope(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity("scope");
|
|
|
|
ecs.set_scope(e);
|
|
|
|
auto s = ecs.get_scope();
|
|
test_assert(s == e);
|
|
test_str(s.name(), "scope");
|
|
}
|
|
|
|
void World_get_scope_type(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.set_scope<ParentScope>();
|
|
|
|
auto s = ecs.get_scope();
|
|
test_assert(s == ecs.id<ParentScope>());
|
|
test_str(s.name(), "ParentScope");
|
|
}
|
|
|
|
struct Outer
|
|
{
|
|
struct Inner { };
|
|
};
|
|
|
|
void World_register_namespace_after_component(void) {
|
|
flecs::world ecs;
|
|
auto inn = ecs.component<Outer::Inner>();
|
|
auto out = ecs.component<Outer>();
|
|
|
|
test_str(inn.path().c_str(), "::Outer::Inner");
|
|
test_str(out.path().c_str(), "::Outer");
|
|
|
|
const char *inn_sym = ecs_get_symbol(ecs, inn);
|
|
const char *out_sym = ecs_get_symbol(ecs, out);
|
|
|
|
test_str(inn_sym, "Outer.Inner");
|
|
test_str(out_sym, "Outer");
|
|
}
|
|
|
|
void World_is_alive(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity();
|
|
|
|
test_bool(ecs.is_alive(e), true);
|
|
test_bool(ecs.is_alive(1000), false);
|
|
|
|
e.destruct();
|
|
|
|
test_bool(ecs.is_alive(e), false);
|
|
}
|
|
|
|
void World_is_valid(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity();
|
|
|
|
test_bool(ecs.is_valid(e), true);
|
|
test_bool(ecs.is_valid(1000), true);
|
|
test_bool(ecs.is_valid(0), false);
|
|
|
|
e.destruct();
|
|
|
|
test_bool(ecs.is_valid(e), false);
|
|
}
|
|
|
|
void World_exists(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e = ecs.entity();
|
|
|
|
test_bool(ecs.exists(e), true);
|
|
test_bool(ecs.exists(1000), false);
|
|
}
|
|
|
|
void World_get_alive(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e_1 = ecs.entity();
|
|
auto e_no_gen = flecs::strip_generation(e_1);
|
|
test_assert(e_1 == e_no_gen);
|
|
e_1.destruct();
|
|
|
|
auto e_2 = ecs.entity();
|
|
test_assert(e_1 != e_2);
|
|
test_assert(e_no_gen == flecs::strip_generation(e_2));
|
|
|
|
test_assert(ecs.get_alive(e_no_gen) == e_2);
|
|
}
|
|
|
|
void World_ensure(void) {
|
|
flecs::world ecs;
|
|
|
|
auto e_1 = ecs.entity();
|
|
e_1.destruct();
|
|
test_assert(!e_1.is_alive());
|
|
|
|
auto e_2 = ecs.entity();
|
|
test_assert(e_1 != e_2);
|
|
test_assert(e_1 == flecs::strip_generation(e_2));
|
|
e_2.destruct();
|
|
test_assert(!e_2.is_alive());
|
|
|
|
auto e_3 = ecs.ensure(e_2);
|
|
test_assert(e_2 == e_3);
|
|
test_assert(e_3.is_alive());
|
|
}
|
|
|
|
void World_reset_all(void) {
|
|
flecs::entity pos, vel;
|
|
|
|
{
|
|
flecs::world ecs;
|
|
pos = ecs.component<Position>();
|
|
vel = ecs.component<Velocity>();
|
|
}
|
|
|
|
test_assert(flecs::type_id<Position>() == pos);
|
|
test_assert(flecs::type_id<Velocity>() == vel);
|
|
|
|
flecs::reset();
|
|
|
|
test_assert(flecs::type_id<Position>() == 0);
|
|
|
|
/* Register components in opposite order, should result in different ids */
|
|
{
|
|
flecs::world ecs;
|
|
test_assert(ecs.component<Position>() != 0);
|
|
test_assert(ecs.component<Velocity>() != 0);
|
|
}
|
|
}
|
|
|
|
void World_get_tick(void) {
|
|
flecs::world ecs;
|
|
|
|
test_int(ecs.get_info()->frame_count_total, 0);
|
|
|
|
ecs.progress();
|
|
|
|
test_int(ecs.get_info()->frame_count_total, 1);
|
|
|
|
ecs.progress();
|
|
|
|
test_int(ecs.get_info()->frame_count_total, 2);
|
|
}
|
|
|
|
struct Scope { };
|
|
|
|
struct FromScope { };
|
|
|
|
namespace Nested {
|
|
struct FromScope { };
|
|
}
|
|
|
|
void World_register_from_scope(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.set_scope<Scope>();
|
|
auto c = ecs.component<FromScope>();
|
|
ecs.set_scope(0);
|
|
|
|
test_assert(c.has(flecs::ChildOf, ecs.id<Scope>()));
|
|
}
|
|
|
|
void World_register_nested_from_scope(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.set_scope<Scope>();
|
|
auto c = ecs.component<Nested::FromScope>();
|
|
ecs.set_scope(0);
|
|
|
|
test_assert(c.has(flecs::ChildOf, ecs.id<Scope>()));
|
|
}
|
|
|
|
void World_register_w_root_name(void) {
|
|
flecs::world ecs;
|
|
|
|
auto c = ecs.component<Scope>("::Root");
|
|
|
|
test_assert(!c.has(flecs::ChildOf, flecs::Wildcard));
|
|
test_str(c.path().c_str(), "::Root");
|
|
}
|
|
|
|
void World_register_nested_w_root_name(void) {
|
|
flecs::world ecs;
|
|
|
|
auto c = ecs.component<Nested::FromScope>("::Root");
|
|
|
|
test_assert(!c.has(flecs::ChildOf, flecs::Wildcard));
|
|
test_str(c.path().c_str(), "::Root");
|
|
}
|
|
|
|
void World_set_lookup_path(void) {
|
|
flecs::world ecs;
|
|
|
|
auto parent = ecs.entity("Parent");
|
|
auto child = ecs.scope(parent).entity("Child");
|
|
|
|
test_assert(ecs.lookup("Parent") == parent);
|
|
test_assert(ecs.lookup("Child") == 0);
|
|
test_assert(ecs.lookup("Parent::Child") == child);
|
|
|
|
flecs::entity_t lookup_path[] = { parent, 0 };
|
|
flecs::entity_t *old_path = ecs.set_lookup_path(lookup_path);
|
|
|
|
test_assert(ecs.lookup("Parent") == parent);
|
|
test_assert(ecs.lookup("Child") == child);
|
|
test_assert(ecs.lookup("Parent::Child") == child);
|
|
|
|
ecs.set_lookup_path(old_path);
|
|
}
|
|
|
|
void World_run_post_frame(void) {
|
|
flecs::world ecs;
|
|
|
|
int ctx = 10;
|
|
|
|
ecs.system()
|
|
.iter([&](flecs::iter& it) {
|
|
it.world().run_post_frame([](flecs::world_t *w, void *ctx) {
|
|
int *i = static_cast<int*>(ctx);
|
|
test_int(*i, 10);
|
|
i[0] ++;
|
|
}, &ctx);
|
|
});
|
|
test_int(ctx, 10);
|
|
|
|
ecs.progress();
|
|
|
|
test_int(ctx, 11);
|
|
}
|
|
|
|
void World_component_w_low_id(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::entity p = ecs.component<Position>();
|
|
|
|
test_assert(p.id() < FLECS_HI_COMPONENT_ID);
|
|
}
|
|
|
|
void World_reregister_after_reset_w_hooks_and_in_use(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.component<Pod>();
|
|
|
|
ecs.entity().add<Pod>();
|
|
test_int(1, Pod::ctor_invoked);
|
|
|
|
flecs::reset();
|
|
|
|
ecs.component<Pod>();
|
|
|
|
ecs.entity().add<Pod>();
|
|
test_int(2, Pod::ctor_invoked);
|
|
}
|
|
|
|
void World_reregister_after_reset_w_hooks_and_in_use_implicit(void) {
|
|
flecs::world ecs;
|
|
|
|
ecs.component<Pod>();
|
|
|
|
ecs.entity().add<Pod>();
|
|
test_int(1, Pod::ctor_invoked);
|
|
|
|
flecs::reset();
|
|
|
|
ecs.entity().add<Pod>();
|
|
test_int(2, Pod::ctor_invoked);
|
|
}
|
|
|
|
void World_get_ref() {
|
|
flecs::world ecs;
|
|
|
|
struct Space { int v; };
|
|
ecs.set<Space>({12});
|
|
|
|
auto space = ecs.get_ref<Space>();
|
|
test_int(12, space->v);
|
|
}
|
|
|
|
void World_get_set_log_level(void) {
|
|
test_int(flecs::log::get_level(), -1);
|
|
flecs::log::set_level(4);
|
|
test_int(flecs::log::get_level(), 4);
|
|
}
|
|
|
|
void World_reset_world(void) {
|
|
flecs::world ecs;
|
|
flecs::entity e = ecs.entity();
|
|
|
|
test_assert(ecs.exists(e));
|
|
ecs.reset();
|
|
test_assert(!ecs.exists(e));
|
|
}
|
|
|
|
void World_id_from_pair_type(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::id id = ecs.id<flecs::pair<Position, Velocity>>();
|
|
test_assert(id.is_pair());
|
|
test_assert(id.first() == ecs.id<Position>());
|
|
test_assert(id.second() == ecs.id<Velocity>());
|
|
}
|
|
|
|
|
|
void World_scope_w_name(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::entity parent = ecs.entity("parent");
|
|
flecs::entity child = ecs.scope("parent").entity();
|
|
|
|
test_assert(child.has(flecs::ChildOf, parent));
|
|
}
|
|
|
|
void World_set_get_context(void) {
|
|
flecs::world ecs;
|
|
|
|
int ctx;
|
|
ecs.set_ctx(&ctx);
|
|
test_assert(ecs.get_ctx() == &ctx);
|
|
test_assert(ecs.get_binding_ctx() == nullptr);
|
|
}
|
|
|
|
void World_set_get_binding_context(void) {
|
|
flecs::world ecs;
|
|
|
|
int ctx;
|
|
ecs.set_binding_ctx(&ctx);
|
|
test_assert(ecs.get_binding_ctx() == &ctx);
|
|
test_assert(ecs.get_ctx() == nullptr);
|
|
}
|
|
|
|
static void ctx_free(void *ctx) {
|
|
static_cast<int*>(ctx)[0] = 10;
|
|
}
|
|
|
|
void World_set_get_context_w_free(void) {
|
|
int ctx = 0;
|
|
|
|
{
|
|
flecs::world ecs;
|
|
|
|
ecs.set_ctx(&ctx, ctx_free);
|
|
test_assert(ecs.get_ctx() == &ctx);
|
|
test_assert(ecs.get_binding_ctx() == nullptr);
|
|
test_int(ctx, 0);
|
|
}
|
|
|
|
test_int(ctx, 10);
|
|
}
|
|
|
|
void World_set_get_binding_context_w_free(void) {
|
|
int ctx = 0;
|
|
|
|
{
|
|
flecs::world ecs;
|
|
|
|
ecs.set_binding_ctx(&ctx, ctx_free);
|
|
test_assert(ecs.get_binding_ctx() == &ctx);
|
|
test_assert(ecs.get_ctx() == nullptr);
|
|
test_int(ctx, 0);
|
|
}
|
|
|
|
test_int(ctx, 10);
|
|
}
|
|
|
|
void World_make_pair(void) {
|
|
flecs::world ecs;
|
|
|
|
flecs::entity r = ecs.entity();
|
|
flecs::entity t = ecs.entity();
|
|
flecs::id id = ecs.pair(r, t);
|
|
|
|
test_assert(id.is_pair());
|
|
test_assert(id.first() == r);
|
|
test_assert(id.second() == t);
|
|
}
|
|
|
|
void World_make_pair_of_pair_id(void) {
|
|
install_test_abort();
|
|
flecs::world ecs;
|
|
|
|
flecs::entity r = ecs.entity();
|
|
flecs::entity t = ecs.entity();
|
|
flecs::id id = ecs.pair(r, t);
|
|
|
|
test_expect_abort();
|
|
ecs.pair(id, t);
|
|
}
|
|
|
|
void World_make_pair_of_pair_id_tgt(void) {
|
|
install_test_abort();
|
|
flecs::world ecs;
|
|
|
|
flecs::entity r = ecs.entity();
|
|
flecs::entity t = ecs.entity();
|
|
flecs::id id = ecs.pair(r, t);
|
|
|
|
test_expect_abort();
|
|
ecs.pair(r, id);
|
|
}
|
|
|
|
void World_make_pair_of_pair_type(void) {
|
|
install_test_abort();
|
|
flecs::world ecs;
|
|
|
|
flecs::entity t = ecs.entity();
|
|
flecs::id id = ecs.pair<Position>(t);
|
|
|
|
test_assert(id.is_pair());
|
|
test_assert(id.first() == ecs.id<Position>());
|
|
test_assert(id.second() == t);
|
|
}
|
|
|
|
void World_delta_time(void) {
|
|
flecs::world ecs;
|
|
|
|
float dt = 0;
|
|
|
|
ecs.entity().add<Tag>();
|
|
|
|
ecs.system<Tag>()
|
|
.each([&](flecs::entity e, Tag) {
|
|
dt = e.world().delta_time();
|
|
});
|
|
|
|
ecs.progress(2);
|
|
|
|
test_int(dt, 2);
|
|
}
|