Use GameController API in profile setup (#153)

* Use GameController API in profile setup

* more

* more

* more

* more

* more

* more

* more
This commit is contained in:
Logan McNaughton 2025-01-16 18:49:46 +01:00 committed by GitHub
parent 842c81988f
commit b581bdcd40
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 78 additions and 20 deletions

View File

@ -18,6 +18,12 @@ struct Args {
help = "Create a new input profile (keyboard/gamepad mappings)."
)]
configure_input_profile: Option<String>,
#[arg(
short,
long,
help = "Use DirectInput when configuring a new input profile."
)]
use_dinput: bool,
#[arg(
short,
long,
@ -139,6 +145,7 @@ fn main() {
ui::input::configure_input_profile(
&mut device.ui,
args.configure_input_profile.unwrap(),
args.use_dinput,
);
return;
}

View File

@ -8,6 +8,7 @@ pub struct InputProfile {
pub joystick_buttons: [(bool, u32); 14],
pub joystick_hat: [(bool, u32, u8); 14],
pub joystick_axis: [(bool, u32, i16); 18],
pub dinput: bool,
}
#[derive(serde::Serialize, serde::Deserialize)]

View File

@ -17,6 +17,7 @@ pub struct GopherEguiApp {
integer_scaling: bool,
fullscreen: bool,
emulate_vru: bool,
dinput: bool,
show_vru_dialog: bool,
vru_window_receiver: Option<std::sync::mpsc::Receiver<Vec<String>>>,
vru_word_notifier: Option<std::sync::mpsc::Sender<String>>,
@ -100,6 +101,7 @@ impl GopherEguiApp {
fullscreen: game_ui.config.video.fullscreen,
emulate_vru: game_ui.config.input.emulate_vru,
show_vru_dialog: false,
dinput: false,
vru_window_receiver: None,
vru_word_notifier: None,
vru_word_list: Vec::new(),
@ -158,13 +160,19 @@ impl eframe::App for GopherEguiApp {
ui.text_edit_singleline(&mut self.profile_name)
.labelled_by(name_label.id);
});
ui.checkbox(&mut self.dinput, "Use DirectInput");
ui.horizontal(|ui| {
if ui.button("Configure Profile").clicked() {
let profile_name = self.profile_name.clone();
let config_dir = self.config_dir.clone();
execute(async {
let dinput = self.dinput;
execute(async move {
let mut game_ui = ui::Ui::new(config_dir);
ui::input::configure_input_profile(&mut game_ui, profile_name);
ui::input::configure_input_profile(
&mut game_ui,
profile_name,
dinput,
);
});
self.configure_profile = false;
if !self.profile_name.is_empty()

View File

@ -256,10 +256,10 @@ pub fn get(ui: &mut ui::Ui, channel: usize) -> u32 {
}
}
if joystick.is_some() {
set_buttons_from_joystick(profile, i, joystick.as_ref().unwrap(), &mut keys);
} else if controller.is_some() {
if controller.is_some() {
set_buttons_from_controller(profile, i, controller.as_ref().unwrap(), &mut keys);
} else if joystick.is_some() {
set_buttons_from_joystick(profile, i, joystick.as_ref().unwrap(), &mut keys);
}
}
@ -270,10 +270,10 @@ pub fn get(ui: &mut ui::Ui, channel: usize) -> u32 {
(x, y) = set_axis_from_keys(profile, keyboard_state);
}
if joystick.is_some() {
(x, y) = set_axis_from_joystick(profile, joystick.as_ref().unwrap())
} else if controller.is_some() {
if controller.is_some() {
(x, y) = set_axis_from_controller(profile, controller.as_ref().unwrap())
} else if joystick.is_some() {
(x, y) = set_axis_from_joystick(profile, joystick.as_ref().unwrap())
}
bound_axis(&mut x, &mut y);
@ -323,7 +323,7 @@ pub fn clear_bindings(ui: &mut ui::Ui) {
}
}
pub fn configure_input_profile(ui: &mut ui::Ui, profile: String) {
pub fn configure_input_profile(ui: &mut ui::Ui, profile: String, dinput: bool) {
if profile == "default" {
println!("Profile name cannot be default");
return;
@ -332,10 +332,20 @@ pub fn configure_input_profile(ui: &mut ui::Ui, profile: String) {
println!("Profile name cannot be empty");
return;
}
let controller_subsystem = ui.controller_subsystem.as_ref().unwrap();
let joystick_subsystem = ui.joystick_subsystem.as_ref().unwrap();
let mut controllers = vec![];
let mut joysticks = vec![];
for i in 0..joystick_subsystem.num_joysticks().unwrap() {
joysticks.push(joystick_subsystem.open(i));
if !dinput {
if let Ok(controller) = controller_subsystem.open(i) {
controllers.push(controller);
continue;
}
}
if let Ok(joystick) = joystick_subsystem.open(i) {
joysticks.push(joystick);
}
}
let mut builder =
@ -374,8 +384,11 @@ pub fn configure_input_profile(ui: &mut ui::Ui, profile: String) {
let mut new_joystick_buttons = [(false, 0u32); 14];
let mut new_joystick_hat = [(false, 0u32, 0); 14];
let mut new_joystick_axis = [(false, 0u32, 0); 18];
let mut new_controller_buttons = [(false, 0i32); 14];
let mut new_controller_axis = [(false, 0i32, 0); 18];
let mut last_axis_result = (false, 0, 0);
let mut last_joystick_axis_result = (false, 0, 0);
let mut last_controller_axis_result = (false, 0, 0);
let mut events = ui.sdl_context.as_ref().unwrap().event_pump().unwrap();
for (key, value) in key_labels.iter() {
for _event in events.poll_iter() {} // clear events
@ -402,12 +415,35 @@ pub fn configure_input_profile(ui: &mut ui::Ui, profile: String) {
new_keys[*value] = (true, scancode as i32);
key_set = true
}
sdl2::event::Event::ControllerButtonDown { button, .. } => {
if !controllers.is_empty() {
new_controller_buttons[*value] = (true, button as i32);
key_set = true
}
}
sdl2::event::Event::ControllerAxisMotion {
axis,
value: axis_value,
..
} => {
if !controllers.is_empty() && axis_value.saturating_abs() > i16::MAX / 2 {
let result =
(true, axis as i32, axis_value / axis_value.saturating_abs());
if result != last_controller_axis_result {
new_controller_axis[*value] = result;
last_controller_axis_result = result;
key_set = true
}
}
}
sdl2::event::Event::JoyButtonDown { button_idx, .. } => {
new_joystick_buttons[*value] = (true, button_idx as u32);
key_set = true
if !joysticks.is_empty() {
new_joystick_buttons[*value] = (true, button_idx as u32);
key_set = true
}
}
sdl2::event::Event::JoyHatMotion { hat_idx, state, .. } => {
if state != sdl2::joystick::HatState::Centered {
if !joysticks.is_empty() && state != sdl2::joystick::HatState::Centered {
new_joystick_hat[*value] = (
true,
hat_idx as u32,
@ -421,15 +457,15 @@ pub fn configure_input_profile(ui: &mut ui::Ui, profile: String) {
value: axis_value,
..
} => {
if axis_value.saturating_abs() > 24576 {
if !joysticks.is_empty() && axis_value.saturating_abs() > i16::MAX / 2 {
let result = (
true,
axis_idx as u32,
axis_value / axis_value.saturating_abs(),
);
if result != last_axis_result {
if result != last_joystick_axis_result {
new_joystick_axis[*value] = result;
last_axis_result = result;
last_joystick_axis_result = result;
key_set = true
}
}
@ -442,11 +478,12 @@ pub fn configure_input_profile(ui: &mut ui::Ui, profile: String) {
let new_profile = ui::config::InputProfile {
keys: new_keys,
controller_buttons: Default::default(),
controller_axis: Default::default(),
controller_buttons: new_controller_buttons,
controller_axis: new_controller_axis,
joystick_buttons: new_joystick_buttons,
joystick_hat: new_joystick_hat,
joystick_axis: new_joystick_axis,
dinput,
};
ui.config.input.input_profiles.insert(profile, new_profile);
}
@ -500,6 +537,7 @@ pub fn get_default_profile() -> ui::config::InputProfile {
joystick_buttons: Default::default(),
joystick_hat: Default::default(),
joystick_axis: Default::default(),
dinput: false,
}
}
@ -522,12 +560,16 @@ pub fn init(ui: &mut ui::Ui) {
}
}
if joystick_index < u32::MAX {
if ui.config.input.input_profile_binding[i] == "default" {
let profile_name = ui.config.input.input_profile_binding[i].clone();
let profile = ui.config.input.input_profiles.get(&profile_name).unwrap();
if !profile.dinput {
let controller_result = controller_subsystem.open(joystick_index);
if controller_result.is_ok() {
ui.controllers[i].game_controller = Some(controller_result.unwrap());
}
}
if ui.controllers[i].game_controller.is_none() {
let joystick_result = joystick_subsystem.open(joystick_index);
if joystick_result.is_err() {