use crate::*; use std::collections::VecDeque; pub struct InputDevice { pub cursor: ScreenPosition, pub x_read: u16, pub y_read: u16, pub h_scroll_read: i16, pub v_scroll_read: i16, pub h_scroll: f32, pub v_scroll: f32, pub pointer_buttons: u8, pub pointer_active: bool, pub navigation: u8, pub modifiers: u8, pub characters: VecDeque, pub gamepad_1: OwnedGamepad, pub gamepad_2: OwnedGamepad, pub gamepad_3: OwnedGamepad, pub gamepad_4: OwnedGamepad, pub accessed: bool, pub wake: bool, } impl Device for InputDevice { fn read(&mut self, port: u8) -> u8 { self.accessed = true; match port { 0x0 => { self.x_read = self.cursor.x; read_h!(self.x_read) }, 0x1 => read_l!(self.cursor.x), 0x2 => { self.y_read = self.cursor.y; read_h!(self.y_read) }, 0x3 => read_l!(self.cursor.y), 0x4 => { self.update_horizontal_scroll(); read_h!(self.h_scroll_read) }, 0x5 => read_l!(self.h_scroll_read), 0x6 => { self.update_vertical_scroll(); read_h!(self.v_scroll_read) }, 0x7 => read_l!(self.v_scroll_read), 0x8 => read_b!(self.pointer_active), 0x9 => self.pointer_buttons, 0xA => self.characters.pop_front().unwrap_or(0), 0xB => self.modifiers, 0xC => self.gamepad_1.state() | self.navigation, 0xD => self.gamepad_2.state(), 0xE => self.gamepad_3.state(), 0xF => self.gamepad_4.state(), _ => unreachable!(), } } fn write(&mut self, port: u8, _value: u8) -> Option { let signal = if self.accessed { None } else { Some(Signal::Break) }; self.accessed = true; match port { 0x0 => (), 0x1 => (), 0x2 => (), 0x3 => (), 0x4 => (), 0x5 => (), 0x6 => (), 0x7 => (), 0x8 => (), 0x9 => (), 0xA => self.characters.clear(), 0xB => (), 0xC => (), 0xD => (), 0xE => (), 0xF => (), _ => unreachable!(), }; return signal; } fn wake(&mut self) -> bool { self.accessed = true; std::mem::take(&mut self.wake) } fn reset(&mut self) { self.cursor = ScreenPosition::ZERO; self.x_read = 0; self.y_read = 0; self.h_scroll_read = 0; self.v_scroll_read = 0; self.h_scroll = 0.0; self.v_scroll = 0.0; self.pointer_active = false; self.pointer_buttons = 0; self.navigation = 0; self.modifiers = 0; self.characters.clear(); self.gamepad_1.reset(); self.gamepad_2.reset(); self.gamepad_3.reset(); self.gamepad_4.reset(); self.accessed = false; self.wake = false; } } impl InputDevice { pub fn new() -> Self { Self { cursor: ScreenPosition::ZERO, x_read: 0, y_read: 0, h_scroll_read: 0, v_scroll_read: 0, h_scroll: 0.0, v_scroll: 0.0, pointer_active: false, pointer_buttons: 0, navigation: 0, modifiers: 0, characters: VecDeque::new(), gamepad_1: OwnedGamepad::new(1), gamepad_2: OwnedGamepad::new(2), gamepad_3: OwnedGamepad::new(3), gamepad_4: OwnedGamepad::new(4), accessed: false, wake: false, } } pub fn on_gamepad_event(&mut self, event: gilrs::Event) { if let Some(g) = self.gamepad_1.register(event.id) { self.wake |= g.process_event(&event); return; } if let Some(g) = self.gamepad_2.register(event.id) { self.wake |= g.process_event(&event); return; } if let Some(g) = self.gamepad_3.register(event.id) { self.wake |= g.process_event(&event); return; } if let Some(g) = self.gamepad_4.register(event.id) { self.wake |= g.process_event(&event); return; } } pub fn on_cursor_enter(&mut self) { self.pointer_active = true; self.wake = true; } pub fn on_cursor_exit(&mut self) { self.pointer_active = false; self.wake = true; } pub fn on_cursor_move(&mut self, position: Position) { self.pointer_active = true; let cursor_position = ScreenPosition { x: position.x as i16 as u16, y: position.y as i16 as u16, }; if self.cursor != cursor_position { self.cursor = cursor_position; self.wake = true; } } pub fn on_mouse_button(&mut self, button: MouseButton, action: Action) { let mask = match button { MouseButton::Left => 0x80, MouseButton::Right => 0x40, MouseButton::Middle => 0x20, _ => return, }; let pointer_buttons = match action { Action::Pressed => self.pointer_buttons | mask, Action::Released => self.pointer_buttons & !mask, }; if self.pointer_buttons != pointer_buttons { self.pointer_buttons = pointer_buttons; self.wake = true; } } pub fn on_horizontal_scroll(&mut self, delta: f32) { self.h_scroll += delta; self.h_scroll = self.h_scroll.clamp(-32768.0, 32767.0); } pub fn on_vertical_scroll(&mut self, delta: f32) { self.v_scroll += delta; self.v_scroll = self.v_scroll.clamp(i16::MIN as f32, i16::MAX as f32); } pub fn update_horizontal_scroll(&mut self) { self.h_scroll_read = self.h_scroll.trunc() as i16; self.h_scroll -= self.h_scroll.trunc(); } pub fn update_vertical_scroll(&mut self) { self.v_scroll_read = self.v_scroll.trunc() as i16; self.v_scroll -= self.v_scroll.trunc(); } pub fn on_character(&mut self, character: char) { let character = match character { '\r' => '\n', _ => character, }; let mut bytes = [0; 4]; let string = character.encode_utf8(&mut bytes); for byte in string.bytes() { self.characters.push_back(byte); } self.wake = true; } pub fn on_keypress(&mut self, key: KeyCode, action: Action) { let shift = self.modifiers & 0x40 != 0; let mask = match key { KeyCode::ArrowUp => 0x80, // up KeyCode::ArrowDown => 0x40, // down KeyCode::ArrowLeft => 0x20, // left KeyCode::ArrowRight => 0x10, // right KeyCode::Enter => 0x08, // confirm KeyCode::Escape => 0x04, // cancel KeyCode::Tab => match shift { // shift false => 0x02, // next true => 0x01 // previous }, _ => return, }; let navigation = match action { Action::Pressed => self.navigation | mask, Action::Released => self.navigation & !mask, }; if self.navigation != navigation { self.navigation = navigation; self.wake = true; } } pub fn on_modifier(&mut self, state: ModifiersState) { let mut modifiers = 0; if state.control_key() { modifiers |= 0x80 } if state.shift_key() { modifiers |= 0x40 } if state.alt_key() { modifiers |= 0x20 } if state.super_key() { modifiers |= 0x10 } if self.modifiers != modifiers { self.modifiers = modifiers; self.wake = true; } } }