Feature: Auto-Assign Controllers #706
@ -14,6 +14,7 @@ using ControllerType = Ryujinx.Common.Configuration.Hid.ControllerType;
|
|||||||
using PlayerIndex = Ryujinx.HLE.HOS.Services.Hid.PlayerIndex;
|
using PlayerIndex = Ryujinx.HLE.HOS.Services.Hid.PlayerIndex;
|
||||||
using Switch = Ryujinx.HLE.Switch;
|
using Switch = Ryujinx.HLE.Switch;
|
||||||
|
|
||||||
|
|
||||||
namespace Ryujinx.Input.HLE
|
namespace Ryujinx.Input.HLE
|
||||||
{
|
{
|
||||||
public class NpadManager : IDisposable
|
public class NpadManager : IDisposable
|
||||||
@ -38,6 +39,8 @@ namespace Ryujinx.Input.HLE
|
|||||||
private bool _enableMouse;
|
private bool _enableMouse;
|
||||||
private Switch _device;
|
private Switch _device;
|
||||||
|
|
||||||
|
public bool AutoAssignEnabled { get; set; } = false;
|
||||||
|
|
||||||
public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IGamepadDriver mouseDriver)
|
public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IGamepadDriver mouseDriver)
|
||||||
{
|
{
|
||||||
_controllers = new NpadController[MaxControllers];
|
_controllers = new NpadController[MaxControllers];
|
||||||
@ -84,12 +87,14 @@ namespace Ryujinx.Input.HLE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (AutoAssignEnabled) return;
|
||||||
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
|
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleOnGamepadConnected(string id)
|
private void HandleOnGamepadConnected(string id)
|
||||||
{
|
{
|
||||||
|
if (AutoAssignEnabled) return;
|
||||||
// Force input reload
|
// Force input reload
|
||||||
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
|
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
|
||||||
}
|
}
|
||||||
@ -202,11 +207,13 @@ namespace Ryujinx.Input.HLE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(Switch device, List<InputConfig> inputConfig, bool enableKeyboard, bool enableMouse)
|
public void Initialize(Switch device, List<InputConfig> inputConfig, bool enableKeyboard, bool enableMouse, bool enableAutoAssign)
|
||||||
{
|
{
|
||||||
_device = device;
|
_device = device;
|
||||||
_device.Configuration.RefreshInputConfig = RefreshInputConfigForHLE;
|
_device.Configuration.RefreshInputConfig = RefreshInputConfigForHLE;
|
||||||
|
|
||||||
|
AutoAssignEnabled = enableAutoAssign;
|
||||||
|
|
||||||
ReloadConfiguration(inputConfig, enableKeyboard, enableMouse);
|
ReloadConfiguration(inputConfig, enableKeyboard, enableMouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,7 +463,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
DisplaySleep.Prevent();
|
DisplaySleep.Prevent();
|
||||||
|
|
||||||
NpadManager.Initialize(Device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
|
NpadManager.Initialize(Device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse, ConfigurationState.Instance.Hid.EnableAutoAssign);
|
||||||
TouchScreenManager.Initialize(Device);
|
TouchScreenManager.Initialize(Device);
|
||||||
|
|
||||||
_viewModel.IsGameRunning = true;
|
_viewModel.IsGameRunning = true;
|
||||||
|
@ -147,6 +147,31 @@
|
|||||||
"zh_TW": "滑鼠直接存取"
|
"zh_TW": "滑鼠直接存取"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "SettingsTabInputAutoAssign",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Auto-assign controllers",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "Assegnamento controller automatico",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "SettingsTabSystemMemoryManagerMode",
|
"ID": "SettingsTabSystemMemoryManagerMode",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
@ -16222,6 +16247,31 @@
|
|||||||
"zh_TW": "支援滑鼠直接存取 (HID)。遊戲可將滑鼠作為指向裝置使用。\n\n僅適用於在 Switch 硬體上原生支援滑鼠控制的遊戲,這類遊戲很少。\n\n啟用後,觸控螢幕功能可能無法使用。\n\n如果不確定,請保持關閉狀態。"
|
"zh_TW": "支援滑鼠直接存取 (HID)。遊戲可將滑鼠作為指向裝置使用。\n\n僅適用於在 Switch 硬體上原生支援滑鼠控制的遊戲,這類遊戲很少。\n\n啟用後,觸控螢幕功能可能無法使用。\n\n如果不確定,請保持關閉狀態。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ID": "AutoAssignTooltip",
|
||||||
|
"Translations": {
|
||||||
|
"ar_SA": "",
|
||||||
|
"de_DE": "",
|
||||||
|
"el_GR": "",
|
||||||
|
"en_US": "Automatic controllers assignment support.\n\nAutomatically assigns connected controllers to each player.\n\nManual configuration remains available, even when this option is activated.\n\nLeave OFF if you prefer to manually assign controllers.",
|
||||||
|
"es_ES": "",
|
||||||
|
"fr_FR": "",
|
||||||
|
"he_IL": "",
|
||||||
|
"it_IT": "Supporto per l'assegnazione automatica dei controller.\n\nAssegna automaticamente i controller connessi a ciascun giocatore.\n\nÈ possibile configurare manualmente i controller anche quando questa opzione è attivata.\n\nLascia disattivato se preferisci assegnare i controller manualmente.",
|
||||||
|
"ja_JP": "",
|
||||||
|
"ko_KR": "",
|
||||||
|
"no_NO": "",
|
||||||
|
"pl_PL": "",
|
||||||
|
"pt_BR": "",
|
||||||
|
"ru_RU": "",
|
||||||
|
"sv_SE": "",
|
||||||
|
"th_TH": "",
|
||||||
|
"tr_TR": "",
|
||||||
|
"uk_UA": "",
|
||||||
|
"zh_CN": "",
|
||||||
|
"zh_TW": "。"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ID": "RegionTooltip",
|
"ID": "RegionTooltip",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
|
@ -46,6 +46,7 @@ namespace Ryujinx.Headless
|
|||||||
private static List<InputConfig> _inputConfiguration = [];
|
private static List<InputConfig> _inputConfiguration = [];
|
||||||
private static bool _enableKeyboard;
|
private static bool _enableKeyboard;
|
||||||
private static bool _enableMouse;
|
private static bool _enableMouse;
|
||||||
|
private static bool _enableAutoAssign;
|
||||||
|
|
||||||
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
|
|
||||||
@ -230,6 +231,7 @@ namespace Ryujinx.Headless
|
|||||||
_inputConfiguration ??= [];
|
_inputConfiguration ??= [];
|
||||||
_enableKeyboard = option.EnableKeyboard;
|
_enableKeyboard = option.EnableKeyboard;
|
||||||
_enableMouse = option.EnableMouse;
|
_enableMouse = option.EnableMouse;
|
||||||
|
_enableAutoAssign = option.EnableAutoAssign;
|
||||||
|
|
||||||
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
|
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
|
||||||
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
||||||
@ -371,7 +373,7 @@ namespace Ryujinx.Headless
|
|||||||
|
|
||||||
DisplaySleep.Prevent();
|
DisplaySleep.Prevent();
|
||||||
|
|
||||||
_window.Initialize(_emulationContext, _inputConfiguration, _enableKeyboard, _enableMouse);
|
_window.Initialize(_emulationContext, _inputConfiguration, _enableKeyboard, _enableMouse, _enableAutoAssign);
|
||||||
|
|
||||||
_window.Execute();
|
_window.Execute();
|
||||||
|
|
||||||
|
@ -27,6 +27,9 @@ namespace Ryujinx.Headless
|
|||||||
if (NeedsOverride(nameof(EnableMouse)))
|
if (NeedsOverride(nameof(EnableMouse)))
|
||||||
EnableMouse = configurationState.Hid.EnableMouse;
|
EnableMouse = configurationState.Hid.EnableMouse;
|
||||||
|
|
||||||
|
if (NeedsOverride(nameof(EnableAutoAssign)))
|
||||||
|
EnableAutoAssign = configurationState.Hid.EnableAutoAssign;
|
||||||
|
|
||||||
if (NeedsOverride(nameof(HideCursorMode)))
|
if (NeedsOverride(nameof(HideCursorMode)))
|
||||||
HideCursorMode = configurationState.HideCursor;
|
HideCursorMode = configurationState.HideCursor;
|
||||||
|
|
||||||
@ -273,6 +276,9 @@ namespace Ryujinx.Headless
|
|||||||
[Option("enable-mouse", Required = false, Default = false, HelpText = "Enable or disable mouse support.")]
|
[Option("enable-mouse", Required = false, Default = false, HelpText = "Enable or disable mouse support.")]
|
||||||
public bool EnableMouse { get; set; }
|
public bool EnableMouse { get; set; }
|
||||||
|
|
||||||
|
[Option("enable-auto-assign", Required = false, Default = false, HelpText = "Enable or disable auto-assigning controllers to players.")]
|
||||||
|
public bool EnableAutoAssign { get; set; }
|
||||||
|
|
||||||
[Option("hide-cursor", Required = false, Default = HideCursorMode.OnIdle, HelpText = "Change when the cursor gets hidden.")]
|
[Option("hide-cursor", Required = false, Default = HideCursorMode.OnIdle, HelpText = "Change when the cursor gets hidden.")]
|
||||||
public HideCursorMode HideCursorMode { get; set; }
|
public HideCursorMode HideCursorMode { get; set; }
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ namespace Ryujinx.Headless
|
|||||||
SDL2Driver.Instance.Initialize();
|
SDL2Driver.Instance.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize(Switch device, List<InputConfig> inputConfigs, bool enableKeyboard, bool enableMouse)
|
public void Initialize(Switch device, List<InputConfig> inputConfigs, bool enableKeyboard, bool enableMouse, bool enableAutoAssign)
|
||||||
{
|
{
|
||||||
Device = device;
|
Device = device;
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ namespace Ryujinx.Headless
|
|||||||
|
|
||||||
Renderer = renderer;
|
Renderer = renderer;
|
||||||
|
|
||||||
NpadManager.Initialize(device, inputConfigs, enableKeyboard, enableMouse);
|
NpadManager.Initialize(device, inputConfigs, enableKeyboard, enableMouse, enableAutoAssign);
|
||||||
TouchScreenManager.Initialize(device);
|
TouchScreenManager.Initialize(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
75
src/Ryujinx/Input/AutoAssignController.cs
Normal file
75
src/Ryujinx/Input/AutoAssignController.cs
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
|
using Ryujinx.Ava.Utilities.Configuration;
|
||||||
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Input;
|
||||||
|
using Ryujinx.Input.HLE;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.Input
|
||||||
|
{
|
||||||
|
public class AutoAssignController
|
||||||
|
{
|
||||||
|
private readonly InputManager _inputManager;
|
||||||
|
private readonly MainWindowViewModel _viewModel;
|
||||||
|
private readonly ConfigurationState _configurationState;
|
||||||
|
|
||||||
|
public event Action ConfigurationUpdated;
|
||||||
|
|
||||||
|
public AutoAssignController(InputManager inputManager, MainWindowViewModel mainWindowViewModel)
|
||||||
|
{
|
||||||
|
_inputManager = inputManager;
|
||||||
|
_viewModel = mainWindowViewModel;
|
||||||
|
_configurationState = ConfigurationState.Instance;
|
||||||
|
|
||||||
|
_inputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
||||||
|
_inputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
||||||
|
|
||||||
|
RefreshControllers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleOnGamepadConnected(string id)
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Application, $"Gamepad connected: {id}");
|
||||||
|
RefreshControllers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleOnGamepadDisconnected(string id)
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Application, $"Gamepad disconnected: {id}");
|
||||||
|
RefreshControllers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RefreshControllers()
|
||||||
|
{
|
||||||
|
if (!_configurationState.Hid.EnableAutoAssign) return;
|
||||||
|
|
||||||
|
List<IGamepad> controllers = _inputManager.GamepadDriver.GetGamepads().ToList();
|
||||||
|
List<InputConfig> oldConfig = _configurationState.Hid.InputConfig.Value.Where(x => x != null).ToList();
|
||||||
|
|
||||||
|
List<InputConfig> newConfig = ControllerAssignmentManager.GetConfiguredControllers(
|
||||||
|
controllers, oldConfig, out bool hasNewControllersConnected);
|
||||||
|
|
||||||
|
_viewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, _configurationState.Hid.EnableKeyboard, _configurationState.Hid.EnableMouse);
|
||||||
|
|
||||||
|
if (!hasNewControllersConnected)
|
||||||
|
{
|
||||||
|
// there is no *new* controller, we must switch the order of the controllers in
|
||||||
|
// oldConfig to match the new order since probably a controller was disconnected
|
||||||
|
// or an old controller was reconnected
|
||||||
|
newConfig = ControllerAssignmentManager.ReorderControllers(newConfig, oldConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
_configurationState.Hid.InputConfig.Value = newConfig;
|
||||||
|
|
||||||
|
// we want to save the configuration only if a *new* controller was connected
|
||||||
|
if(hasNewControllersConnected)
|
||||||
|
{
|
||||||
|
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||||
|
}
|
||||||
|
ConfigurationUpdated?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
274
src/Ryujinx/Input/ControllerAssignmentManager.cs
Normal file
274
src/Ryujinx/Input/ControllerAssignmentManager.cs
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
using Ryujinx.Ava.UI.Models.Input;
|
||||||
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
|
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Input;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using StickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.Input
|
||||||
|
{
|
||||||
|
public static class ControllerAssignmentManager
|
||||||
|
{
|
||||||
|
private static readonly uint[] _playerColors =
|
||||||
|
[
|
||||||
|
0xFF0000FF, // Player 1 - Blue
|
||||||
|
0xFFFF0000, // Player 2 - Red
|
||||||
|
0xFF00FF00, // Player 3 - Green
|
||||||
|
0xFFFFFF00, // Player 4 - Yellow
|
||||||
|
0xFFFF00FF, // Player 5 - Magenta
|
||||||
|
0xFFFFA500, // Player 6 - Orange
|
||||||
|
0xFF00FFFF, // Player 7 - Cyan
|
||||||
|
0xFF800080 // Player 8 - Purple
|
||||||
|
];
|
||||||
|
|
||||||
|
private const int MaxControllers = 9;
|
||||||
|
|
||||||
|
public static List<InputConfig> ReorderControllers(List<InputConfig> newConfig, List<InputConfig> oldConfig)
|
||||||
|
{
|
||||||
|
if(newConfig == null || oldConfig == null || newConfig.Count == 0 || oldConfig.Count == 0) return [];
|
||||||
|
|
||||||
|
List<InputConfig> reorderedConfig = oldConfig.Select(config => new GamepadInputConfig(config).GetConfig()).ToList();
|
||||||
|
|
||||||
|
foreach (var config in newConfig)
|
||||||
|
{
|
||||||
|
InputConfig substitute = reorderedConfig.FirstOrDefault(x => x.Id == config.Id);
|
||||||
|
InputConfig toBeReplaced = reorderedConfig.FirstOrDefault(x => x.PlayerIndex == config.PlayerIndex);
|
||||||
|
|
||||||
|
if (substitute == null || toBeReplaced == null || substitute.PlayerIndex == toBeReplaced.PlayerIndex) continue;
|
||||||
|
|
||||||
|
(substitute.PlayerIndex, toBeReplaced.PlayerIndex) = (toBeReplaced.PlayerIndex, substitute.PlayerIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reorderedConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<InputConfig> GetConfiguredControllers(
|
||||||
|
List<IGamepad> controllers,
|
||||||
|
List<InputConfig> oldConfig,
|
||||||
|
out bool hasNewControllersConnected)
|
||||||
|
{
|
||||||
|
if(controllers == null || controllers.Count == 0)
|
||||||
|
{
|
||||||
|
hasNewControllersConnected = false;
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string, InputConfig> oldConfigMap = oldConfig
|
||||||
|
.Where(c => c?.Id != null)
|
||||||
|
.ToDictionary(x => x.Id);
|
||||||
|
|
||||||
|
Dictionary<int, InputConfig> playerIndexMap = new();
|
||||||
|
HashSet<int> usedIndices = [];
|
||||||
|
int recognizedControllersCount = 0;
|
||||||
|
|
||||||
|
List<IGamepad> remainingControllers = controllers.Where(c => c?.Id != null).ToList();
|
||||||
|
|
||||||
|
// Add controllers with existing configurations
|
||||||
|
AddExistingControllers(remainingControllers, oldConfigMap, playerIndexMap, usedIndices, ref recognizedControllersCount);
|
||||||
|
|
||||||
|
// Add new controllers
|
||||||
|
AddNewControllers(remainingControllers, playerIndexMap, usedIndices);
|
||||||
|
|
||||||
|
List<InputConfig> orderedConfigs = playerIndexMap
|
||||||
|
.OrderBy(x => x.Key)
|
||||||
|
.Select(x => x.Value)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
// Update player indices and LED colors
|
||||||
|
UpdatePlayerIndicesAndLEDs(orderedConfigs);
|
||||||
|
|
||||||
|
hasNewControllersConnected = controllers.Count > recognizedControllersCount;
|
||||||
|
return orderedConfigs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddExistingControllers(
|
||||||
|
List<IGamepad> controllers,
|
||||||
|
Dictionary<string, InputConfig> oldConfigMap,
|
||||||
|
Dictionary<int, InputConfig> playerIndexMap,
|
||||||
|
HashSet<int> usedIndices,
|
||||||
|
ref int recognizedControllersCount)
|
||||||
|
{
|
||||||
|
foreach (var controller in controllers.ToList())
|
||||||
|
{
|
||||||
|
if (!oldConfigMap.TryGetValue(controller.Id, out InputConfig existingConfig))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int desiredIndex = (int)existingConfig.PlayerIndex;
|
||||||
|
|
||||||
|
// Ensure the index is valid and available
|
||||||
|
if (desiredIndex < 0 || desiredIndex >= MaxControllers || usedIndices.Contains(desiredIndex))
|
||||||
|
{
|
||||||
|
desiredIndex = GetFirstAvailableIndex(usedIndices);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(desiredIndex == -1) continue;
|
||||||
|
|
||||||
|
InputConfig config = new GamepadInputConfig(existingConfig).GetConfig();
|
||||||
|
config.PlayerIndex = (PlayerIndex)desiredIndex;
|
||||||
|
usedIndices.Add(desiredIndex);
|
||||||
|
playerIndexMap[desiredIndex] = config;
|
||||||
|
recognizedControllersCount++;
|
||||||
|
|
||||||
|
controllers.Remove(controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddNewControllers(
|
||||||
|
List<IGamepad> controllers,
|
||||||
|
Dictionary<int, InputConfig> playerIndexMap,
|
||||||
|
HashSet<int> usedIndices)
|
||||||
|
{
|
||||||
|
foreach (var controller in controllers)
|
||||||
|
{
|
||||||
|
InputConfig config = CreateConfigFromController(controller);
|
||||||
|
int freeIndex = GetFirstAvailableIndex(usedIndices);
|
||||||
|
config.PlayerIndex = (PlayerIndex)freeIndex;
|
||||||
|
usedIndices.Add(freeIndex);
|
||||||
|
playerIndexMap[freeIndex] = config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetFirstAvailableIndex(HashSet<int> usedIndices)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MaxControllers; i++)
|
||||||
|
{
|
||||||
|
if (!usedIndices.Contains(i)) return i;
|
||||||
|
}
|
||||||
|
return -1; // Should not happen unless MaxControllers is exceeded
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdatePlayerIndicesAndLEDs(List<InputConfig> orderedConfigs)
|
||||||
|
{
|
||||||
|
for (int index = 0; index < orderedConfigs.Count; index++)
|
||||||
|
{
|
||||||
|
orderedConfigs[index].PlayerIndex = (PlayerIndex)index;
|
||||||
|
|
||||||
|
if (orderedConfigs[index] is not StandardControllerInputConfig standardConfig ||
|
||||||
|
standardConfig.Led.UseRainbow)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Warning?.Print(LogClass.Application, $"Setting color for Player{index + 1}");
|
||||||
|
standardConfig.Led = new LedConfigController
|
||||||
|
{
|
||||||
|
EnableLed = true,
|
||||||
|
LedColor = _playerColors[index]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static 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 joy-con 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<GamepadInputId>
|
||||||
|
{
|
||||||
|
DpadUp = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.Y : GamepadInputId.DpadUp,
|
||||||
|
DpadDown = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.A : GamepadInputId.DpadDown,
|
||||||
|
DpadLeft = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.B : GamepadInputId.DpadLeft,
|
||||||
|
DpadRight = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.X : GamepadInputId.DpadRight,
|
||||||
|
ButtonMinus = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.Plus : GamepadInputId.Minus,
|
||||||
|
ButtonL = GamepadInputId.LeftShoulder,
|
||||||
|
ButtonZl = GamepadInputId.LeftTrigger,
|
||||||
|
ButtonSl = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.LeftShoulder : GamepadInputId.Unbound,
|
||||||
|
ButtonSr = (controllerType == ControllerType.JoyconLeft) ? GamepadInputId.RightShoulder : GamepadInputId.Unbound,
|
||||||
|
},
|
||||||
|
LeftJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
|
||||||
|
{
|
||||||
|
Joystick = StickInputId.Left,
|
||||||
|
StickButton = GamepadInputId.LeftStick,
|
||||||
|
InvertStickX = false,
|
||||||
|
InvertStickY = false,
|
||||||
|
Rotate90CW = (controllerType == ControllerType.JoyconLeft),
|
||||||
|
},
|
||||||
|
RightJoycon = new RightJoyconCommonConfig<GamepadInputId>
|
||||||
|
{
|
||||||
|
ButtonA = GamepadInputId.B,
|
||||||
|
ButtonB = (controllerType == ControllerType.JoyconRight) ? GamepadInputId.Y : GamepadInputId.A,
|
||||||
|
ButtonX = (controllerType == ControllerType.JoyconRight) ? GamepadInputId.A : GamepadInputId.Y,
|
||||||
|
ButtonY = GamepadInputId.X,
|
||||||
|
ButtonPlus = GamepadInputId.Plus,
|
||||||
|
ButtonR = GamepadInputId.RightShoulder,
|
||||||
|
ButtonZr = GamepadInputId.RightTrigger,
|
||||||
|
ButtonSl = (controllerType == ControllerType.JoyconRight) ? GamepadInputId.LeftShoulder : GamepadInputId.Unbound,
|
||||||
|
ButtonSr = (controllerType == ControllerType.JoyconRight) ? GamepadInputId.RightShoulder : GamepadInputId.Unbound,
|
||||||
|
},
|
||||||
|
RightJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
|
||||||
|
{
|
||||||
|
Joystick = (controllerType == ControllerType.JoyconRight) ? StickInputId.Left : StickInputId.Right,
|
||||||
|
StickButton = GamepadInputId.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 = true,
|
||||||
|
TurnOffLed = false,
|
||||||
|
UseRainbow = false,
|
||||||
|
LedColor = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -252,6 +252,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
||||||
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
||||||
|
|
||||||
|
_mainWindow.AutoAssignController.ConfigurationUpdated += OnConfigurationUpdated;
|
||||||
|
|
||||||
_mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates();
|
_mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates();
|
||||||
|
|
||||||
_isLoaded = false;
|
_isLoaded = false;
|
||||||
@ -365,14 +367,47 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
|
|
||||||
private void HandleOnGamepadDisconnected(string id)
|
private void HandleOnGamepadDisconnected(string id)
|
||||||
{
|
{
|
||||||
|
if(ConfigurationState.Instance.Hid.EnableAutoAssign) return;
|
||||||
Dispatcher.UIThread.Post(LoadDevices);
|
Dispatcher.UIThread.Post(LoadDevices);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleOnGamepadConnected(string id)
|
private void HandleOnGamepadConnected(string id)
|
||||||
{
|
{
|
||||||
|
if(ConfigurationState.Instance.Hid.EnableAutoAssign) return;
|
||||||
Dispatcher.UIThread.Post(LoadDevices);
|
Dispatcher.UIThread.Post(LoadDevices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnConfigurationUpdated()
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.Post(() => {
|
||||||
|
LoadDevices();
|
||||||
|
_isLoaded = false;
|
||||||
|
LoadConfiguration();
|
||||||
|
LoadDevice();
|
||||||
|
_isLoaded = true;
|
||||||
|
|
||||||
|
UpdateGamepadLed();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateGamepadLed()
|
||||||
|
{
|
||||||
|
if (ConfigViewModel is not ControllerInputViewModel controllerInputViewModel) return;
|
||||||
|
GamepadInputConfig inputConfig = controllerInputViewModel.Config;
|
||||||
|
|
||||||
|
if (inputConfig is not { EnableLedChanging: true }) return;
|
||||||
|
|
||||||
|
if (inputConfig.TurnOffLed)
|
||||||
|
{
|
||||||
|
SelectedGamepad.ClearLed();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inputConfig.TurnOffLed && !inputConfig.UseRainbowLed)
|
||||||
|
{
|
||||||
|
SelectedGamepad.SetLed(inputConfig.LedColor.ToUInt32());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string GetCurrentGamepadId()
|
private string GetCurrentGamepadId()
|
||||||
{
|
{
|
||||||
if (_device < 0)
|
if (_device < 0)
|
||||||
@ -859,6 +894,12 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_mainWindow.ViewModel.AppHost != null)
|
||||||
|
{
|
||||||
|
_mainWindow.ViewModel.AppHost.NpadManager.AutoAssignEnabled =
|
||||||
|
ConfigurationState.Instance.Hid.EnableAutoAssign;
|
||||||
|
}
|
||||||
|
|
||||||
_mainWindow.ViewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
|
_mainWindow.ViewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
|
||||||
|
|
||||||
// Atomically replace and signal input change.
|
// Atomically replace and signal input change.
|
||||||
@ -890,6 +931,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
|||||||
|
|
||||||
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected -= HandleOnGamepadConnected;
|
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected -= HandleOnGamepadConnected;
|
||||||
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected -= HandleOnGamepadDisconnected;
|
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected -= HandleOnGamepadDisconnected;
|
||||||
|
_mainWindow.AutoAssignController.ConfigurationUpdated -= OnConfigurationUpdated;
|
||||||
|
|
||||||
_mainWindow.ViewModel.AppHost?.NpadManager.UnblockInputUpdates();
|
_mainWindow.ViewModel.AppHost?.NpadManager.UnblockInputUpdates();
|
||||||
|
|
||||||
|
@ -140,6 +140,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
public bool EnableDockedMode { get; set; }
|
public bool EnableDockedMode { get; set; }
|
||||||
public bool EnableKeyboard { get; set; }
|
public bool EnableKeyboard { get; set; }
|
||||||
public bool EnableMouse { get; set; }
|
public bool EnableMouse { get; set; }
|
||||||
|
public bool EnableAutoAssign { get; set; }
|
||||||
public bool DisableInputWhenOutOfFocus { get; set; }
|
public bool DisableInputWhenOutOfFocus { get; set; }
|
||||||
|
|
||||||
public int FocusLostActionType { get; set; }
|
public int FocusLostActionType { get; set; }
|
||||||
@ -563,6 +564,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
EnableDockedMode = config.System.EnableDockedMode;
|
EnableDockedMode = config.System.EnableDockedMode;
|
||||||
EnableKeyboard = config.Hid.EnableKeyboard;
|
EnableKeyboard = config.Hid.EnableKeyboard;
|
||||||
EnableMouse = config.Hid.EnableMouse;
|
EnableMouse = config.Hid.EnableMouse;
|
||||||
|
EnableAutoAssign = config.Hid.EnableAutoAssign;
|
||||||
DisableInputWhenOutOfFocus = config.Hid.DisableInputWhenOutOfFocus;
|
DisableInputWhenOutOfFocus = config.Hid.DisableInputWhenOutOfFocus;
|
||||||
|
|
||||||
// Keyboard Hotkeys
|
// Keyboard Hotkeys
|
||||||
@ -668,6 +670,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
config.System.EnableDockedMode.Value = EnableDockedMode;
|
config.System.EnableDockedMode.Value = EnableDockedMode;
|
||||||
config.Hid.EnableKeyboard.Value = EnableKeyboard;
|
config.Hid.EnableKeyboard.Value = EnableKeyboard;
|
||||||
config.Hid.EnableMouse.Value = EnableMouse;
|
config.Hid.EnableMouse.Value = EnableMouse;
|
||||||
|
bool activatingAutoAssign = EnableAutoAssign && !config.Hid.EnableAutoAssign;
|
||||||
|
config.Hid.EnableAutoAssign.Value = EnableAutoAssign;
|
||||||
config.Hid.DisableInputWhenOutOfFocus.Value = DisableInputWhenOutOfFocus;
|
config.Hid.DisableInputWhenOutOfFocus.Value = DisableInputWhenOutOfFocus;
|
||||||
|
|
||||||
// Keyboard Hotkeys
|
// Keyboard Hotkeys
|
||||||
@ -690,7 +694,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
|
config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
|
||||||
config.System.DramSize.Value = DramSize;
|
config.System.DramSize.Value = DramSize;
|
||||||
config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
|
config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
|
||||||
config.System.IgnoreControllerApplet.Value = IgnoreApplet;
|
config.System.IgnoreControllerApplet.Value = (EnableAutoAssign) || IgnoreApplet;
|
||||||
|
|
||||||
// CPU
|
// CPU
|
||||||
config.System.EnablePtc.Value = EnablePptc;
|
config.System.EnablePtc.Value = EnablePptc;
|
||||||
@ -766,7 +770,14 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
MainWindow.UpdateGraphicsConfig();
|
MainWindow.UpdateGraphicsConfig();
|
||||||
RyujinxApp.MainWindow.ViewModel.VSyncModeSettingChanged();
|
RyujinxApp.MainWindow.ViewModel.VSyncModeSettingChanged();
|
||||||
|
|
||||||
|
if(activatingAutoAssign)
|
||||||
|
{
|
||||||
|
RyujinxApp.MainWindow.AutoAssignController.RefreshControllers();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
SaveSettingsEvent?.Invoke();
|
SaveSettingsEvent?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
GameListNeedsRefresh = false;
|
GameListNeedsRefresh = false;
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,12 @@
|
|||||||
<TextBlock
|
<TextBlock
|
||||||
Text="{ext:Locale SettingsTabInputDirectMouseAccess}" />
|
Text="{ext:Locale SettingsTabInputDirectMouseAccess}" />
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
|
<CheckBox
|
||||||
|
ToolTip.Tip="{ext:Locale AutoAssignTooltip}"
|
||||||
|
IsChecked="{Binding EnableAutoAssign}">
|
||||||
|
<TextBlock
|
||||||
|
Text="{ext:Locale SettingsTabInputAutoAssign}" />
|
||||||
|
</CheckBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@ -319,6 +319,7 @@
|
|||||||
<TextBlock Text="{ext:Locale SettingsTabSystemIgnoreMissingServices}" />
|
<TextBlock Text="{ext:Locale SettingsTabSystemIgnoreMissingServices}" />
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
<CheckBox
|
<CheckBox
|
||||||
|
IsEnabled="{Binding !EnableAutoAssign}"
|
||||||
IsChecked="{Binding IgnoreApplet}"
|
IsChecked="{Binding IgnoreApplet}"
|
||||||
ToolTip.Tip="{ext:Locale IgnoreControllerAppletTooltip}">
|
ToolTip.Tip="{ext:Locale IgnoreControllerAppletTooltip}">
|
||||||
<TextBlock Text="{ext:Locale SettingsTabSystemIgnoreControllerApplet}" />
|
<TextBlock Text="{ext:Locale SettingsTabSystemIgnoreControllerApplet}" />
|
||||||
|
@ -64,6 +64,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
public LibHacHorizonManager LibHacHorizonManager { get; private set; }
|
public LibHacHorizonManager LibHacHorizonManager { get; private set; }
|
||||||
|
|
||||||
public InputManager InputManager { get; private set; }
|
public InputManager InputManager { get; private set; }
|
||||||
|
public AutoAssignController AutoAssignController { get; private set; }
|
||||||
|
|
||||||
public SettingsWindow SettingsWindow { get; set; }
|
public SettingsWindow SettingsWindow { get; set; }
|
||||||
|
|
||||||
@ -110,6 +111,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
if (Program.PreviewerDetached)
|
if (Program.PreviewerDetached)
|
||||||
{
|
{
|
||||||
InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver());
|
InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver());
|
||||||
|
AutoAssignController = new AutoAssignController(InputManager, ViewModel);
|
||||||
|
|
||||||
_ = this.GetObservable(IsActiveProperty).Subscribe(it => ViewModel.IsActive = it);
|
_ = this.GetObservable(IsActiveProperty).Subscribe(it => ViewModel.IsActive = it);
|
||||||
this.ScalingChanged += OnScalingChanged;
|
this.ScalingChanged += OnScalingChanged;
|
||||||
|
@ -389,6 +389,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableMouse { get; set; }
|
public bool EnableMouse { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable or disable automatic controller assignment for players
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableAutoAssign { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -144,6 +144,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
|
|
||||||
Hid.EnableKeyboard.Value = cff.EnableKeyboard;
|
Hid.EnableKeyboard.Value = cff.EnableKeyboard;
|
||||||
Hid.EnableMouse.Value = cff.EnableMouse;
|
Hid.EnableMouse.Value = cff.EnableMouse;
|
||||||
|
Hid.EnableAutoAssign.Value = cff.EnableAutoAssign;
|
||||||
Hid.DisableInputWhenOutOfFocus.Value = shouldLoadFromFile ? cff.DisableInputWhenOutOfFocus: Hid.DisableInputWhenOutOfFocus.Value; // Get from global config only
|
Hid.DisableInputWhenOutOfFocus.Value = shouldLoadFromFile ? cff.DisableInputWhenOutOfFocus: Hid.DisableInputWhenOutOfFocus.Value; // Get from global config only
|
||||||
Hid.Hotkeys.Value = shouldLoadFromFile ? cff.Hotkeys : Hid.Hotkeys.Value; // Get from global config only
|
Hid.Hotkeys.Value = shouldLoadFromFile ? cff.Hotkeys : Hid.Hotkeys.Value; // Get from global config only
|
||||||
Hid.InputConfig.Value = cff.InputConfig ?? [];
|
Hid.InputConfig.Value = cff.InputConfig ?? [];
|
||||||
|
@ -449,6 +449,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<bool> EnableMouse { get; private set; }
|
public ReactiveObject<bool> EnableMouse { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable or disable auto-assigning controllers to players
|
||||||
|
/// </summary>
|
||||||
|
public ReactiveObject<bool> EnableAutoAssign { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -475,6 +480,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
{
|
{
|
||||||
EnableKeyboard = new ReactiveObject<bool>();
|
EnableKeyboard = new ReactiveObject<bool>();
|
||||||
EnableMouse = new ReactiveObject<bool>();
|
EnableMouse = new ReactiveObject<bool>();
|
||||||
|
EnableAutoAssign = new ReactiveObject<bool>();
|
||||||
DisableInputWhenOutOfFocus = new ReactiveObject<bool>();
|
DisableInputWhenOutOfFocus = new ReactiveObject<bool>();
|
||||||
Hotkeys = new ReactiveObject<KeyboardHotkeys>();
|
Hotkeys = new ReactiveObject<KeyboardHotkeys>();
|
||||||
InputConfig = new ReactiveObject<List<InputConfig>>();
|
InputConfig = new ReactiveObject<List<InputConfig>>();
|
||||||
|
@ -133,6 +133,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
ShowConsole = UI.ShowConsole,
|
ShowConsole = UI.ShowConsole,
|
||||||
EnableKeyboard = Hid.EnableKeyboard,
|
EnableKeyboard = Hid.EnableKeyboard,
|
||||||
EnableMouse = Hid.EnableMouse,
|
EnableMouse = Hid.EnableMouse,
|
||||||
|
EnableAutoAssign = Hid.EnableAutoAssign,
|
||||||
DisableInputWhenOutOfFocus = Hid.DisableInputWhenOutOfFocus,
|
DisableInputWhenOutOfFocus = Hid.DisableInputWhenOutOfFocus,
|
||||||
Hotkeys = Hid.Hotkeys,
|
Hotkeys = Hid.Hotkeys,
|
||||||
InputConfig = Hid.InputConfig,
|
InputConfig = Hid.InputConfig,
|
||||||
@ -249,6 +250,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
UI.WindowStartup.WindowMaximized.Value = false;
|
UI.WindowStartup.WindowMaximized.Value = false;
|
||||||
Hid.EnableKeyboard.Value = false;
|
Hid.EnableKeyboard.Value = false;
|
||||||
Hid.EnableMouse.Value = false;
|
Hid.EnableMouse.Value = false;
|
||||||
|
Hid.EnableAutoAssign.Value = false;
|
||||||
Hid.DisableInputWhenOutOfFocus.Value = false;
|
Hid.DisableInputWhenOutOfFocus.Value = false;
|
||||||
Hid.Hotkeys.Value = new KeyboardHotkeys
|
Hid.Hotkeys.Value = new KeyboardHotkeys
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user