use super::time_helper::*;
use std::collections::HashMap;
use std::time::Instant;
pub const DEFAULT_MOUSE_SENSIBILITY: f64 = 1.0;
pub const DEFAULT_KEYBOARD_SENSIBILITY: f64 = 1000.0;
pub const INTENSITY_MIN: f64 = 0.0;
pub const INTENSITY_MAX: f64 = 1.0;
pub const BASE_KEYBOARD_ACC_VALUE: f64 = 0.01f64;
#[derive(Debug, Clone, Copy)]
struct KeyState {
acc: f64,
intensity: f64,
last_press: Option<Instant>,
}
impl KeyState {
fn new(intensity: f64, now: Option<Instant>) -> KeyState {
KeyState {
acc: BASE_KEYBOARD_ACC_VALUE,
intensity,
last_press: now,
}
}
fn bump(&mut self, intensity: f64, now: Option<Instant>) {
let now = unwrap_now(now);
match self.last_press {
Some(last_press) => {
if now < last_press {
return;
}
let d = now - last_press;
self.acc += self.intensity * d.as_secs_f64();
}
None => {
self.acc = BASE_KEYBOARD_ACC_VALUE;
}
}
self.intensity = intensity;
self.last_press = Some(now);
}
fn release(&mut self, now: Option<Instant>) {
if let Some(_) = self.last_press {
self.bump(self.intensity, now);
self.acc -= BASE_KEYBOARD_ACC_VALUE;
if self.acc < 0f64 {
self.acc = 0f64;
}
self.intensity = 0f64;
self.last_press = None;
}
}
fn flush(&mut self, now: Option<Instant>) -> f64 {
if let Some(_) = self.last_press {
self.bump(self.intensity, now);
}
let acc = self.acc;
self.acc = 0f64;
acc
}
}
#[derive(Debug)]
pub struct InputSteer {
pub mouse_sensibility: f64,
pub keyboard_sensibility: f64,
mouse_acc: f64,
right_keys: HashMap<i64, KeyState>,
left_keys: HashMap<i64, KeyState>,
}
impl InputSteer {
pub fn new() -> InputSteer {
InputSteer {
mouse_sensibility: DEFAULT_MOUSE_SENSIBILITY,
keyboard_sensibility: DEFAULT_KEYBOARD_SENSIBILITY,
mouse_acc: 0f64,
right_keys: HashMap::new(),
left_keys: HashMap::new(),
}
}
fn flush_mouse(&mut self) -> f64 {
let acc = self.mouse_acc;
self.mouse_acc = 0f64;
acc
}
pub fn mouse_move(&mut self, delta_px: f64) {
self.mouse_acc += delta_px;
}
fn bump_key(keys: &mut HashMap<i64, KeyState>, id: i64, intensity: f64, now: Option<Instant>) {
let intensity = if intensity > INTENSITY_MIN {
if intensity < INTENSITY_MAX {
intensity
} else {
INTENSITY_MAX
}
} else {
INTENSITY_MIN
};
if intensity <= 0.0 {
return;
}
match keys.get_mut(&id) {
Some(key_state) => {
key_state.bump(intensity, now);
}
None => {
let key_state = KeyState::new(intensity, now);
keys.insert(id.clone(), key_state);
}
}
}
fn release_key(keys: &mut HashMap<i64, KeyState>, id: i64, now: Option<Instant>) {
if let Some(key_state) = keys.get_mut(&id) {
key_state.release(now);
}
}
fn flush_keys(keys: &mut HashMap<i64, KeyState>, now: Option<Instant>) -> f64 {
let mut acc: f64 = 0f64;
for key_state in keys.values_mut() {
acc += key_state.flush(now);
}
acc
}
fn handle_key(
keys: &mut HashMap<i64, KeyState>,
id: i64,
intensity: f64,
state: bool,
now: Option<Instant>,
) {
if state {
Self::bump_key(keys, id, intensity, now);
} else {
Self::release_key(keys, id, now);
}
}
pub fn right_key(&mut self, id: i64, intensity: f64, state: bool, now: Option<Instant>) {
Self::handle_key(&mut self.right_keys, id, intensity, state, now);
}
pub fn left_key(&mut self, id: i64, intensity: f64, state: bool, now: Option<Instant>) {
Self::handle_key(&mut self.left_keys, id, intensity, state, now);
}
pub fn pop_steer(&mut self, now: Option<Instant>) -> f64 {
let mouse_steer = self.flush_mouse();
let key_steer = Self::flush_keys(&mut self.right_keys, now)
- Self::flush_keys(&mut self.left_keys, now);
mouse_steer * self.mouse_sensibility + key_steer * self.keyboard_sensibility
}
}
impl std::default::Default for InputSteer {
fn default() -> Self {
Self::new()
}
}