103 lines
3.2 KiB
Rust
103 lines
3.2 KiB
Rust
use std::{hash::{Hash, Hasher}, collections::{HashMap, hash_map::DefaultHasher}};
|
|
|
|
use winit::event::ElementState;
|
|
|
|
//pub trait Button : Clone + Hash + Eq + PartialEq + 'static {}
|
|
/* pub trait Button {}
|
|
impl<T: Clone + Hash + Eq + PartialEq + 'static> Button for T {} */
|
|
|
|
pub trait Button = Clone + Hash + Eq + PartialEq + 'static;
|
|
|
|
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
|
pub enum ButtonEvent<T: Button> {
|
|
Pressed(T),
|
|
Released(T),
|
|
JustPressed(T),
|
|
}
|
|
|
|
impl<T: Button> ButtonEvent<T> {
|
|
fn take_val(self) -> T {
|
|
match self {
|
|
ButtonEvent::Pressed(t) => t,
|
|
ButtonEvent::JustPressed(t) => t,
|
|
ButtonEvent::Released(t) => t,
|
|
}
|
|
}
|
|
|
|
fn clone_val(&self) -> T {
|
|
self.clone().take_val()
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct InputButtons<T: Button> {
|
|
// the u64 as the key is the hashed value of T. this makes it easier to
|
|
// search for a button and see its state
|
|
button_events: HashMap<u64, ButtonEvent<T>>,
|
|
}
|
|
|
|
impl<T: Button> Default for InputButtons<T> {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl<T: Button> InputButtons<T> {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
button_events: HashMap::new(),
|
|
}
|
|
}
|
|
|
|
fn get_button_hash(button: &T) -> u64 {
|
|
let mut hasher = DefaultHasher::new();
|
|
button.hash(&mut hasher);
|
|
hasher.finish()
|
|
}
|
|
|
|
/// Add a button event to this input type
|
|
pub fn add_input(&mut self, button: ButtonEvent<T>) {
|
|
let hash = Self::get_button_hash(&button.clone_val());
|
|
|
|
self.button_events.insert(hash, button);
|
|
}
|
|
|
|
pub(crate) fn add_input_from_winit(&mut self, button: T, state: ElementState) {
|
|
let event = match state {
|
|
// TODO: there is a pause between pressed events of a key when holding down, so it stays in a just pressed state for too long
|
|
// When a button is held down, this would change a just pressed button into a pressed button.
|
|
ElementState::Pressed if self.is_pressed(button.clone()) => ButtonEvent::Pressed(button),
|
|
ElementState::Pressed => ButtonEvent::JustPressed(button),
|
|
ElementState::Released => ButtonEvent::Released(button),
|
|
};
|
|
|
|
self.add_input(event);
|
|
}
|
|
|
|
/// Returns true if the button is pressed (or was just pressed)
|
|
pub fn is_pressed(&self, button: T) -> bool
|
|
{
|
|
let hash = Self::get_button_hash(&button);
|
|
match self.button_events.get(&hash) {
|
|
Some(button_event) => match button_event {
|
|
// this if statement should always be true, but just in case ;)
|
|
ButtonEvent::Pressed(b) | ButtonEvent::JustPressed(b) if button == *b => true,
|
|
_ => false,
|
|
},
|
|
None => false
|
|
}
|
|
}
|
|
|
|
/// Returns true if the button was just pressed this tick
|
|
pub fn was_just_pressed(&self, button: T) -> bool {
|
|
let hash = Self::get_button_hash(&button);
|
|
match self.button_events.get(&hash) {
|
|
Some(button_event) => match button_event {
|
|
// this if statement should always be true, but just in case ;)
|
|
ButtonEvent::JustPressed(b) if button == *b => true,
|
|
_ => false,
|
|
},
|
|
None => false
|
|
}
|
|
}
|
|
} |