@@ -24100,6 +24100,151 @@ struct each_invoker : public invoker {
24100
24100
Func m_func;
24101
24101
};
24102
24102
24103
+ template <typename Func, typename ... Components>
24104
+ struct find_invoker : public invoker {
24105
+ // If the number of arguments in the function signature is one more than the
24106
+ // number of components in the query, an extra entity arg is required.
24107
+ static constexpr bool PassEntity =
24108
+ (sizeof...(Components) + 1) == (arity<Func>::value);
24109
+
24110
+ // If the number of arguments in the function is two more than the number of
24111
+ // components in the query, extra iter + index arguments are required.
24112
+ static constexpr bool PassIter =
24113
+ (sizeof...(Components) + 2) == (arity<Func>::value);
24114
+
24115
+ static_assert(arity<Func>::value > 0,
24116
+ "each() must have at least one argument");
24117
+
24118
+ using Terms = typename term_ptrs<Components ...>::array;
24119
+
24120
+ template < if_not_t< is_same< decay_t<Func>, decay_t<Func>& >::value > = 0>
24121
+ explicit find_invoker(Func&& func) noexcept
24122
+ : m_func(FLECS_MOV(func)) { }
24123
+
24124
+ explicit find_invoker(const Func& func) noexcept
24125
+ : m_func(func) { }
24126
+
24127
+ // Invoke object directly. This operation is useful when the calling
24128
+ // function has just constructed the invoker, such as what happens when
24129
+ // iterating a query.
24130
+ void invoke(ecs_iter_t *iter) const {
24131
+ term_ptrs<Components...> terms;
24132
+
24133
+ if (terms.populate(iter)) {
24134
+ invoke_callback< each_ref_column >(iter, m_func, 0, terms.m_terms);
24135
+ } else {
24136
+ invoke_callback< each_column >(iter, m_func, 0, terms.m_terms);
24137
+ }
24138
+ }
24139
+
24140
+ // Find invokers always use instanced iterators
24141
+ static bool instanced() {
24142
+ return true;
24143
+ }
24144
+
24145
+ private:
24146
+ // Number of function arguments is one more than number of components, pass
24147
+ // entity as argument.
24148
+ template <template<typename X, typename = int> class ColumnType,
24149
+ typename... Args, if_t<
24150
+ sizeof...(Components) == sizeof...(Args) && PassEntity> = 0>
24151
+ static flecs::entity invoke_callback(
24152
+ ecs_iter_t *iter, const Func& func, size_t, Terms&, Args... comps)
24153
+ {
24154
+ ECS_TABLE_LOCK(iter->world, iter->table);
24155
+
24156
+ ecs_world_t *world = iter->world;
24157
+ size_t count = static_cast<size_t>(iter->count);
24158
+
24159
+ ecs_assert(count > 0, ECS_INVALID_OPERATION,
24160
+ "no entities returned, use find() without flecs::entity argument");
24161
+
24162
+ for (size_t i = 0; i < count; i ++) {
24163
+ if (func(flecs::entity(world, iter->entities[i]),
24164
+ (ColumnType< remove_reference_t<Components> >(comps, i)
24165
+ .get_row())...))
24166
+ {
24167
+ return flecs::entity(world, iter->entities[i]);
24168
+ }
24169
+ }
24170
+
24171
+ ECS_TABLE_UNLOCK(iter->world, iter->table);
24172
+
24173
+ return flecs::entity();
24174
+ }
24175
+
24176
+ // Number of function arguments is two more than number of components, pass
24177
+ // iter + index as argument.
24178
+ template <template<typename X, typename = int> class ColumnType,
24179
+ typename... Args, int Enabled = PassIter, if_t<
24180
+ sizeof...(Components) == sizeof...(Args) && Enabled> = 0>
24181
+ static flecs::entity invoke_callback(
24182
+ ecs_iter_t *iter, const Func& func, size_t, Terms&, Args... comps)
24183
+ {
24184
+ size_t count = static_cast<size_t>(iter->count);
24185
+ if (count == 0) {
24186
+ // If query has no This terms, count can be 0. Since each does not
24187
+ // have an entity parameter, just pass through components
24188
+ count = 1;
24189
+ }
24190
+
24191
+ flecs::iter it(iter);
24192
+
24193
+ ECS_TABLE_LOCK(iter->world, iter->table);
24194
+
24195
+ for (size_t i = 0; i < count; i ++) {
24196
+ if (func(it, i, (ColumnType< remove_reference_t<Components> >(comps, i)
24197
+ .get_row())...))
24198
+ {
24199
+ return flecs::entity(world, iter->entities[i]);
24200
+ }
24201
+ }
24202
+
24203
+ ECS_TABLE_UNLOCK(iter->world, iter->table);
24204
+
24205
+ return flecs::entity();
24206
+ }
24207
+
24208
+ // Number of function arguments is equal to number of components, no entity
24209
+ template <template<typename X, typename = int> class ColumnType,
24210
+ typename... Args, if_t<
24211
+ sizeof...(Components) == sizeof...(Args) && !PassEntity && !PassIter> = 0>
24212
+ static flecs::entity invoke_callback(
24213
+ ecs_iter_t *iter, const Func& func, size_t, Terms&, Args... comps)
24214
+ {
24215
+ size_t count = static_cast<size_t>(iter->count);
24216
+ if (count == 0) {
24217
+ // If query has no This terms, count can be 0. Since each does not
24218
+ // have an entity parameter, just pass through components
24219
+ count = 1;
24220
+ }
24221
+
24222
+ flecs::iter it(iter);
24223
+
24224
+ ECS_TABLE_LOCK(iter->world, iter->table);
24225
+
24226
+ for (size_t i = 0; i < count; i ++) {
24227
+ if (func( (ColumnType< remove_reference_t<Components> >(comps, i)
24228
+ .get_row())...))
24229
+ {
24230
+ return flecs::entity(world, iter->entities[i]);
24231
+ }
24232
+ }
24233
+
24234
+ ECS_TABLE_UNLOCK(iter->world, iter->table);
24235
+ }
24236
+
24237
+ template <template<typename X, typename = int> class ColumnType,
24238
+ typename... Args, if_t< sizeof...(Components) != sizeof...(Args) > = 0>
24239
+ static flecs::entity invoke_callback(ecs_iter_t *iter, const Func& func,
24240
+ size_t index, Terms& columns, Args... comps)
24241
+ {
24242
+ return invoke_callback<ColumnType>(
24243
+ iter, func, index + 1, columns, comps..., columns[index]);
24244
+ }
24245
+
24246
+ Func m_func;
24247
+ };
24103
24248
24104
24249
////////////////////////////////////////////////////////////////////////////////
24105
24250
//// Utility class to invoke a system iterate action
@@ -24480,6 +24625,12 @@ struct iterable {
24480
24625
this->next_each_action());
24481
24626
}
24482
24627
24628
+ template <typename Func>
24629
+ flecs::entity find(Func&& func) const {
24630
+ iterate<_::find_invoker>(nullptr, FLECS_FWD(func),
24631
+ this->next_each_action());
24632
+ }
24633
+
24483
24634
/** Iter iterator.
24484
24635
* The "iter" iterator accepts a function that is invoked for each matching
24485
24636
* table. The following function signatures are valid:
0 commit comments