Skip to content

Commit a6935cf

Browse files
committed
QueryState::new_with_config
1 parent c475e27 commit a6935cf

File tree

12 files changed

+135
-39
lines changed

12 files changed

+135
-39
lines changed

crates/bevy_ecs/macros/src/fetch.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
245245
type Fetch<'__w> = #fetch_struct_name #user_ty_generics_with_world;
246246
type ReadOnly = #read_only_struct_name #user_ty_generics;
247247
type State = #state_struct_name #user_ty_generics;
248+
type Config = ();
248249

249250
fn shrink<'__wlong: '__wshort, '__wshort>(
250251
item: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Item<'__wlong>
@@ -347,9 +348,11 @@ pub fn derive_world_query_impl(input: TokenStream) -> TokenStream {
347348
)*
348349
}
349350

350-
fn init_state(world: &mut #path::world::World) -> #state_struct_name #user_ty_generics {
351+
fn init_state(_config: Self::Config, world: &mut #path::world::World) -> #state_struct_name #user_ty_generics {
351352
#state_struct_name {
352-
#(#named_field_idents: <#field_types>::init_state(world),)*
353+
// TODO: instead of using `Default::default` for the config (and thus failing to compile on query types needing configuration like `Ptr<'_>`)
354+
// we could have a tuple with configuration for each field, or generate a mirror struct with the same field names but storing the configuration values
355+
#(#named_field_idents: <#field_types>::init_state(Default::default(), world),)*
353356
}
354357
}
355358

crates/bevy_ecs/src/lib.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,10 @@ mod tests {
907907
}
908908
}
909909

910-
fn get_filtered<F: ReadOnlyWorldQuery>(world: &mut World) -> Vec<Entity> {
910+
fn get_filtered<F: ReadOnlyWorldQuery>(world: &mut World) -> Vec<Entity>
911+
where
912+
F::Config: Default,
913+
{
911914
world
912915
.query_filtered::<Entity, F>()
913916
.iter(world)
@@ -990,7 +993,10 @@ mod tests {
990993
}
991994
}
992995

993-
fn get_filtered<F: ReadOnlyWorldQuery>(world: &mut World) -> Vec<Entity> {
996+
fn get_filtered<F: ReadOnlyWorldQuery>(world: &mut World) -> Vec<Entity>
997+
where
998+
F::Config: Default,
999+
{
9941000
world
9951001
.query_filtered::<Entity, F>()
9961002
.iter(world)

crates/bevy_ecs/src/query/fetch.rs

+30-14
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,9 @@ pub unsafe trait WorldQuery {
328328
/// constructing [`Self::Fetch`](crate::query::WorldQuery::Fetch).
329329
type State: Send + Sync + Sized;
330330

331+
/// Runtime config value passed to [`WorldQuery::init_state`]
332+
type Config;
333+
331334
/// This function manually implements subtyping for the query items.
332335
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort>;
333336

@@ -434,7 +437,9 @@ pub unsafe trait WorldQuery {
434437
);
435438

436439
/// Creates and initializes a [`State`](WorldQuery::State) for this [`WorldQuery`] type.
437-
fn init_state(world: &mut World) -> Self::State;
440+
///
441+
/// [`WorldQuery::Config`] is used to pass runtime data for dynamic queries.
442+
fn init_state(config: Self::Config, world: &mut World) -> Self::State;
438443

439444
/// Returns `true` if this query matches a set of components. Otherwise, returns `false`.
440445
fn matches_component_set(
@@ -465,6 +470,7 @@ unsafe impl WorldQuery for Entity {
465470
type Item<'w> = Entity;
466471
type ReadOnly = Self;
467472
type State = ();
473+
type Config = ();
468474

469475
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> {
470476
item
@@ -515,7 +521,7 @@ unsafe impl WorldQuery for Entity {
515521
) {
516522
}
517523

518-
fn init_state(_world: &mut World) {}
524+
fn init_state(_config: (), _world: &mut World) {}
519525

520526
fn matches_component_set(
521527
_state: &Self::State,
@@ -542,6 +548,7 @@ unsafe impl<T: Component> WorldQuery for &T {
542548
type Item<'w> = &'w T;
543549
type ReadOnly = Self;
544550
type State = ComponentId;
551+
type Config = ();
545552

546553
fn shrink<'wlong: 'wshort, 'wshort>(item: &'wlong T) -> &'wshort T {
547554
item
@@ -652,7 +659,7 @@ unsafe impl<T: Component> WorldQuery for &T {
652659
}
653660
}
654661

655-
fn init_state(world: &mut World) -> ComponentId {
662+
fn init_state(_config: (), world: &mut World) -> ComponentId {
656663
world.init_component::<T>()
657664
}
658665

@@ -688,6 +695,7 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> {
688695
type Item<'w> = Ref<'w, T>;
689696
type ReadOnly = Self;
690697
type State = ComponentId;
698+
type Config = ();
691699

692700
fn shrink<'wlong: 'wshort, 'wshort>(item: Ref<'wlong, T>) -> Ref<'wshort, T> {
693701
item
@@ -814,7 +822,7 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> {
814822
}
815823
}
816824

817-
fn init_state(world: &mut World) -> ComponentId {
825+
fn init_state(_config: (), world: &mut World) -> ComponentId {
818826
world.init_component::<T>()
819827
}
820828

@@ -850,6 +858,7 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
850858
type Item<'w> = Mut<'w, T>;
851859
type ReadOnly = &'__w T;
852860
type State = ComponentId;
861+
type Config = ();
853862

854863
fn shrink<'wlong: 'wshort, 'wshort>(item: Mut<'wlong, T>) -> Mut<'wshort, T> {
855864
item
@@ -976,7 +985,7 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T {
976985
}
977986
}
978987

979-
fn init_state(world: &mut World) -> ComponentId {
988+
fn init_state(_config: (), world: &mut World) -> ComponentId {
980989
world.init_component::<T>()
981990
}
982991

@@ -1000,6 +1009,7 @@ unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
10001009
type Item<'w> = Option<T::Item<'w>>;
10011010
type ReadOnly = Option<T::ReadOnly>;
10021011
type State = T::State;
1012+
type Config = T::Config;
10031013

10041014
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> {
10051015
item.map(T::shrink)
@@ -1081,8 +1091,8 @@ unsafe impl<T: WorldQuery> WorldQuery for Option<T> {
10811091
}
10821092
}
10831093

1084-
fn init_state(world: &mut World) -> T::State {
1085-
T::init_state(world)
1094+
fn init_state(config: Self::Config, world: &mut World) -> T::State {
1095+
T::init_state(config, world)
10861096
}
10871097

10881098
fn matches_component_set(
@@ -1106,6 +1116,7 @@ macro_rules! impl_tuple_fetch {
11061116
type Item<'w> = ($($name::Item<'w>,)*);
11071117
type ReadOnly = ($($name::ReadOnly,)*);
11081118
type State = ($($name::State,)*);
1119+
type Config = ($($name::Config,)*);
11091120

11101121
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> {
11111122
let ($($name,)*) = item;
@@ -1183,8 +1194,9 @@ macro_rules! impl_tuple_fetch {
11831194
}
11841195

11851196

1186-
fn init_state(_world: &mut World) -> Self::State {
1187-
($($name::init_state(_world),)*)
1197+
fn init_state(config: Self::Config, _world: &mut World) -> Self::State {
1198+
let ($($state,)*) = config;
1199+
($($name::init_state($state, _world),)*)
11881200
}
11891201

11901202
fn matches_component_set(state: &Self::State, _set_contains_id: &impl Fn(ComponentId) -> bool) -> bool {
@@ -1216,6 +1228,7 @@ macro_rules! impl_anytuple_fetch {
12161228
type Item<'w> = ($(Option<$name::Item<'w>>,)*);
12171229
type ReadOnly = AnyOf<($($name::ReadOnly,)*)>;
12181230
type State = ($($name::State,)*);
1231+
type Config = ($($name::Config,)*);
12191232

12201233
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> {
12211234
let ($($name,)*) = item;
@@ -1313,8 +1326,9 @@ macro_rules! impl_anytuple_fetch {
13131326
)*
13141327
}
13151328

1316-
fn init_state(_world: &mut World) -> Self::State {
1317-
($($name::init_state(_world),)*)
1329+
fn init_state(config: Self::Config, _world: &mut World) -> Self::State {
1330+
let ($($state,)*) = config;
1331+
($($name::init_state($state, _world),)*)
13181332
}
13191333

13201334
fn matches_component_set(_state: &Self::State, _set_contains_id: &impl Fn(ComponentId) -> bool) -> bool {
@@ -1342,6 +1356,7 @@ unsafe impl<Q: WorldQuery> WorldQuery for NopWorldQuery<Q> {
13421356
type Item<'w> = ();
13431357
type ReadOnly = Self;
13441358
type State = Q::State;
1359+
type Config = Q::Config;
13451360

13461361
fn shrink<'wlong: 'wshort, 'wshort>(_: ()) {}
13471362

@@ -1383,8 +1398,8 @@ unsafe impl<Q: WorldQuery> WorldQuery for NopWorldQuery<Q> {
13831398
) {
13841399
}
13851400

1386-
fn init_state(world: &mut World) -> Self::State {
1387-
Q::init_state(world)
1401+
fn init_state(config: Self::Config, world: &mut World) -> Self::State {
1402+
Q::init_state(config, world)
13881403
}
13891404

13901405
fn matches_component_set(
@@ -1404,6 +1419,7 @@ unsafe impl<T: ?Sized> WorldQuery for PhantomData<T> {
14041419
type Fetch<'a> = ();
14051420
type ReadOnly = Self;
14061421
type State = ();
1422+
type Config = ();
14071423

14081424
fn shrink<'wlong: 'wshort, 'wshort>(_item: Self::Item<'wlong>) -> Self::Item<'wshort> {}
14091425

@@ -1450,7 +1466,7 @@ unsafe impl<T: ?Sized> WorldQuery for PhantomData<T> {
14501466
) {
14511467
}
14521468

1453-
fn init_state(_world: &mut World) -> Self::State {}
1469+
fn init_state(_config: Self::Config, _world: &mut World) -> Self::State {}
14541470

14551471
fn matches_component_set(
14561472
_state: &Self::State,

crates/bevy_ecs/src/query/filter.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ unsafe impl<T: Component> WorldQuery for With<T> {
4747
type Item<'w> = ();
4848
type ReadOnly = Self;
4949
type State = ComponentId;
50+
type Config = ();
5051

5152
fn shrink<'wlong: 'wshort, 'wshort>(_: Self::Item<'wlong>) -> Self::Item<'wshort> {}
5253

@@ -97,7 +98,7 @@ unsafe impl<T: Component> WorldQuery for With<T> {
9798
) {
9899
}
99100

100-
fn init_state(world: &mut World) -> ComponentId {
101+
fn init_state(_config: (), world: &mut World) -> ComponentId {
101102
world.init_component::<T>()
102103
}
103104

@@ -144,6 +145,7 @@ unsafe impl<T: Component> WorldQuery for Without<T> {
144145
type Item<'w> = ();
145146
type ReadOnly = Self;
146147
type State = ComponentId;
148+
type Config = ();
147149

148150
fn shrink<'wlong: 'wshort, 'wshort>(_: Self::Item<'wlong>) -> Self::Item<'wshort> {}
149151

@@ -194,7 +196,7 @@ unsafe impl<T: Component> WorldQuery for Without<T> {
194196
) {
195197
}
196198

197-
fn init_state(world: &mut World) -> ComponentId {
199+
fn init_state(_config: (), world: &mut World) -> ComponentId {
198200
world.init_component::<T>()
199201
}
200202

@@ -258,6 +260,7 @@ macro_rules! impl_query_filter_tuple {
258260
type Item<'w> = bool;
259261
type ReadOnly = Or<($($filter::ReadOnly,)*)>;
260262
type State = ($($filter::State,)*);
263+
type Config = ($($filter::Config,)*);
261264

262265
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> {
263266
item
@@ -361,8 +364,9 @@ macro_rules! impl_query_filter_tuple {
361364
$($filter::update_archetype_component_access($filter, archetype, access);)*
362365
}
363366

364-
fn init_state(world: &mut World) -> Self::State {
365-
($($filter::init_state(world),)*)
367+
fn init_state(config: Self::Config, world: &mut World) -> Self::State {
368+
let ($($state,)*) = config;
369+
($($filter::init_state($state, world),)*)
366370
}
367371

368372
fn matches_component_set(_state: &Self::State, _set_contains_id: &impl Fn(ComponentId) -> bool) -> bool {
@@ -406,6 +410,7 @@ macro_rules! impl_tick_filter {
406410
type Item<'w> = bool;
407411
type ReadOnly = Self;
408412
type State = ComponentId;
413+
type Config = ();
409414

410415
fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> {
411416
item
@@ -532,7 +537,7 @@ macro_rules! impl_tick_filter {
532537
}
533538
}
534539

535-
fn init_state(world: &mut World) -> ComponentId {
540+
fn init_state(_config: (), world: &mut World) -> ComponentId {
536541
world.init_component::<T>()
537542
}
538543

crates/bevy_ecs/src/query/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ mod tests {
114114
Q: ReadOnlyWorldQuery,
115115
F: ReadOnlyWorldQuery,
116116
F::ReadOnly: ArchetypeFilter,
117+
Q::Config: Default,
118+
F::Config: Default,
117119
{
118120
let mut query = world.query_filtered::<Q, F>();
119121
let query_type = type_name::<QueryCombinationIter<Q, F, K>>();
@@ -129,6 +131,8 @@ mod tests {
129131
Q: ReadOnlyWorldQuery,
130132
F: ReadOnlyWorldQuery,
131133
F::ReadOnly: ArchetypeFilter,
134+
Q::Config: Default,
135+
F::Config: Default,
132136
{
133137
let mut query = world.query_filtered::<Q, F>();
134138
let query_type = type_name::<QueryState<Q, F>>();

crates/bevy_ecs/src/query/state.rs

+21-4
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> std::fmt::Debug for QueryState<Q, F>
4949
}
5050
}
5151

52-
impl<Q: WorldQuery, F: ReadOnlyWorldQuery> FromWorld for QueryState<Q, F> {
52+
impl<Q: WorldQuery, F: ReadOnlyWorldQuery> FromWorld for QueryState<Q, F>
53+
where
54+
<Q as WorldQuery>::Config: Default,
55+
<F as WorldQuery>::Config: Default,
56+
{
5357
fn from_world(world: &mut World) -> Self {
5458
world.query_filtered()
5559
}
@@ -95,9 +99,22 @@ impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
9599

96100
impl<Q: WorldQuery, F: ReadOnlyWorldQuery> QueryState<Q, F> {
97101
/// Creates a new [`QueryState`] from a given [`World`] and inherits the result of `world.id()`.
98-
pub fn new(world: &mut World) -> Self {
99-
let fetch_state = Q::init_state(world);
100-
let filter_state = F::init_state(world);
102+
pub fn new(world: &mut World) -> Self
103+
where
104+
<Q as WorldQuery>::Config: Default,
105+
<F as WorldQuery>::Config: Default,
106+
{
107+
QueryState::new_with_config(world, Default::default(), Default::default())
108+
}
109+
110+
/// Creates a new [`QueryState`] from a given [`World`], config, and inherits the result of `world.id()`.
111+
pub fn new_with_config(
112+
world: &mut World,
113+
fetch_config: <Q as WorldQuery>::Config,
114+
filter_config: <F as WorldQuery>::Config,
115+
) -> Self {
116+
let fetch_state = Q::init_state(fetch_config, world);
117+
let filter_state = F::init_state(filter_config, world);
101118

102119
let mut component_access = FilteredAccess::default();
103120
Q::update_component_access(&fetch_state, &mut component_access);

crates/bevy_ecs/src/system/exclusive_system_param.rs

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ pub type ExclusiveSystemParamItem<'s, P> = <P as ExclusiveSystemParam>::Item<'s>
3131

3232
impl<'a, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> ExclusiveSystemParam
3333
for &'a mut QueryState<Q, F>
34+
where
35+
<Q as WorldQuery>::Config: Default,
36+
<F as WorldQuery>::Config: Default,
3437
{
3538
type State = QueryState<Q, F>;
3639
type Item<'s> = &'s mut QueryState<Q, F>;

0 commit comments

Comments
 (0)