refactor: remove auto-assign option from NpadManager initialization and update related components

This commit is contained in:
uncavo-hdmi 2025-02-01 19:36:55 +01:00
parent 97be01d473
commit ab4bb0a885
9 changed files with 222 additions and 85 deletions

View File

@ -97,7 +97,7 @@ namespace Ryujinx.Input.SDL2
private void HandleJoyStickConnected(int joystickDeviceId, int joystickInstanceId)
{
Logger.Warning?.Print(LogClass.Application, "(SDL2) Joystick connected: " + joystickDeviceId + " " + joystickInstanceId);
Logger.Warning?.Print(LogClass.Application, "(SDL2GamepadDriver) Joystick connected: " + joystickDeviceId + " " + joystickInstanceId);
if (SDL_IsGameController(joystickDeviceId) == SDL_bool.SDL_TRUE)
{
if (_gamepadsInstanceIdsMapping.ContainsKey(joystickInstanceId))

View File

@ -89,14 +89,14 @@ namespace Ryujinx.Input.HLE
}
}
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse, _enableAutoAssign);
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
}
}
private void HandleOnGamepadConnected(string id)
{
// Force input reload
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse, _enableAutoAssign);
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -123,86 +123,41 @@ namespace Ryujinx.Input.HLE
return controller.GamepadDriver != null;
}
public void ReloadConfiguration(List<InputConfig> inputConfig, bool enableKeyboard, bool enableMouse, bool enableAutoAssign)
public void ReloadConfiguration(List<InputConfig> inputConfig, bool enableKeyboard, bool enableMouse)
{
lock (_lock)
{
NpadController[] oldControllers = _controllers.ToArray();
List<InputConfig> validInputs = new();
// if auto assign is disabled, we want to keep the old logic with profiles.
if (!enableAutoAssign)
foreach (InputConfig inputConfigEntry in inputConfig)
{
foreach (InputConfig inputConfigEntry in inputConfig)
NpadController controller;
int index = (int)inputConfigEntry.PlayerIndex;
if (oldControllers[index] != null)
{
NpadController controller;
int index = (int)inputConfigEntry.PlayerIndex;
if (oldControllers[index] != null)
{
// Try reuse the existing controller.
controller = oldControllers[index];
oldControllers[index] = null;
}
else
{
controller = new(_cemuHookClient);
}
bool isValid = DriverConfigurationUpdate(ref controller, inputConfigEntry);
if (!isValid)
{
_controllers[index] = null;
controller.Dispose();
}
else
{
_controllers[index] = controller;
validInputs.Add(inputConfigEntry);
}
// Try reuse the existing controller.
controller = oldControllers[index];
oldControllers[index] = null;
}
}
else
{
List<IGamepad> controllers = _gamepadDriver.GetGamepads().ToList();
foreach (IGamepad activeController in controllers)
else
{
NpadController controller;
int index = controllers.FindIndex(x => x == activeController);
// Also if old controller exists, try to reuse it (and create their config too).
InputConfig config = CreateConfigFromController(activeController);
config.PlayerIndex = (Common.Configuration.Hid.PlayerIndex)index;
if (oldControllers[index] != null)
{
// Try reuse the existing controller.
controller = oldControllers[index];
oldControllers[index] = null;
}
else
{
controller = new(_cemuHookClient);
}
// TODO: call function to get config from controller here
bool isValid = DriverConfigurationUpdate(ref controller, config);
if (!isValid)
{
_controllers[index] = null;
controller.Dispose();
}
else
{
_controllers[index] = controller;
validInputs.Add(config);
}
controller = new(_cemuHookClient);
}
bool isValid = DriverConfigurationUpdate(ref controller, inputConfigEntry);
if (!isValid)
{
_controllers[index] = null;
controller.Dispose();
}
else
{
_controllers[index] = controller;
validInputs.Add(inputConfigEntry);
}
}
@ -214,10 +169,9 @@ namespace Ryujinx.Input.HLE
oldControllers[i] = null;
}
_inputConfig = (enableAutoAssign) ? validInputs : inputConfig;
_inputConfig = inputConfig;
_enableKeyboard = enableKeyboard;
_enableMouse = enableMouse;
_enableAutoAssign = enableAutoAssign;
_device.Hid.RefreshInputConfig(validInputs);
@ -350,12 +304,12 @@ namespace Ryujinx.Input.HLE
}
}
public void Initialize(Switch device, List<InputConfig> inputConfig, bool enableKeyboard, bool enableMouse, bool enableAutoAssign)
public void Initialize(Switch device, List<InputConfig> inputConfig, bool enableKeyboard, bool enableMouse)
{
_device = device;
_device.Configuration.RefreshInputConfig = RefreshInputConfigForHLE;
ReloadConfiguration(inputConfig, enableKeyboard, enableMouse, enableAutoAssign);
ReloadConfiguration(inputConfig, enableKeyboard, enableMouse);
}
public void Update(float aspectRatio = 1)

View File

@ -483,7 +483,7 @@ namespace Ryujinx.Ava
DisplaySleep.Prevent();
NpadManager.Initialize(Device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse, ConfigurationState.Instance.Hid.EnableAutoAssign);
NpadManager.Initialize(Device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
TouchScreenManager.Initialize(Device);
_viewModel.IsGameRunning = true;

View File

@ -0,0 +1,179 @@
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
using Ryujinx.Common.Logging;
using Ryujinx.Input;
using Ryujinx.Input.HLE;
using System.Collections.Generic;
using System.Linq;
namespace Ryujinx.Ava
{
public class AutoAssignController
{
private readonly InputManager _inputManager;
private readonly ConfigurationState _configurationState;
private readonly IGamepad[] _controllers;
public AutoAssignController(InputManager inputManager)
{
_configurationState = ConfigurationState.Instance;
_inputManager = inputManager;
_inputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
_inputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
}
public void RefreshControllers(List<InputConfig> inputConfig = null)
{
if (!_configurationState.Hid.EnableAutoAssign) return;
List<IGamepad> controllers = _inputManager.GamepadDriver.GetGamepads().ToList();
if (controllers.Count == 0) return;
MainWindow _mainWindow = RyujinxApp.MainWindow;
// Get every controller config and update the configuration state
List<InputConfig> newConfig = new();
List<InputConfig> oldConfigs = (inputConfig != null) ? inputConfig : ConfigurationState.Instance.Hid.InputConfig.Value.Where(x => x != null).ToList();
int index = 0;
foreach (var controller in controllers)
{
InputConfig config = oldConfigs.FirstOrDefault(x => x.Id == controller.Id) ?? CreateConfigFromController(controller);
config.PlayerIndex = (PlayerIndex)index;
newConfig.Add(config);
index++;
}
_mainWindow.ViewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
ConfigurationState.Instance.Hid.InputConfig.Value = newConfig;
}
private void HandleOnGamepadConnected(string id)
{
Logger.Warning?.Print(LogClass.Application, $"Gamepad disconnected: {id}");
RefreshControllers();
}
private void HandleOnGamepadDisconnected(string id)
{
Logger.Warning?.Print(LogClass.Application, $"Gamepad disconnected: {id}");
RefreshControllers();
}
private InputConfig CreateConfigFromController(IGamepad controller)
{
if (controller == null) return null;
Logger.Warning?.Print(LogClass.Application, $"Creating config for controller: {controller.Id}");
string id = controller.Id.Split(" ")[0];
bool isNintendoStyle = controller.Name.Contains("Nintendo");
ControllerType controllerType;
if (isNintendoStyle && !controller.Name.Contains("(L/R)"))
{
if (controller.Name.Contains("(L)"))
{
controllerType = ControllerType.JoyconLeft;
}
else if (controller.Name.Contains("(R)"))
{
controllerType = ControllerType.JoyconRight;
}
else
{
controllerType = ControllerType.ProController;
}
}
else
{
// if it's not a nintendo controller, we assume it's a pro controller or a joycon pair
controllerType = ControllerType.ProController;
}
InputConfig config = new StandardControllerInputConfig
{
Version = InputConfig.CurrentVersion,
Backend = InputBackendType.GamepadSDL2,
Id = id,
ControllerType = controllerType,
DeadzoneLeft = 0.1f,
DeadzoneRight = 0.1f,
RangeLeft = 1.0f,
RangeRight = 1.0f,
TriggerThreshold = 0.5f,
LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
{
DpadUp = (controllerType == ControllerType.JoyconLeft) ? ConfigGamepadInputId.Y : ConfigGamepadInputId.DpadUp,
DpadDown = (controllerType == ControllerType.JoyconLeft) ? ConfigGamepadInputId.A : ConfigGamepadInputId.DpadDown,
DpadLeft = (controllerType == ControllerType.JoyconLeft) ? ConfigGamepadInputId.B : ConfigGamepadInputId.DpadLeft,
DpadRight = (controllerType == ControllerType.JoyconLeft) ? ConfigGamepadInputId.X : ConfigGamepadInputId.DpadRight,
ButtonMinus = (controllerType == ControllerType.JoyconLeft) ? ConfigGamepadInputId.Plus : ConfigGamepadInputId.Minus,
ButtonL = ConfigGamepadInputId.LeftShoulder,
ButtonZl = ConfigGamepadInputId.LeftTrigger,
ButtonSl = (controllerType == ControllerType.JoyconLeft) ? ConfigGamepadInputId.LeftShoulder : ConfigGamepadInputId.Unbound,
ButtonSr = (controllerType == ControllerType.JoyconLeft) ? ConfigGamepadInputId.RightShoulder : ConfigGamepadInputId.Unbound,
},
LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
{
Joystick = ConfigStickInputId.Left,
StickButton = ConfigGamepadInputId.LeftStick,
InvertStickX = false,
InvertStickY = false,
Rotate90CW = (controllerType == ControllerType.JoyconLeft),
},
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
{
ButtonA = ConfigGamepadInputId.B,
ButtonB = (controllerType == ControllerType.JoyconRight) ? ConfigGamepadInputId.Y : ConfigGamepadInputId.A,
ButtonX = (controllerType == ControllerType.JoyconRight) ? ConfigGamepadInputId.A : ConfigGamepadInputId.Y,
ButtonY = ConfigGamepadInputId.X,
ButtonPlus = ConfigGamepadInputId.Plus,
ButtonR = ConfigGamepadInputId.RightShoulder,
ButtonZr = ConfigGamepadInputId.RightTrigger,
ButtonSl = (controllerType == ControllerType.JoyconRight) ? ConfigGamepadInputId.LeftShoulder : ConfigGamepadInputId.Unbound,
ButtonSr = (controllerType == ControllerType.JoyconRight) ? ConfigGamepadInputId.RightShoulder : ConfigGamepadInputId.Unbound,
},
RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
{
Joystick = (controllerType == ControllerType.JoyconRight) ? ConfigStickInputId.Left : ConfigStickInputId.Right,
StickButton = ConfigGamepadInputId.RightStick,
InvertStickX = (controllerType == ControllerType.JoyconRight),
InvertStickY = (controllerType == ControllerType.JoyconRight),
Rotate90CW = (controllerType == ControllerType.JoyconRight),
},
Motion = new StandardMotionConfigController
{
MotionBackend = MotionInputBackendType.GamepadDriver,
EnableMotion = true,
Sensitivity = 100,
GyroDeadzone = 1,
},
Rumble = new RumbleConfigController
{
StrongRumble = 1f,
WeakRumble = 1f,
EnableRumble = false,
},
Led = new LedConfigController
{
EnableLed = false,
TurnOffLed = false,
UseRainbow = false,
LedColor = 0,
},
};
return config;
}
}
}

View File

@ -38,6 +38,7 @@ namespace Ryujinx.Headless
private static LibHacHorizonManager _libHacHorizonManager;
private static UserChannelPersistence _userChannelPersistence;
private static InputManager _inputManager;
private static AutoAssignController _autoAssignController;
private static Switch _emulationContext;
private static WindowBase _window;
private static WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution;
@ -370,7 +371,7 @@ namespace Ryujinx.Headless
DisplaySleep.Prevent();
_window.Initialize(_emulationContext, _inputConfiguration, _enableKeyboard, _enableMouse, _enableAutoAssign);
_window.Initialize(_emulationContext, _inputConfiguration, _enableKeyboard, _enableMouse);
_window.Execute();

View File

@ -120,7 +120,7 @@ namespace Ryujinx.Headless
SDL2Driver.Instance.Initialize();
}
public void Initialize(Switch device, List<InputConfig> inputConfigs, bool enableKeyboard, bool enableMouse, bool enableAutoAssign)
public void Initialize(Switch device, List<InputConfig> inputConfigs, bool enableKeyboard, bool enableMouse)
{
Device = device;
@ -133,7 +133,7 @@ namespace Ryujinx.Headless
Renderer = renderer;
NpadManager.Initialize(device, inputConfigs, enableKeyboard, enableMouse, enableAutoAssign);
NpadManager.Initialize(device, inputConfigs, enableKeyboard, enableMouse);
TouchScreenManager.Initialize(device);
}

View File

@ -19,6 +19,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.Common.SystemInterop;
using Ryujinx.Graphics.Vulkan.MoltenVK;
using Ryujinx.Headless;
using Ryujinx.Input.SDL2;
using Ryujinx.SDL2.Common;
using System;
using System.Collections.Generic;
@ -130,7 +131,7 @@ namespace Ryujinx.Ava
SDL2Driver.MainThreadDispatcher = action => Dispatcher.UIThread.InvokeAsync(action, DispatcherPriority.Input);
ReloadConfig();
WindowScaleFactor = ForceDpiAware.GetWindowScaleFactor();
// Logging system information.

View File

@ -852,11 +852,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
}
}
_mainWindow.ViewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse, ConfigurationState.Instance.Hid.EnableAutoAssign);
//_mainWindow.ViewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
// Atomically replace and signal input change.
// NOTE: Do not modify InputConfig.Value directly as other code depends on the on-change event.
ConfigurationState.Instance.Hid.InputConfig.Value = newConfig;
//ConfigurationState.Instance.Hid.InputConfig.Value = newConfig;
_mainWindow.AutoAssignController.RefreshControllers(newConfig);
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
}

View File

@ -63,6 +63,7 @@ namespace Ryujinx.Ava.UI.Windows
public LibHacHorizonManager LibHacHorizonManager { get; private set; }
public InputManager InputManager { get; private set; }
public AutoAssignController AutoAssignController { get; private set; }
public SettingsWindow SettingsWindow { get; set; }
@ -109,6 +110,7 @@ namespace Ryujinx.Ava.UI.Windows
if (Program.PreviewerDetached)
{
InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver());
AutoAssignController = new AutoAssignController(InputManager);
_ = this.GetObservable(IsActiveProperty).Subscribe(it => ViewModel.IsActive = it);
this.ScalingChanged += OnScalingChanged;