diff --git a/distr/flecs.h b/distr/flecs.h index d36f391eee..b81cfdbad2 100644 --- a/distr/flecs.h +++ b/distr/flecs.h @@ -29759,6 +29759,37 @@ struct query_builder_i : term_builder_i { return *this; } + /** Sets the current term to the one with the provided type. + * This loops over all terms to find the one with the provided type. + * For performance-critical paths, use term_at(int32_t) instead. + */ + template + Base& term_at() { + flecs::id_t term_id = _::type::id(this->world_v()); + + for (int i = 0; i < term_index_; i ++) { + if (desc_->terms[i].first.id == term_id) { + return term_at(i); + } + } + + ecs_assert(ecs_term_is_initialized(this->term_), + ECS_INVALID_PARAMETER, NULL); + ecs_assert(this->term_->first.id == term_id, + ECS_INVALID_PARAMETER, "term not found"); + return *this; + } + + /** Sets the current term to the one at the provided index and asserts that the type matches. + */ + template + Base& term_at(int32_t term_index) { + this->term_at(term_index); + ecs_assert(this->term_->first.id == _::type::id(this->world_v()), + ECS_INVALID_PARAMETER, "term type mismatch"); + return *this; + } + /** Sort the output of a query. * This enables sorting of entities across matched tables. As a result of this * operation, the order of entities in the matched tables may be changed. diff --git a/include/flecs/addons/cpp/mixins/query/builder_i.hpp b/include/flecs/addons/cpp/mixins/query/builder_i.hpp index c5e7258e22..4e2476eb77 100644 --- a/include/flecs/addons/cpp/mixins/query/builder_i.hpp +++ b/include/flecs/addons/cpp/mixins/query/builder_i.hpp @@ -246,6 +246,37 @@ struct query_builder_i : term_builder_i { return *this; } + /** Sets the current term to the one with the provided type. + * This loops over all terms to find the one with the provided type. + * For performance-critical paths, use term_at(int32_t) instead. + */ + template + Base& term_at() { + flecs::id_t term_id = _::type::id(this->world_v()); + + for (int i = 0; i < term_index_; i ++) { + if (desc_->terms[i].first.id == term_id) { + return term_at(i); + } + } + + ecs_assert(ecs_term_is_initialized(this->term_), + ECS_INVALID_PARAMETER, NULL); + ecs_assert(this->term_->first.id == term_id, + ECS_INVALID_PARAMETER, "term not found"); + return *this; + } + + /** Sets the current term to the one at the provided index and asserts that the type matches. + */ + template + Base& term_at(int32_t term_index) { + this->term_at(term_index); + ecs_assert(this->term_->first.id == _::type::id(this->world_v()), + ECS_INVALID_PARAMETER, "term type mismatch"); + return *this; + } + /** Sort the output of a query. * This enables sorting of entities across matched tables. As a result of this * operation, the order of entities in the matched tables may be changed. diff --git a/test/cpp/project.json b/test/cpp/project.json index 7d35c391a8..ca6ba09d9c 100644 --- a/test/cpp/project.json +++ b/test/cpp/project.json @@ -747,6 +747,8 @@ "relation_w_predicate_wildcard", "add_pair_w_rel_type", "template_term", + "template_term_at", + "template_term_at_index", "explicit_subject_w_id", "explicit_subject_w_type", "explicit_object_w_id", diff --git a/test/cpp/src/QueryBuilder.cpp b/test/cpp/src/QueryBuilder.cpp index c540008f34..a466aed835 100644 --- a/test/cpp/src/QueryBuilder.cpp +++ b/test/cpp/src/QueryBuilder.cpp @@ -1592,6 +1592,54 @@ void QueryBuilder_template_term(void) { test_int(count, 1); } +void QueryBuilder_template_term_at(void) { + flecs::world ecs; + + struct Rel { int foo; }; + + int32_t count = 0; + + auto s = ecs.system() + .term_at().singleton() + .term_at().second(flecs::Wildcard) + .run([&](flecs::iter it){ + while (it.next()) { + count += it.count(); + } + }); + + ecs.entity().add(); + ecs.set({}); + + s.run(); + + test_int(count, 1); +} + +void QueryBuilder_template_term_at_index(void) { + flecs::world ecs; + + struct Rel { int foo; }; + + int32_t count = 0; + + auto s = ecs.system() + .term_at(1).singleton() + .term_at(0).second(flecs::Wildcard) + .run([&](flecs::iter it){ + while (it.next()) { + count += it.count(); + } + }); + + ecs.entity().add(); + ecs.set({}); + + s.run(); + + test_int(count, 1); +} + void QueryBuilder_explicit_subject_w_id(void) { flecs::world ecs; diff --git a/test/cpp/src/main.cpp b/test/cpp/src/main.cpp index d1fdaf7e55..2c443b1dc9 100644 --- a/test/cpp/src/main.cpp +++ b/test/cpp/src/main.cpp @@ -718,6 +718,8 @@ void QueryBuilder_relation_w_object_wildcard(void); void QueryBuilder_relation_w_predicate_wildcard(void); void QueryBuilder_add_pair_w_rel_type(void); void QueryBuilder_template_term(void); +void QueryBuilder_template_term_at(void); +void QueryBuilder_template_term_at_index(void); void QueryBuilder_explicit_subject_w_id(void); void QueryBuilder_explicit_subject_w_type(void); void QueryBuilder_explicit_object_w_id(void); @@ -4160,6 +4162,14 @@ bake_test_case QueryBuilder_testcases[] = { "template_term", QueryBuilder_template_term }, + { + "template_term_at", + QueryBuilder_template_term_at + }, + { + "template_term_at_index", + QueryBuilder_template_term_at_index + }, { "explicit_subject_w_id", QueryBuilder_explicit_subject_w_id @@ -6805,7 +6815,7 @@ static bake_test_suite suites[] = { "QueryBuilder", QueryBuilder_setup, NULL, - 166, + 168, QueryBuilder_testcases, 1, QueryBuilder_params