UX tuning + mini-refactor

This commit is contained in:
Danny McGee
2023-09-29 23:58:36 -04:00
parent 2e3979b336
commit b11155c649
2 changed files with 38 additions and 18 deletions
+34 -10
View File
@@ -4,7 +4,7 @@ use bevy::{
core_pipeline::prepass::{DepthPrepass, NormalPrepass},
input::mouse::{MouseButton, MouseMotion},
prelude::*,
window::PrimaryWindow,
window::{CursorGrabMode, PrimaryWindow},
};
pub struct OrbitCamPlugin;
@@ -64,13 +64,27 @@ fn spawn_camera(mut cmd: Commands) {
}
pub fn pan_orbit_camera(
window: Query<&Window, With<PrimaryWindow>>,
mut window: Query<&mut Window, With<PrimaryWindow>>,
mut mouse_motion: EventReader<MouseMotion>,
mouse_buttons: Res<Input<MouseButton>>,
keyboard: Res<Input<KeyCode>>,
mut camera: Query<(&mut OrbitCam, &mut Transform, &Projection)>,
) {
if !(keyboard.pressed(KeyCode::AltLeft) || keyboard.pressed(KeyCode::AltRight)) {
if (keyboard.just_released(KeyCode::AltLeft) && !keyboard.pressed(KeyCode::AltRight))
|| (keyboard.just_released(KeyCode::AltRight) && !keyboard.pressed(KeyCode::AltLeft))
|| mouse_buttons.just_released(OrbitCam::ORBIT_BTN)
|| mouse_buttons.just_released(OrbitCam::PAN_BTN)
|| mouse_buttons.just_released(OrbitCam::ZOOM_BTN)
{
let mut window = window.single_mut();
window.cursor.visible = true;
window.cursor.grab_mode = CursorGrabMode::None;
}
if !(keyboard.pressed(KeyCode::AltLeft)
|| keyboard.pressed(KeyCode::AltRight)
|| mouse_buttons.pressed(OrbitCam::PAN_BTN))
{
return;
}
@@ -92,11 +106,21 @@ pub fn pan_orbit_camera(
return;
};
let window = window.single();
let mouse_delta = mouse_motion
.into_iter()
.fold(Vec2::ZERO, |accum, current| accum + current.delta);
// TODO: This is nice because it allows movement input beyond the limits of
// the viewport, but it's a little awkward that the cursor doesn't
// move while confined and hidden. We have a `set_cursor_position`
// API, so maybe do the Blender thing and let the cursor wrap around
// at the viewport edges?
let mut window = window.single_mut();
window.cursor.visible = false;
window.cursor.grab_mode = CursorGrabMode::Confined;
let window = window.as_ref();
match control_mode {
ControlMode::Orbit => {
do_orbit(window, mouse_delta, &mut xform, &orbit);
@@ -105,7 +129,7 @@ pub fn pan_orbit_camera(
do_pan(proj, window, mouse_delta, &mut xform, &mut orbit);
}
ControlMode::Zoom => {
let delta = (mouse_delta.y * 1.5) / window.height();
let delta = (mouse_delta.y * 1.5) / (window.physical_height() as f32);
orbit.radius -= orbit.radius * delta;
xform.translation = orbit.focus + xform.back() * orbit.radius;
}
@@ -119,13 +143,13 @@ fn do_orbit(win: &Window, mouse_delta: Vec2, xform: &mut Transform, orbit: &Orbi
// Calculate rotation
let delta_x = {
let delta = mouse_delta.x / win.width() * consts::PI * 2.0;
let delta = mouse_delta.x / (win.physical_width() as f32) * consts::PI * 2.0;
match orbit.upside_down {
true => -delta,
false => delta,
}
};
let delta_y = mouse_delta.y / win.height() * consts::PI;
let delta_y = mouse_delta.y / (win.physical_height() as f32) * consts::PI;
let yaw = Quat::from_rotation_y(-delta_x);
let pitch = Quat::from_rotation_x(-delta_y);
@@ -151,8 +175,8 @@ fn do_pan(
Projection::Perspective(p) => {
mouse_delta
* Vec2 {
x: (p.fov * p.aspect_ratio) / win.width(),
y: p.fov / win.height(),
x: (p.fov * p.aspect_ratio) / (win.physical_width() as f32),
y: p.fov / (win.physical_height() as f32),
}
}
_ => mouse_delta,
@@ -161,7 +185,7 @@ fn do_pan(
// Pan along local XY plane, with the distance scaled by the radius
let up = xform.up();
let left = xform.left();
let delta = (pan.y * up + pan.x * left) * orbit.radius * 0.8;
let delta = (pan.y * up + pan.x * left) * orbit.radius;
// Update camera translation and focus point
xform.translation += delta;
+4 -8
View File
@@ -70,7 +70,7 @@ pub mod wasm {
impl Plugin for ViewportPlugin {
fn build(&self, app: &mut App) {
app.add_event::<ViewportResizeEvent>()
.add_systems(PreUpdate, dispatch_viewport_events)
.add_systems(PreUpdate, dispatch_resize_events)
.add_systems(Update, sync_window_to_viewport);
}
}
@@ -82,17 +82,13 @@ pub mod wasm {
mut events: EventReader<ViewportResizeEvent>,
mut window: Query<&mut Window>,
) {
let mut resize = None;
for event in events.into_iter() {
resize = Some(event.0);
}
if let Some(ViewportSize { width, height }) = resize {
if let Some(event) = events.into_iter().last() {
let ViewportSize { width, height } = event.0;
window.single_mut().resolution.set(width, height);
}
}
fn dispatch_viewport_events(mut events: EventWriter<ViewportResizeEvent>) {
fn dispatch_resize_events(mut events: EventWriter<ViewportResizeEvent>) {
let buffer = RESIZE_BUF.get_or_init(|| ReentrantMutex::new(RefCell::new(None)));
if let Some(lock) = buffer.try_lock() {
if let Some(resize) = lock.borrow_mut().take() {