use glfw::{Action, WindowEvent};
pub use glfw::{Key, MouseButton};
use std::collections::HashSet;
use std::sync::{Mutex, OnceLock};
static KEYS_PRESSED: OnceLock<Mutex<HashSet<Key>>> = OnceLock::new();
static MOUSE_BUTTONS_PRESSED: OnceLock<Mutex<HashSet<MouseButton>>> = OnceLock::new();
static MOUSE_POSITION: OnceLock<Mutex<(f64, f64)>> = OnceLock::new();
static MOUSE_SCROLL: OnceLock<Mutex<(f64, f64)>> = OnceLock::new();
fn ensure_init() {
static INIT: OnceLock<()> = OnceLock::new();
INIT.get_or_init(|| {
KEYS_PRESSED.get_or_init(|| Mutex::new(HashSet::new()));
MOUSE_BUTTONS_PRESSED.get_or_init(|| Mutex::new(HashSet::new()));
MOUSE_POSITION.get_or_init(|| Mutex::new((0.0, 0.0)));
MOUSE_SCROLL.get_or_init(|| Mutex::new((0.0, 0.0)));
});
}
fn with_lock<T, F, R>(lock: &Mutex<T>, f: F) -> R
where
F: FnOnce(&mut T) -> R,
{
let mut guard = lock.lock().unwrap();
f(&mut guard)
}
pub fn process_event(event: &WindowEvent) {
ensure_init();
match event {
WindowEvent::Key(key, _, Action::Press, _) => {
with_lock(KEYS_PRESSED.get().unwrap(), |keys| keys.insert(*key));
}
WindowEvent::Key(key, _, Action::Release, _) => {
with_lock(KEYS_PRESSED.get().unwrap(), |keys| keys.remove(key));
}
WindowEvent::MouseButton(button, Action::Press, _) => {
with_lock(MOUSE_BUTTONS_PRESSED.get().unwrap(), |buttons| {
buttons.insert(*button)
});
}
WindowEvent::MouseButton(button, Action::Release, _) => {
with_lock(MOUSE_BUTTONS_PRESSED.get().unwrap(), |buttons| {
buttons.remove(button)
});
}
WindowEvent::CursorPos(x, y) => {
with_lock(MOUSE_POSITION.get().unwrap(), |pos| *pos = (*x, *y));
}
WindowEvent::Scroll(xoffset, yoffset) => {
with_lock(MOUSE_SCROLL.get().unwrap(), |scroll| {
*scroll = (*xoffset, *yoffset)
});
}
_ => {}
}
}
pub fn is_key_pressed(key: Key) -> bool {
ensure_init();
with_lock(KEYS_PRESSED.get().unwrap(), |keys| keys.contains(&key))
}
pub fn is_mouse_button_pressed(button: MouseButton) -> bool {
ensure_init();
with_lock(MOUSE_BUTTONS_PRESSED.get().unwrap(), |buttons| {
buttons.contains(&button)
})
}
pub fn get_mouse_position() -> (f64, f64) {
ensure_init();
with_lock(MOUSE_POSITION.get().unwrap(), |pos| *pos)
}
pub fn get_mouse_scroll() -> (f64, f64) {
ensure_init();
with_lock(MOUSE_SCROLL.get().unwrap(), |scroll| *scroll)
}
pub fn reset_state() {
ensure_init();
with_lock(KEYS_PRESSED.get().unwrap(), |keys| keys.clear());
with_lock(MOUSE_BUTTONS_PRESSED.get().unwrap(), |buttons| {
buttons.clear()
});
with_lock(MOUSE_POSITION.get().unwrap(), |pos| *pos = (0.0, 0.0));
with_lock(MOUSE_SCROLL.get().unwrap(), |scroll| *scroll = (0.0, 0.0));
}