use crate::types::MouseButton;
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct MouseButtonState {
pub is_down: bool,
pub just_pressed_frame: Option<u32>,
pub just_released_frame: Option<u32>,
pub held_duration_ms: f32,
}
impl Default for MouseButtonState {
fn default() -> Self {
Self {
is_down: false,
just_pressed_frame: None,
just_released_frame: None,
held_duration_ms: 0.0,
}
}
}
pub struct MouseState {
pub position: (f32, f32),
pub delta: (f32, f32),
pub buttons: HashMap<MouseButton, MouseButtonState>,
pub scroll: (f32, f32),
}
impl Default for MouseState {
fn default() -> Self {
Self::new()
}
}
impl MouseState {
pub fn new() -> Self {
Self {
position: (0.0, 0.0),
delta: (0.0, 0.0),
buttons: HashMap::new(),
scroll: (0.0, 0.0),
}
}
pub fn move_to(&mut self, x: f32, y: f32) {
let delta_x = x - self.position.0;
let delta_y = y - self.position.1;
self.delta.0 += delta_x;
self.delta.1 += delta_y;
self.position = (x, y);
}
pub fn move_rel(&mut self, dx: f32, dy: f32) {
self.position.0 += dx;
self.position.1 += dy;
self.delta.0 += dx;
self.delta.1 += dy;
}
pub fn button_press(&mut self, button: MouseButton, frame: u32) {
let state = self.buttons.entry(button).or_default();
if !state.is_down {
state.is_down = true;
state.just_pressed_frame = Some(frame);
state.held_duration_ms = 0.0;
}
}
pub fn button_release(&mut self, button: MouseButton, frame: u32) {
let state = self.buttons.entry(button).or_default();
if state.is_down {
state.is_down = false;
state.just_released_frame = Some(frame);
}
}
pub fn scroll(&mut self, delta_x: f32, delta_y: f32) {
self.scroll.0 += delta_x;
self.scroll.1 += delta_y;
}
pub fn end_frame(&mut self, delta_time_ms: f32) {
self.delta = (0.0, 0.0);
self.scroll = (0.0, 0.0);
for state in self.buttons.values_mut() {
state.just_pressed_frame = None;
state.just_released_frame = None;
if state.is_down {
state.held_duration_ms += delta_time_ms;
} else {
state.held_duration_ms = 0.0;
}
}
}
pub fn is_button_down(&self, button: MouseButton) -> bool {
self.buttons
.get(&button)
.map(|b| b.is_down)
.unwrap_or(false)
}
pub fn was_button_just_pressed(&self, button: MouseButton) -> bool {
self.buttons
.get(&button)
.map(|b| b.just_pressed_frame.is_some())
.unwrap_or(false)
}
pub fn was_button_just_released(&self, button: MouseButton) -> bool {
self.buttons
.get(&button)
.map(|b| b.just_released_frame.is_some())
.unwrap_or(false)
}
}