Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ensure gamepads connect automatically to first player without controller #405

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/Ryujinx.Headless.SDL2/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,8 @@ static void LoadPlayerConfiguration(string inputProfileName, string inputId, Pla
return;
}

_inputManager.AddUpdaterForConfiguration(_inputConfiguration);

// Setup logging level
Logger.SetEnable(LogLevel.Debug, option.LoggingEnableDebug);
Logger.SetEnable(LogLevel.Stub, !option.LoggingDisableStub);
Expand Down Expand Up @@ -482,7 +484,7 @@ static void LoadPlayerConfiguration(string inputProfileName, string inputId, Pla
}

_inputManager.Dispose();
}
}

private static void SetupProgressHandler()
{
Expand Down
75 changes: 75 additions & 0 deletions src/Ryujinx.Input/HLE/InputManager.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
using LibHac.Common;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Logging;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Ryujinx.Input.HLE
{
Expand Down Expand Up @@ -41,6 +46,76 @@ protected virtual void Dispose(bool disposing)
}
}

private void removeSDPWhenExternalPadsConnected(List<Tuple<string,string>> availableDevices) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RemoveSdpWhenExternalPadsConnected

//remove all steam virtual gamepads
availableDevices.RemoveAll(a => a.Item2 == "Steam Virtual Gamepad");
//remove Steam Deck Controller if external controllers are connected (docked game mode)
if (availableDevices.Count > 1) {
var steamDeckPad = availableDevices.FindFirst( a => a.Item2 == "Steam Deck Controller");
if (steamDeckPad.HasValue) {
availableDevices.Remove(steamDeckPad.Value);
}
}
}

private List<Tuple<string,string>> getGamepadsDescriptions() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetGamepadsDescriptions

var result = new List<Tuple<string,string>> ();
foreach (string id in GamepadDriver.GamepadsIds) {
result.Add(Tuple.Create(id,GamepadDriver.GetGamepad(id).Name));
}
return result;
}

private void LinkDevicesToPlayers(List<InputConfig> _inputConfig) {
var _availableDevices = getGamepadsDescriptions();
removeSDPWhenExternalPadsConnected(_availableDevices);
var _playersWithNoDevices = new List<PlayerIndex>();
//Remove all used Devices in current Config and at the same time list player with missing Devices
foreach(PlayerIndex _playerId in Enum.GetValues(typeof(PlayerIndex)))
{
var _config = _inputConfig.Find(inputConfig => inputConfig.PlayerIndex == _playerId);
if (_config != null && _config.Backend != InputBackendType.WindowKeyboard)
{
//check device id of the player is in the existing/connected devices
var _connectedDevice = _availableDevices.FindFirst(d => d.Item1 == _config.Id);
if (_connectedDevice.HasValue)
{
_availableDevices.Remove(_connectedDevice.Value);
}
else
{
_playersWithNoDevices.Add(_playerId);
}
}
}

var hasChanges = _playersWithNoDevices.Count() > 0 && _availableDevices.Count() > 0;
if (hasChanges)
{
Logger.Info?.Print(LogClass.Configuration, $"Controllers configuration changed. Updating players configuration...");
for (int i = 0; i < _playersWithNoDevices.Count; i++)
{
var _playerId = _playersWithNoDevices[i];
var _config = _inputConfig.Find(inputConfig => inputConfig.PlayerIndex == _playerId);
if (_config != null && _availableDevices.Count > 0)
{
var _device = _availableDevices.First();
var deviceId = _device.Item1;
var deviceName = _device.Item2;
_config.Id = _device.Item1;
Logger.Info?.Print(LogClass.Configuration, $"Link Player {_playerId} to Device {deviceName}");
_availableDevices.Remove(_device);
}
}
Logger.Info?.Print(LogClass.Configuration, $"Updated players configuration to sync with Controllers configuration changes.");
}
}

public void AddUpdaterForConfiguration(List<InputConfig> _inputConfig) {
GamepadDriver.OnGamepadConnected += id => LinkDevicesToPlayers(_inputConfig);
GamepadDriver.OnGamepadDisconnected += id => LinkDevicesToPlayers(_inputConfig);
}

public void Dispose()
{
GC.SuppressFinalize(this);
Expand Down
26 changes: 22 additions & 4 deletions src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public PlayerIndex PlayerId
{
if (IsModified)
{

_playerIdChoose = value;
return;
}
Expand Down Expand Up @@ -367,12 +367,12 @@ private void LoadInputDriver()

private void HandleOnGamepadDisconnected(string id)
{
Dispatcher.UIThread.Post(LoadDevices);
Dispatcher.UIThread.Post(RefreshDevicesAndCurrentPlayerConfiguration);
}

private void HandleOnGamepadConnected(string id)
{
Dispatcher.UIThread.Post(LoadDevices);
Dispatcher.UIThread.Post(RefreshDevicesAndCurrentPlayerConfiguration);
}

private string GetCurrentGamepadId()
Expand Down Expand Up @@ -441,6 +441,21 @@ private static string GetShortGamepadId(string str)
return str[(str.IndexOf(Hyphen) + Offset)..];
}

public void RefreshDevicesAndCurrentPlayerConfiguration()
{
LoadDevices();

//update Device for current user based on new configuration.
var config = ConfigurationState.Instance.Hid.InputConfig.Value.Find(inputConfig => inputConfig.PlayerIndex == PlayerId);
var device = Devices.FindFirst(d => d.Id==config.Id);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please apply proper spacing.

if (device.HasValue) {
Device=Devices.IndexOf(device);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too

} else {
//0 is the None Device
Device = 0;
}
}

public void LoadDevices()
{
string GetGamepadName(IGamepad gamepad, int controllerNumber)
Expand All @@ -464,24 +479,27 @@ string GetUniqueGamepadName(IGamepad gamepad, ref int controllerNumber)
DeviceList.Clear();
Devices.Add((DeviceType.None, Disabled, LocaleManager.Instance[LocaleKeys.ControllerSettingsDeviceDisabled]));

int controllerNumber = 0;
int controllerNumber = 1;
foreach (string id in _mainWindow.InputManager.KeyboardDriver.GamepadsIds)
{
using IGamepad gamepad = _mainWindow.InputManager.KeyboardDriver.GetGamepad(id);

if (gamepad != null)
{
controllerNumber++;
Devices.Add((DeviceType.Keyboard, id, $"{GetShortGamepadName(gamepad.Name)}"));
}
}

controllerNumber = 1;
foreach (string id in _mainWindow.InputManager.GamepadDriver.GamepadsIds)
{
using IGamepad gamepad = _mainWindow.InputManager.GamepadDriver.GetGamepad(id);

if (gamepad != null)
{
string name = GetUniqueGamepadName(gamepad, ref controllerNumber);
controllerNumber++;
Devices.Add((DeviceType.Controller, id, name));
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/Ryujinx/UI/Windows/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.FileSystem;
Expand Down Expand Up @@ -103,6 +104,8 @@ public MainWindow()
if (Program.PreviewerDetached)
{
InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver());
InputManager.AddUpdaterForConfiguration(ConfigurationState.Instance.Hid.InputConfig);


_ = this.GetObservable(IsActiveProperty).Subscribe(it => ViewModel.IsActive = it);
this.ScalingChanged += OnScalingChanged;
Expand Down
Loading