mirror of
https://github.com/gopher64/gopher64.git
synced 2026-07-11 01:25:20 +02:00
update controllers when clicking on controller config (#841)
* update controllers when clicking on controller config * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more * more
This commit is contained in:
+1
-1
@@ -207,7 +207,7 @@ pub fn get_rom_contents(file_path: &std::path::Path) -> Option<Vec<u8>> {
|
||||
pub struct Device {
|
||||
#[serde(skip)]
|
||||
pub netplay: Option<netplay::Netplay>,
|
||||
#[serde(skip, default = "ui::Ui::default")]
|
||||
#[serde(skip, default = "ui::Ui::new")]
|
||||
pub ui: ui::Ui,
|
||||
pub byte_swap: usize,
|
||||
pub save_state: bool,
|
||||
|
||||
+22
-21
@@ -249,10 +249,10 @@ async fn main() -> std::io::Result<()> {
|
||||
ui::usb::close(shutdown_tx);
|
||||
}
|
||||
} else if std::env::args().count() > 1 {
|
||||
let mut ui = ui::Ui::new();
|
||||
let mut config = ui::config::Config::new();
|
||||
|
||||
if args.clear_input_bindings {
|
||||
ui::input::clear_bindings(&mut ui);
|
||||
ui::input::clear_bindings(&mut config);
|
||||
return Ok(());
|
||||
}
|
||||
if let Some(port) = args.port
|
||||
@@ -260,34 +260,35 @@ async fn main() -> std::io::Result<()> {
|
||||
{
|
||||
return Err(Error::other("Port must be between 1 and 4"));
|
||||
}
|
||||
if args.list_controllers {
|
||||
let controllers = ui::input::get_controller_names(&ui);
|
||||
for (i, controller) in controllers.iter().enumerate() {
|
||||
println!("Controller {i}: {controller}");
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
if let Some(profile) = args.configure_input_profile {
|
||||
ui::input::configure_input_profile(
|
||||
&mut ui,
|
||||
&mut config,
|
||||
profile,
|
||||
args.use_dinput,
|
||||
args.deadzone.unwrap_or(ui::input::DEADZONE_DEFAULT),
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
if let Some(assign_controller) = args.assign_controller {
|
||||
let Some(port) = args.port else {
|
||||
return Err(Error::other("Must specify port number"));
|
||||
};
|
||||
ui::input::assign_controller(&mut ui, assign_controller, port);
|
||||
}
|
||||
if let Some(profile) = args.bind_input_profile {
|
||||
let Some(port) = args.port else {
|
||||
return Err(Error::other("Must specify port number"));
|
||||
};
|
||||
ui::input::bind_input_profile(&mut ui, profile, port);
|
||||
if args.list_controllers {
|
||||
let controllers = ui::input::get_controller_names();
|
||||
for (i, controller) in controllers.iter().enumerate() {
|
||||
println!("Controller {i}: {controller}");
|
||||
}
|
||||
} else {
|
||||
if let Some(assign_controller) = args.assign_controller {
|
||||
let Some(port) = args.port else {
|
||||
return Err(Error::other("Must specify port number"));
|
||||
};
|
||||
ui::input::assign_controller(&mut config, assign_controller - 1, port);
|
||||
}
|
||||
if let Some(profile) = args.bind_input_profile {
|
||||
let Some(port) = args.port else {
|
||||
return Err(Error::other("Must specify port number"));
|
||||
};
|
||||
ui::input::bind_input_profile(&mut config, profile, port);
|
||||
}
|
||||
}
|
||||
unsafe { sdl3_sys::init::SDL_Quit() };
|
||||
} else {
|
||||
#[cfg(feature = "gui")]
|
||||
{
|
||||
|
||||
@@ -38,7 +38,6 @@ pub struct Audio {
|
||||
}
|
||||
|
||||
pub struct Input {
|
||||
pub joysticks: Vec<sdl3_sys::joystick::SDL_JoystickID>,
|
||||
pub keyboard_state: *const bool,
|
||||
pub controllers: [input::Controllers; 4],
|
||||
}
|
||||
@@ -77,7 +76,6 @@ pub struct Ui {
|
||||
pub config: config::Config,
|
||||
pub game_id: String,
|
||||
pub game_hash: String,
|
||||
pub with_sdl: bool,
|
||||
pub audio: Audio,
|
||||
pub input: Input,
|
||||
pub storage: Storage,
|
||||
@@ -85,17 +83,6 @@ pub struct Ui {
|
||||
pub usb: Usb,
|
||||
}
|
||||
|
||||
impl Drop for Ui {
|
||||
fn drop(&mut self) {
|
||||
if self.with_sdl {
|
||||
unsafe {
|
||||
sdl3_ttf_sys::ttf::TTF_Quit();
|
||||
sdl3_sys::init::SDL_Quit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sdl_init(flag: sdl3_sys::init::SDL_InitFlags) {
|
||||
unsafe {
|
||||
if sdl3_sys::init::SDL_WasInit(flag) == 0 && !sdl3_sys::init::SDL_InitSubSystem(flag) {
|
||||
@@ -141,7 +128,7 @@ pub fn get_dirs() -> Dirs {
|
||||
}
|
||||
|
||||
impl Ui {
|
||||
fn construct_ui(joysticks: Vec<sdl3_sys::everything::SDL_JoystickID>, with_sdl: bool) -> Ui {
|
||||
pub fn new() -> Ui {
|
||||
let dirs = get_dirs();
|
||||
|
||||
let (fps_tx, fps_rx) = tokio::sync::mpsc::channel(1000);
|
||||
@@ -179,7 +166,6 @@ impl Ui {
|
||||
},
|
||||
],
|
||||
keyboard_state: std::ptr::null_mut(),
|
||||
joysticks,
|
||||
},
|
||||
storage: Storage {
|
||||
save_state_slot: 0,
|
||||
@@ -241,26 +227,6 @@ impl Ui {
|
||||
cart_rx: None,
|
||||
},
|
||||
dirs,
|
||||
with_sdl,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default() -> Ui {
|
||||
Self::construct_ui(vec![], false)
|
||||
}
|
||||
|
||||
pub fn new() -> Ui {
|
||||
sdl_init(sdl3_sys::init::SDL_INIT_GAMEPAD);
|
||||
let mut num_joysticks = 0;
|
||||
let joysticks = unsafe { sdl3_sys::joystick::SDL_GetJoysticks(&mut num_joysticks) };
|
||||
if joysticks.is_null() {
|
||||
panic!("Could not get joystick list");
|
||||
}
|
||||
let mut joystick_vec = vec![];
|
||||
for i in 0..num_joysticks {
|
||||
joystick_vec.push(unsafe { *joysticks.add(i as usize) });
|
||||
}
|
||||
unsafe { sdl3_sys::stdinc::SDL_free(joysticks as *mut std::ffi::c_void) }
|
||||
Self::construct_ui(joystick_vec, true)
|
||||
}
|
||||
}
|
||||
|
||||
+84
-76
@@ -53,18 +53,13 @@ fn check_latest_version(weak: slint::Weak<AppWindow>) {
|
||||
});
|
||||
}
|
||||
|
||||
fn run_with_path(
|
||||
weak: slint::Weak<AppWindow>,
|
||||
path: std::path::PathBuf,
|
||||
controller_paths: &[Option<String>],
|
||||
) {
|
||||
let controller_paths = controller_paths.to_owned();
|
||||
fn run_with_path(weak: slint::Weak<AppWindow>, path: std::path::PathBuf) {
|
||||
let weak2 = weak.clone();
|
||||
weak.upgrade_in_event_loop(move |handle| {
|
||||
if handle.get_game_running() {
|
||||
return;
|
||||
}
|
||||
save_settings(&handle, &controller_paths);
|
||||
save_settings(&handle);
|
||||
|
||||
run_rom(
|
||||
path,
|
||||
@@ -87,23 +82,18 @@ fn run_with_path(
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn file_dropped(app: &AppWindow, controller_paths: &[Option<String>]) {
|
||||
fn file_dropped(app: &AppWindow) {
|
||||
let weak = app.as_weak();
|
||||
let controller_paths = controller_paths.to_owned();
|
||||
app.window()
|
||||
.on_winit_window_event(move |_winit_window, event| {
|
||||
if let slint::winit_030::winit::event::WindowEvent::DroppedFile(path) = event {
|
||||
run_with_path(weak.clone(), path.to_path_buf(), &controller_paths);
|
||||
run_with_path(weak.clone(), path.to_path_buf());
|
||||
}
|
||||
slint::winit_030::EventResult::Propagate
|
||||
});
|
||||
}
|
||||
|
||||
fn local_game_window(
|
||||
app: &AppWindow,
|
||||
config: &ui::config::Config,
|
||||
controller_paths: &[Option<String>],
|
||||
) {
|
||||
fn local_game_window(app: &AppWindow, config: &ui::config::Config) {
|
||||
let dirs = ui::get_dirs();
|
||||
|
||||
app.set_recent_roms(slint::ModelRc::from(std::rc::Rc::new(
|
||||
@@ -128,26 +118,18 @@ fn local_game_window(
|
||||
)));
|
||||
|
||||
let weak = app.as_weak();
|
||||
let owned_controller_paths = controller_paths.to_owned();
|
||||
app.on_open_rom_button_clicked(move || {
|
||||
let controller_paths = owned_controller_paths.clone();
|
||||
weak.upgrade_in_event_loop(move |handle| {
|
||||
save_settings(&handle, &controller_paths);
|
||||
save_settings(&handle);
|
||||
open_rom(&handle)
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
let weak = app.as_weak();
|
||||
let owned_controller_paths = controller_paths.to_owned();
|
||||
app.on_recent_rom_button_clicked(move |rom| {
|
||||
let controller_paths = owned_controller_paths.clone();
|
||||
weak.upgrade_in_event_loop(move |handle| {
|
||||
run_with_path(
|
||||
handle.as_weak(),
|
||||
std::path::PathBuf::from(rom.to_string()),
|
||||
&controller_paths,
|
||||
);
|
||||
run_with_path(handle.as_weak(), std::path::PathBuf::from(rom.to_string()));
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
@@ -158,7 +140,7 @@ fn local_game_window(
|
||||
eprintln!("Error opening saves folder: {}", e);
|
||||
}
|
||||
});
|
||||
file_dropped(app, controller_paths);
|
||||
file_dropped(app);
|
||||
}
|
||||
|
||||
fn input_profiles(config: &ui::config::Config) -> Vec<String> {
|
||||
@@ -195,7 +177,6 @@ fn settings_window(app: &AppWindow, config: &ui::config::Config) {
|
||||
fn update_input_profiles(weak: &slint::Weak<AppWindow>, config: &ui::config::Config) {
|
||||
let profiles = input_profiles(config);
|
||||
let config_bindings = config.input.input_profile_binding.clone();
|
||||
let weak2 = weak.clone();
|
||||
weak.upgrade_in_event_loop(move |handle| {
|
||||
let profile_bindings = slint::VecModel::default();
|
||||
for (i, input_profile_binding) in handle.get_selected_profile_binding().iter().enumerate() {
|
||||
@@ -221,16 +202,6 @@ fn update_input_profiles(weak: &slint::Weak<AppWindow>, config: &ui::config::Con
|
||||
|
||||
handle
|
||||
.set_selected_profile_binding(slint::ModelRc::from(std::rc::Rc::new(profile_bindings)));
|
||||
|
||||
// this is a workaround to make the input profile combobox update
|
||||
handle.set_blank_profiles(true);
|
||||
slint::Timer::single_shot(std::time::Duration::from_millis(200), move || {
|
||||
weak2
|
||||
.upgrade_in_event_loop(move |handle| {
|
||||
handle.set_blank_profiles(false);
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
@@ -247,12 +218,7 @@ fn clear_gb_paths(weak: &slint::Weak<AppWindow>, player: i32) {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn controller_window(
|
||||
app: &AppWindow,
|
||||
config: &ui::config::Config,
|
||||
controller_names: &[String],
|
||||
controller_paths: &[Option<String>],
|
||||
) {
|
||||
fn controller_window(app: &AppWindow, config: &ui::config::Config) {
|
||||
app.set_emulate_vru(config.input.emulate_vru);
|
||||
|
||||
app.set_controller_enabled(slint::ModelRc::from(std::rc::Rc::new(
|
||||
@@ -287,28 +253,66 @@ fn controller_window(
|
||||
|
||||
update_input_profiles(&app.as_weak(), config);
|
||||
|
||||
app.set_controller_names(slint::ModelRc::from(std::rc::Rc::new(
|
||||
slint::VecModel::from(
|
||||
controller_names
|
||||
.iter()
|
||||
.map(|x| x.into())
|
||||
.collect::<Vec<slint::SharedString>>(),
|
||||
),
|
||||
app.set_controller_changed(slint::ModelRc::from(std::rc::Rc::new(
|
||||
slint::VecModel::from(vec![false, false, false, false]),
|
||||
)));
|
||||
|
||||
let controller_changed = slint::VecModel::default();
|
||||
let selected_controllers = slint::VecModel::default();
|
||||
for selected in config.input.controller_assignment.iter() {
|
||||
let selected_index = controller_paths
|
||||
.iter()
|
||||
.position(|path| selected == path)
|
||||
.unwrap_or(0) as i32;
|
||||
selected_controllers.push(selected_index);
|
||||
controller_changed.push(false);
|
||||
}
|
||||
app.set_selected_controller(slint::ModelRc::from(std::rc::Rc::new(selected_controllers)));
|
||||
let config_controller_assignment = config.input.controller_assignment.clone();
|
||||
let weak_app = app.as_weak();
|
||||
app.on_controller_window_created(move || {
|
||||
let controller_assignment = config_controller_assignment.clone();
|
||||
weak_app
|
||||
.upgrade_in_event_loop(move |handle| {
|
||||
let mut current_selected_paths = vec![None; 4];
|
||||
for (i, selected_controller) in handle.get_selected_controller().iter().enumerate()
|
||||
{
|
||||
current_selected_paths[i] = handle
|
||||
.get_controller_paths()
|
||||
.row_data(selected_controller as usize);
|
||||
}
|
||||
|
||||
app.set_controller_changed(slint::ModelRc::from(std::rc::Rc::new(controller_changed)));
|
||||
let controller_names = ui::input::get_controller_names();
|
||||
handle.set_controller_names(slint::ModelRc::from(std::rc::Rc::new(
|
||||
slint::VecModel::from(
|
||||
controller_names
|
||||
.iter()
|
||||
.map(|x| x.into())
|
||||
.collect::<Vec<slint::SharedString>>(),
|
||||
),
|
||||
)));
|
||||
|
||||
let controller_paths = ui::input::get_controller_paths();
|
||||
handle.set_controller_paths(slint::ModelRc::from(std::rc::Rc::new(
|
||||
slint::VecModel::from(
|
||||
controller_paths
|
||||
.iter()
|
||||
.map(|x| x.into())
|
||||
.collect::<Vec<slint::SharedString>>(),
|
||||
),
|
||||
)));
|
||||
|
||||
let selected_controllers = slint::VecModel::default();
|
||||
for i in 0..4 {
|
||||
let assigned_path =
|
||||
if let Some(current_selected_path) = ¤t_selected_paths[i] {
|
||||
current_selected_path.to_string()
|
||||
} else if let Some(config_assigned_path) = &controller_assignment[i] {
|
||||
config_assigned_path.to_string()
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
let selected_index = controller_paths
|
||||
.iter()
|
||||
.position(|controller_path| assigned_path == *controller_path)
|
||||
.unwrap_or(0) as i32;
|
||||
selected_controllers.push(selected_index);
|
||||
}
|
||||
handle.set_selected_controller(slint::ModelRc::from(std::rc::Rc::new(
|
||||
selected_controllers,
|
||||
)));
|
||||
})
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
let weak_app = app.as_weak();
|
||||
app.on_input_profile_button_clicked(move || {
|
||||
@@ -411,7 +415,7 @@ fn controller_window(
|
||||
});
|
||||
}
|
||||
|
||||
pub fn save_settings(app: &AppWindow, controller_paths: &[Option<String>]) {
|
||||
pub fn save_settings(app: &AppWindow) {
|
||||
let mut config = ui::config::Config::new();
|
||||
config.video.integer_scaling = app.get_integer_scaling();
|
||||
config.video.fullscreen = app.get_fullscreen();
|
||||
@@ -443,8 +447,16 @@ pub fn save_settings(app: &AppWindow, controller_paths: &[Option<String>]) {
|
||||
|
||||
for (i, selected_controller) in app.get_selected_controller().iter().enumerate() {
|
||||
if app.get_controller_changed().row_data(i).unwrap_or(false) {
|
||||
config.input.controller_assignment[i] =
|
||||
controller_paths[selected_controller as usize].clone();
|
||||
let controller_path = app
|
||||
.get_controller_paths()
|
||||
.row_data(selected_controller as usize)
|
||||
.unwrap()
|
||||
.to_string();
|
||||
if controller_path.is_empty() {
|
||||
config.input.controller_assignment[i] = None;
|
||||
} else {
|
||||
config.input.controller_assignment[i] = Some(controller_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -493,21 +505,17 @@ pub fn app_window() {
|
||||
let app = AppWindow::new().unwrap();
|
||||
about_window(&app);
|
||||
ui::retroachievements::ra_window(&app);
|
||||
let mut controller_paths;
|
||||
{
|
||||
let game_ui = ui::Ui::new();
|
||||
let mut controller_names = ui::input::get_controller_names(&game_ui);
|
||||
controller_names.insert(0, "None".into());
|
||||
controller_paths = ui::input::get_controller_paths(&game_ui);
|
||||
controller_paths.insert(0, None);
|
||||
settings_window(&app, &game_ui.config);
|
||||
controller_window(&app, &game_ui.config, &controller_names, &controller_paths);
|
||||
local_game_window(&app, &game_ui.config, &controller_paths);
|
||||
let config = ui::config::Config::new();
|
||||
settings_window(&app, &config);
|
||||
controller_window(&app, &config);
|
||||
local_game_window(&app, &config);
|
||||
}
|
||||
ui::netplay::netplay_window(&app, &controller_paths);
|
||||
ui::netplay::netplay_window(&app);
|
||||
ui::cheats::cheats_window(&app);
|
||||
app.run().unwrap();
|
||||
save_settings(&app, &controller_paths);
|
||||
save_settings(&app);
|
||||
unsafe { sdl3_sys::init::SDL_Quit() };
|
||||
}
|
||||
|
||||
pub fn run_rom(
|
||||
|
||||
@@ -41,6 +41,7 @@ export component AppWindow inherits Window {
|
||||
callback ra_games_clicked;
|
||||
callback ra_show_profile_clicked;
|
||||
callback ra_toggled(bool,bool,bool,bool);
|
||||
callback controller_window_created;
|
||||
in property version <=> AboutData.version;
|
||||
in property has_update <=> AboutData.has_update;
|
||||
in-out property ra_username <=> RAData.ra_username;
|
||||
@@ -72,10 +73,10 @@ export component AppWindow inherits Window {
|
||||
in-out property selected_profile_binding <=> ControllerData.selected_profile_binding;
|
||||
in-out property input_profiles <=> ControllerData.input_profiles;
|
||||
in-out property controller_names <=> ControllerData.controller_names;
|
||||
in-out property controller_paths <=> ControllerData.controller_paths;
|
||||
in-out property selected_controller <=> ControllerData.selected_controller;
|
||||
in-out property game_running <=> State.game_running;
|
||||
in-out property recent_roms <=> State.recent_roms;
|
||||
in-out property blank_profiles <=> ControllerData.blank_profiles;
|
||||
in-out property cheat_game_name <=> CheatsData.cheat_game_name;
|
||||
in-out property cheat_game_crc <=> CheatsData.cheat_game_crc;
|
||||
in-out property cheats <=> CheatsData.cheats;
|
||||
@@ -119,6 +120,9 @@ export component AppWindow inherits Window {
|
||||
transferpak_toggled(player,enabled) => {
|
||||
transferpak_toggled(player,enabled);
|
||||
}
|
||||
controller_window_created => {
|
||||
controller_window_created();
|
||||
}
|
||||
}
|
||||
if(side-bar.current-item == 2): Netplay {
|
||||
create_session_button_clicked => {
|
||||
|
||||
@@ -14,16 +14,21 @@ export global ControllerData {
|
||||
in-out property <[int]> selected_profile_binding: [-1, -1, -1, -1];
|
||||
in-out property <[string]> input_profiles;
|
||||
in-out property <[string]> controller_names;
|
||||
in-out property <[string]> controller_paths;
|
||||
in-out property <[int]> selected_controller;
|
||||
in-out property <[bool]> controller_changed;
|
||||
in-out property <bool> blank_profiles;
|
||||
}
|
||||
|
||||
export component ControllerConfig inherits Page {
|
||||
callback input_profile_button_clicked;
|
||||
callback transferpak_toggled(int,bool);
|
||||
callback controller_window_created;
|
||||
title: @tr("Controller Configuration");
|
||||
|
||||
init => {
|
||||
controller_window_created();
|
||||
}
|
||||
|
||||
VerticalBox {
|
||||
alignment: start;
|
||||
HorizontalBox {
|
||||
@@ -92,7 +97,7 @@ export component ControllerConfig inherits Page {
|
||||
}
|
||||
}
|
||||
|
||||
if !ControllerData.blank_profiles: GroupBox {
|
||||
GroupBox {
|
||||
title: @tr("Profile");
|
||||
horizontal-stretch: 0.25;
|
||||
VerticalLayout {
|
||||
|
||||
+50
-23
@@ -341,10 +341,10 @@ fn hotkey_pressed(
|
||||
pressed
|
||||
}
|
||||
|
||||
pub fn get_controller_names(game_ui: &ui::Ui) -> Vec<String> {
|
||||
pub fn get_controller_names() -> Vec<String> {
|
||||
let mut controllers: Vec<String> = vec![];
|
||||
|
||||
for joystick in game_ui.input.joysticks.iter() {
|
||||
for joystick in get_joysticks().iter() {
|
||||
let name = unsafe { sdl3_sys::joystick::SDL_GetJoystickNameForID(*joystick) };
|
||||
controllers.push(if name.is_null() {
|
||||
"Unknown controller".to_string()
|
||||
@@ -352,22 +352,24 @@ pub fn get_controller_names(game_ui: &ui::Ui) -> Vec<String> {
|
||||
unsafe { std::ffi::CStr::from_ptr(name).to_str().unwrap() }.to_string()
|
||||
});
|
||||
}
|
||||
controllers.insert(0, "None".into());
|
||||
|
||||
controllers
|
||||
}
|
||||
|
||||
#[cfg(feature = "gui")]
|
||||
pub fn get_controller_paths(game_ui: &ui::Ui) -> Vec<Option<String>> {
|
||||
let mut controller_paths: Vec<Option<String>> = vec![];
|
||||
pub fn get_controller_paths() -> Vec<String> {
|
||||
let mut controller_paths: Vec<String> = vec![];
|
||||
|
||||
for joystick in game_ui.input.joysticks.iter() {
|
||||
for joystick in get_joysticks().iter() {
|
||||
let path = unsafe { sdl3_sys::joystick::SDL_GetJoystickPathForID(*joystick) };
|
||||
controller_paths.push(if path.is_null() {
|
||||
None
|
||||
String::new()
|
||||
} else {
|
||||
Some(unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() }.to_string())
|
||||
unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() }.to_string()
|
||||
});
|
||||
}
|
||||
controller_paths.insert(0, String::new());
|
||||
|
||||
controller_paths
|
||||
}
|
||||
@@ -553,13 +555,15 @@ pub fn get(ui: &mut ui::Ui, channel: usize) -> InputData {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assign_controller(ui: &mut ui::Ui, controller: i32, port: usize) {
|
||||
if controller < ui.input.joysticks.len() as i32 {
|
||||
let path = unsafe {
|
||||
sdl3_sys::joystick::SDL_GetJoystickPathForID(ui.input.joysticks[controller as usize])
|
||||
};
|
||||
pub fn assign_controller(config: &mut ui::config::Config, controller: i32, port: usize) {
|
||||
let joysticks = get_joysticks();
|
||||
if controller < 0 {
|
||||
config.input.controller_assignment[port - 1] = None;
|
||||
} else if controller < joysticks.len() as i32 {
|
||||
let path =
|
||||
unsafe { sdl3_sys::joystick::SDL_GetJoystickPathForID(joysticks[controller as usize]) };
|
||||
if !path.is_null() {
|
||||
ui.config.input.controller_assignment[port - 1] =
|
||||
config.input.controller_assignment[port - 1] =
|
||||
Some(unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap().to_string() });
|
||||
} else {
|
||||
eprintln!("Invalid controller path for controller {controller}");
|
||||
@@ -569,18 +573,18 @@ pub fn assign_controller(ui: &mut ui::Ui, controller: i32, port: usize) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind_input_profile(ui: &mut ui::Ui, profile: String, port: usize) {
|
||||
if ui.config.input.input_profiles.contains_key(&profile) {
|
||||
ui.config.input.input_profile_binding[port - 1] = profile;
|
||||
pub fn bind_input_profile(config: &mut ui::config::Config, profile: String, port: usize) {
|
||||
if config.input.input_profiles.contains_key(&profile) {
|
||||
config.input.input_profile_binding[port - 1] = profile;
|
||||
} else {
|
||||
eprintln!("Invalid profile name")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_bindings(ui: &mut ui::Ui) {
|
||||
pub fn clear_bindings(config: &mut ui::config::Config) {
|
||||
for i in 0..4 {
|
||||
ui.config.input.controller_assignment[i] = None;
|
||||
ui.config.input.input_profile_binding[i] = "default".to_string();
|
||||
config.input.controller_assignment[i] = None;
|
||||
config.input.input_profile_binding[i] = "default".to_string();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -604,10 +608,17 @@ fn close_input_profile_window(
|
||||
sdl3_ttf_sys::ttf::TTF_DestroyRendererTextEngine(text_engine);
|
||||
sdl3_sys::render::SDL_DestroyRenderer(renderer);
|
||||
sdl3_sys::video::SDL_DestroyWindow(window);
|
||||
sdl3_ttf_sys::ttf::TTF_Quit();
|
||||
sdl3_sys::init::SDL_Quit();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn configure_input_profile(ui: &mut ui::Ui, profile: String, dinput: bool, deadzone: i32) {
|
||||
pub fn configure_input_profile(
|
||||
config: &mut ui::config::Config,
|
||||
profile: String,
|
||||
dinput: bool,
|
||||
deadzone: i32,
|
||||
) {
|
||||
ui::sdl_init(sdl3_sys::init::SDL_INIT_VIDEO);
|
||||
ui::ttf_init();
|
||||
|
||||
@@ -622,7 +633,7 @@ pub fn configure_input_profile(ui: &mut ui::Ui, profile: String, dinput: bool, d
|
||||
let mut open_joysticks: Vec<*mut sdl3_sys::joystick::SDL_Joystick> = Vec::new();
|
||||
let mut open_controllers: Vec<*mut sdl3_sys::gamepad::SDL_Gamepad> = Vec::new();
|
||||
|
||||
for joystick in ui.input.joysticks.iter() {
|
||||
for joystick in get_joysticks().iter() {
|
||||
if !dinput {
|
||||
let controller = unsafe { sdl3_sys::gamepad::SDL_OpenGamepad(*joystick) };
|
||||
if !controller.is_null() {
|
||||
@@ -847,7 +858,7 @@ pub fn configure_input_profile(ui: &mut ui::Ui, profile: String, dinput: bool, d
|
||||
dinput,
|
||||
deadzone,
|
||||
};
|
||||
ui.config.input.input_profiles.insert(profile, new_profile);
|
||||
config.input.input_profiles.insert(profile, new_profile);
|
||||
}
|
||||
|
||||
pub fn get_default_profile() -> ui::config::InputProfile {
|
||||
@@ -1050,6 +1061,22 @@ pub fn get_default_profile() -> ui::config::InputProfile {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_joysticks() -> Vec<sdl3_sys::joystick::SDL_JoystickID> {
|
||||
ui::sdl_init(sdl3_sys::init::SDL_INIT_GAMEPAD);
|
||||
unsafe { sdl3_sys::events::SDL_PumpEvents() };
|
||||
let mut num_joysticks = 0;
|
||||
let sdl_joysticks = unsafe { sdl3_sys::joystick::SDL_GetJoysticks(&mut num_joysticks) };
|
||||
if !sdl_joysticks.is_null() {
|
||||
let parts =
|
||||
unsafe { std::slice::from_raw_parts(sdl_joysticks, num_joysticks as usize) }.to_vec();
|
||||
unsafe { sdl3_sys::stdinc::SDL_free(sdl_joysticks as *mut std::ffi::c_void) };
|
||||
parts
|
||||
} else {
|
||||
eprintln!("Could not get joysticks");
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(ui: &mut ui::Ui) {
|
||||
ui.input.keyboard_state =
|
||||
unsafe { sdl3_sys::keyboard::SDL_GetKeyboardState(std::ptr::null_mut()) };
|
||||
@@ -1063,7 +1090,7 @@ pub fn init(ui: &mut ui::Ui) {
|
||||
{
|
||||
let mut joystick_id = sdl3_sys::everything::SDL_JoystickID(0);
|
||||
|
||||
for joystick in ui.input.joysticks.iter() {
|
||||
for joystick in get_joysticks().iter() {
|
||||
let path = unsafe { sdl3_sys::joystick::SDL_GetJoystickPathForID(*joystick) };
|
||||
if !path.is_null()
|
||||
&& unsafe { std::ffi::CStr::from_ptr(path).to_str().unwrap() }
|
||||
|
||||
+3
-7
@@ -1208,17 +1208,15 @@ pub fn setup_join_window(
|
||||
join_window.show().unwrap();
|
||||
}
|
||||
|
||||
pub fn netplay_window(app: &AppWindow, controller_paths: &[Option<String>]) {
|
||||
pub fn netplay_window(app: &AppWindow) {
|
||||
let weak_create = app.as_weak();
|
||||
let weak_app = app.as_weak();
|
||||
let controller_paths_create = controller_paths.to_owned();
|
||||
app.on_create_session_button_clicked(move || {
|
||||
let controller_paths = controller_paths_create.clone();
|
||||
let weak_app = weak_app.clone();
|
||||
weak_create
|
||||
.upgrade_in_event_loop(move |handle| {
|
||||
let create_window = NetplayCreate::new().unwrap();
|
||||
save_settings(&handle, &controller_paths);
|
||||
save_settings(&handle);
|
||||
setup_create_window(
|
||||
&create_window,
|
||||
ui::GameSettings {
|
||||
@@ -1242,14 +1240,12 @@ pub fn netplay_window(app: &AppWindow, controller_paths: &[Option<String>]) {
|
||||
|
||||
let weak_join = app.as_weak();
|
||||
let weak_app = app.as_weak();
|
||||
let controller_paths_join = controller_paths.to_owned();
|
||||
app.on_join_session_button_clicked(move || {
|
||||
let controller_paths = controller_paths_join.clone();
|
||||
let weak_app = weak_app.clone();
|
||||
weak_join
|
||||
.upgrade_in_event_loop(move |handle| {
|
||||
let join_window = NetplayJoin::new().unwrap();
|
||||
save_settings(&handle, &controller_paths);
|
||||
save_settings(&handle);
|
||||
setup_join_window(
|
||||
&join_window,
|
||||
handle.get_rom_dir(),
|
||||
|
||||
@@ -150,6 +150,8 @@ pub fn close(ui: &ui::Ui) {
|
||||
unsafe {
|
||||
rdp_close();
|
||||
sdl3_sys::video::SDL_DestroyWindow(ui.video.window);
|
||||
sdl3_ttf_sys::ttf::TTF_Quit();
|
||||
sdl3_sys::init::SDL_Quit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user