more code cleanup, add a stub implementation of the mouse input device

This commit is contained in:
Lily Tsuru 2024-08-04 21:23:24 -04:00
parent a7544cb64d
commit cfbbc37f8a
6 changed files with 91 additions and 17 deletions

View file

@ -35,6 +35,11 @@ pub trait FrontendInterface {
/// Called to poll input /// Called to poll input
fn input_poll(&mut self); fn input_poll(&mut self);
// TODO(lily): Provide APIs for gathering a GL context/fbo.
// This should be abstracted so if a frontend written on top of retro_frontend
// wants to give a FBO from a GLX/WGL/windowed whatever context, it can,
// but a headless frontend can itself provide a headless EGL context just the same.
} }
/// Per-core settings /// Per-core settings
@ -62,11 +67,14 @@ pub struct Frontend {
/// Converted pixel buffer. We store it here so we don't keep allocating over and over. /// Converted pixel buffer. We store it here so we don't keep allocating over and over.
pub(crate) converted_pixel_buffer: Vec<u32>, pub(crate) converted_pixel_buffer: Vec<u32>,
// Framebuffer attributes. TODO: This really should be another struct or something
// with members to make dealing with it less annoying.
pub(crate) fb_width: u32, pub(crate) fb_width: u32,
pub(crate) fb_height: u32, pub(crate) fb_height: u32,
pub(crate) fb_pitch: u32, pub(crate) fb_pitch: u32,
/// The "system" directory. Used for BIOS roms /// The "system" directory. Used for BIOS roms.
pub(crate) system_directory: CString, pub(crate) system_directory: CString,
/// The save directory. Used for saves. (TODO: Should make this per-core!!!) /// The save directory. Used for saves. (TODO: Should make this per-core!!!)
@ -75,10 +83,11 @@ pub struct Frontend {
/// The config directory. Stores configuration for each core. /// The config directory. Stores configuration for each core.
pub(crate) config_directory: String, pub(crate) config_directory: String,
/// Hashmap of core variabels. /// Hashmap of core variables.
pub(crate) variables: HashMap<String, CoreVariable>, pub(crate) variables: HashMap<String, CoreVariable>,
pub(crate) joypads: HashMap<u32 /* port */, *mut dyn InputDevice>, /// Hashmap of connected input devices.
pub(crate) input_devices: HashMap<u32 /* port */, *mut dyn InputDevice>,
pub(crate) interface: *mut dyn FrontendInterface, pub(crate) interface: *mut dyn FrontendInterface,
} }
@ -110,12 +119,12 @@ impl Frontend {
variables: HashMap::new(), variables: HashMap::new(),
joypads: HashMap::new(), input_devices: HashMap::new(),
interface: interface, interface: interface,
}); });
// Assign to the global fronend pointer // Assign to the global frontend pointer
unsafe { unsafe {
assert!(FRONTEND.is_null(), "Cannot have multiple frontends."); assert!(FRONTEND.is_null(), "Cannot have multiple frontends.");
FRONTEND = &mut *boxed as *mut Frontend; FRONTEND = &mut *boxed as *mut Frontend;
@ -138,10 +147,10 @@ impl Frontend {
(core_api.retro_set_controller_port_device)(port, (*device).device_type()); (core_api.retro_set_controller_port_device)(port, (*device).device_type());
} }
if !self.joypads.contains_key(&port) { if !self.input_devices.contains_key(&port) {
self.joypads.insert(port, device); self.input_devices.insert(port, device);
} else { } else {
(*self.joypads.get_mut(&port).unwrap()) = device; (*self.input_devices.get_mut(&port).unwrap()) = device;
} }
} }
} }
@ -155,8 +164,8 @@ impl Frontend {
(core_api.retro_set_controller_port_device)(port, DEVICE_NONE); (core_api.retro_set_controller_port_device)(port, DEVICE_NONE);
} }
if !self.joypads.contains_key(&port) { if !self.input_devices.contains_key(&port) {
self.joypads.remove(&port); self.input_devices.remove(&port);
} }
} }
} }
@ -349,7 +358,7 @@ impl Frontend {
self.fb_pitch = 0; self.fb_pitch = 0;
// disconnect all currently connected joypads // disconnect all currently connected joypads
self.joypads.clear(); self.input_devices.clear();
Ok(()) Ok(())
} }

View file

@ -2,16 +2,21 @@
pub mod retropad; pub mod retropad;
pub use retropad::*; pub use retropad::*;
pub mod mouse;
pub use mouse::*;
/// Trait for implementing Libretro input devices /// Trait for implementing Libretro input devices
pub trait InputDevice { pub trait InputDevice {
// TODO: is_pressed(id: u32)? /// Gets the device type. This should never EVER change, and simply return a constant.
fn device_type(&self) -> u32; fn device_type(&self) -> u32;
/// Gets the state of one button/axis.
/// is_pressed(id) can simply be expressed as `(get_button(id) != 0)`.
fn get_button(&self, id: u32) -> i16; fn get_button(&self, id: u32) -> i16;
/// Clears the state of all buttons/axes.
fn reset(&mut self); fn reset(&mut self);
/// Presses a button/axis.
fn press_button(&mut self, id: u32, pressure: Option<i16>); fn press_button(&mut self, id: u32, pressure: Option<i16>);
} }

View file

@ -0,0 +1,57 @@
//! Mouse
use super::InputDevice;
use crate::libretro_sys_new;
/// Implementation of the [InputDevice] trait for the Libretro mouse.
pub struct Mouse {
buttons: [i16; 8],
// TODO: hold the last x/y so we can calculate relative position
}
impl Mouse {
pub fn new() -> Self {
Self { buttons: [0; 8] }
}
// helpers:
//
// set_pos(x, y) (will do all the stupid scaling, and press the axes with the right value)
// set_buttons(mask) (will press all buttons, including wheel based on standard button mask)
}
impl InputDevice for Mouse {
fn device_type(&self) -> u32 {
libretro_sys_new::DEVICE_MOUSE
}
fn get_button(&self, id: u32) -> i16 {
if id > 8 {
return 0;
}
self.buttons[id as usize]
}
fn reset(&mut self) {
for button in &mut self.buttons {
*button = 0i16;
}
}
fn press_button(&mut self, id: u32, pressure: Option<i16>) {
if id > 8 {
return;
}
match pressure {
Some(pressure_value) => {
self.buttons[id as usize] = pressure_value;
}
None => {
// ? or 0x7fff ? Unsure
self.buttons[id as usize] = 0x7fff;
}
}
}
}

View file

@ -45,7 +45,7 @@ impl InputDevice for RetroPad {
} }
None => { None => {
// ? or 0x7fff ? Unsure // ? or 0x7fff ? Unsure
self.buttons[id as usize] = 1; self.buttons[id as usize] = 0x7fff;
} }
} }
} }

View file

@ -240,9 +240,9 @@ pub(crate) unsafe extern "C" fn input_state_callback(
_index: ffi::c_uint, // not used? _index: ffi::c_uint, // not used?
button_id: ffi::c_uint, button_id: ffi::c_uint,
) -> ffi::c_short { ) -> ffi::c_short {
if (*FRONTEND).joypads.contains_key(&port) { if (*FRONTEND).input_devices.contains_key(&port) {
let joypad = *(*FRONTEND) let joypad = *(*FRONTEND)
.joypads .input_devices
.get(&port) .get(&port)
.expect("How do we get here when contains_key() returns true but the key doen't exist"); .expect("How do we get here when contains_key() returns true but the key doen't exist");

View file

@ -125,6 +125,9 @@ impl RfbServer {
} }
} }
// TODO: Pull this out of here, and instead do it in retrovnc app proper.
// This will also make the rfb code more generic which is always a good thing
pub fn get_buttons(&self) -> [bool; 32] { pub fn get_buttons(&self) -> [bool; 32] {
self.buttons self.buttons
} }