use std::collections::HashSet;
use backend::middling::{self, InputHandler};
use winit::dpi::PhysicalPosition;
use winit::event::{ElementState, WindowEvent};
use winit::keyboard::PhysicalKey;
use crate::util::vector::Vector;
pub use winit::event::MouseButton;
pub use winit::keyboard::KeyCode;
#[derive(Clone, Default, Debug)]
pub struct Keyboard {
pressed: HashSet<KeyCode>,
was_pressed: HashSet<KeyCode>,
}
impl Keyboard {
pub fn new() -> Self {
Self::default()
}
pub fn is_pressed(&self, key: KeyCode) -> bool {
self.pressed.contains(&key)
}
pub fn just_pressed(&self, key: KeyCode) -> bool {
self.pressed.contains(&key) && !self.was_pressed.contains(&key)
}
pub fn just_released(&self, key: KeyCode) -> bool {
!self.pressed.contains(&key) && self.was_pressed.contains(&key)
}
pub fn is_pressed_any(&self) -> bool {
!self.pressed.is_empty()
}
pub fn just_pressed_any(&self) -> bool {
self.pressed.difference(&self.was_pressed).any(|_| true)
}
}
impl<Context> InputHandler<WindowEvent, Context> for Keyboard {
fn handle_event(&mut self, event: WindowEvent, _context: &Context) -> Option<WindowEvent> {
if let WindowEvent::KeyboardInput { event, .. } = event {
if let PhysicalKey::Code(code) = event.physical_key {
match event.state {
ElementState::Pressed => self.pressed.insert(code),
ElementState::Released => self.pressed.remove(&code),
};
}
None
} else {
Some(event)
}
}
fn update(&mut self) {
self.was_pressed.clone_from(&self.pressed)
}
}
pub type MousePosition = Option<Vector<i32>>;
#[derive(Clone, Debug)]
pub struct Mouse {
position: MousePosition,
pressed: HashSet<MouseButton>,
was_pressed: HashSet<MouseButton>,
}
impl Mouse {
pub fn new() -> Self {
let position = None;
let pressed = Default::default();
let was_pressed = Default::default();
Self {
position,
pressed,
was_pressed,
}
}
pub fn is_pressed(&self, button: MouseButton) -> bool {
self.pressed.contains(&button)
}
pub fn just_pressed(&self, button: MouseButton) -> bool {
self.pressed.contains(&button) && !self.was_pressed.contains(&button)
}
pub fn just_released(&self, button: MouseButton) -> bool {
!self.pressed.contains(&button) && self.was_pressed.contains(&button)
}
pub fn position(&self) -> MousePosition {
self.position
}
}
impl<EventContext, SurfaceSpace> InputHandler<WindowEvent, EventContext> for Mouse
where
EventContext: middling::EventContext<
PhysicalPosition<f64>,
SurfaceSpace = Option<PhysicalPosition<SurfaceSpace>>,
>,
SurfaceSpace: TryInto<i32>,
{
fn handle_event(&mut self, event: WindowEvent, context: &EventContext) -> Option<WindowEvent> {
match event {
WindowEvent::MouseInput { state, button, .. } => {
match state {
ElementState::Pressed => self.pressed.insert(button),
ElementState::Released => self.pressed.remove(&button),
};
None
}
WindowEvent::CursorMoved { position, .. } => {
fn convert<SurfaceSpace>(
PhysicalPosition { x, y }: PhysicalPosition<SurfaceSpace>,
) -> Option<Vector<i32>>
where
SurfaceSpace: TryInto<i32>,
{
Some(Vector::new(x.try_into().ok()?, y.try_into().ok()?))
}
self.position = context.estimate_surface_space(position).and_then(convert);
None
}
_ => Some(event),
}
}
fn update(&mut self) {
self.was_pressed.clone_from(&self.pressed)
}
}
impl Default for Mouse {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Debug, Default)]
pub struct KeyboardMouse {
keyboard: Keyboard,
mouse: Mouse,
}
impl KeyboardMouse {
pub fn new() -> Self {
Self::default()
}
pub fn keyboard(&self) -> &Keyboard {
&self.keyboard
}
pub fn mouse(&self) -> &Mouse {
&self.mouse
}
}
impl<EventContext, SurfaceSpace> InputHandler<WindowEvent, EventContext> for KeyboardMouse
where
EventContext: middling::EventContext<
PhysicalPosition<f64>,
SurfaceSpace = Option<PhysicalPosition<SurfaceSpace>>,
>,
SurfaceSpace: TryInto<i32>,
{
fn handle_event(&mut self, event: WindowEvent, context: &EventContext) -> Option<WindowEvent> {
let event = self.keyboard.handle_event(event, context)?;
self.mouse.handle_event(event, context)
}
fn update(&mut self) {
InputHandler::<WindowEvent, EventContext>::update(&mut self.keyboard);
InputHandler::<WindowEvent, EventContext>::update(&mut self.mouse);
}
}
#[derive(Debug, Clone, Copy)]
pub struct NoInput;
impl<Event, EventContext> InputHandler<Event, EventContext> for NoInput {
fn handle_event(&mut self, event: Event, _: &EventContext) -> Option<Event> {
Some(event)
}
fn update(&mut self) {}
}