diff --git a/src/main.rs b/src/main.rs index 137ea65..8d43e1e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,12 @@ struct Args { help = "Create a new input profile (keyboard/gamepad mappings)." )] configure_input_profile: Option, + #[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; } diff --git a/src/ui/config.rs b/src/ui/config.rs index b54a7e1..7d8938b 100644 --- a/src/ui/config.rs +++ b/src/ui/config.rs @@ -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)] diff --git a/src/ui/gui.rs b/src/ui/gui.rs index e635f1b..161b801 100644 --- a/src/ui/gui.rs +++ b/src/ui/gui.rs @@ -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>>, vru_word_notifier: Option>, @@ -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() diff --git a/src/ui/input.rs b/src/ui/input.rs index 6639e36..9534380 100644 --- a/src/ui/input.rs +++ b/src/ui/input.rs @@ -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() {