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