use crate::prelude::*;
use crate::core::Display;
pub const NUM_KEYS: usize = 256;
pub const NUM_BUTTONS: usize = 16;
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum InputState {
Up,
Pressed,
Down,
Released,
Repeat,
}
pub struct InputData {
pub mouse : (i32, i32),
pub mouse_delta : (i32, i32),
pub button : [ InputState; NUM_BUTTONS ],
pub key : [ InputState; NUM_KEYS ],
pub should_close : bool,
pub cursor_grabbed : bool,
pub has_focus : bool,
pub dimensions : (u32, u32),
}
impl InputData {
pub fn new() -> InputData {
InputData {
mouse : (0, 0),
mouse_delta : (0, 0),
button : [ InputState::Up; NUM_BUTTONS ],
key : [ InputState::Up; NUM_KEYS ],
should_close : false,
cursor_grabbed : false,
has_focus : true,
dimensions : (0, 0),
}
}
pub fn reset(self: &mut Self) {
for key_id in 0..NUM_KEYS {
match self.key[key_id] {
InputState::Pressed | InputState::Repeat => {
self.key[key_id] = InputState::Down;
}
InputState::Released => {
self.key[key_id] = InputState::Up;
}
_ => { }
}
}
for button_id in 0..NUM_BUTTONS {
match self.button[button_id] {
InputState::Pressed => {
self.button[button_id] = InputState::Down;
}
InputState::Released => {
self.button[button_id] = InputState::Up;
}
_ => { }
}
}
self.mouse_delta = (0, 0);
}
}
enum_from_primitive! {
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum InputId {
Key1,
Key2,
Key3,
Key4,
Key5,
Key6,
Key7,
Key8,
Key9,
Key0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
Escape,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
Snapshot,
Scroll,
Pause,
Insert,
Home,
Delete,
End,
PageDown,
PageUp,
CursorLeft,
CursorUp,
CursorRight,
CursorDown,
Backspace,
Return,
Space,
Numlock,
Numpad0,
Numpad1,
Numpad2,
Numpad3,
Numpad4,
Numpad5,
Numpad6,
Numpad7,
Numpad8,
Numpad9,
AbntC1,
AbntC2,
Add,
Apostrophe,
Apps,
At,
Ax,
Backslash,
Calculator,
Capital,
Caret,
Colon,
Comma,
Convert,
Decimal,
Divide,
Equals,
Grave,
Kana,
Kanji,
LAlt,
LBracket,
LControl,
LMenu,
LShift,
LWin,
Mail,
MediaSelect,
MediaStop,
Minus,
Multiply,
Mute,
MyComputer,
NextTrack,
NoConvert,
NumpadComma,
NumpadEnter,
NumpadEquals,
OEM102,
Period,
PlayPause,
Power,
PrevTrack,
RAlt,
RBracket,
RControl,
RMenu,
RShift,
RWin,
Semicolon,
Slash,
Sleep,
Stop,
Subtract,
Sysrq,
Tab,
Underline,
Unlabeled,
VolumeDown,
VolumeUp,
Wake,
WebBack,
WebFavorites,
WebForward,
WebHome,
WebRefresh,
WebSearch,
WebStop,
Yen,
Compose,
NavigateForward,
NavigateBackward,
Mouse1 = NUM_KEYS as isize +0,
Mouse2 = NUM_KEYS as isize +1,
Mouse3 = NUM_KEYS as isize +2,
Mouse4 = NUM_KEYS as isize +3,
Mouse5 = NUM_KEYS as isize +4,
Mouse6 = NUM_KEYS as isize +5,
Mouse7 = NUM_KEYS as isize +6,
Mouse8 = NUM_KEYS as isize +7,
Mouse9 = NUM_KEYS as isize +8,
Mouse10 = NUM_KEYS as isize +9,
Mouse11 = NUM_KEYS as isize +10,
Mouse12 = NUM_KEYS as isize +11,
Mouse13 = NUM_KEYS as isize +12,
Mouse14 = NUM_KEYS as isize +13,
Mouse15 = NUM_KEYS as isize +14,
Mouse16 = NUM_KEYS as isize +15,
Unsupported = (NUM_KEYS + NUM_BUTTONS) as isize,
}
}
impl InputId {
pub fn button(id: usize) -> InputId {
use enum_primitive::FromPrimitive;
let base = InputId::Mouse1 as isize;
if (id >= 1) & (id <= 16) {
InputId::from_isize(base + (id as isize - 1)).unwrap()
} else {
InputId::Unsupported
}
}
}
#[derive(Clone)]
pub struct Input {
pub (crate) input_data: Arc<RwLock<InputData>>,
}
impl Debug for Input {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Input")
}
}
impl Input {
pub fn new(display: &Display) -> Self {
Input {
input_data: display.input_data.clone(),
}
}
pub fn iter(self: &Self) -> InputIterator<'_> {
InputIterator {
input_data: self.input_data.read().unwrap(),
position: 0,
}
}
pub fn mouse(self: &Self) -> (i32, i32) {
self.get().mouse
}
pub fn mouse_delta(self: &Self) -> (i32, i32) {
self.get().mouse_delta
}
pub fn down(self: &Self, key: InputId) -> bool {
let id = key as usize;
let data = self.get();
if id < NUM_KEYS {
(data.key[id] == InputState::Pressed) || (data.key[id] == InputState::Down) || (data.key[id] == InputState::Repeat)
} else {
(data.button[id - NUM_KEYS] == InputState::Pressed) || (data.button[id - NUM_KEYS] == InputState::Down)
}
}
pub fn pressed(self: &Self, key: InputId, report_repeats: bool) -> bool {
let id = key as usize;
let data = self.get();
if id < NUM_KEYS {
(data.key[id] == InputState::Pressed) || (report_repeats && data.key[id] == InputState::Repeat)
} else {
data.button[id - NUM_KEYS] == InputState::Pressed
}
}
pub fn up(self: &Self, key: InputId) -> bool {
let id = key as usize;
let data = self.get();
if id < NUM_KEYS {
data.key[id] == InputState::Released || (data.key[id] == InputState::Up)
} else {
data.button[id - NUM_KEYS] == InputState::Released || (data.button[id - NUM_KEYS] == InputState::Up)
}
}
pub fn released(self: &Self, key: InputId) -> bool {
let id = key as usize;
let data = self.get();
if id < NUM_KEYS {
data.key[id] == InputState::Released
} else {
data.button[id - NUM_KEYS] == InputState::Released
}
}
pub fn state(self: &Self, key: InputId) -> InputState {
let id = key as usize;
let data = self.get();
if id < NUM_KEYS {
data.key[id]
} else {
data.button[id - NUM_KEYS]
}
}
fn get(self: &Self) -> RwLockReadGuard<'_, InputData> {
self.input_data.read().unwrap()
}
}
pub struct InputIterator<'a> {
input_data: RwLockReadGuard<'a, InputData>,
position: usize,
}
impl<'a> InputIterator<'a> {
pub fn down(self: Self) -> InputDownIterator<'a> {
InputDownIterator(self)
}
pub fn up(self: Self) -> InputUpIterator<'a> {
InputUpIterator(self)
}
}
impl<'a> Iterator for InputIterator<'a> {
type Item = (InputId, InputState);
fn next(self: &mut Self) -> Option<(InputId, InputState)> {
use enum_primitive::FromPrimitive;
let position = self.position;
self.position += 1;
if position < NUM_KEYS {
Some((InputId::from_usize(position).unwrap_or(InputId::Unsupported), self.input_data.key[position]))
} else if position < NUM_KEYS + NUM_BUTTONS {
Some((InputId::from_usize(position).unwrap_or(InputId::Unsupported), self.input_data.button[position - NUM_KEYS]))
} else {
None
}
}
}
pub struct InputDownIterator<'a>(InputIterator<'a>);
impl<'a> Iterator for InputDownIterator<'a> {
type Item = InputId;
fn next(self: &mut Self) -> Option<InputId> {
while let Some(current) = self.0.next() {
let (input_id, button_state) = current;
if (button_state == InputState::Down) || (button_state == InputState::Pressed) {
return Some(input_id);
}
}
None
}
}
pub struct InputUpIterator<'a>(InputIterator<'a>);
impl<'a> Iterator for InputUpIterator<'a> {
type Item = InputId;
fn next(self: &mut Self) -> Option<InputId> {
while let Some(current) = self.0.next() {
let (input_id, button_state) = current;
if (button_state == InputState::Up) || (button_state == InputState::Released) {
return Some(input_id);
}
}
None
}
}