use std::collections::HashSet;
use winit::event::{ElementState, MouseButton};
use winit::keyboard::{KeyCode, ModifiersState};
pub struct InputState {
pressed_keys: HashSet<KeyCode>,
just_pressed_keys: HashSet<KeyCode>,
just_released_keys: HashSet<KeyCode>,
modifiers: ModifiersState,
pressed_buttons: HashSet<MouseButton>,
just_pressed_buttons: HashSet<MouseButton>,
just_released_buttons: HashSet<MouseButton>,
cursor_position: (f32, f32),
cursor_delta: (f32, f32),
scroll_delta: f32,
needs_redraw: bool,
}
impl InputState {
pub fn new() -> Self {
Self {
pressed_keys: HashSet::new(),
just_pressed_keys: HashSet::new(),
just_released_keys: HashSet::new(),
modifiers: ModifiersState::default(),
pressed_buttons: HashSet::new(),
just_pressed_buttons: HashSet::new(),
just_released_buttons: HashSet::new(),
cursor_position: (0.0, 0.0),
cursor_delta: (0.0, 0.0),
scroll_delta: 0.0,
needs_redraw: false,
}
}
pub fn update(&mut self) {
self.just_pressed_keys.clear();
self.just_released_keys.clear();
self.just_pressed_buttons.clear();
self.just_released_buttons.clear();
self.cursor_delta = (0.0, 0.0);
self.scroll_delta = 0.0;
self.needs_redraw = false;
}
pub fn key_input(&mut self, key_code: KeyCode, state: ElementState) {
match state {
ElementState::Pressed => {
if !self.pressed_keys.contains(&key_code) {
self.just_pressed_keys.insert(key_code);
}
self.pressed_keys.insert(key_code);
}
ElementState::Released => {
self.pressed_keys.remove(&key_code);
self.just_released_keys.insert(key_code);
}
}
self.needs_redraw = true;
}
pub fn key_pressed(&self, key_code: KeyCode) -> bool {
self.pressed_keys.contains(&key_code)
}
pub fn key_just_pressed(&self, key_code: KeyCode) -> bool {
self.just_pressed_keys.contains(&key_code)
}
pub fn key_just_released(&self, key_code: KeyCode) -> bool {
self.just_released_keys.contains(&key_code)
}
pub fn pressed_keys(&self) -> &HashSet<KeyCode> {
&self.pressed_keys
}
pub fn set_modifiers(&mut self, modifiers: ModifiersState) {
self.modifiers = modifiers;
}
pub fn modifiers(&self) -> ModifiersState {
self.modifiers
}
pub fn mouse_button(&mut self, button: MouseButton, state: ElementState) {
match state {
ElementState::Pressed => {
if !self.pressed_buttons.contains(&button) {
self.just_pressed_buttons.insert(button);
}
self.pressed_buttons.insert(button);
}
ElementState::Released => {
self.pressed_buttons.remove(&button);
self.just_released_buttons.insert(button);
}
}
self.needs_redraw = true;
}
pub fn mouse_button_pressed(&self, button: MouseButton) -> bool {
self.pressed_buttons.contains(&button)
}
pub fn mouse_button_just_pressed(&self, button: MouseButton) -> bool {
self.just_pressed_buttons.contains(&button)
}
pub fn mouse_button_just_released(&self, button: MouseButton) -> bool {
self.just_released_buttons.contains(&button)
}
pub fn set_cursor_position(&mut self, x: f32, y: f32) {
let old_pos = self.cursor_position;
self.cursor_position = (x, y);
self.cursor_delta = (x - old_pos.0, y - old_pos.1);
}
pub fn cursor_position(&self) -> (f32, f32) {
self.cursor_position
}
pub fn cursor_delta(&self) -> (f32, f32) {
self.cursor_delta
}
pub fn set_scroll_delta(&mut self, delta: f32) {
self.scroll_delta = delta;
self.needs_redraw = true;
}
pub fn scroll_delta(&self) -> f32 {
self.scroll_delta
}
pub fn needs_redraw(&self) -> bool {
self.needs_redraw
}
pub fn request_redraw(&mut self) {
self.needs_redraw = true;
}
}
impl Default for InputState {
fn default() -> Self {
Self::new()
}
}
pub mod utils {
use cgmath::num_traits::Float as _;
use super::*;
pub fn any_key_pressed(input: &InputState, keys: &[KeyCode]) -> bool {
keys.iter().any(|&key| input.key_pressed(key))
}
pub fn all_keys_pressed(input: &InputState, keys: &[KeyCode]) -> bool {
keys.iter().all(|&key| input.key_pressed(key))
}
pub fn should_exit(input: &InputState) -> bool {
input.key_just_pressed(KeyCode::Escape)
|| (input.key_pressed(KeyCode::ControlLeft) && input.key_just_pressed(KeyCode::KeyC))
|| (input.key_pressed(KeyCode::AltLeft) && input.key_just_pressed(KeyCode::F4))
}
pub fn wasd_movement(input: &InputState) -> (f32, f32) {
let mut x = 0.0;
let mut z = 0.0;
if input.key_pressed(KeyCode::KeyW) || input.key_pressed(KeyCode::ArrowUp) {
z -= 1.0;
}
if input.key_pressed(KeyCode::KeyS) || input.key_pressed(KeyCode::ArrowDown) {
z += 1.0;
}
if input.key_pressed(KeyCode::KeyA) || input.key_pressed(KeyCode::ArrowLeft) {
x -= 1.0;
}
if input.key_pressed(KeyCode::KeyD) || input.key_pressed(KeyCode::ArrowRight) {
x += 1.0;
}
if x != 0.0 && z != 0.0 {
let len = (x * x + z * z).sqrt();
x /= len;
z /= len;
}
(x, z)
}
pub fn jump_pressed(input: &InputState) -> bool {
input.key_pressed(KeyCode::Space)
}
pub fn crouch_pressed(input: &InputState) -> bool {
input.key_pressed(KeyCode::ShiftLeft) || input.key_pressed(KeyCode::ShiftRight)
}
}