simplify example, replace get_single to Single Query (#16187)

# Objective

clean up example get_single method, make code clean;

## Solution

- replace `Query`  with `Single` Query
- remove `get_single` or `get_single_mut` condition block
This commit is contained in:
ZoOL 2024-11-02 02:25:42 +08:00 committed by GitHub
parent 46566980a6
commit 17e504812b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 147 additions and 214 deletions

View file

@ -12,15 +12,11 @@ fn main() {
fn draw_cursor( fn draw_cursor(
camera_query: Single<(&Camera, &GlobalTransform)>, camera_query: Single<(&Camera, &GlobalTransform)>,
windows: Query<&Window>, window: Single<&Window>,
mut gizmos: Gizmos, mut gizmos: Gizmos,
) { ) {
let (camera, camera_transform) = *camera_query; let (camera, camera_transform) = *camera_query;
let Ok(window) = windows.get_single() else {
return;
};
let Some(cursor_position) = window.cursor_position() else { let Some(cursor_position) = window.cursor_position() else {
return; return;
}; };

View file

@ -253,13 +253,9 @@ fn move_camera_view(
// To ensure viewports remain the same at any window size // To ensure viewports remain the same at any window size
fn resize_viewports( fn resize_viewports(
windows: Query<&Window, With<bevy::window::PrimaryWindow>>, window: Single<&Window, With<bevy::window::PrimaryWindow>>,
mut viewports: Query<(&mut Camera, &ExampleViewports)>, mut viewports: Query<(&mut Camera, &ExampleViewports)>,
) { ) {
let Ok(window) = windows.get_single() else {
return;
};
let window_size = window.physical_size(); let window_size = window.physical_size();
let small_height = window_size.y / 5; let small_height = window_size.y / 5;

View file

@ -127,21 +127,17 @@ fn setup(
fn environment_map_load_finish( fn environment_map_load_finish(
mut commands: Commands, mut commands: Commands,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
environment_maps: Query<&EnvironmentMapLight>, environment_map: Single<&EnvironmentMapLight>,
label_query: Query<Entity, With<EnvironmentMapLabel>>, label_entity: Single<Entity, With<EnvironmentMapLabel>>,
) { ) {
if let Ok(environment_map) = environment_maps.get_single() { if asset_server
if asset_server .load_state(&environment_map.diffuse_map)
.load_state(&environment_map.diffuse_map) .is_loaded()
&& asset_server
.load_state(&environment_map.specular_map)
.is_loaded() .is_loaded()
&& asset_server {
.load_state(&environment_map.specular_map) commands.entity(*label_entity).despawn();
.is_loaded()
{
if let Ok(label_entity) = label_query.get_single() {
commands.entity(label_entity).despawn();
}
}
} }
} }

View file

@ -149,13 +149,11 @@ fn spawn_text(mut commands: Commands) {
fn alter_handle( fn alter_handle(
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
mut right_shape: Query<(&mut Mesh3d, &mut Shape), Without<Left>>, right_shape: Single<(&mut Mesh3d, &mut Shape), Without<Left>>,
) { ) {
// Mesh handles, like other parts of the ECS, can be queried as mutable and modified at // Mesh handles, like other parts of the ECS, can be queried as mutable and modified at
// runtime. We only spawned one shape without the `Left` marker component. // runtime. We only spawned one shape without the `Left` marker component.
let Ok((mut mesh, mut shape)) = right_shape.get_single_mut() else { let (mut mesh, mut shape) = right_shape.into_inner();
return;
};
// Switch to a new Shape variant // Switch to a new Shape variant
shape.set_next_variant(); shape.set_next_variant();
@ -174,17 +172,11 @@ fn alter_handle(
fn alter_mesh( fn alter_mesh(
mut is_mesh_scaled: Local<bool>, mut is_mesh_scaled: Local<bool>,
left_shape: Query<&Mesh3d, With<Left>>, left_shape: Single<&Mesh3d, With<Left>>,
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
) { ) {
// It's convenient to retrieve the asset handle stored with the shape on the left. However,
// we could just as easily have retained this in a resource or a dedicated component.
let Ok(handle) = left_shape.get_single() else {
return;
};
// Obtain a mutable reference to the Mesh asset. // Obtain a mutable reference to the Mesh asset.
let Some(mesh) = meshes.get_mut(handle) else { let Some(mesh) = meshes.get_mut(*left_shape) else {
return; return;
}; };

View file

@ -107,13 +107,11 @@ fn spawn_text(mut commands: Commands) {
fn alter_handle( fn alter_handle(
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
mut right_bird: Query<(&mut Bird, &mut Sprite), Without<Left>>, right_bird: Single<(&mut Bird, &mut Sprite), Without<Left>>,
) { ) {
// Image handles, like other parts of the ECS, can be queried as mutable and modified at // Image handles, like other parts of the ECS, can be queried as mutable and modified at
// runtime. We only spawned one bird without the `Left` marker component. // runtime. We only spawned one bird without the `Left` marker component.
let Ok((mut bird, mut sprite)) = right_bird.get_single_mut() else { let (mut bird, mut sprite) = right_bird.into_inner();
return;
};
// Switch to a new Bird variant // Switch to a new Bird variant
bird.set_next_variant(); bird.set_next_variant();
@ -124,15 +122,9 @@ fn alter_handle(
sprite.image = asset_server.load(bird.get_texture_path()); sprite.image = asset_server.load(bird.get_texture_path());
} }
fn alter_asset(mut images: ResMut<Assets<Image>>, left_bird: Query<&Sprite, With<Left>>) { fn alter_asset(mut images: ResMut<Assets<Image>>, left_bird: Single<&Sprite, With<Left>>) {
// It's convenient to retrieve the asset handle stored with the bird on the left. However,
// we could just as easily have retained this in a resource or a dedicated component.
let Ok(sprite) = left_bird.get_single() else {
return;
};
// Obtain a mutable reference to the Image asset. // Obtain a mutable reference to the Image asset.
let Some(image) = images.get_mut(&sprite.image) else { let Some(image) = images.get_mut(&left_bird.image) else {
return; return;
}; };

View file

@ -20,32 +20,20 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
#[derive(Component)] #[derive(Component)]
struct MyMusic; struct MyMusic;
fn update_speed(music_controller: Query<&AudioSink, With<MyMusic>>, time: Res<Time>) { fn update_speed(sink: Single<&AudioSink, With<MyMusic>>, time: Res<Time>) {
if let Ok(sink) = music_controller.get_single() { sink.set_speed((ops::sin(time.elapsed_secs() / 5.0) + 1.0).max(0.1));
sink.set_speed((ops::sin(time.elapsed_secs() / 5.0) + 1.0).max(0.1));
}
} }
fn pause( fn pause(keyboard_input: Res<ButtonInput<KeyCode>>, sink: Single<&AudioSink, With<MyMusic>>) {
keyboard_input: Res<ButtonInput<KeyCode>>,
music_controller: Query<&AudioSink, With<MyMusic>>,
) {
if keyboard_input.just_pressed(KeyCode::Space) { if keyboard_input.just_pressed(KeyCode::Space) {
if let Ok(sink) = music_controller.get_single() { sink.toggle();
sink.toggle();
}
} }
} }
fn volume( fn volume(keyboard_input: Res<ButtonInput<KeyCode>>, sink: Single<&AudioSink, With<MyMusic>>) {
keyboard_input: Res<ButtonInput<KeyCode>>, if keyboard_input.just_pressed(KeyCode::Equal) {
music_controller: Query<&AudioSink, With<MyMusic>>, sink.set_volume(sink.volume() + 0.1);
) { } else if keyboard_input.just_pressed(KeyCode::Minus) {
if let Ok(sink) = music_controller.get_single() { sink.set_volume(sink.volume() - 0.1);
if keyboard_input.just_pressed(KeyCode::Equal) {
sink.set_volume(sink.volume() + 0.1);
} else if keyboard_input.just_pressed(KeyCode::Minus) {
sink.set_volume(sink.volume() - 0.1);
}
} }
} }

View file

@ -73,18 +73,10 @@ fn setup_camera(mut commands: Commands) {
/// Update the camera position by tracking the player. /// Update the camera position by tracking the player.
fn update_camera( fn update_camera(
mut camera: Query<&mut Transform, (With<Camera2d>, Without<Player>)>, mut camera: Single<&mut Transform, (With<Camera2d>, Without<Player>)>,
player: Query<&Transform, (With<Player>, Without<Camera2d>)>, player: Single<&Transform, (With<Player>, Without<Camera2d>)>,
time: Res<Time>, time: Res<Time>,
) { ) {
let Ok(mut camera) = camera.get_single_mut() else {
return;
};
let Ok(player) = player.get_single() else {
return;
};
let Vec3 { x, y, .. } = player.translation; let Vec3 { x, y, .. } = player.translation;
let direction = Vec3::new(x, y, camera.translation.z); let direction = Vec3::new(x, y, camera.translation.z);
@ -101,14 +93,10 @@ fn update_camera(
/// ///
/// A more robust solution for player movement can be found in `examples/movement/physics_in_fixed_timestep.rs`. /// A more robust solution for player movement can be found in `examples/movement/physics_in_fixed_timestep.rs`.
fn move_player( fn move_player(
mut player: Query<&mut Transform, With<Player>>, mut player: Single<&mut Transform, With<Player>>,
time: Res<Time>, time: Res<Time>,
kb_input: Res<ButtonInput<KeyCode>>, kb_input: Res<ButtonInput<KeyCode>>,
) { ) {
let Ok(mut player) = player.get_single_mut() else {
return;
};
let mut direction = Vec2::ZERO; let mut direction = Vec2::ZERO;
if kb_input.pressed(KeyCode::KeyW) { if kb_input.pressed(KeyCode::KeyW) {

View file

@ -207,11 +207,10 @@ fn spawn_text(mut commands: Commands) {
fn move_player( fn move_player(
accumulated_mouse_motion: Res<AccumulatedMouseMotion>, accumulated_mouse_motion: Res<AccumulatedMouseMotion>,
mut player: Query<(&mut Transform, &CameraSensitivity), With<Player>>, player: Single<(&mut Transform, &CameraSensitivity), With<Player>>,
) { ) {
let Ok((mut transform, camera_sensitivity)) = player.get_single_mut() else { let (mut transform, camera_sensitivity) = player.into_inner();
return;
};
let delta = accumulated_mouse_motion.delta; let delta = accumulated_mouse_motion.delta;
if delta != Vec2::ZERO { if delta != Vec2::ZERO {
@ -242,12 +241,9 @@ fn move_player(
fn change_fov( fn change_fov(
input: Res<ButtonInput<KeyCode>>, input: Res<ButtonInput<KeyCode>>,
mut world_model_projection: Query<&mut Projection, With<WorldModelCamera>>, mut world_model_projection: Single<&mut Projection, With<WorldModelCamera>>,
) { ) {
let Ok(mut projection) = world_model_projection.get_single_mut() else { let Projection::Perspective(ref mut perspective) = world_model_projection.as_mut() else {
return;
};
let Projection::Perspective(ref mut perspective) = projection.as_mut() else {
unreachable!( unreachable!(
"The `Projection` component was explicitly built with `Projection::Perspective`" "The `Projection` component was explicitly built with `Projection::Perspective`"
); );

View file

@ -109,118 +109,117 @@ fn run_camera_controller(
key_input: Res<ButtonInput<KeyCode>>, key_input: Res<ButtonInput<KeyCode>>,
mut toggle_cursor_grab: Local<bool>, mut toggle_cursor_grab: Local<bool>,
mut mouse_cursor_grab: Local<bool>, mut mouse_cursor_grab: Local<bool>,
mut query: Query<(&mut Transform, &mut CameraController), With<Camera>>, query: Single<(&mut Transform, &mut CameraController), With<Camera>>,
) { ) {
let dt = time.delta_secs(); let dt = time.delta_secs();
if let Ok((mut transform, mut controller)) = query.get_single_mut() { let (mut transform, mut controller) = query.into_inner();
if !controller.initialized {
let (yaw, pitch, _roll) = transform.rotation.to_euler(EulerRot::YXZ);
controller.yaw = yaw;
controller.pitch = pitch;
controller.initialized = true;
info!("{}", *controller);
}
if !controller.enabled {
return;
}
let mut scroll = 0.0; if !controller.initialized {
let (yaw, pitch, _roll) = transform.rotation.to_euler(EulerRot::YXZ);
controller.yaw = yaw;
controller.pitch = pitch;
controller.initialized = true;
info!("{}", *controller);
}
if !controller.enabled {
return;
}
let amount = match accumulated_mouse_scroll.unit { let mut scroll = 0.0;
MouseScrollUnit::Line => accumulated_mouse_scroll.delta.y,
MouseScrollUnit::Pixel => accumulated_mouse_scroll.delta.y / 16.0,
};
scroll += amount;
controller.walk_speed += scroll * controller.scroll_factor * controller.walk_speed;
controller.run_speed = controller.walk_speed * 3.0;
// Handle key input let amount = match accumulated_mouse_scroll.unit {
let mut axis_input = Vec3::ZERO; MouseScrollUnit::Line => accumulated_mouse_scroll.delta.y,
if key_input.pressed(controller.key_forward) { MouseScrollUnit::Pixel => accumulated_mouse_scroll.delta.y / 16.0,
axis_input.z += 1.0; };
} scroll += amount;
if key_input.pressed(controller.key_back) { controller.walk_speed += scroll * controller.scroll_factor * controller.walk_speed;
axis_input.z -= 1.0; controller.run_speed = controller.walk_speed * 3.0;
}
if key_input.pressed(controller.key_right) {
axis_input.x += 1.0;
}
if key_input.pressed(controller.key_left) {
axis_input.x -= 1.0;
}
if key_input.pressed(controller.key_up) {
axis_input.y += 1.0;
}
if key_input.pressed(controller.key_down) {
axis_input.y -= 1.0;
}
let mut cursor_grab_change = false; // Handle key input
if key_input.just_pressed(controller.keyboard_key_toggle_cursor_grab) { let mut axis_input = Vec3::ZERO;
*toggle_cursor_grab = !*toggle_cursor_grab; if key_input.pressed(controller.key_forward) {
cursor_grab_change = true; axis_input.z += 1.0;
} }
if mouse_button_input.just_pressed(controller.mouse_key_cursor_grab) { if key_input.pressed(controller.key_back) {
*mouse_cursor_grab = true; axis_input.z -= 1.0;
cursor_grab_change = true; }
} if key_input.pressed(controller.key_right) {
if mouse_button_input.just_released(controller.mouse_key_cursor_grab) { axis_input.x += 1.0;
*mouse_cursor_grab = false; }
cursor_grab_change = true; if key_input.pressed(controller.key_left) {
} axis_input.x -= 1.0;
let cursor_grab = *mouse_cursor_grab || *toggle_cursor_grab; }
if key_input.pressed(controller.key_up) {
axis_input.y += 1.0;
}
if key_input.pressed(controller.key_down) {
axis_input.y -= 1.0;
}
// Apply movement update let mut cursor_grab_change = false;
if axis_input != Vec3::ZERO { if key_input.just_pressed(controller.keyboard_key_toggle_cursor_grab) {
let max_speed = if key_input.pressed(controller.key_run) { *toggle_cursor_grab = !*toggle_cursor_grab;
controller.run_speed cursor_grab_change = true;
} else { }
controller.walk_speed if mouse_button_input.just_pressed(controller.mouse_key_cursor_grab) {
}; *mouse_cursor_grab = true;
controller.velocity = axis_input.normalize() * max_speed; cursor_grab_change = true;
}
if mouse_button_input.just_released(controller.mouse_key_cursor_grab) {
*mouse_cursor_grab = false;
cursor_grab_change = true;
}
let cursor_grab = *mouse_cursor_grab || *toggle_cursor_grab;
// Apply movement update
if axis_input != Vec3::ZERO {
let max_speed = if key_input.pressed(controller.key_run) {
controller.run_speed
} else { } else {
let friction = controller.friction.clamp(0.0, 1.0); controller.walk_speed
controller.velocity *= 1.0 - friction; };
if controller.velocity.length_squared() < 1e-6 { controller.velocity = axis_input.normalize() * max_speed;
controller.velocity = Vec3::ZERO; } else {
} let friction = controller.friction.clamp(0.0, 1.0);
} controller.velocity *= 1.0 - friction;
let forward = *transform.forward(); if controller.velocity.length_squared() < 1e-6 {
let right = *transform.right(); controller.velocity = Vec3::ZERO;
transform.translation += controller.velocity.x * dt * right
+ controller.velocity.y * dt * Vec3::Y
+ controller.velocity.z * dt * forward;
// Handle cursor grab
if cursor_grab_change {
if cursor_grab {
for mut window in &mut windows {
if !window.focused {
continue;
}
window.cursor_options.grab_mode = CursorGrabMode::Locked;
window.cursor_options.visible = false;
}
} else {
for mut window in &mut windows {
window.cursor_options.grab_mode = CursorGrabMode::None;
window.cursor_options.visible = true;
}
}
}
// Handle mouse input
if accumulated_mouse_motion.delta != Vec2::ZERO && cursor_grab {
// Apply look update
controller.pitch = (controller.pitch
- accumulated_mouse_motion.delta.y * RADIANS_PER_DOT * controller.sensitivity)
.clamp(-PI / 2., PI / 2.);
controller.yaw -=
accumulated_mouse_motion.delta.x * RADIANS_PER_DOT * controller.sensitivity;
transform.rotation =
Quat::from_euler(EulerRot::ZYX, 0.0, controller.yaw, controller.pitch);
} }
} }
let forward = *transform.forward();
let right = *transform.right();
transform.translation += controller.velocity.x * dt * right
+ controller.velocity.y * dt * Vec3::Y
+ controller.velocity.z * dt * forward;
// Handle cursor grab
if cursor_grab_change {
if cursor_grab {
for mut window in &mut windows {
if !window.focused {
continue;
}
window.cursor_options.grab_mode = CursorGrabMode::Locked;
window.cursor_options.visible = false;
}
} else {
for mut window in &mut windows {
window.cursor_options.grab_mode = CursorGrabMode::None;
window.cursor_options.visible = true;
}
}
}
// Handle mouse input
if accumulated_mouse_motion.delta != Vec2::ZERO && cursor_grab {
// Apply look update
controller.pitch = (controller.pitch
- accumulated_mouse_motion.delta.y * RADIANS_PER_DOT * controller.sensitivity)
.clamp(-PI / 2., PI / 2.);
controller.yaw -=
accumulated_mouse_motion.delta.x * RADIANS_PER_DOT * controller.sensitivity;
transform.rotation = Quat::from_euler(EulerRot::ZYX, 0.0, controller.yaw, controller.pitch);
}
} }

View file

@ -308,7 +308,7 @@ fn handle_mouse_press(
mouse_position: Res<MousePosition>, mouse_position: Res<MousePosition>,
mut edit_move: ResMut<MouseEditMove>, mut edit_move: ResMut<MouseEditMove>,
mut control_points: ResMut<ControlPoints>, mut control_points: ResMut<ControlPoints>,
camera: Query<(&Camera, &GlobalTransform)>, camera: Single<(&Camera, &GlobalTransform)>,
) { ) {
let Some(mouse_pos) = mouse_position.0 else { let Some(mouse_pos) = mouse_position.0 else {
return; return;
@ -336,9 +336,7 @@ fn handle_mouse_press(
continue; continue;
}; };
let Ok((camera, camera_transform)) = camera.get_single() else { let (camera, camera_transform) = *camera;
continue;
};
// Convert the starting point and end point (current mouse pos) into world coords: // Convert the starting point and end point (current mouse pos) into world coords:
let Ok(point) = camera.viewport_to_world_2d(camera_transform, start) else { let Ok(point) = camera.viewport_to_world_2d(camera_transform, start) else {
@ -365,7 +363,7 @@ fn draw_edit_move(
edit_move: Res<MouseEditMove>, edit_move: Res<MouseEditMove>,
mouse_position: Res<MousePosition>, mouse_position: Res<MousePosition>,
mut gizmos: Gizmos, mut gizmos: Gizmos,
camera: Query<(&Camera, &GlobalTransform)>, camera: Single<(&Camera, &GlobalTransform)>,
) { ) {
let Some(start) = edit_move.start else { let Some(start) = edit_move.start else {
return; return;
@ -373,9 +371,8 @@ fn draw_edit_move(
let Some(mouse_pos) = mouse_position.0 else { let Some(mouse_pos) = mouse_position.0 else {
return; return;
}; };
let Ok((camera, camera_transform)) = camera.get_single() else {
return; let (camera, camera_transform) = *camera;
};
// Resources store data in viewport coordinates, so we need to convert to world coordinates // Resources store data in viewport coordinates, so we need to convert to world coordinates
// to display them: // to display them:

View file

@ -171,12 +171,8 @@ fn setup_music(asset_server: Res<AssetServer>, mut commands: Commands) {
// This is handled by the OS on iOS, but not on Android. // This is handled by the OS on iOS, but not on Android.
fn handle_lifetime( fn handle_lifetime(
mut lifecycle_events: EventReader<AppLifecycle>, mut lifecycle_events: EventReader<AppLifecycle>,
music_controller: Query<&AudioSink>, music_controller: Single<&AudioSink>,
) { ) {
let Ok(music_controller) = music_controller.get_single() else {
return;
};
for event in lifecycle_events.read() { for event in lifecycle_events.read() {
match event { match event {
AppLifecycle::Idle | AppLifecycle::WillSuspend | AppLifecycle::WillResume => {} AppLifecycle::Idle | AppLifecycle::WillSuspend | AppLifecycle::WillResume => {}

View file

@ -32,18 +32,15 @@ fn screenshot_on_spacebar(
fn screenshot_saving( fn screenshot_saving(
mut commands: Commands, mut commands: Commands,
screenshot_saving: Query<Entity, With<Capturing>>, screenshot_saving: Query<Entity, With<Capturing>>,
windows: Query<Entity, With<Window>>, window: Single<Entity, With<Window>>,
) { ) {
let Ok(window) = windows.get_single() else {
return;
};
match screenshot_saving.iter().count() { match screenshot_saving.iter().count() {
0 => { 0 => {
commands.entity(window).remove::<CursorIcon>(); commands.entity(*window).remove::<CursorIcon>();
} }
x if x > 0 => { x if x > 0 => {
commands commands
.entity(window) .entity(*window)
.insert(CursorIcon::from(SystemCursorIcon::Progress)); .insert(CursorIcon::from(SystemCursorIcon::Progress));
} }
_ => {} _ => {}