bevy 0.11 camera2d zoom and pan with touchpad on macos
use bevy::prelude::*;
use bevy::{input::mouse::MouseWheel, render::camera::ScalingMode};
use bevy::input::touchpad::TouchpadMagnify;
use bevy::window::PrimaryWindow;
const GRID_SIZE: usize = 200;
pub struct SimpleCameraPlugin;
impl Plugin for SimpleCameraPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, spawn_camera)
.add_systems(Update, (camera_pan, camera_zoom));
}
}
#[cfg(not(target_os = "macos"))]
#[derive(Component)]
pub struct CameraSettings {
pub pan_speed: f32,
pub zoom_speed: f32,
}
fn spawn_camera(mut commands: Commands) {
let mut camera = Camera2dBundle::default();
camera.transform.translation.x = GRID_SIZE as f32 / 2.0;
camera.transform.translation.y = GRID_SIZE as f32 / 2.0;
camera.projection.scaling_mode = ScalingMode::AutoMin {
min_width: 64.0,
min_height: 36.0,
};
commands.spawn((
camera,
#[cfg(not(target_os = "macos"))]
CameraSettings {
pan_speed: 6.0,
zoom_speed: 10.0,
},
));
}
#[cfg(target_os = "macos")]
fn camera_zoom(
mut camera: Query<&mut OrthographicProjection, With<Camera2d>>,
mut touchpad: EventReader<TouchpadMagnify>,
) {
let mut projection = camera.single_mut();
if let ScalingMode::AutoMin {
min_width,
min_height,
} = projection.scaling_mode
{
if let Some(ev) = touchpad.iter().last() {
let width_delta = -ev.0 * min_width;
let height_delta = width_delta * 9. / 16.;
let new_width = num::clamp(min_width + width_delta, 16.0, 128.0);
let new_height = num::clamp(min_height + height_delta, 9.0, 72.0);
// TODO units
projection.scaling_mode = ScalingMode::AutoMin {
min_width: new_width,
min_height: new_height,
};
}
}
}
#[cfg(target_os = "macos")]
fn camera_pan(
window: Query<&Window, With<PrimaryWindow>>,
mut camera: Query<(&mut Transform, &OrthographicProjection), With<Camera2d>>,
mut mouse: EventReader<MouseWheel>,
) {
if mouse.is_empty() { return; }
let window = window.single();
let (win_width, win_height) = (window.physical_width() as f32, window.physical_height() as f32);
let (mut transform, projection) = camera.single_mut();
if let ScalingMode::AutoMin { min_width, min_height } = projection.scaling_mode {
if let Some(ev) = mouse.iter().last() {
transform.translation.x -= ev.x / win_width * min_width;
transform.translation.y += ev.y / win_height * min_height;
}
transform.translation.x = num::clamp(transform.translation.x, min_width/2. - 2., GRID_SIZE as f32 - min_width/2. + 1.);
transform.translation.y = num::clamp(transform.translation.y, min_height/2. - 2., GRID_SIZE as f32 - min_height/2. + 1.);
}
}
#[cfg(not(target_os = "macos"))]
fn camera_zoom(
mut camera: Query<(&mut OrthographicProjection, &CameraSettings), With<Camera2d>>,
mut mouse: EventReader<MouseWheel>,
) {
let (mut projection, settings) = camera.single_mut();
if let ScalingMode::AutoMin {
min_width,
min_height,
} = projection.scaling_mode
{
for ev in mouse.iter() {
let width_delta = ev.y * settings.zoom_speed;
let height_delta = width_delta * min_height / min_width;
let new_width = num::clamp(min_width + width_delta, 16.0, 128.0);
let new_height = num::clamp(min_height + height_delta, 9.0, 72.0);
// TODO units
projection.scaling_mode = ScalingMode::AutoMin {
min_width: new_width,
min_height: new_height,
};
}
}
}
#[cfg(not(target_os = "macos"))]
fn camera_pan(
mut camera: Query<(&mut Transform, &CameraSettings), With<Camera2d>>,
keyboard: Res<Input<KeyCode>>,
time: Res<Time>,
) {
let (mut transform, settings) = camera.single_mut();
if keyboard.pressed(KeyCode::A) {
transform.translation.x -= time.delta_seconds() * settings.pan_speed;
}
if keyboard.pressed(KeyCode::D) {
transform.translation.x += time.delta_seconds() * settings.pan_speed;
}
if keyboard.pressed(KeyCode::W) {
transform.translation.y += time.delta_seconds() * settings.pan_speed;
}
if keyboard.pressed(KeyCode::S) {
transform.translation.y -= time.delta_seconds() * settings.pan_speed;
}
}
+V why_null 请备注:from博客园