#![deny(missing_docs)]
use winit::dpi::PhysicalPosition;
use winit::event::DeviceEvent::MouseMotion;
use winit::event::ElementState::{Pressed, Released};
use winit::event::Event::{self, DeviceEvent, WindowEvent};
use winit::event::KeyboardInput;
pub use winit::event::MouseButton;
use winit::event::MouseScrollDelta;
pub use winit::event::VirtualKeyCode as Key;
use winit::event::WindowEvent::KeyboardInput as WKeyboardInput;
use winit::event::WindowEvent::{
AxisMotion, CursorMoved, MouseInput, MouseWheel, ReceivedCharacter,
};
use winit::window::Window;
pub struct Input {
pub mouse_pos: (f32, f32),
pub mouse_delta: (f32, f32),
pub raw_mouse_delta: (f32, f32),
pub mouse_axis_motion: (f32, f32),
pub mouse_wheel_delta: (f32, f32),
pub keys_down: Vec<Key>,
pub keys_pressed: Vec<Key>,
pub keys_released: Vec<Key>,
pub characters_down: Vec<char>,
pub mouse_btns_down: Vec<MouseButton>,
pub mouse_btns_pressed: Vec<MouseButton>,
pub mouse_btns_released: Vec<MouseButton>,
pub hide_mouse: bool,
}
impl Default for Input {
fn default() -> Self {
Self::new()
}
}
impl Input {
pub fn new() -> Input {
Input {
mouse_pos: (0f32, 0f32),
mouse_delta: (0f32, 0f32),
raw_mouse_delta: (0f32, 0f32),
mouse_axis_motion: (0f32, 0f32),
mouse_wheel_delta: (0f32, 0f32),
keys_down: Vec::new(),
keys_pressed: Vec::new(),
keys_released: Vec::new(),
characters_down: Vec::new(),
mouse_btns_down: Vec::new(),
mouse_btns_pressed: Vec::new(),
mouse_btns_released: Vec::new(),
hide_mouse: true,
}
}
pub fn update_inputs(&mut self, window: &Window, events: &Vec<Event<()>>) {
let (width, height): (u32, u32) = window.inner_size().into();
let h_width = (width as u32 / 2u32) as f32;
let h_height = (height / 2u32) as f32;
{
self.mouse_delta = (0f32, 0f32);
self.mouse_wheel_delta = (0f32, 0f32);
self.keys_pressed.clear();
self.keys_released.clear();
self.mouse_btns_pressed.clear();
self.mouse_btns_released.clear();
self.characters_down.clear();
}
let keys_down = &mut self.keys_down;
let keys_pressed = &mut self.keys_pressed;
let keys_released = &mut self.keys_released;
let mouse_delta = &mut self.mouse_delta;
let raw_mouse_delta = &mut self.raw_mouse_delta;
let mouse_axis_motion = &mut self.mouse_axis_motion;
let mouse_pos = &mut self.mouse_pos;
let mouse_btns_down = &mut self.mouse_btns_down;
let mouse_btns_pressed = &mut self.mouse_btns_pressed;
let mouse_btns_released = &mut self.mouse_btns_released;
let mouse_wheel_delta = &mut self.mouse_wheel_delta;
let characters_down = &mut self.characters_down;
for event in events {
match event {
WindowEvent { event, .. } => match event {
WKeyboardInput {
input:
KeyboardInput {
state: Pressed,
virtual_keycode: vkey,
..
},
..
} => {
if let Some(key) = vkey {
keys_down.push(*key);
keys_pressed.push(*key);
}
}
WKeyboardInput {
input:
KeyboardInput {
state: Released,
virtual_keycode: vkey,
..
},
..
} => {
if let Some(key) = vkey {
keys_down.retain(|&k| k != *key);
keys_released.push(*key);
}
}
CursorMoved { position: pos, .. } => {
let (x, y): (i32, i32) = (*pos).into();
mouse_delta.0 = (h_width - x as f32) / width as f32;
mouse_delta.1 = (h_height - y as f32) / height as f32;
(*mouse_pos) = (x as f32, y as f32);
}
AxisMotion { axis, value, .. } => match axis {
0 => mouse_axis_motion.0 = *value as f32,
1 => mouse_axis_motion.1 = *value as f32,
_ => {}
},
MouseInput {
state: Pressed,
button: btn,
..
} => {
mouse_btns_down.push(*btn);
mouse_btns_pressed.push(*btn);
}
MouseInput {
state: Released,
button: btn,
..
} => {
mouse_btns_down.retain(|&mb| mb != *btn);
mouse_btns_released.push(*btn);
}
MouseWheel { delta, .. } => {
(*mouse_wheel_delta) = match delta {
MouseScrollDelta::LineDelta(x, y) => (*x, *y),
MouseScrollDelta::PixelDelta(pos) => {
let (x, y): (i32, i32) = (*pos).into();
(x as f32, y as f32)
}
};
}
ReceivedCharacter(c) => characters_down.push(*c),
_ => (),
},
DeviceEvent { event, .. } => {
if let MouseMotion { delta } = event {
(*raw_mouse_delta) = (delta.0 as f32, delta.1 as f32);
}
}
_ => (),
}
}
if self.hide_mouse {
window.set_cursor_visible(false);
window.set_cursor_grab(true).unwrap();
let _ = window.set_cursor_position(PhysicalPosition::new(h_width, h_height));
} else {
window.set_cursor_visible(true);
window.set_cursor_grab(false).unwrap();
}
}
}