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
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
@ -62,11 +67,14 @@ pub struct Frontend {
/// Converted pixel buffer. We store it here so we don't keep allocating over and over.
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_height: 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,
/// 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.
pub(crate) config_directory: String,
/// Hashmap of core variabels.
/// Hashmap of core variables.
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,
}
@ -110,12 +119,12 @@ impl Frontend {
variables: HashMap::new(),
joypads: HashMap::new(),
input_devices: HashMap::new(),
interface: interface,
});
// Assign to the global fronend pointer
// Assign to the global frontend pointer
unsafe {
assert!(FRONTEND.is_null(), "Cannot have multiple frontends.");
FRONTEND = &mut *boxed as *mut Frontend;
@ -138,10 +147,10 @@ impl Frontend {
(core_api.retro_set_controller_port_device)(port, (*device).device_type());
}
if !self.joypads.contains_key(&port) {
self.joypads.insert(port, device);
if !self.input_devices.contains_key(&port) {
self.input_devices.insert(port, device);
} 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);
}
if !self.joypads.contains_key(&port) {
self.joypads.remove(&port);
if !self.input_devices.contains_key(&port) {
self.input_devices.remove(&port);
}
}
}
@ -349,7 +358,7 @@ impl Frontend {
self.fb_pitch = 0;
// disconnect all currently connected joypads
self.joypads.clear();
self.input_devices.clear();
Ok(())
}

View file

@ -2,16 +2,21 @@
pub mod retropad;
pub use retropad::*;
pub mod mouse;
pub use mouse::*;
/// Trait for implementing Libretro input devices
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;
/// 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;
/// Clears the state of all buttons/axes.
fn reset(&mut self);
/// Presses a button/axis.
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 => {
// ? 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?
button_id: ffi::c_uint,
) -> ffi::c_short {
if (*FRONTEND).joypads.contains_key(&port) {
if (*FRONTEND).input_devices.contains_key(&port) {
let joypad = *(*FRONTEND)
.joypads
.input_devices
.get(&port)
.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] {
self.buttons
}