Skip to content

Commit d96a9d1

Browse files
authored
Migrate from Query::single and friends to Single (#15872)
# Objective - closes #15866 ## Solution - Simply migrate where possible. ## Testing - Expect that CI will do most of the work. Examples is another way of testing this, as most of the work is in that area. --- ## Notes For now, this PR doesn't migrate `QueryState::single` and friends as for now, this look like another issue. So for example, QueryBuilders that used single or `World::query` that used single wasn't migrated. If there is a easy way to migrate those, please let me know. Most of the uses of `Query::single` were removed, the only other uses that I found was related to tests of said methods, so will probably be removed when we remove `Query::single`.
1 parent 3d6b248 commit d96a9d1

File tree

83 files changed

+352
-483
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+352
-483
lines changed

benches/benches/bevy_ecs/scheduling/run_condition.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ pub fn run_condition_yes_with_query(criterion: &mut Criterion) {
6767
group.warm_up_time(core::time::Duration::from_millis(500));
6868
group.measurement_time(core::time::Duration::from_secs(3));
6969
fn empty() {}
70-
fn yes_with_query(query: Query<&TestBool>) -> bool {
71-
query.single().0
70+
fn yes_with_query(query: Single<&TestBool>) -> bool {
71+
query.0
7272
}
7373
for amount in 0..21 {
7474
let mut schedule = Schedule::default();

crates/bevy_app/src/app.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -800,8 +800,8 @@ impl App {
800800
/// commands.spawn(A);
801801
/// }
802802
///
803-
/// fn validate(query: Query<(&A, &B, &C)>) {
804-
/// let (a, b, c) = query.single();
803+
/// fn validate(query: Option<Single<(&A, &B, &C)>>) {
804+
/// let (a, b, c) = query.unwrap().into_inner();
805805
/// assert_eq!(b, &B(0));
806806
/// assert_eq!(c, &C(0));
807807
/// }
@@ -863,8 +863,8 @@ impl App {
863863
/// commands.spawn(A);
864864
/// }
865865
///
866-
/// fn validate(query: Query<(&A, &B, &C)>) {
867-
/// let (a, b, c) = query.single();
866+
/// fn validate(query: Option<Single<(&A, &B, &C)>>) {
867+
/// let (a, b, c) = query.unwrap().into_inner();
868868
/// assert_eq!(b, &B(0));
869869
/// assert_eq!(c, &C(2));
870870
/// }
@@ -928,8 +928,8 @@ impl App {
928928
/// commands.spawn(A);
929929
/// }
930930
///
931-
/// fn validate(query: Query<(&A, &B, &C)>) {
932-
/// let (a, b, c) = query.single();
931+
/// fn validate(query: Option<Single<(&A, &B, &C)>>) {
932+
/// let (a, b, c) = query.unwrap().into_inner();
933933
/// assert_eq!(b, &B(0));
934934
/// assert_eq!(c, &C(0));
935935
/// }
@@ -993,8 +993,8 @@ impl App {
993993
/// commands.spawn(A);
994994
/// }
995995
///
996-
/// fn validate(query: Query<(&A, &B, &C)>) {
997-
/// let (a, b, c) = query.single();
996+
/// fn validate(query: Option<Single<(&A, &B, &C)>>) {
997+
/// let (a, b, c) = query.unwrap().into_inner();
998998
/// assert_eq!(b, &B(0));
999999
/// assert_eq!(c, &C(2));
10001000
/// }

crates/bevy_ecs/src/change_detection.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,7 @@ mod tests {
12061206
Mut, NonSendMut, Ref, ResMut, TicksMut, CHECK_TICK_THRESHOLD, MAX_CHANGE_AGE,
12071207
},
12081208
component::{Component, ComponentTicks, Tick},
1209-
system::{IntoSystem, Query, System},
1209+
system::{IntoSystem, Single, System},
12101210
world::World,
12111211
};
12121212

@@ -1236,12 +1236,12 @@ mod tests {
12361236

12371237
#[test]
12381238
fn change_expiration() {
1239-
fn change_detected(query: Query<Ref<C>>) -> bool {
1240-
query.single().is_changed()
1239+
fn change_detected(query: Option<Single<Ref<C>>>) -> bool {
1240+
query.unwrap().is_changed()
12411241
}
12421242

1243-
fn change_expired(query: Query<Ref<C>>) -> bool {
1244-
query.single().is_changed()
1243+
fn change_expired(query: Option<Single<Ref<C>>>) -> bool {
1244+
query.unwrap().is_changed()
12451245
}
12461246

12471247
let mut world = World::new();

crates/bevy_ecs/src/system/mod.rs

+15-11
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ mod tests {
328328
},
329329
system::{
330330
Commands, In, IntoSystem, Local, NonSend, NonSendMut, ParamSet, Query, Res, ResMut,
331-
Resource, StaticSystemParam, System, SystemState,
331+
Resource, Single, StaticSystemParam, System, SystemState,
332332
},
333333
world::{EntityMut, FromWorld, World},
334334
};
@@ -1157,12 +1157,15 @@ mod tests {
11571157
world.insert_resource(A(42));
11581158
world.spawn(B(7));
11591159

1160-
let mut system_state: SystemState<(Res<A>, Query<&B>, ParamSet<(Query<&C>, Query<&D>)>)> =
1161-
SystemState::new(&mut world);
1160+
let mut system_state: SystemState<(
1161+
Res<A>,
1162+
Option<Single<&B>>,
1163+
ParamSet<(Query<&C>, Query<&D>)>,
1164+
)> = SystemState::new(&mut world);
11621165
let (a, query, _) = system_state.get(&world);
11631166
assert_eq!(*a, A(42), "returned resource matches initial value");
11641167
assert_eq!(
1165-
*query.single(),
1168+
**query.unwrap(),
11661169
B(7),
11671170
"returned component matches initial value"
11681171
);
@@ -1180,16 +1183,16 @@ mod tests {
11801183
world.insert_resource(A(42));
11811184
world.spawn(B(7));
11821185

1183-
let mut system_state: SystemState<(ResMut<A>, Query<&mut B>)> =
1186+
let mut system_state: SystemState<(ResMut<A>, Option<Single<&mut B>>)> =
11841187
SystemState::new(&mut world);
11851188

11861189
// The following line shouldn't compile because the parameters used are not ReadOnlySystemParam
11871190
// let (a, query) = system_state.get(&world);
11881191

1189-
let (a, mut query) = system_state.get_mut(&mut world);
1192+
let (a, query) = system_state.get_mut(&mut world);
11901193
assert_eq!(*a, A(42), "returned resource matches initial value");
11911194
assert_eq!(
1192-
*query.single_mut(),
1195+
**query.unwrap(),
11931196
B(7),
11941197
"returned component matches initial value"
11951198
);
@@ -1203,21 +1206,22 @@ mod tests {
12031206
let mut world = World::default();
12041207
let entity = world.spawn(A(1)).id();
12051208

1206-
let mut system_state: SystemState<Query<&A, Changed<A>>> = SystemState::new(&mut world);
1209+
let mut system_state: SystemState<Option<Single<&A, Changed<A>>>> =
1210+
SystemState::new(&mut world);
12071211
{
12081212
let query = system_state.get(&world);
1209-
assert_eq!(*query.single(), A(1));
1213+
assert_eq!(**query.unwrap(), A(1));
12101214
}
12111215

12121216
{
12131217
let query = system_state.get(&world);
1214-
assert!(query.get_single().is_err());
1218+
assert!(query.is_none());
12151219
}
12161220

12171221
world.entity_mut(entity).get_mut::<A>().unwrap().0 = 2;
12181222
{
12191223
let query = system_state.get(&world);
1220-
assert_eq!(*query.single(), A(2));
1224+
assert_eq!(**query.unwrap(), A(2));
12211225
}
12221226
}
12231227

crates/bevy_ecs/src/system/query.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1384,7 +1384,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
13841384
/// * `&mut T` -> `&T`
13851385
/// * `&mut T` -> `Ref<T>`
13861386
/// * [`EntityMut`](crate::world::EntityMut) -> [`EntityRef`](crate::world::EntityRef)
1387-
///
1387+
///
13881388
/// [`EntityLocation`]: crate::entity::EntityLocation
13891389
/// [`&Archetype`]: crate::archetype::Archetype
13901390
#[track_caller]

crates/bevy_ecs/src/system/system_param.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1214,18 +1214,17 @@ pub trait SystemBuffer: FromWorld + Send + 'static {
12141214
///
12151215
/// // Sound the alarm if there are any criminals who pose a threat.
12161216
/// fn alert_criminal(
1217-
/// settlements: Query<&Settlement>,
1217+
/// settlement: Single<&Settlement>,
12181218
/// criminals: Query<&Criminal>,
12191219
/// mut alarm: Deferred<AlarmFlag>
12201220
/// ) {
1221-
/// let settlement = settlements.single();
12221221
/// for criminal in &criminals {
12231222
/// // Only sound the alarm if the criminal is a threat.
12241223
/// // For this example, assume that this check is expensive to run.
12251224
/// // Since the majority of this system's run-time is dominated
12261225
/// // by calling `is_threat()`, we defer sounding the alarm to
12271226
/// // allow this system to run in parallel with other alarm systems.
1228-
/// if criminal.is_threat(settlement) {
1227+
/// if criminal.is_threat(*settlement) {
12291228
/// alarm.flag();
12301229
/// }
12311230
/// }

crates/bevy_hierarchy/src/query_extension.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,8 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> {
6060
/// # use bevy_hierarchy::prelude::*;
6161
/// # #[derive(Component)]
6262
/// # struct Marker;
63-
/// fn system(query: Query<Entity, With<Marker>>, children_query: Query<&Children>) {
64-
/// let entity = query.single();
65-
/// for descendant in children_query.iter_descendants(entity) {
63+
/// fn system(entity: Single<Entity, With<Marker>>, children_query: Query<&Children>) {
64+
/// for descendant in children_query.iter_descendants(*entity) {
6665
/// // Do something!
6766
/// }
6867
/// }
@@ -95,9 +94,8 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> {
9594
/// # use bevy_hierarchy::prelude::*;
9695
/// # #[derive(Component)]
9796
/// # struct Marker;
98-
/// fn system(query: Query<Entity, With<Marker>>, parent_query: Query<&Parent>) {
99-
/// let entity = query.single();
100-
/// for ancestor in parent_query.iter_ancestors(entity) {
97+
/// fn system(entity: Single<Entity, With<Marker>>, parent_query: Query<&Parent>) {
98+
/// for ancestor in parent_query.iter_ancestors(*entity) {
10199
/// // Do something!
102100
/// }
103101
/// }

examples/2d/2d_viewport_to_world.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ fn main() {
1111
}
1212

1313
fn draw_cursor(
14-
camera_query: Query<(&Camera, &GlobalTransform)>,
14+
camera_query: Single<(&Camera, &GlobalTransform)>,
1515
windows: Query<&Window>,
1616
mut gizmos: Gizmos,
1717
) {
18-
let (camera, camera_transform) = camera_query.single();
18+
let (camera, camera_transform) = *camera_query;
1919

2020
let Ok(window) = windows.get_single() else {
2121
return;

examples/2d/bloom_2d.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,17 @@ fn setup(
7171
// ------------------------------------------------------------------------------------------------
7272

7373
fn update_bloom_settings(
74-
mut camera: Query<(Entity, Option<&mut Bloom>), With<Camera>>,
75-
mut text: Query<&mut Text>,
74+
camera: Single<(Entity, Option<&mut Bloom>), With<Camera>>,
75+
mut text: Single<&mut Text>,
7676
mut commands: Commands,
7777
keycode: Res<ButtonInput<KeyCode>>,
7878
time: Res<Time>,
7979
) {
80-
let bloom = camera.single_mut();
81-
let mut text = text.single_mut();
80+
let bloom = camera.into_inner();
8281

8382
match bloom {
8483
(entity, Some(mut bloom)) => {
85-
**text = "Bloom (Toggle: Space)\n".to_string();
84+
text.0 = "Bloom (Toggle: Space)\n".to_string();
8685
text.push_str(&format!("(Q/A) Intensity: {}\n", bloom.intensity));
8786
text.push_str(&format!(
8887
"(W/S) Low-frequency boost: {}\n",
@@ -173,7 +172,7 @@ fn update_bloom_settings(
173172
}
174173

175174
(entity, None) => {
176-
**text = "Bloom: Off (Toggle: Space)".to_string();
175+
text.0 = "Bloom: Off (Toggle: Space)".to_string();
177176

178177
if keycode.just_pressed(KeyCode::Space) {
179178
commands.entity(entity).insert(Bloom::default());

examples/2d/bounding_2d.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,11 @@ fn update_test_state(
7272
state.set(next);
7373
}
7474

75-
fn update_text(mut text: Query<&mut Text>, cur_state: Res<State<Test>>) {
75+
fn update_text(mut text: Single<&mut Text>, cur_state: Res<State<Test>>) {
7676
if !cur_state.is_changed() {
7777
return;
7878
}
7979

80-
let mut text = text.single_mut();
8180
text.clear();
8281

8382
text.push_str("Intersection test:\n");

examples/2d/pixel_grid_snap.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,11 @@ fn rotate(time: Res<Time>, mut transforms: Query<&mut Transform, With<Rotate>>)
144144
/// Scales camera projection to fit the window (integer multiples only).
145145
fn fit_canvas(
146146
mut resize_events: EventReader<WindowResized>,
147-
mut projections: Query<&mut OrthographicProjection, With<OuterCamera>>,
147+
mut projection: Single<&mut OrthographicProjection, With<OuterCamera>>,
148148
) {
149149
for event in resize_events.read() {
150150
let h_scale = event.width / RES_WIDTH as f32;
151151
let v_scale = event.height / RES_HEIGHT as f32;
152-
let mut projection = projections.single_mut();
153152
projection.scaling_mode = ScalingMode::WindowSize(h_scale.min(v_scale).round());
154153
}
155154
}

examples/2d/rotation.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
102102
fn player_movement_system(
103103
time: Res<Time>,
104104
keyboard_input: Res<ButtonInput<KeyCode>>,
105-
mut query: Query<(&Player, &mut Transform)>,
105+
query: Single<(&Player, &mut Transform)>,
106106
) {
107-
let (ship, mut transform) = query.single_mut();
107+
let (ship, mut transform) = query.into_inner();
108108

109109
let mut rotation_factor = 0.0;
110110
let mut movement_factor = 0.0;
@@ -143,9 +143,8 @@ fn player_movement_system(
143143
/// Demonstrates snapping the enemy ship to face the player ship immediately.
144144
fn snap_to_player_system(
145145
mut query: Query<&mut Transform, (With<SnapToPlayer>, Without<Player>)>,
146-
player_query: Query<&Transform, With<Player>>,
146+
player_transform: Single<&Transform, With<Player>>,
147147
) {
148-
let player_transform = player_query.single();
149148
// get the player translation in 2D
150149
let player_translation = player_transform.translation.xy();
151150

@@ -186,9 +185,8 @@ fn snap_to_player_system(
186185
fn rotate_to_player_system(
187186
time: Res<Time>,
188187
mut query: Query<(&RotateToPlayer, &mut Transform), Without<Player>>,
189-
player_query: Query<&Transform, With<Player>>,
188+
player_transform: Single<&Transform, With<Player>>,
190189
) {
191-
let player_transform = player_query.single();
192190
// get the player translation in 2D
193191
let player_translation = player_transform.translation.xy();
194192

examples/2d/sprite_animation.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ fn main() {
2424
}
2525

2626
// This system runs when the user clicks the left arrow key or right arrow key
27-
fn trigger_animation<S: Component>(mut query: Query<&mut AnimationConfig, With<S>>) {
28-
// we expect the Component of type S to be used as a marker Component by only a single entity
29-
let mut animation = query.single_mut();
27+
fn trigger_animation<S: Component>(mut animation: Single<&mut AnimationConfig, With<S>>) {
3028
// we create a new timer when the animation is triggered
3129
animation.frame_timer = AnimationConfig::timer_from_fps(animation.fps);
3230
}

examples/2d/wireframe_2d.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@ fn update_colors(
104104
keyboard_input: Res<ButtonInput<KeyCode>>,
105105
mut config: ResMut<Wireframe2dConfig>,
106106
mut wireframe_colors: Query<&mut Wireframe2dColor>,
107-
mut text: Query<&mut Text>,
107+
mut text: Single<&mut Text>,
108108
) {
109-
**text.single_mut() = format!(
109+
text.0 = format!(
110110
"Controls
111111
---------------
112112
Z - Toggle global

examples/3d/3d_viewport_to_world.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ fn main() {
1111
}
1212

1313
fn draw_cursor(
14-
camera_query: Query<(&Camera, &GlobalTransform)>,
15-
ground_query: Query<&GlobalTransform, With<Ground>>,
16-
windows: Query<&Window>,
14+
camera_query: Single<(&Camera, &GlobalTransform)>,
15+
ground: Single<&GlobalTransform, With<Ground>>,
16+
windows: Single<&Window>,
1717
mut gizmos: Gizmos,
1818
) {
19-
let (camera, camera_transform) = camera_query.single();
20-
let ground = ground_query.single();
19+
let (camera, camera_transform) = *camera_query;
2120

22-
let Some(cursor_position) = windows.single().cursor_position() else {
21+
let Some(cursor_position) = windows.cursor_position() else {
2322
return;
2423
};
2524

0 commit comments

Comments
 (0)