Skip to content

Commit

Permalink
Migrate from Query::single and friends to Single (bevyengine#15872)
Browse files Browse the repository at this point in the history
# Objective

- closes bevyengine#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`.
  • Loading branch information
pablo-lua authored Oct 13, 2024
1 parent 3d6b248 commit d96a9d1
Show file tree
Hide file tree
Showing 83 changed files with 352 additions and 483 deletions.
4 changes: 2 additions & 2 deletions benches/benches/bevy_ecs/scheduling/run_condition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ pub fn run_condition_yes_with_query(criterion: &mut Criterion) {
group.warm_up_time(core::time::Duration::from_millis(500));
group.measurement_time(core::time::Duration::from_secs(3));
fn empty() {}
fn yes_with_query(query: Query<&TestBool>) -> bool {
query.single().0
fn yes_with_query(query: Single<&TestBool>) -> bool {
query.0
}
for amount in 0..21 {
let mut schedule = Schedule::default();
Expand Down
16 changes: 8 additions & 8 deletions crates/bevy_app/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -800,8 +800,8 @@ impl App {
/// commands.spawn(A);
/// }
///
/// fn validate(query: Query<(&A, &B, &C)>) {
/// let (a, b, c) = query.single();
/// fn validate(query: Option<Single<(&A, &B, &C)>>) {
/// let (a, b, c) = query.unwrap().into_inner();
/// assert_eq!(b, &B(0));
/// assert_eq!(c, &C(0));
/// }
Expand Down Expand Up @@ -863,8 +863,8 @@ impl App {
/// commands.spawn(A);
/// }
///
/// fn validate(query: Query<(&A, &B, &C)>) {
/// let (a, b, c) = query.single();
/// fn validate(query: Option<Single<(&A, &B, &C)>>) {
/// let (a, b, c) = query.unwrap().into_inner();
/// assert_eq!(b, &B(0));
/// assert_eq!(c, &C(2));
/// }
Expand Down Expand Up @@ -928,8 +928,8 @@ impl App {
/// commands.spawn(A);
/// }
///
/// fn validate(query: Query<(&A, &B, &C)>) {
/// let (a, b, c) = query.single();
/// fn validate(query: Option<Single<(&A, &B, &C)>>) {
/// let (a, b, c) = query.unwrap().into_inner();
/// assert_eq!(b, &B(0));
/// assert_eq!(c, &C(0));
/// }
Expand Down Expand Up @@ -993,8 +993,8 @@ impl App {
/// commands.spawn(A);
/// }
///
/// fn validate(query: Query<(&A, &B, &C)>) {
/// let (a, b, c) = query.single();
/// fn validate(query: Option<Single<(&A, &B, &C)>>) {
/// let (a, b, c) = query.unwrap().into_inner();
/// assert_eq!(b, &B(0));
/// assert_eq!(c, &C(2));
/// }
Expand Down
10 changes: 5 additions & 5 deletions crates/bevy_ecs/src/change_detection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1206,7 +1206,7 @@ mod tests {
Mut, NonSendMut, Ref, ResMut, TicksMut, CHECK_TICK_THRESHOLD, MAX_CHANGE_AGE,
},
component::{Component, ComponentTicks, Tick},
system::{IntoSystem, Query, System},
system::{IntoSystem, Single, System},
world::World,
};

Expand Down Expand Up @@ -1236,12 +1236,12 @@ mod tests {

#[test]
fn change_expiration() {
fn change_detected(query: Query<Ref<C>>) -> bool {
query.single().is_changed()
fn change_detected(query: Option<Single<Ref<C>>>) -> bool {
query.unwrap().is_changed()
}

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

let mut world = World::new();
Expand Down
26 changes: 15 additions & 11 deletions crates/bevy_ecs/src/system/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ mod tests {
},
system::{
Commands, In, IntoSystem, Local, NonSend, NonSendMut, ParamSet, Query, Res, ResMut,
Resource, StaticSystemParam, System, SystemState,
Resource, Single, StaticSystemParam, System, SystemState,
},
world::{EntityMut, FromWorld, World},
};
Expand Down Expand Up @@ -1157,12 +1157,15 @@ mod tests {
world.insert_resource(A(42));
world.spawn(B(7));

let mut system_state: SystemState<(Res<A>, Query<&B>, ParamSet<(Query<&C>, Query<&D>)>)> =
SystemState::new(&mut world);
let mut system_state: SystemState<(
Res<A>,
Option<Single<&B>>,
ParamSet<(Query<&C>, Query<&D>)>,
)> = SystemState::new(&mut world);
let (a, query, _) = system_state.get(&world);
assert_eq!(*a, A(42), "returned resource matches initial value");
assert_eq!(
*query.single(),
**query.unwrap(),
B(7),
"returned component matches initial value"
);
Expand All @@ -1180,16 +1183,16 @@ mod tests {
world.insert_resource(A(42));
world.spawn(B(7));

let mut system_state: SystemState<(ResMut<A>, Query<&mut B>)> =
let mut system_state: SystemState<(ResMut<A>, Option<Single<&mut B>>)> =
SystemState::new(&mut world);

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

let (a, mut query) = system_state.get_mut(&mut world);
let (a, query) = system_state.get_mut(&mut world);
assert_eq!(*a, A(42), "returned resource matches initial value");
assert_eq!(
*query.single_mut(),
**query.unwrap(),
B(7),
"returned component matches initial value"
);
Expand All @@ -1203,21 +1206,22 @@ mod tests {
let mut world = World::default();
let entity = world.spawn(A(1)).id();

let mut system_state: SystemState<Query<&A, Changed<A>>> = SystemState::new(&mut world);
let mut system_state: SystemState<Option<Single<&A, Changed<A>>>> =
SystemState::new(&mut world);
{
let query = system_state.get(&world);
assert_eq!(*query.single(), A(1));
assert_eq!(**query.unwrap(), A(1));
}

{
let query = system_state.get(&world);
assert!(query.get_single().is_err());
assert!(query.is_none());
}

world.entity_mut(entity).get_mut::<A>().unwrap().0 = 2;
{
let query = system_state.get(&world);
assert_eq!(*query.single(), A(2));
assert_eq!(**query.unwrap(), A(2));
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/system/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1384,7 +1384,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
/// * `&mut T` -> `&T`
/// * `&mut T` -> `Ref<T>`
/// * [`EntityMut`](crate::world::EntityMut) -> [`EntityRef`](crate::world::EntityRef)
///
///
/// [`EntityLocation`]: crate::entity::EntityLocation
/// [`&Archetype`]: crate::archetype::Archetype
#[track_caller]
Expand Down
5 changes: 2 additions & 3 deletions crates/bevy_ecs/src/system/system_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1214,18 +1214,17 @@ pub trait SystemBuffer: FromWorld + Send + 'static {
///
/// // Sound the alarm if there are any criminals who pose a threat.
/// fn alert_criminal(
/// settlements: Query<&Settlement>,
/// settlement: Single<&Settlement>,
/// criminals: Query<&Criminal>,
/// mut alarm: Deferred<AlarmFlag>
/// ) {
/// let settlement = settlements.single();
/// for criminal in &criminals {
/// // Only sound the alarm if the criminal is a threat.
/// // For this example, assume that this check is expensive to run.
/// // Since the majority of this system's run-time is dominated
/// // by calling `is_threat()`, we defer sounding the alarm to
/// // allow this system to run in parallel with other alarm systems.
/// if criminal.is_threat(settlement) {
/// if criminal.is_threat(*settlement) {
/// alarm.flag();
/// }
/// }
Expand Down
10 changes: 4 additions & 6 deletions crates/bevy_hierarchy/src/query_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,8 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> {
/// # use bevy_hierarchy::prelude::*;
/// # #[derive(Component)]
/// # struct Marker;
/// fn system(query: Query<Entity, With<Marker>>, children_query: Query<&Children>) {
/// let entity = query.single();
/// for descendant in children_query.iter_descendants(entity) {
/// fn system(entity: Single<Entity, With<Marker>>, children_query: Query<&Children>) {
/// for descendant in children_query.iter_descendants(*entity) {
/// // Do something!
/// }
/// }
Expand Down Expand Up @@ -95,9 +94,8 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> {
/// # use bevy_hierarchy::prelude::*;
/// # #[derive(Component)]
/// # struct Marker;
/// fn system(query: Query<Entity, With<Marker>>, parent_query: Query<&Parent>) {
/// let entity = query.single();
/// for ancestor in parent_query.iter_ancestors(entity) {
/// fn system(entity: Single<Entity, With<Marker>>, parent_query: Query<&Parent>) {
/// for ancestor in parent_query.iter_ancestors(*entity) {
/// // Do something!
/// }
/// }
Expand Down
4 changes: 2 additions & 2 deletions examples/2d/2d_viewport_to_world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ fn main() {
}

fn draw_cursor(
camera_query: Query<(&Camera, &GlobalTransform)>,
camera_query: Single<(&Camera, &GlobalTransform)>,
windows: Query<&Window>,
mut gizmos: Gizmos,
) {
let (camera, camera_transform) = camera_query.single();
let (camera, camera_transform) = *camera_query;

let Ok(window) = windows.get_single() else {
return;
Expand Down
11 changes: 5 additions & 6 deletions examples/2d/bloom_2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,18 +71,17 @@ fn setup(
// ------------------------------------------------------------------------------------------------

fn update_bloom_settings(
mut camera: Query<(Entity, Option<&mut Bloom>), With<Camera>>,
mut text: Query<&mut Text>,
camera: Single<(Entity, Option<&mut Bloom>), With<Camera>>,
mut text: Single<&mut Text>,
mut commands: Commands,
keycode: Res<ButtonInput<KeyCode>>,
time: Res<Time>,
) {
let bloom = camera.single_mut();
let mut text = text.single_mut();
let bloom = camera.into_inner();

match bloom {
(entity, Some(mut bloom)) => {
**text = "Bloom (Toggle: Space)\n".to_string();
text.0 = "Bloom (Toggle: Space)\n".to_string();
text.push_str(&format!("(Q/A) Intensity: {}\n", bloom.intensity));
text.push_str(&format!(
"(W/S) Low-frequency boost: {}\n",
Expand Down Expand Up @@ -173,7 +172,7 @@ fn update_bloom_settings(
}

(entity, None) => {
**text = "Bloom: Off (Toggle: Space)".to_string();
text.0 = "Bloom: Off (Toggle: Space)".to_string();

if keycode.just_pressed(KeyCode::Space) {
commands.entity(entity).insert(Bloom::default());
Expand Down
3 changes: 1 addition & 2 deletions examples/2d/bounding_2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,11 @@ fn update_test_state(
state.set(next);
}

fn update_text(mut text: Query<&mut Text>, cur_state: Res<State<Test>>) {
fn update_text(mut text: Single<&mut Text>, cur_state: Res<State<Test>>) {
if !cur_state.is_changed() {
return;
}

let mut text = text.single_mut();
text.clear();

text.push_str("Intersection test:\n");
Expand Down
3 changes: 1 addition & 2 deletions examples/2d/pixel_grid_snap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,11 @@ fn rotate(time: Res<Time>, mut transforms: Query<&mut Transform, With<Rotate>>)
/// Scales camera projection to fit the window (integer multiples only).
fn fit_canvas(
mut resize_events: EventReader<WindowResized>,
mut projections: Query<&mut OrthographicProjection, With<OuterCamera>>,
mut projection: Single<&mut OrthographicProjection, With<OuterCamera>>,
) {
for event in resize_events.read() {
let h_scale = event.width / RES_WIDTH as f32;
let v_scale = event.height / RES_HEIGHT as f32;
let mut projection = projections.single_mut();
projection.scaling_mode = ScalingMode::WindowSize(h_scale.min(v_scale).round());
}
}
10 changes: 4 additions & 6 deletions examples/2d/rotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
fn player_movement_system(
time: Res<Time>,
keyboard_input: Res<ButtonInput<KeyCode>>,
mut query: Query<(&Player, &mut Transform)>,
query: Single<(&Player, &mut Transform)>,
) {
let (ship, mut transform) = query.single_mut();
let (ship, mut transform) = query.into_inner();

let mut rotation_factor = 0.0;
let mut movement_factor = 0.0;
Expand Down Expand Up @@ -143,9 +143,8 @@ fn player_movement_system(
/// Demonstrates snapping the enemy ship to face the player ship immediately.
fn snap_to_player_system(
mut query: Query<&mut Transform, (With<SnapToPlayer>, Without<Player>)>,
player_query: Query<&Transform, With<Player>>,
player_transform: Single<&Transform, With<Player>>,
) {
let player_transform = player_query.single();
// get the player translation in 2D
let player_translation = player_transform.translation.xy();

Expand Down Expand Up @@ -186,9 +185,8 @@ fn snap_to_player_system(
fn rotate_to_player_system(
time: Res<Time>,
mut query: Query<(&RotateToPlayer, &mut Transform), Without<Player>>,
player_query: Query<&Transform, With<Player>>,
player_transform: Single<&Transform, With<Player>>,
) {
let player_transform = player_query.single();
// get the player translation in 2D
let player_translation = player_transform.translation.xy();

Expand Down
4 changes: 1 addition & 3 deletions examples/2d/sprite_animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ fn main() {
}

// This system runs when the user clicks the left arrow key or right arrow key
fn trigger_animation<S: Component>(mut query: Query<&mut AnimationConfig, With<S>>) {
// we expect the Component of type S to be used as a marker Component by only a single entity
let mut animation = query.single_mut();
fn trigger_animation<S: Component>(mut animation: Single<&mut AnimationConfig, With<S>>) {
// we create a new timer when the animation is triggered
animation.frame_timer = AnimationConfig::timer_from_fps(animation.fps);
}
Expand Down
4 changes: 2 additions & 2 deletions examples/2d/wireframe_2d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ fn update_colors(
keyboard_input: Res<ButtonInput<KeyCode>>,
mut config: ResMut<Wireframe2dConfig>,
mut wireframe_colors: Query<&mut Wireframe2dColor>,
mut text: Query<&mut Text>,
mut text: Single<&mut Text>,
) {
**text.single_mut() = format!(
text.0 = format!(
"Controls
---------------
Z - Toggle global
Expand Down
11 changes: 5 additions & 6 deletions examples/3d/3d_viewport_to_world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,14 @@ fn main() {
}

fn draw_cursor(
camera_query: Query<(&Camera, &GlobalTransform)>,
ground_query: Query<&GlobalTransform, With<Ground>>,
windows: Query<&Window>,
camera_query: Single<(&Camera, &GlobalTransform)>,
ground: Single<&GlobalTransform, With<Ground>>,
windows: Single<&Window>,
mut gizmos: Gizmos,
) {
let (camera, camera_transform) = camera_query.single();
let ground = ground_query.single();
let (camera, camera_transform) = *camera_query;

let Some(cursor_position) = windows.single().cursor_position() else {
let Some(cursor_position) = windows.cursor_position() else {
return;
};

Expand Down
Loading

0 comments on commit d96a9d1

Please sign in to comment.