Skip to content

Commit

Permalink
Add modifier detection to CameraAction, and remove event remapping
Browse files Browse the repository at this point in the history
  • Loading branch information
thatcomputerguy0101 committed Oct 1, 2024
1 parent fd004c1 commit c1e3f08
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 53 deletions.
28 changes: 26 additions & 2 deletions src/renderer/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ pub enum Event {
modifiers: Modifiers,
/// Whether or not this event already have been handled.
handled: bool,
/// Whether or not this event came from a gesture-capable input
gesture_capable: bool,
},
/// Fired continuously when a pinch input gesture is recognized, such as on a Mac trackpad
PinchGesture {
Expand Down Expand Up @@ -226,3 +224,29 @@ pub struct Modifiers {
/// On Mac, this should be set whenever one of the ⌘ Command keys are down.
pub command: bool,
}

/// Set of requirements to match against the modifier state (None is a wildcard)
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct ModifierSet {
/// Either of the alt keys are down (option ⌥ on Mac).
pub alt: Option<bool>,
/// Either of the control keys are down.
/// When checking for keyboard shortcuts, consider using [`Self::command`] instead.
pub ctrl: Option<bool>,
/// Either of the shift keys are down.
pub shift: Option<bool>,
/// On Windows and Linux, set this to the same value as `ctrl`.
/// On Mac, this should be set whenever one of the ⌘ Command keys are down.
pub command: Option<bool>,
}

impl Modifiers {
/// Checks if this modifier set matches the modifiers specified in the required set
/// None values in required act as wildcards on self
pub fn matches(&self, required: &ModifierSet) -> bool {
required.alt.map_or(true, |state| self.alt == state)
&& required.ctrl.map_or(true, |state| self.ctrl == state)
&& required.shift.map_or(true, |state| self.shift == state)
&& required.command.map_or(true, |state| self.command == state)
}
}
100 changes: 68 additions & 32 deletions src/renderer/control/camera_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::renderer::*;
///
/// A set of possible actions to apply to a camera when recieving input.
///
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub enum CameraAction {
/// No action.
None,
Expand Down Expand Up @@ -76,6 +76,15 @@ pub enum CameraAction {
/// The maximum distance to the target.
max: f32,
},
/// Conditional camera action depending on modifier state
ModifierMap {
/// Modifier set to evaluate against the modifier state
modifier_set: ModifierSet,
/// Action to run if the modifiers match
matches: Box<CameraAction>,
/// Action to run if the modifiers don't match
contradicts: Box<CameraAction>,
},
}

impl std::default::Default for CameraAction {
Expand All @@ -88,7 +97,7 @@ impl std::default::Default for CameraAction {
/// A customizable controller for the camera.
/// It is possible to specify a [CameraAction] for each of the input events.
///
#[derive(Clone, Copy, Debug, Default)]
#[derive(Clone, Debug, Default)]
pub struct CameraControl {
/// Specifies what happens when dragging horizontally with the left mouse button.
pub left_drag_horizontal: CameraAction,
Expand Down Expand Up @@ -125,6 +134,7 @@ impl CameraControl {
match event {
Event::MouseMotion {
delta,
modifiers,
button,
handled,
..
Expand All @@ -133,48 +143,57 @@ impl CameraControl {
if let Some(b) = button {
let (control_horizontal, control_vertical) = match b {
MouseButton::Left => {
(self.left_drag_horizontal, self.left_drag_vertical)
(&self.left_drag_horizontal, &self.left_drag_vertical)
}
MouseButton::Middle => {
(self.middle_drag_horizontal, self.middle_drag_vertical)
(&self.middle_drag_horizontal, &self.middle_drag_vertical)
}
MouseButton::Right => {
(self.right_drag_horizontal, self.right_drag_vertical)
(&self.right_drag_horizontal, &self.right_drag_vertical)
}
};
*handled = self.handle_action(camera, control_horizontal, delta.0);
*handled |= self.handle_action(camera, control_vertical, delta.1);
*handled =
self.handle_action(camera, control_horizontal, delta.0, modifiers);
*handled |=
self.handle_action(camera, control_vertical, delta.1, modifiers);
change |= *handled;
}
}
}
Event::MouseWheel {
delta,
modifiers,
gesture_capable,
handled,
..
} => {
if !*handled {
if !*gesture_capable && modifiers.ctrl {
// Remap vertical scrolling to the pinch event if the ctrl key is held (automatically triggered by some trackpads)
*handled = self.handle_action(camera, self.pinch, delta.1);
} else {
*handled = self.handle_action(camera, self.scroll_horizontal, delta.0);
*handled |= self.handle_action(camera, self.scroll_vertical, delta.1);
}
*handled =
self.handle_action(camera, &self.scroll_horizontal, delta.0, modifiers);
*handled |=
self.handle_action(camera, &self.scroll_vertical, delta.1, modifiers);
change |= *handled;
}
}
Event::PinchGesture { delta, handled, .. } => {
Event::PinchGesture {
delta,
modifiers,
handled,
..
} => {
if !*handled {
*handled = self.handle_action(camera, self.pinch, *delta * 100.0);
*handled =
self.handle_action(camera, &self.pinch, *delta * 100.0, modifiers);
change |= *handled;
}
}
Event::RotationGesture { delta, handled, .. } => {
Event::RotationGesture {
delta,
modifiers,
handled,
..
} => {
if !*handled {
*handled = self.handle_action(camera, self.rotate, delta.0);
*handled = self.handle_action(camera, &self.rotate, delta.0, modifiers);
change |= *handled;
}
}
Expand All @@ -184,53 +203,70 @@ impl CameraControl {
change
}

fn handle_action(&mut self, camera: &mut Camera, control_type: CameraAction, x: f32) -> bool {
fn handle_action(
&self,
camera: &mut Camera,
control_type: &CameraAction,
x: f32,
modifiers: &mut Modifiers,
) -> bool {
match control_type {
CameraAction::Pitch { speed } => {
&CameraAction::Pitch { speed } => {
camera.pitch(radians(speed * x));
}
CameraAction::OrbitUp { speed, target } => {
&CameraAction::OrbitUp { speed, target } => {
camera.rotate_around_with_fixed_up(&target, 0.0, speed * x);
}
CameraAction::FreeOrbitUp { speed, target } => {
&CameraAction::FreeOrbitUp { speed, target } => {
camera.rotate_around(&target, 0.0, speed * x);
}
CameraAction::Yaw { speed } => {
&CameraAction::Yaw { speed } => {
camera.yaw(radians(speed * x));
}
CameraAction::OrbitLeft { speed, target } => {
&CameraAction::OrbitLeft { speed, target } => {
camera.rotate_around_with_fixed_up(&target, speed * x, 0.0);
}
CameraAction::FreeOrbitLeft { speed, target } => {
&CameraAction::FreeOrbitLeft { speed, target } => {
camera.rotate_around(&target, speed * x, 0.0);
}
CameraAction::Roll { speed } => {
&CameraAction::Roll { speed } => {
camera.roll(radians(speed * x));
}
CameraAction::Left { speed } => {
&CameraAction::Left { speed } => {
let change = -camera.right_direction() * x * speed;
camera.translate(&change);
}
CameraAction::Up { speed } => {
&CameraAction::Up { speed } => {
let right = camera.right_direction();
let up = right.cross(camera.view_direction());
let change = up * x * speed;
camera.translate(&change);
}
CameraAction::Forward { speed } => {
&CameraAction::Forward { speed } => {
let change = camera.view_direction() * speed * x;
camera.translate(&change);
}
CameraAction::Zoom {
&CameraAction::Zoom {
target,
speed,
min,
max,
} => {
camera.zoom_towards(&target, speed * x, min, max);
}
CameraAction::ModifierMap {
modifier_set,
matches,
contradicts,
} => {
if modifiers.matches(modifier_set) {
return self.handle_action(camera, matches.as_ref(), x, modifiers);
} else {
return self.handle_action(camera, contradicts.as_ref(), x, modifiers);
}
}
CameraAction::None => {}
}
control_type != CameraAction::None
*control_type != CameraAction::None
}
}
22 changes: 3 additions & 19 deletions src/window/winit_window/frame_input_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ use crate::control::*;
use crate::core::*;
#[cfg(target_arch = "wasm32")]
use instant::Instant;
use std::collections::HashSet;
#[cfg(not(target_arch = "wasm32"))]
use std::time::Instant;
use winit::dpi::PhysicalSize;
use winit::event::DeviceId;
use winit::event::TouchPhase;
use winit::event::WindowEvent;

Expand All @@ -30,7 +28,6 @@ pub struct FrameInputGenerator {
secondary_finger_id: Option<u64>,
modifiers: Modifiers,
mouse_pressed: Option<MouseButton>,
gesture_input_devices: HashSet<DeviceId>,
}

impl FrameInputGenerator {
Expand All @@ -55,7 +52,6 @@ impl FrameInputGenerator {
secondary_finger_id: None,
modifiers: Modifiers::default(),
mouse_pressed: None,
gesture_input_devices: HashSet::new(),
}
}

Expand Down Expand Up @@ -191,9 +187,7 @@ impl FrameInputGenerator {
}
}
}
WindowEvent::MouseWheel {
delta, device_id, ..
} => {
WindowEvent::MouseWheel { delta, .. } => {
if let Some(position) = self.cursor_pos {
match delta {
winit::event::MouseScrollDelta::LineDelta(x, y) => {
Expand All @@ -203,7 +197,6 @@ impl FrameInputGenerator {
position: position.into(),
modifiers: self.modifiers,
handled: false,
gesture_capable: self.gesture_input_devices.contains(device_id),
});
}
winit::event::MouseScrollDelta::PixelDelta(delta) => {
Expand All @@ -213,17 +206,13 @@ impl FrameInputGenerator {
position: position.into(),
modifiers: self.modifiers,
handled: false,
gesture_capable: self.gesture_input_devices.contains(device_id),
});
}
}
}
}
WindowEvent::TouchpadMagnify {
delta, device_id, ..
} => {
WindowEvent::TouchpadMagnify { delta, .. } => {
// Renamed to PinchGesture in winit 0.30.0
self.gesture_input_devices.insert(*device_id);
if let Some(position) = self.cursor_pos {
let d = *delta as f32;
self.events.push(crate::Event::PinchGesture {
Expand All @@ -234,11 +223,8 @@ impl FrameInputGenerator {
});
}
}
WindowEvent::TouchpadRotate {
delta, device_id, ..
} => {
WindowEvent::TouchpadRotate { delta, .. } => {
// Renamed to RotationGesture in winit 0.30.0
self.gesture_input_devices.insert(*device_id);
if let Some(position) = self.cursor_pos {
let d = radians(*delta);
self.events.push(crate::Event::RotationGesture {
Expand Down Expand Up @@ -368,7 +354,6 @@ impl FrameInputGenerator {
(position.x - p.x).abs() - (last_pos.x - p.x).abs(),
(position.y - p.y).abs() - (last_pos.y - p.y).abs(),
),
gesture_capable: false,
});
} else {
self.events.push(crate::Event::MouseMotion {
Expand All @@ -395,7 +380,6 @@ impl FrameInputGenerator {
(position.x - p.x).abs() - (last_pos.x - p.x).abs(),
(position.y - p.y).abs() - (last_pos.y - p.y).abs(),
),
gesture_capable: false,
});
}
self.secondary_cursor_pos = Some(position);
Expand Down

0 comments on commit c1e3f08

Please sign in to comment.