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(
camera_query: Single<(&Camera, &GlobalTransform)>,
windows: Query<&Window>,
window: Single<&Window>,
mut gizmos: Gizmos,
) {
let (camera, camera_transform) = *camera_query;
let Ok(window) = windows.get_single() else {
return;
};
let Some(cursor_position) = window.cursor_position() else {
return;
};

View file

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

View file

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

View file

@ -149,13 +149,11 @@ fn spawn_text(mut commands: Commands) {
fn alter_handle(
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
// runtime. We only spawned one shape without the `Left` marker component.
let Ok((mut mesh, mut shape)) = right_shape.get_single_mut() else {
return;
};
let (mut mesh, mut shape) = right_shape.into_inner();
// Switch to a new Shape variant
shape.set_next_variant();
@ -174,17 +172,11 @@ fn alter_handle(
fn alter_mesh(
mut is_mesh_scaled: Local<bool>,
left_shape: Query<&Mesh3d, With<Left>>,
left_shape: Single<&Mesh3d, With<Left>>,
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.
let Some(mesh) = meshes.get_mut(handle) else {
let Some(mesh) = meshes.get_mut(*left_shape) else {
return;
};

View file

@ -107,13 +107,11 @@ fn spawn_text(mut commands: Commands) {
fn alter_handle(
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
// runtime. We only spawned one bird without the `Left` marker component.
let Ok((mut bird, mut sprite)) = right_bird.get_single_mut() else {
return;
};
let (mut bird, mut sprite) = right_bird.into_inner();
// Switch to a new Bird variant
bird.set_next_variant();
@ -124,15 +122,9 @@ fn alter_handle(
sprite.image = asset_server.load(bird.get_texture_path());
}
fn alter_asset(mut images: ResMut<Assets<Image>>, left_bird: Query<&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;
};
fn alter_asset(mut images: ResMut<Assets<Image>>, left_bird: Single<&Sprite, With<Left>>) {
// 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;
};

View file

@ -20,32 +20,20 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
#[derive(Component)]
struct MyMusic;
fn update_speed(music_controller: Query<&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));
}
fn update_speed(sink: Single<&AudioSink, With<MyMusic>>, time: Res<Time>) {
sink.set_speed((ops::sin(time.elapsed_secs() / 5.0) + 1.0).max(0.1));
}
fn pause(
keyboard_input: Res<ButtonInput<KeyCode>>,
music_controller: Query<&AudioSink, With<MyMusic>>,
) {
fn pause(keyboard_input: Res<ButtonInput<KeyCode>>, sink: Single<&AudioSink, With<MyMusic>>) {
if keyboard_input.just_pressed(KeyCode::Space) {
if let Ok(sink) = music_controller.get_single() {
sink.toggle();
}
sink.toggle();
}
}
fn volume(
keyboard_input: Res<ButtonInput<KeyCode>>,
music_controller: Query<&AudioSink, With<MyMusic>>,
) {
if let Ok(sink) = music_controller.get_single() {
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);
}
fn volume(keyboard_input: Res<ButtonInput<KeyCode>>, sink: Single<&AudioSink, With<MyMusic>>) {
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.
fn update_camera(
mut camera: Query<&mut Transform, (With<Camera2d>, Without<Player>)>,
player: Query<&Transform, (With<Player>, Without<Camera2d>)>,
mut camera: Single<&mut Transform, (With<Camera2d>, Without<Player>)>,
player: Single<&Transform, (With<Player>, Without<Camera2d>)>,
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 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`.
fn move_player(
mut player: Query<&mut Transform, With<Player>>,
mut player: Single<&mut Transform, With<Player>>,
time: Res<Time>,
kb_input: Res<ButtonInput<KeyCode>>,
) {
let Ok(mut player) = player.get_single_mut() else {
return;
};
let mut direction = Vec2::ZERO;
if kb_input.pressed(KeyCode::KeyW) {

View file

@ -207,11 +207,10 @@ fn spawn_text(mut commands: Commands) {
fn move_player(
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 {
return;
};
let (mut transform, camera_sensitivity) = player.into_inner();
let delta = accumulated_mouse_motion.delta;
if delta != Vec2::ZERO {
@ -242,12 +241,9 @@ fn move_player(
fn change_fov(
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 {
return;
};
let Projection::Perspective(ref mut perspective) = projection.as_mut() else {
let Projection::Perspective(ref mut perspective) = world_model_projection.as_mut() else {
unreachable!(
"The `Projection` component was explicitly built with `Projection::Perspective`"
);

View file

@ -109,118 +109,117 @@ fn run_camera_controller(
key_input: Res<ButtonInput<KeyCode>>,
mut toggle_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();
if let Ok((mut transform, mut controller)) = query.get_single_mut() {
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 transform, mut controller) = query.into_inner();
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 {
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;
let mut scroll = 0.0;
// Handle key input
let mut axis_input = Vec3::ZERO;
if key_input.pressed(controller.key_forward) {
axis_input.z += 1.0;
}
if key_input.pressed(controller.key_back) {
axis_input.z -= 1.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 amount = match accumulated_mouse_scroll.unit {
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;
let mut cursor_grab_change = false;
if key_input.just_pressed(controller.keyboard_key_toggle_cursor_grab) {
*toggle_cursor_grab = !*toggle_cursor_grab;
cursor_grab_change = true;
}
if mouse_button_input.just_pressed(controller.mouse_key_cursor_grab) {
*mouse_cursor_grab = true;
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;
// Handle key input
let mut axis_input = Vec3::ZERO;
if key_input.pressed(controller.key_forward) {
axis_input.z += 1.0;
}
if key_input.pressed(controller.key_back) {
axis_input.z -= 1.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;
}
// Apply movement update
if axis_input != Vec3::ZERO {
let max_speed = if key_input.pressed(controller.key_run) {
controller.run_speed
} else {
controller.walk_speed
};
controller.velocity = axis_input.normalize() * max_speed;
let mut cursor_grab_change = false;
if key_input.just_pressed(controller.keyboard_key_toggle_cursor_grab) {
*toggle_cursor_grab = !*toggle_cursor_grab;
cursor_grab_change = true;
}
if mouse_button_input.just_pressed(controller.mouse_key_cursor_grab) {
*mouse_cursor_grab = true;
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 {
let friction = controller.friction.clamp(0.0, 1.0);
controller.velocity *= 1.0 - friction;
if controller.velocity.length_squared() < 1e-6 {
controller.velocity = Vec3::ZERO;
}
}
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);
controller.walk_speed
};
controller.velocity = axis_input.normalize() * max_speed;
} else {
let friction = controller.friction.clamp(0.0, 1.0);
controller.velocity *= 1.0 - friction;
if controller.velocity.length_squared() < 1e-6 {
controller.velocity = Vec3::ZERO;
}
}
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>,
mut edit_move: ResMut<MouseEditMove>,
mut control_points: ResMut<ControlPoints>,
camera: Query<(&Camera, &GlobalTransform)>,
camera: Single<(&Camera, &GlobalTransform)>,
) {
let Some(mouse_pos) = mouse_position.0 else {
return;
@ -336,9 +336,7 @@ fn handle_mouse_press(
continue;
};
let Ok((camera, camera_transform)) = camera.get_single() else {
continue;
};
let (camera, camera_transform) = *camera;
// 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 {
@ -365,7 +363,7 @@ fn draw_edit_move(
edit_move: Res<MouseEditMove>,
mouse_position: Res<MousePosition>,
mut gizmos: Gizmos,
camera: Query<(&Camera, &GlobalTransform)>,
camera: Single<(&Camera, &GlobalTransform)>,
) {
let Some(start) = edit_move.start else {
return;
@ -373,9 +371,8 @@ fn draw_edit_move(
let Some(mouse_pos) = mouse_position.0 else {
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
// 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.
fn handle_lifetime(
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() {
match event {
AppLifecycle::Idle | AppLifecycle::WillSuspend | AppLifecycle::WillResume => {}

View file

@ -32,18 +32,15 @@ fn screenshot_on_spacebar(
fn screenshot_saving(
mut commands: Commands,
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() {
0 => {
commands.entity(window).remove::<CursorIcon>();
commands.entity(*window).remove::<CursorIcon>();
}
x if x > 0 => {
commands
.entity(window)
.entity(*window)
.insert(CursorIcon::from(SystemCursorIcon::Progress));
}
_ => {}