use std::collections::HashSet;
use devotee_backend::winit::dpi::PhysicalPosition;
use devotee_backend::winit::event::{ElementState, KeyboardInput, WindowEvent};
use devotee_backend::Backend;
use super::Input;
use crate::app::window::Window;
use crate::util::vector::Vector;
pub use devotee_backend::winit::event::{MouseButton, VirtualKeyCode};
#[derive(Clone, Default)]
pub struct KeyMouse {
keyboard: Keyboard,
mouse: Mouse,
}
impl KeyMouse {
pub fn new() -> Self {
Default::default()
}
pub fn keys(&self) -> &Keyboard {
&self.keyboard
}
pub fn mouse(&self) -> &Mouse {
&self.mouse
}
}
#[derive(Clone, Default)]
pub struct Keyboard {
currently_pressed: HashSet<VirtualKeyCode>,
previously_pressed: HashSet<VirtualKeyCode>,
}
impl Keyboard {
pub fn is_pressed(&self, key: VirtualKeyCode) -> bool {
self.currently_pressed.contains(&key)
}
pub fn just_pressed(&self, key: VirtualKeyCode) -> bool {
self.currently_pressed.contains(&key) & !self.previously_pressed.contains(&key)
}
pub fn just_released(&self, key: VirtualKeyCode) -> bool {
!self.currently_pressed.contains(&key) & self.previously_pressed.contains(&key)
}
fn step(&mut self) {
self.previously_pressed = self.currently_pressed.clone();
}
fn register_key_event(&mut self, event: KeyboardInput) {
if let Some(keycode) = event.virtual_keycode {
match event.state {
ElementState::Pressed => self.register_key_pressed(keycode),
ElementState::Released => self.register_key_released(keycode),
}
}
}
fn register_key_pressed(&mut self, key: VirtualKeyCode) {
self.currently_pressed.insert(key);
}
fn register_key_released(&mut self, key: VirtualKeyCode) {
self.currently_pressed.remove(&key);
}
}
#[derive(Clone, Default)]
pub struct Mouse {
position: Option<Vector<i32>>,
currently_pressed: HashSet<MouseButton>,
previously_pressed: HashSet<MouseButton>,
}
impl Mouse {
pub fn position(&self) -> Option<Vector<i32>> {
self.position
}
pub fn is_pressed(&self, button: MouseButton) -> bool {
self.currently_pressed.contains(&button)
}
pub fn just_pressed(&self, button: MouseButton) -> bool {
self.currently_pressed.contains(&button) & !self.previously_pressed.contains(&button)
}
pub fn just_released(&self, button: MouseButton) -> bool {
!self.currently_pressed.contains(&button) & self.previously_pressed.contains(&button)
}
fn register_button_press_event(&mut self, button: MouseButton, state: ElementState) {
match state {
ElementState::Pressed => self.currently_pressed.insert(button),
ElementState::Released => self.currently_pressed.remove(&button),
};
}
fn step(&mut self) {
self.previously_pressed = self.currently_pressed.clone();
}
fn register_cursor_left(&mut self) {
self.position = None;
}
fn register_cursor_moved<Bck>(
&mut self,
position: PhysicalPosition<f64>,
window: &Window,
back: &Bck,
) where
Bck: Backend,
{
self.position = Some(match window.window_pos_to_inner(back, position) {
Ok(in_bounds) => in_bounds,
Err(out_of_bounds) => out_of_bounds,
});
}
}
impl<Bck> Input<Bck> for KeyMouse
where
Bck: Backend,
{
fn next_frame(&mut self) {
self.keyboard.step();
self.mouse.step();
}
fn consume_window_event<'a>(
&mut self,
event: WindowEvent<'a>,
window: &Window,
back: &Bck,
) -> Option<WindowEvent<'a>> {
match event {
WindowEvent::KeyboardInput { input, .. } => {
self.keyboard.register_key_event(input);
None
}
WindowEvent::CursorLeft { .. } => {
self.mouse.register_cursor_left();
None
}
WindowEvent::CursorMoved { position, .. } => {
self.mouse.register_cursor_moved(position, window, back);
None
}
WindowEvent::MouseInput { state, button, .. } => {
self.mouse.register_button_press_event(button, state);
None
}
event => Some(event),
}
}
}