258 lines
7.8 KiB
Rust
Raw Normal View History

use cgmath::Vector2;
use winit::event::{ElementState, KeyEvent, MouseScrollDelta, Modifiers, WindowEvent};
use winit::keyboard::{Key as WinitKey, ModifiersKeyState};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Key {
// Symbols
Comma, Period, Minus, Plus, Slash, Backslash, Semicolon, Apostrophe,
LeftBracket, RightBracket, Grave, Equal,
// Digits
Num0, Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9,
// Letters
A, B, C, D, E, F, G, H, I, J, K, L, M,
N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
// Arrows
ArrowUp, ArrowDown, ArrowLeft, ArrowRight,
// Controls
Escape, Enter, Space, Tab, Backspace,
Insert, Delete, Home, End, PageUp, PageDown,
// Modifier keys
Shift, Control, Alt, Super,
// Function keys
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
// Numpad
Numpad0, Numpad1, Numpad2, Numpad3, Numpad4,
Numpad5, Numpad6, Numpad7, Numpad8, Numpad9,
NumpadAdd, NumpadSubtract, NumpadMultiply, NumpadDivide, NumpadEnter,
Unknown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct KeyModifiers {
pub lshift: bool,
pub rshift: bool,
pub lcontrol: bool,
pub rcontrol: bool,
pub lalt: bool,
pub ralt: bool,
pub rsuper_key: bool,
pub lsuper_key: bool,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MouseButton {
Left,
Right,
Middle,
Other(u16),
}
#[derive(Debug, Clone)]
pub enum InputEvent {
KeyPressed {
key: Key,
modifiers: KeyModifiers,
text: String,
},
KeyReleased {
key: Key,
modifiers: KeyModifiers,
},
MouseMoved {
position: (f64, f64),
},
MouseDragged {
delta: Vector2<f64>,
button: MouseButton,
},
MouseWheel {
delta: f32,
},
}
#[derive(Default)]
pub struct InputTracker {
pub last_cursor_pos: Option<(f64, f64)>,
pub dragging_button: Option<MouseButton>,
}
impl InputTracker {
pub fn handle_window_event(&mut self, event: &WindowEvent, modifiers: Modifiers) -> Option<InputEvent> {
match event {
WindowEvent::KeyboardInput { event, .. } => {
Some(handle_keyboard_input(event, modifiers))
}
WindowEvent::CursorMoved { position, .. } => {
if let (Some(last), Some(button)) = (self.last_cursor_pos, self.dragging_button) {
let delta = Vector2::new(position.x - last.0, position.y - last.1);
self.last_cursor_pos = Some((position.x, position.y));
Some(InputEvent::MouseDragged { delta, button })
} else {
self.last_cursor_pos = Some((position.x, position.y));
Some(InputEvent::MouseMoved {
position: (position.x, position.y),
})
}
}
WindowEvent::MouseInput { state, button, .. } => {
let mapped = map_button(*button);
match state {
ElementState::Pressed => {
self.dragging_button = Some(mapped);
}
ElementState::Released => {
self.dragging_button = None;
}
}
None
}
WindowEvent::MouseWheel { delta, .. } => {
let scroll = match delta {
MouseScrollDelta::LineDelta(_, y) => *y,
MouseScrollDelta::PixelDelta(p) => p.y as f32,
};
Some(InputEvent::MouseWheel { delta: scroll })
}
_ => None,
}
}
}
fn handle_keyboard_input(event: &KeyEvent, modifiers: Modifiers) -> InputEvent {
let key = map_winit_key(&event.logical_key);
let mods = KeyModifiers {
lshift: modifiers.lshift_state() == ModifiersKeyState::Pressed,
rshift: modifiers.rshift_state() == ModifiersKeyState::Pressed,
lcontrol: modifiers.lcontrol_state() == ModifiersKeyState::Pressed,
rcontrol: modifiers.rcontrol_state() == ModifiersKeyState::Pressed,
lalt: modifiers.lalt_state() == ModifiersKeyState::Pressed,
ralt: modifiers.ralt_state() == ModifiersKeyState::Pressed,
rsuper_key: modifiers.rsuper_state() == ModifiersKeyState::Pressed,
lsuper_key: modifiers.lsuper_state() == ModifiersKeyState::Pressed,
};
match event.state {
ElementState::Pressed => InputEvent::KeyPressed {
key,
modifiers: mods,
text: event.text.clone().unwrap_or_default().into(),
},
ElementState::Released => InputEvent::KeyReleased {
key,
modifiers: mods,
},
}
}
pub fn map_button(button: winit::event::MouseButton) -> MouseButton {
match button {
winit::event::MouseButton::Left => MouseButton::Left,
winit::event::MouseButton::Right => MouseButton::Right,
winit::event::MouseButton::Middle => MouseButton::Middle,
winit::event::MouseButton::Other(n) => MouseButton::Other(n),
_ => MouseButton::Other(0),
}
}
pub fn map_winit_key(key: &WinitKey) -> Key {
use Key::*;
2025-05-05 21:29:51 +02:00
use winit::keyboard::NamedKey;
match key {
WinitKey::Character(s) => match s.as_str() {
"a" | "A" => A,
"b" | "B" => B,
"c" | "C" => C,
"d" | "D" => D,
"e" | "E" => E,
"f" | "F" => F,
"g" | "G" => G,
"h" | "H" => H,
"i" | "I" => I,
"j" | "J" => J,
"k" | "K" => K,
"l" | "L" => L,
"m" | "M" => M,
"n" | "N" => N,
"o" | "O" => O,
"p" | "P" => P,
"q" | "Q" => Q,
"r" | "R" => R,
"s" | "S" => S,
"t" | "T" => T,
"u" | "U" => U,
"v" | "V" => V,
"w" | "W" => W,
"x" | "X" => X,
"y" | "Y" => Y,
"z" | "Z" => Z,
"0" => Num0,
"1" => Num1,
"2" => Num2,
"3" => Num3,
"4" => Num4,
"5" => Num5,
"6" => Num6,
"7" => Num7,
"8" => Num8,
"9" => Num9,
"," => Comma,
"." => Period,
"-" => Minus,
"+" => Plus,
"/" => Slash,
"\\" => Backslash,
";" => Semicolon,
"'" => Apostrophe,
"[" => LeftBracket,
"]" => RightBracket,
"`" => Grave,
"=" => Equal,
_ => Unknown,
},
2025-05-05 21:29:51 +02:00
WinitKey::Named(named_key) => match named_key {
NamedKey::ArrowUp => ArrowUp,
NamedKey::ArrowDown => ArrowDown,
NamedKey::ArrowLeft => ArrowLeft,
NamedKey::ArrowRight => ArrowRight,
NamedKey::Escape => Escape,
NamedKey::Enter => Enter,
NamedKey::Tab => Tab,
NamedKey::Space => Space,
NamedKey::Backspace => Backspace,
NamedKey::Insert => Insert,
NamedKey::Delete => Delete,
NamedKey::Home => Home,
NamedKey::End => End,
NamedKey::PageUp => PageUp,
NamedKey::PageDown => PageDown,
NamedKey::Shift => Shift,
NamedKey::Control => Control,
NamedKey::Alt => Alt,
NamedKey::Super => Super,
NamedKey::F1 => F1,
NamedKey::F2 => F2,
NamedKey::F3 => F3,
NamedKey::F4 => F4,
NamedKey::F5 => F5,
NamedKey::F6 => F6,
NamedKey::F7 => F7,
NamedKey::F8 => F8,
NamedKey::F9 => F9,
NamedKey::F10 => F10,
NamedKey::F11 => F11,
NamedKey::F12 => F12,
_ => Unknown,
},
_ => Unknown,
}
}