use std::collections::HashSet;
use sdl2::event::Event;
mod buttons;
mod keys;
pub use self::{
buttons::Button,
keys::Key
};
use super::config::Config;
pub struct System {
mouse_sensitivity: i32,
left_hand: bool,
event_pump: sdl2::EventPump,
keys_buffer: HashSet<Key>,
buttons_buffer: HashSet<Button>,
mouse_dx: i32,
mouse_dy: i32,
mouse_dw: i32 }
impl System {
pub fn init(sdl: &sdl2::Sdl, config: &Config) -> Result<System, String> {
sdl.mouse().show_cursor(false); sdl.mouse().set_relative_mouse_mode(true);
let event_pump = sdl.event_pump()?;
let keys_buffer: HashSet<Key> = HashSet::new();
let buttons_buffer: HashSet<Button> = HashSet::new();
Ok(System{
mouse_sensitivity: config.mouse_sensitivity,
left_hand: config.left_hand,
event_pump,
keys_buffer,
buttons_buffer,
mouse_dx: 0,
mouse_dy: 0,
mouse_dw: 0
})
}
pub fn mouse_dx(&self) -> i32 {
self.mouse_dx * self.mouse_sensitivity / 100
}
pub fn mouse_dy(&self) -> i32 {
self.mouse_dy * self.mouse_sensitivity / 100
}
pub fn mouse_dw(&self) -> i32 {
self.mouse_dw
}
pub fn poll_mouse_dx(&mut self) -> i32 {
let dx = self.mouse_dx();
self.mouse_dx = 0;
dx
}
pub fn poll_mouse_dy(&mut self) -> i32 {
let dy = self.mouse_dy();
self.mouse_dy = 0;
dy
}
pub fn poll_mouse_dw(&mut self) -> i32 {
let dw = self.mouse_dw();
self.mouse_dw = 0;
dw
}
pub fn test_key(&self, key: Key) -> bool {
match keys::to_sdl(Some(key)) {
Some(s) => self.event_pump.keyboard_state().is_scancode_pressed(s),
None => false
}
}
pub fn test_keys(&self, keys: &[Key]) -> bool {
for k in keys {
if self.test_key(*k) {
return true
}
}
false
}
pub fn test_modkeys(&self) -> bool {
self.test_keys(&[Key::LAlt, Key::RAlt, Key::LCtrl, Key::RCtrl, Key::LShift, Key::RShift])
}
pub fn poll_key(&mut self, key: Key) -> bool {
match self.keys_buffer.take(&key) { Some(_) => true,
None => false
}
}
pub fn poll_keys(&mut self, keys: &[Key]) -> bool {
keys.iter().fold(false, |any_pressed, this_pressed| any_pressed | self.poll_key(*this_pressed)) }
pub fn get_poll_char(&mut self) -> Option<char> {
let mut char_key: Option<Key> = None;
for key in & self.keys_buffer {
if ![Key::LShift, Key::RShift].contains(key) {
char_key = Some(*key);
break;
}
}
if let Some(ch_key) = char_key {
let shift = self.test_keys(&[Key::LShift, Key::RShift]);
let ch = if ((ch_key as usize) >= (Key::A as usize)) && ((ch_key as usize) <= (Key::Z as usize)) {
let mut ascii = (0x61 + (ch_key as usize) - (Key::A as usize)) as u8;
if shift { ascii -= 0x20; }
ascii as char
} else {
match ch_key { Key::Space => ' ',
Key::Num0 => match shift { false => '0', true => ')' },
Key::Num1 => match shift { false => '1', true => '!' },
Key::Num2 => match shift { false => '2', true => '@' },
Key::Num3 => match shift { false => '3', true => '#' },
Key::Num4 => match shift { false => '4', true => '$' },
Key::Num5 => match shift { false => '5', true => '%' },
Key::Num6 => match shift { false => '6', true => '^' },
Key::Num7 => match shift { false => '7', true => '&' },
Key::Num8 => match shift { false => '8', true => '*' },
Key::Num9 => match shift { false => '9', true => '(' },
Key::Minus => match shift {false => '-', true => '_'},
Key::Equals => match shift {false => '=', true => '+'},
Key::LeftBracket => match shift {false => '[', true => '{'},
Key::RightBracket => match shift {false => ']', true => '}'},
Key::Backslash => match shift {false => '\\', true => '|'},
Key::Semicolon => match shift {false => ';', true => ':'},
Key::Apostrophe => match shift {false => '\'', true => '"'},
Key::Grave => match shift {false => '`', true => '~'},
Key::Comma => match shift {false => ',', true => '<'},
Key::Period => match shift {false => '.', true => '>'},
Key::Slash => match shift {false => '/', true => '?'},
Key::KpDivide => '/',
Key::KpMultiply => '*',
Key::KpMinus => '-',
Key::KpPlus => '+',
_ => 0u8 as char
}
};
if ch as u32 != 0 {
self.keys_buffer.remove(&ch_key);
Some(ch)
} else { None
}
} else {
None
}
}
fn swap_if_lefthand(&self, btn: Button) -> Button {
if self.left_hand {
match btn {
Button::Left => Button::Right,
Button::Right => Button::Left,
_ => btn
}
} else {
btn
}
}
pub fn test_btn(&self, btn: Button) -> bool {
match buttons::to_sdl(Some(self.swap_if_lefthand(btn))) {
Some(b) => self.event_pump.relative_mouse_state().is_mouse_button_pressed(b),
None => false
}
}
pub fn poll_btn(&mut self, btn: Button) -> bool {
match self.buttons_buffer.take(&(self.swap_if_lefthand(btn))) { Some(_) => true,
None => false
}
}
fn clear(&mut self) {
self.keys_buffer.clear();
self.buttons_buffer.clear();
self.mouse_dx = 0;
self.mouse_dy = 0;
self.mouse_dw = 0;
}
pub fn sync(&mut self) -> Result<(), String> {
self.clear();
for event in self.event_pump.poll_iter() {
match event {
Event::KeyDown{scancode, ..} => {
match keys::from_sdl(scancode) {
Some(k) => {self.keys_buffer.insert(k);},
None => {}
}
},
Event::MouseButtonDown{mouse_btn, ..} => {
match buttons::from_sdl(Some(mouse_btn)) {
Some(b) => {self.buttons_buffer.insert(b);},
None => {}
}
},
Event::MouseWheel{y, ..} => {
self.mouse_dw += y;
},
Event::MouseMotion{xrel, yrel, ..} => {
self.mouse_dx += xrel;
self.mouse_dy += yrel;
},
_ => {}
}
}
Ok(())
}
pub fn shut(&mut self) -> Result<(), String> {
Ok(())
}
}