ferretro/ferretro_components/src/provided/sdl2/keyboard.rs

89 lines
3.5 KiB
Rust

use std::collections::HashMap;
use crate::base::ControlFlow;
use crate::prelude::*;
use sdl2::Sdl;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
// FIXME: make it not hard require EventPump ownership, or allow user-provided function?
/// Maps the first "RetroPad" layout to the keyboard.
///
/// NOTE: This component is intended for exceedingly simple use-cases, and *must own* the
/// [sdl2::EventPump].
pub struct SimpleSdl2KeyboardComponent {
button_map: HashMap<Keycode, InputDeviceId>,
button_state: HashMap<InputDeviceId, i16>,
event_pump: sdl2::EventPump,
}
impl RetroCallbacks for SimpleSdl2KeyboardComponent {
fn input_state(&mut self, port: u32, device: InputDeviceId, _index: InputIndex) -> i16 {
if port != 0 {
return 0;
}
self.button_state.get(&device).cloned().unwrap_or_default()
}
fn get_input_device_capabilities(&mut self) -> Option<u64> {
let bits = 1 << (DeviceType::Joypad as u32);
Some(bits as u64)
}
}
impl RetroComponent for SimpleSdl2KeyboardComponent {
fn pre_run(&mut self, _retro: &mut LibretroWrapper) -> ControlFlow {
for event in self.event_pump.poll_iter() {
match event {
Event::Quit { .. }
| Event::KeyDown {
keycode: Some(Keycode::Escape),
..
} => return ControlFlow::Break,
Event::KeyDown { keycode: Some(k), .. } => {
if let Some(button) = self.button_map.get(&k) {
self.button_state.insert(button.to_owned(), 1);
}
}
Event::KeyUp { keycode: Some(k), .. } => {
if let Some(button) = self.button_map.get(&k) {
self.button_state.remove(button);
}
}
_ => {}
}
}
ControlFlow::Continue
}
}
impl SimpleSdl2KeyboardComponent {
pub fn new(sdl_context: &mut Sdl) -> crate::base::Result<Self> {
let event_pump = sdl_context.event_pump()?;
Ok(SimpleSdl2KeyboardComponent {
button_map: [
(Keycode::Up, InputDeviceId::Joypad(JoypadButton::Up)),
(Keycode::Down, InputDeviceId::Joypad(JoypadButton::Down)),
(Keycode::Left, InputDeviceId::Joypad(JoypadButton::Left)),
(Keycode::Right, InputDeviceId::Joypad(JoypadButton::Right)),
(Keycode::X, InputDeviceId::Joypad(JoypadButton::A)),
(Keycode::Z, InputDeviceId::Joypad(JoypadButton::B)),
(Keycode::S, InputDeviceId::Joypad(JoypadButton::X)),
(Keycode::A, InputDeviceId::Joypad(JoypadButton::Y)),
(Keycode::Q, InputDeviceId::Joypad(JoypadButton::L)),
(Keycode::W, InputDeviceId::Joypad(JoypadButton::R)),
(Keycode::E, InputDeviceId::Joypad(JoypadButton::L2)),
(Keycode::R, InputDeviceId::Joypad(JoypadButton::R2)),
(Keycode::T, InputDeviceId::Joypad(JoypadButton::L3)),
(Keycode::Y, InputDeviceId::Joypad(JoypadButton::R3)),
(Keycode::Return, InputDeviceId::Joypad(JoypadButton::Start)),
(Keycode::Backspace, InputDeviceId::Joypad(JoypadButton::Select)),
(Keycode::Tab, InputDeviceId::Joypad(JoypadButton::Select)),
].into_iter().collect(),
button_state: Default::default(),
event_pump,
})
}
}