use crate::types::KeyCode;
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct KeyState {
pub is_down: bool,
pub just_pressed_frame: Option<u32>,
pub just_released_frame: Option<u32>,
pub held_duration_ms: f32,
pub last_press_time: f64,
}
impl Default for KeyState {
fn default() -> Self {
Self {
is_down: false,
just_pressed_frame: None,
just_released_frame: None,
held_duration_ms: 0.0,
last_press_time: 0.0,
}
}
}
pub struct KeyboardState {
keys: HashMap<KeyCode, KeyState>,
}
impl Default for KeyboardState {
fn default() -> Self {
Self::new()
}
}
impl KeyboardState {
pub fn new() -> Self {
Self {
keys: HashMap::new(),
}
}
pub fn is_down(&self, key: KeyCode) -> bool {
self.keys.get(&key).map(|k| k.is_down).unwrap_or(false)
}
pub fn was_just_pressed(&self, key: KeyCode) -> bool {
self.keys
.get(&key)
.map(|k| k.just_pressed_frame.is_some())
.unwrap_or(false)
}
pub fn was_just_released(&self, key: KeyCode) -> bool {
self.keys
.get(&key)
.map(|k| k.just_released_frame.is_some())
.unwrap_or(false)
}
pub fn press(&mut self, key: KeyCode, timestamp: f64, frame: u32) {
let state = self.keys.entry(key).or_default();
if !state.is_down {
state.is_down = true;
state.just_pressed_frame = Some(frame);
state.held_duration_ms = 0.0;
state.last_press_time = timestamp;
}
}
pub fn release(&mut self, key: KeyCode, frame: u32) {
let state = self.keys.entry(key).or_default();
if state.is_down {
state.is_down = false;
state.just_released_frame = Some(frame);
}
}
pub fn end_frame(&mut self, delta_time_ms: f32) {
for state in self.keys.values_mut() {
state.just_pressed_frame = None;
state.just_released_frame = None;
if state.is_down {
state.held_duration_ms += delta_time_ms;
}
}
}
pub fn get_held_duration(&self, key: KeyCode) -> f32 {
self.keys
.get(&key)
.map(|k| k.held_duration_ms)
.unwrap_or(0.0)
}
}