#include enum Color { Red, Green, Blue }; void Misc_setup(void) { ecs_os_set_api_defaults(); } void Misc_string_compare_w_char_ptr(void) { const char *ptr_1 = "foo"; const char *ptr_2 = "foo"; const char *ptr_3 = "bar"; flecs::string str = flecs::string(ecs_os_strdup(ptr_1)); test_assert(str == ptr_1); test_assert(str == ptr_2); test_assert(str != ptr_3); } void Misc_string_view_compare_w_char_ptr(void) { const char *ptr_1 = "foo"; const char *ptr_2 = "foo"; const char *ptr_3 = "bar"; flecs::string str = flecs::string_view(ptr_1); test_assert(str == ptr_1); test_assert(str == ptr_2); test_assert(str != ptr_3); } void Misc_string_compare_w_char_ptr_length_diff(void) { const char *ptr_1 = "foo"; const char *ptr_2 = "foo"; const char *ptr_3 = "barrr"; const char *ptr_4 = "ba"; flecs::string str = flecs::string_view(ptr_1); test_assert(str == ptr_1); test_assert(str == ptr_2); test_assert(str != ptr_3); test_assert(str != ptr_4); } void Misc_string_compare_w_string(void) { const char *ptr_1 = "foo"; const char *ptr_2 = "bar"; flecs::string str_1 = flecs::string(ecs_os_strdup(ptr_1)); flecs::string str_2 = flecs::string(ecs_os_strdup(ptr_2)); flecs::string str_3 = flecs::string(ecs_os_strdup(ptr_1)); flecs::string str_4 = flecs::string(ecs_os_strdup(ptr_2)); test_assert(str_1 == str_1); test_assert(str_1 == str_3); test_assert(str_2 == str_2); test_assert(str_2 == str_4); test_assert(str_1 != str_2); test_assert(str_2 != str_1); } void Misc_string_view_compare_w_string(void) { const char *ptr_1 = "foo"; const char *ptr_2 = "bar"; flecs::string str_1 = flecs::string_view(ptr_1); flecs::string str_2 = flecs::string_view(ptr_2); flecs::string str_3 = flecs::string(ecs_os_strdup(ptr_1)); flecs::string str_4 = flecs::string(ecs_os_strdup(ptr_2)); test_assert(str_1 == str_1); test_assert(str_1 == str_3); test_assert(str_2 == str_2); test_assert(str_2 == str_4); test_assert(str_1 != str_2); test_assert(str_2 != str_1); } void Misc_string_compare_nullptr(void) { const char *ptr_1 = "foo"; flecs::string str = flecs::string_view(ptr_1); test_assert(str != nullptr); } void Misc_nullptr_string_compare(void) { const char *ptr = "foo"; flecs::string str_1 = flecs::string_view(nullptr); flecs::string str_2 = flecs::string_view(ptr); test_assert(str_1 == ""); test_assert(str_1 != ptr); test_assert(str_1 != str_2); } void Misc_nullptr_string_compare_nullptr(void) { const char *ptr_1 = "foo"; flecs::string str = flecs::string_view(nullptr); test_assert(str == ""); test_assert(str != ptr_1); } static ECS_COMPONENT_DECLARE(Velocity); static ECS_DECLARE(TagB); static ECS_DECLARE(E2); static int sys_invoked_count = 0; static int obs_invoked_count = 0; static int trig_invoked_count = 0; void Sys(ecs_iter_t *it) { Position *p = ecs_field(it, Position, 1); Velocity *v = ecs_field(it, Velocity, 2); test_assert(p != NULL); test_assert(v != NULL); sys_invoked_count += it->count; } void Obs(ecs_iter_t *it) { Position *p = ecs_field(it, Position, 1); Velocity *v = ecs_field(it, Velocity, 2); test_assert(p != NULL); test_assert(v != NULL); obs_invoked_count += it->count; } void Trig(ecs_iter_t *it) { Position *p = ecs_field(it, Position, 1); test_assert(p != NULL); trig_invoked_count += it->count; } void Misc_c_macros(void) { flecs::world world; ECS_COMPONENT(world, Position); ECS_COMPONENT_DEFINE(world, Velocity); ECS_TAG(world, TagA); ECS_TAG_DEFINE(world, TagB); ECS_ENTITY(world, E1, 0); ECS_ENTITY_DEFINE(world, E2, 0); ECS_MODULE(world, MyModule); ECS_SYSTEM(world, Sys, EcsOnUpdate, Position, Velocity); ECS_OBSERVER(world, Obs, EcsOnAdd, Position, Velocity); ECS_OBSERVER(world, Trig, EcsOnAdd, Position); ECS_PIPELINE(world, Pip, flecs.system.System, TagA); test_assert(ecs_id(Position) != 0); test_assert(ecs_id(Velocity) != 0); test_assert(TagA != 0); test_assert(TagB != 0); test_assert(E1 != 0); test_assert(E2 != 0); test_assert(ecs_id(MyModule) != 0); test_assert(ecs_id(Sys) != 0); test_assert(ecs_id(Obs) != 0); test_assert(ecs_id(Trig) != 0); test_assert(Pip != 0); ecs_add(world, E1, TagA); ecs_add(world, E1, TagB); test_assert( ecs_has(world, E1, TagA)); test_assert( ecs_has(world, E1, TagB)); ecs_add(world, E1, Position); test_int(obs_invoked_count, 0); test_int(trig_invoked_count, 1); ecs_add(world, E1, Velocity); test_int(obs_invoked_count, 1); test_assert( ecs_has(world, E1, Position)); test_assert( ecs_has(world, E1, Velocity)); test_assert( ecs_has_id(world, ecs_id(MyModule), EcsModule)); test_assert( ecs_has(world, Pip, EcsPipeline)); ecs_progress(world, 0); test_int(sys_invoked_count, 1); } void Misc_app_run(void) { flecs::world ecs; bool system_ran = false; ecs.system().iter([&](flecs::iter& it) { system_ran = true; it.world().quit(); }); test_int(ecs.app().run(), 0); test_bool(system_ran, true); } void Misc_app_run_target_fps(void) { flecs::world ecs; int32_t count = 0; ecs.system().iter([&](flecs::iter& it) { count ++; test_int(it.world().get_info()->target_fps, 10); it.world().quit(); }); ecs.set_target_fps(10); ecs.app().run(); test_int(count, 1); } void Misc_app_run_set_frames(void) { flecs::world ecs; int32_t count = 0; ecs.system().iter([&](flecs::iter& it) { count ++; }); ecs.app().frames(100).run(); test_int(count, 100); } void Misc_app_on_remove_on_fini(void) { flecs::world ecs; ecs.entity().set({10, 20}); int invoked = 0; ecs.observer() .event(flecs::OnRemove) .each([&](Position& p) { invoked ++; test_int(p.x, 10); test_int(p.y, 20); }); test_int(invoked, 0); ecs.app().frames(1).run(); test_int(invoked, 1); } void Misc_member_gauge_metric(void) { flecs::world ecs; ecs.import(); ecs.component() .member("x") .member("y"); ecs.metric("metrics::position_y") .kind() .member("y"); flecs::entity e1 = ecs.entity().set({10, 20}); flecs::entity e2 = ecs.entity().set({20, 30}); ecs.progress(); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 20); test_int(i[1].value, 30); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); } void Misc_id_gauge_metric(void) { flecs::world ecs; ecs.import(); ecs.metric("metrics::has_foo") .kind() .id(); flecs::entity e1 = ecs.entity().add(); flecs::entity e2 = ecs.entity().add(); ecs.progress(1.0); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 1); test_int(i[1].value, 1); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); ecs.progress(1.0); test_int(count, 2); count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 1); test_int(i[1].value, 1); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); } void Misc_oneof_gauge_metric(void) { flecs::world ecs; ecs.import(); struct ColorMetric { double value[3]; }; flecs::entity m = ecs.metric("metrics::has_oneof") .kind() .id(flecs::Wildcard) .targets(); flecs::entity e1 = ecs.entity().add(Color::Red); flecs::entity e2 = ecs.entity().add(Color::Green); flecs::entity e3 = ecs.entity().add(Color::Blue); ecs.progress(1.0); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s) { ColorMetric *i = static_cast(it.range().get(m, ecs.id())); test_assert(i != nullptr); count += it.count(); test_int(count, 3); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_uint(s[2].entity, e3); test_str(ecs.to_json(m, &i[0]), "{\"blue\":0, \"green\":0, \"red\":1}"); test_str(ecs.to_json(m, &i[1]), "{\"blue\":0, \"green\":1, \"red\":0}"); test_str(ecs.to_json(m, &i[2]), "{\"blue\":1, \"green\":0, \"red\":0}"); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); test_assert(it.entity(2).has()); }); test_int(count, 3); count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s) { ColorMetric *i = static_cast(it.range().get(m, ecs.id())); test_assert(i != nullptr); count += it.count(); test_int(count, 3); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_uint(s[2].entity, e3); test_str(ecs.to_json(m, &i[0]), "{\"blue\":0, \"green\":0, \"red\":1}"); test_str(ecs.to_json(m, &i[1]), "{\"blue\":0, \"green\":1, \"red\":0}"); test_str(ecs.to_json(m, &i[2]), "{\"blue\":1, \"green\":0, \"red\":0}"); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); test_assert(it.entity(2).has()); }); test_int(count, 3); } void Misc_id_counter_metric(void) { flecs::world ecs; ecs.import(); ecs.metric("metrics::has_foo") .kind() .id(); flecs::entity e1 = ecs.entity().add(); flecs::entity e2 = ecs.entity().add(); ecs.progress(1.0); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 1); test_int(i[1].value, 1); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); ecs.progress(1.0); test_int(count, 2); count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 2); test_int(i[1].value, 2); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); } void Misc_oneof_counter_metric(void) { flecs::world ecs; ecs.import(); struct ColorMetric { double value[3]; }; flecs::entity m = ecs.metric("metrics::has_oneof") .kind() .id(flecs::Wildcard) .targets(); flecs::entity e1 = ecs.entity().add(Color::Red); flecs::entity e2 = ecs.entity().add(Color::Green); flecs::entity e3 = ecs.entity().add(Color::Blue); ecs.progress(1.0); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s) { ColorMetric *i = static_cast(it.range().get(m, ecs.id())); test_assert(i != nullptr); count += it.count(); test_int(count, 3); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_uint(s[2].entity, e3); test_str(ecs.to_json(m, &i[0]), "{\"blue\":0, \"green\":0, \"red\":1}"); test_str(ecs.to_json(m, &i[1]), "{\"blue\":0, \"green\":1, \"red\":0}"); test_str(ecs.to_json(m, &i[2]), "{\"blue\":1, \"green\":0, \"red\":0}"); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); test_assert(it.entity(2).has()); }); test_int(count, 3); ecs.progress(1.0); count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s) { ColorMetric *i = static_cast(it.range().get(m, ecs.id())); test_assert(i != nullptr); count += it.count(); test_int(count, 3); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_uint(s[2].entity, e3); test_str(ecs.to_json(m, &i[0]), "{\"blue\":0, \"green\":0, \"red\":2}"); test_str(ecs.to_json(m, &i[1]), "{\"blue\":0, \"green\":2, \"red\":0}"); test_str(ecs.to_json(m, &i[2]), "{\"blue\":2, \"green\":0, \"red\":0}"); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); test_assert(it.entity(2).has()); }); test_int(count, 3); } void Misc_component_mixin_member_metric(void) { flecs::world ecs; ecs.import(); ecs.component() .member("x") .member("y").metric(); flecs::entity e1 = ecs.entity().set({10, 20}); flecs::entity e2 = ecs.entity().set({20, 30}); ecs.progress(); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 20); test_int(i[1].value, 30); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); } void Misc_component_mixin_member_metric_custom_parent_entity(void) { flecs::world ecs; ecs.import(); flecs::entity parent = ecs.entity(); ecs.component() .member("x") .member("y").metric(parent); test_assert(parent.lookup("y") != 0); flecs::entity e1 = ecs.entity().set({10, 20}); flecs::entity e2 = ecs.entity().set({20, 30}); ecs.progress(); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 20); test_int(i[1].value, 30); test_assert(it.entity(0).parent().parent() == parent); test_assert(it.entity(1).parent().parent() == parent); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); } void Misc_metric_description(void) { flecs::world ecs; ecs.import(); ecs.component() .member("x") .member("y"); flecs::entity m = ecs.metric("metrics::position_y") .kind() .member("y") .brief("Position y"); test_str(m.doc_brief(), "Position y"); flecs::entity e1 = ecs.entity().set({10, 20}); flecs::entity e2 = ecs.entity().set({20, 30}); ecs.progress(); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 20); test_int(i[1].value, 30); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); } void Misc_component_mixin_member_metric_description(void) { flecs::world ecs; ecs.import(); ecs.component() .member("x") .member("y").metric(0, "Position y"); flecs::entity m = ecs.entity("Position::y"); test_str(m.doc_brief(), "Position y"); flecs::entity e1 = ecs.entity().set({10, 20}); flecs::entity e2 = ecs.entity().set({20, 30}); ecs.progress(); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 20); test_int(i[1].value, 30); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); } void Misc_member_metric_w_value_name(void) { flecs::world ecs; ecs.import(); flecs::entity parent = ecs.entity(); ecs.component() .member("value").metric(parent); test_assert(parent.lookup("value") == 0); test_assert(parent.lookup("mass") != 0); flecs::entity e1 = ecs.entity().set({10}); flecs::entity e2 = ecs.entity().set({20}); ecs.progress(); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 10); test_int(i[1].value, 20); test_assert(it.entity(0).parent().parent() == parent); test_assert(it.entity(1).parent().parent() == parent); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); } struct FooBar { float value; }; void Misc_member_metric_w_value_name_camel_case_type(void) { flecs::world ecs; ecs.import(); flecs::entity parent = ecs.entity(); ecs.component() .member("value").metric(parent); test_assert(parent.lookup("value") == 0); test_assert(parent.lookup("foo_bar") != 0); flecs::entity e1 = ecs.entity().set({10}); flecs::entity e2 = ecs.entity().set({20}); ecs.progress(); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 10); test_int(i[1].value, 20); test_assert(it.entity(0).parent().parent() == parent); test_assert(it.entity(1).parent().parent() == parent); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); } void Misc_member_metric_w_custom_name(void) { flecs::world ecs; ecs.import(); flecs::entity parent = ecs.entity(); ecs.component() .member("value").metric(parent, nullptr, "custom_name"); test_assert(parent.lookup("value") == 0); test_assert(parent.lookup("custom_name") != 0); flecs::entity e1 = ecs.entity().set({10}); flecs::entity e2 = ecs.entity().set({20}); ecs.progress(); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 10); test_int(i[1].value, 20); test_assert(it.entity(0).parent().parent() == parent); test_assert(it.entity(1).parent().parent() == parent); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); } void Misc_dotmember_metric(void) { flecs::world ecs; struct Point { float x; float y; }; struct Position { float dummy; Point position; }; ecs.import(); ecs.component() .member("x") .member("y"); ecs.component() .member("dummy") .member("position"); ecs.metric("metrics::position_y") .kind() .dotmember("position.y"); flecs::entity e1 = ecs.entity().set({10, {20, 30}}); ecs.progress(); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 1); test_uint(s[0].entity, e1); test_int(i[0].value, 30); test_assert(it.entity(0).has()); }); test_int(count, 1); } void Misc_counter_id_metric(void) { flecs::world ecs; ecs.import(); flecs::entity m = ecs.metric("metrics.position") .kind() .id(); ecs.entity().set({10, 20}); ecs.progress(1.0); { const flecs::metrics::Value *v = m.get(); test_assert(v != nullptr); test_int(v->value, 1); } ecs.entity().set({10, 20}); ecs.entity().set({10, 20}); ecs.progress(1.0); { const flecs::metrics::Value *v = m.get(); test_assert(v != nullptr); test_int(v->value, 4); } } void Misc_counter_target_metric(void) { flecs::world ecs; ecs.import(); flecs::entity m = ecs.metric("metrics::color") .kind() .id(flecs::Wildcard) .targets(); test_assert(m != 0); ecs.entity().add(Color::Red); ecs.entity().add(Color::Green); ecs.entity().add(Color::Blue); ecs.entity().add(Color::Blue); ecs.progress(1.0); { flecs::entity red = ecs.lookup("metrics::color::Red"); test_assert(red != 0); const flecs::metrics::Value *v = red.get(); test_assert(v != nullptr); test_int(v->value, 1); } { flecs::entity green = ecs.lookup("metrics::color::Green"); test_assert(green != 0); const flecs::metrics::Value *v = green.get(); test_assert(v != nullptr); test_int(v->value, 1); } { flecs::entity blue = ecs.lookup("metrics::color::Blue"); test_assert(blue != 0); const flecs::metrics::Value *v = blue.get(); test_assert(v != nullptr); test_int(v->value, 2); } } void Misc_alert(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("position_without_velocity") .with() .without() .build(); test_assert(a != 0); test_str(a.name().c_str(), "position_without_velocity"); auto e1 = ecs.entity("e1").set({10, 20}); auto e2 = ecs.entity("e2").set({10, 20}); e1.set({1, 2}); ecs.progress(1.0); test_assert(!e1.has()); test_assert(e2.has()); test_int(e2.alert_count(), 1); test_int(e2.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e2); test_assert(ai.parent() == a); } e2.add(); ecs.progress(1.0); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai == 0); } } void Misc_alert_w_message(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("position_without_velocity") .with() .without() .message("$this has position but not velocity") .build(); test_assert(a != 0); test_str(a.name().c_str(), "position_without_velocity"); auto e1 = ecs.entity("e1").set({10, 20}); auto e2 = ecs.entity("e2").set({10, 20}); e1.set({1, 2}); ecs.progress(1.0); test_assert(!e1.has()); test_assert(e2.has()); test_int(e2.alert_count(), 1); test_int(e2.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e2); test_assert(ai.parent() == a); test_str(ai.get()->message, "e2 has position but not velocity"); } e2.add(); ecs.progress(1.0); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai == 0); } } void Misc_alert_w_brief(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("has_position") .with() .brief("Entity has Position") .build(); test_assert(a != 0); test_str(a.name().c_str(), "has_position"); test_str(a.doc_brief(), "Entity has Position"); } void Misc_alert_doc_name(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("has_position") .with() .doc_name("Has Position") .build(); test_assert(a != 0); test_str(a.name().c_str(), "has_position"); test_str(a.doc_name(), "Has Position"); } void Misc_alert_severity_info(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("has_position") .with() .severity() .build(); test_assert(a != 0); test_str(a.name().c_str(), "has_position"); test_assert(a.target() == ecs.id()); } void Misc_alert_severity_warning(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("has_position") .with() .severity() .build(); test_assert(a != 0); test_str(a.name().c_str(), "has_position"); test_assert(a.target() == ecs.id()); } void Misc_alert_severity_error(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("has_position") .with() .severity() .build(); test_assert(a != 0); test_str(a.name().c_str(), "has_position"); test_assert(a.target() == ecs.id()); } void Misc_alert_severity_implicit(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("has_position") .with() .build(); test_assert(a != 0); test_str(a.name().c_str(), "has_position"); test_assert(a.target() == ecs.id()); } void Misc_alert_w_retain_period(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("position_without_velocity") .with() .without() .retain_period(1.0) .build(); test_assert(a != 0); test_str(a.name().c_str(), "position_without_velocity"); auto e1 = ecs.entity("e1").set({10, 20}); auto e2 = ecs.entity("e2").set({10, 20}); e1.set({1, 2}); ecs.progress(1.0); test_assert(!e1.has()); test_assert(e2.has()); test_int(e2.alert_count(), 1); test_int(e2.alert_count(a), 1); flecs::entity ai; { ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e2); test_assert(ai.parent() == a); } e2.add(); ecs.progress(1.0); test_assert(ai.is_alive()); test_assert(!e1.has()); test_assert(!e2.has()); test_int(e2.alert_count(), 0); test_int(e2.alert_count(a), 0); ecs.progress(1.0); test_assert(!ai.is_alive()); test_assert(!e1.has()); test_assert(!e2.has()); test_int(e2.alert_count(), 0); test_int(e2.alert_count(a), 0); } void Misc_alert_w_severity_filter(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("position_without_velocity") .with() .without() .severity_filter(ecs.id(), ecs.id()) .build(); test_assert(a != 0); test_str(a.name().c_str(), "position_without_velocity"); auto e1 = ecs.entity("e1").set({10, 20}); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } e1.add(); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } e1.remove(); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } } void Misc_alert_w_severity_filter_severity_type(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("position_without_velocity") .with() .without() .severity_filter(ecs.id()) .build(); test_assert(a != 0); test_str(a.name().c_str(), "position_without_velocity"); auto e1 = ecs.entity("e1").set({10, 20}); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } e1.add(); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } e1.remove(); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } } void Misc_alert_w_severity_filter_severity_type_id_type(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("position_without_velocity") .with() .without() .severity_filter() .build(); test_assert(a != 0); test_str(a.name().c_str(), "position_without_velocity"); auto e1 = ecs.entity("e1").set({10, 20}); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } e1.add(); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } e1.remove(); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } } void Misc_alert_w_severity_filter_severity_type_enum_constant(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("position_without_velocity") .with() .without() .severity_filter(Green) .build(); test_assert(a != 0); test_str(a.name().c_str(), "position_without_velocity"); auto e1 = ecs.entity("e1").set({10, 20}); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } e1.add(Green); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } e1.add(Blue); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } e1.remove(flecs::Wildcard); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } } void Misc_alert_w_severity_filter_w_var(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("position_without_velocity") .with() .without() .with(flecs::ChildOf).second("$parent") .severity_filter(ecs.id(), ecs.id(), "parent") .build(); test_assert(a != 0); test_str(a.name().c_str(), "position_without_velocity"); auto p = ecs.entity(); auto e1 = ecs.entity("e1").set({10, 20}).add().child_of(p); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } p.add(); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } p.remove(); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } } void Misc_alert_w_severity_filter_severity_type_w_var(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("position_without_velocity") .with() .without() .with(flecs::ChildOf).second("$parent") .severity_filter(ecs.id(), "parent") .build(); test_assert(a != 0); test_str(a.name().c_str(), "position_without_velocity"); auto p = ecs.entity(); auto e1 = ecs.entity("e1").set({10, 20}).add().child_of(p); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } p.add(); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } p.remove(); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } } void Misc_alert_w_severity_filter_severity_type_id_type_w_var(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("position_without_velocity") .with() .without() .with(flecs::ChildOf).second("$parent") .severity_filter("parent") .build(); test_assert(a != 0); test_str(a.name().c_str(), "position_without_velocity"); auto p = ecs.entity(); auto e1 = ecs.entity("e1").set({10, 20}).add().child_of(p); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } p.add(); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } p.remove(); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } } void Misc_alert_w_severity_filter_severity_type_enum_constant_w_var(void) { flecs::world ecs; ecs.import(); flecs::entity a = ecs.alert("position_without_velocity") .with() .without() .with(flecs::ChildOf).second("$parent") .severity_filter(Color::Green, "parent") .build(); test_assert(a != 0); test_str(a.name().c_str(), "position_without_velocity"); auto p = ecs.entity(); auto e1 = ecs.entity("e1").set({10, 20}).add(Color::Green).child_of(p); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } p.add(Color::Green); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } p.remove(flecs::Wildcard); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert((ai.has())); test_assert(ai.parent() == a); } } void Misc_alert_for_member_range(void) { flecs::world ecs; ecs.import(); ecs.component() .member("value") .error_range(0, 100); flecs::entity a = ecs.alert("high_mass") .with() .message("$this has high mass") .member("value") .build(); test_assert(a != 0); test_str(a.name().c_str(), "high_mass"); auto e1 = ecs.entity("e1").set({25}); ecs.progress(1.0); test_assert(!e1.has()); e1.set({150}); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert(ai.parent() == a); test_str(ai.get()->message, "e1 has high mass"); } e1.set({0}); ecs.progress(1.0); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai == 0); } } void Misc_alert_w_member_range_from_var(void) { flecs::world ecs; ecs.import(); ecs.component() .member("value") .error_range(0, 100); flecs::entity a = ecs.alert("high_parent_mass") .with(flecs::ChildOf).second("$parent") .with().src("$parent") .message("$this has high mass") .member("value", "parent") .build(); test_assert(a != 0); test_str(a.name().c_str(), "high_parent_mass"); auto p = ecs.entity().set({25}); auto e1 = ecs.entity("e1").child_of(p); ecs.progress(1.0); test_assert(!e1.has()); p.set({150}); ecs.progress(1.0); test_assert(e1.has()); test_int(e1.alert_count(), 1); test_int(e1.alert_count(a), 1); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai != 0); test_assert(ai.has()); test_assert(ai.has()); test_assert(ai.get()->entity == e1); test_assert(ai.parent() == a); } p.set({0}); ecs.progress(1.0); { flecs::entity ai = ecs.filter_builder() .with() .build() .first(); test_assert(ai == 0); } } void Misc_map_api(void) { flecs::world ecs; ecs_map_t m; ecs_map_init(&m, 0); test_int(0, ecs_map_count(&m)); int32_t *v = ecs_map_insert_alloc_t(&m, int32_t, 10); test_assert(v != NULL); test_assert(ecs_map_ensure_alloc_t(&m, int32_t, 10) == v); test_assert(ecs_map_get_deref(&m, int32_t, 10) == v); int32_t w; ecs_map_insert_ptr(&m, 20, &w); test_assert(ecs_map_ensure_alloc_t(&m, int32_t, 20) == &w); test_assert(ecs_map_get_deref(&m, int32_t, 20) == &w); test_assert(ecs_map_count(&m) == 2); ecs_map_iter_t it = ecs_map_iter(&m); test_bool(true, ecs_map_next(&it)); test_uint(20, ecs_map_key(&it)); test_assert(&w == ecs_map_ptr(&it)); test_bool(true, ecs_map_next(&it)); test_uint(10, ecs_map_key(&it)); test_assert(v == ecs_map_ptr(&it)); test_bool(false, ecs_map_next(&it)); test_assert(ecs_map_remove_ptr(&m, 10) == v); test_assert(ecs_map_remove_ptr(&m, 20) == &w); ecs_os_free(v); ecs_map_fini(&m); } void Misc_member_metric_w_pair_R_T(void) { flecs::world ecs; ecs.import(); ecs.component() .member("value"); flecs::entity m = ecs.metric("mass") .kind() .id() .member("value"); flecs::entity e1 = ecs.entity().set({10}); flecs::entity e2 = ecs.entity().set({20}); ecs.progress(); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 10); test_int(i[1].value, 20); test_assert(it.entity(0).parent() == m); test_assert(it.entity(1).parent() == m); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); } void Misc_member_metric_w_pair_R_t(void) { flecs::world ecs; ecs.import(); ecs.component() .member("value"); flecs::entity m = ecs.metric("mass") .kind() .id(ecs.id()) .member("value"); flecs::entity e1 = ecs.entity().set({10}); flecs::entity e2 = ecs.entity().set({20}); ecs.progress(); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 10); test_int(i[1].value, 20); test_assert(it.entity(0).parent() == m); test_assert(it.entity(1).parent() == m); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); } void Misc_member_metric_w_pair_r_t(void) { flecs::world ecs; ecs.import(); ecs.component() .member("value"); flecs::entity m = ecs.metric("mass") .kind() .id(ecs.id(), ecs.id()) .member("value"); flecs::entity e1 = ecs.entity().set({10}); flecs::entity e2 = ecs.entity().set({20}); ecs.progress(); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 10); test_int(i[1].value, 20); test_assert(it.entity(0).parent() == m); test_assert(it.entity(1).parent() == m); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); } void Misc_member_metric_w_pair_r_T(void) { flecs::world ecs; ecs.import(); ecs.component() .member("value"); flecs::entity m = ecs.metric("mass") .kind() .id_second(ecs.id()) .member("value"); flecs::entity e1 = ecs.entity().set({10}); flecs::entity e2 = ecs.entity().set({20}); ecs.progress(); int32_t count = 0; ecs.filter() .iter([&](flecs::iter& it, flecs::metrics::Source *s, flecs::metrics::Value *i) { count += it.count(); test_int(count, 2); test_uint(s[0].entity, e1); test_uint(s[1].entity, e2); test_int(i[0].value, 10); test_int(i[1].value, 20); test_assert(it.entity(0).parent() == m); test_assert(it.entity(1).parent() == m); test_assert(it.entity(0).has()); test_assert(it.entity(1).has()); }); test_int(count, 2); }