Compare commits
30 Commits
metal
...
f024c8a695
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f024c8a695 | ||
|
|
6ecdf690be | ||
|
|
c6e82046dd | ||
|
|
538a9c83bd | ||
|
|
c3bfa67393 | ||
|
|
72c3ca7769 | ||
|
|
da268ebbee | ||
|
|
55f3a4b7ff | ||
|
|
cc905280cd | ||
|
|
38ecb3d5bc | ||
|
|
fd9bce0f6b | ||
|
|
b8cb70ef32 | ||
|
|
e238ea85c9 | ||
|
|
8cc74dab08 | ||
|
|
62dfbb5dcb | ||
|
|
5b88a2dd89 | ||
|
|
5034ef18c9 | ||
|
|
287d68c2cc | ||
|
|
f07efb751e | ||
|
|
6c8a60db08 | ||
|
|
7999a973f3 | ||
|
|
5513de93e5 | ||
|
|
9cccaac9d3 | ||
|
|
9b7dc6f4ee | ||
|
|
3ff9d1e128 | ||
|
|
ab4bb0a885 | ||
|
|
97be01d473 | ||
|
|
24cef89b6c | ||
|
|
2fe157e2b2 | ||
|
|
186ed4f984 |
@@ -42,7 +42,7 @@
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||
<PackageVersion Include="Gommon" Version="2.7.1.1" />
|
||||
<PackageVersion Include="Gommon" Version="2.7.1" />
|
||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageVersion Include="Sep" Version="0.6.0" />
|
||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||
|
||||
@@ -1436,7 +1436,7 @@
|
||||
010083A018262000,"Hitman: Blood Money — Reprisal",deadlock,ingame,2024-09-28 16:28:50
|
||||
01004B100A5CC000,"Hob: The Definitive Edition",,playable,2021-01-13 09:39:19
|
||||
0100F7300ED2C000,"Hoggy2",,playable,2022-10-10 13:53:35
|
||||
0100F7E00C70E000,"Hogwarts Legacy",UE4;slow,ingame,2024-09-03 19:53:58
|
||||
0100F7E00C70E000,"Hogwarts Legacy",slow,ingame,2024-09-03 19:53:58
|
||||
0100633007D48000,"Hollow Knight",nvdec,playable,2023-01-16 15:44:56
|
||||
0100F2100061E800,"Hollow0",UE4;gpu,ingame,2021-03-03 23:42:56
|
||||
0100342009E16000,"Holy Potatoes! What The Hell?!",,playable,2020-07-03 10:48:56
|
||||
@@ -1800,7 +1800,6 @@
|
||||
010005A00B312000,"Megaton Rainfall",gpu;opengl,boots,2022-08-04 18:29:43
|
||||
0100EA100DF92000,"Meiji Katsugeki Haikara Ryuuseigumi - Seibai Shimaseu, Yonaoshi Kagyou",32-bit;nvdec,playable,2022-12-05 13:19:12
|
||||
0100B360068B2000,"Mekorama",gpu,boots,2021-06-17 16:37:21
|
||||
010012301932A000,"Melatonin",,playable,2025-02-16 04:08:17
|
||||
01000FA010340000,"Melbits World",nvdec;online,menus,2021-11-26 13:51:22
|
||||
0100F68019636000,"Melon Journey",,playable,2023-04-23 21:20:01
|
||||
010079C012896000,"Memories Off -Innocent Fille- for Dearest",,playable,2020-08-04 07:31:22
|
||||
|
||||
|
@@ -1,9 +0,0 @@
|
||||
namespace Ryujinx.Common
|
||||
{
|
||||
public static class SharedConstants
|
||||
{
|
||||
public const string DefaultLanPlayHost = "ryuldn.vudjun.com";
|
||||
public const short LanPlayPort = 30456;
|
||||
public const string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,9 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
||||
{
|
||||
class IUserLocalCommunicationService : IpcService, IDisposable
|
||||
{
|
||||
public static string DefaultLanPlayHost = "ryuldn.vudjun.com";
|
||||
public static short LanPlayPort = 30456;
|
||||
|
||||
public INetworkClient NetworkClient { get; private set; }
|
||||
|
||||
private const int NifmRequestID = 90;
|
||||
@@ -1089,18 +1092,20 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
||||
case MultiplayerMode.LdnRyu:
|
||||
try
|
||||
{
|
||||
string ldnServer = context.Device.Configuration.MultiplayerLdnServer
|
||||
?? throw new InvalidOperationException("Cannot initialize RyuLDN with a null Multiplayer server.");
|
||||
|
||||
string ldnServer = context.Device.Configuration.MultiplayerLdnServer;
|
||||
if (string.IsNullOrEmpty(ldnServer))
|
||||
{
|
||||
ldnServer = DefaultLanPlayHost;
|
||||
}
|
||||
if (!IPAddress.TryParse(ldnServer, out IPAddress ipAddress))
|
||||
{
|
||||
ipAddress = Dns.GetHostEntry(ldnServer).AddressList[0];
|
||||
}
|
||||
NetworkClient = new LdnMasterProxyClient(ipAddress.ToString(), SharedConstants.LanPlayPort, context.Device.Configuration);
|
||||
NetworkClient = new LdnMasterProxyClient(ipAddress.ToString(), LanPlayPort, context.Device.Configuration);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.ServiceLdn, "Could not locate RyuLDN server. Defaulting to stubbed wireless.");
|
||||
Logger.Error?.Print(LogClass.ServiceLdn, "Could not locate LdnRyu server. Defaulting to stubbed wireless.");
|
||||
Logger.Error?.Print(LogClass.ServiceLdn, ex.Message);
|
||||
NetworkClient = new LdnDisabledClient();
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace Ryujinx.Input.SDL2
|
||||
byte blue = packedRgb > 0 ? (byte)(packedRgb % 256) : (byte)0;
|
||||
|
||||
if (SDL_GameControllerSetLED(_gamepadHandle, red, green, blue) != 0)
|
||||
Logger.Debug?.Print(LogClass.Hid, "LED setting failed; probably in the middle of disconnecting.");
|
||||
Logger.Error?.Print(LogClass.Hid, "LED setting failed; probably in the middle of disconnecting.");
|
||||
}
|
||||
|
||||
private GamepadFeaturesFlag GetFeaturesFlag()
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace Ryujinx.Input.SDL2
|
||||
}
|
||||
|
||||
private void HandleJoyStickConnected(int joystickDeviceId, int joystickInstanceId)
|
||||
{
|
||||
{
|
||||
if (SDL_IsGameController(joystickDeviceId) == SDL_bool.SDL_TRUE)
|
||||
{
|
||||
if (_gamepadsInstanceIdsMapping.ContainsKey(joystickInstanceId))
|
||||
|
||||
@@ -14,6 +14,7 @@ using ControllerType = Ryujinx.Common.Configuration.Hid.ControllerType;
|
||||
using PlayerIndex = Ryujinx.HLE.HOS.Services.Hid.PlayerIndex;
|
||||
using Switch = Ryujinx.HLE.Switch;
|
||||
|
||||
|
||||
namespace Ryujinx.Input.HLE
|
||||
{
|
||||
public class NpadManager : IDisposable
|
||||
@@ -38,6 +39,8 @@ namespace Ryujinx.Input.HLE
|
||||
private bool _enableMouse;
|
||||
private Switch _device;
|
||||
|
||||
public bool AutoAssignEnabled { get; set; } = false;
|
||||
|
||||
public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IGamepadDriver mouseDriver)
|
||||
{
|
||||
_controllers = new NpadController[MaxControllers];
|
||||
@@ -84,12 +87,14 @@ namespace Ryujinx.Input.HLE
|
||||
}
|
||||
}
|
||||
|
||||
if (AutoAssignEnabled) return;
|
||||
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleOnGamepadConnected(string id)
|
||||
{
|
||||
if (AutoAssignEnabled) return;
|
||||
// Force input reload
|
||||
ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
|
||||
}
|
||||
@@ -171,7 +176,7 @@ namespace Ryujinx.Input.HLE
|
||||
_device.Hid.RefreshInputConfig(validInputs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void UnblockInputUpdates()
|
||||
{
|
||||
lock (_lock)
|
||||
@@ -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.Configuration.RefreshInputConfig = RefreshInputConfigForHLE;
|
||||
|
||||
AutoAssignEnabled = enableAutoAssign;
|
||||
|
||||
ReloadConfiguration(inputConfig, enableKeyboard, enableMouse);
|
||||
}
|
||||
|
||||
|
||||
@@ -464,7 +464,7 @@ namespace Ryujinx.Ava
|
||||
|
||||
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);
|
||||
|
||||
_viewModel.IsGameRunning = true;
|
||||
@@ -951,7 +951,7 @@ namespace Ryujinx.Ava
|
||||
ConfigurationState.Instance.Multiplayer.Mode,
|
||||
ConfigurationState.Instance.Multiplayer.DisableP2p,
|
||||
ConfigurationState.Instance.Multiplayer.LdnPassphrase,
|
||||
ConfigurationState.Instance.Multiplayer.GetLdnServer(),
|
||||
ConfigurationState.Instance.Multiplayer.LdnServer,
|
||||
ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value,
|
||||
ConfigurationState.Instance.Hacks.ShowDirtyHacks ? ConfigurationState.Instance.Hacks.EnabledHacks : null));
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -46,6 +46,7 @@ namespace Ryujinx.Headless
|
||||
private static List<InputConfig> _inputConfiguration = [];
|
||||
private static bool _enableKeyboard;
|
||||
private static bool _enableMouse;
|
||||
private static bool _enableAutoAssign;
|
||||
|
||||
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
|
||||
@@ -230,6 +231,7 @@ namespace Ryujinx.Headless
|
||||
_inputConfiguration ??= [];
|
||||
_enableKeyboard = option.EnableKeyboard;
|
||||
_enableMouse = option.EnableMouse;
|
||||
_enableAutoAssign = option.EnableAutoAssign;
|
||||
|
||||
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
|
||||
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
|
||||
@@ -374,7 +376,7 @@ namespace Ryujinx.Headless
|
||||
|
||||
DisplaySleep.Prevent();
|
||||
|
||||
_window.Initialize(_emulationContext, _inputConfiguration, _enableKeyboard, _enableMouse);
|
||||
_window.Initialize(_emulationContext, _inputConfiguration, _enableKeyboard, _enableMouse, _enableAutoAssign);
|
||||
|
||||
_window.Execute();
|
||||
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace Ryujinx.Headless
|
||||
|
||||
if (NeedsOverride(nameof(EnableMouse)))
|
||||
EnableMouse = configurationState.Hid.EnableMouse;
|
||||
|
||||
if (NeedsOverride(nameof(EnableAutoAssign)))
|
||||
EnableAutoAssign = configurationState.Hid.EnableAutoAssign;
|
||||
|
||||
if (NeedsOverride(nameof(HideCursorMode)))
|
||||
HideCursorMode = configurationState.HideCursor;
|
||||
@@ -272,6 +275,9 @@ namespace Ryujinx.Headless
|
||||
|
||||
[Option("enable-mouse", Required = false, Default = false, HelpText = "Enable or disable mouse support.")]
|
||||
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.")]
|
||||
public HideCursorMode HideCursorMode { get; set; }
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace Ryujinx.Headless
|
||||
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;
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Ryujinx.Headless
|
||||
|
||||
Renderer = renderer;
|
||||
|
||||
NpadManager.Initialize(device, inputConfigs, enableKeyboard, enableMouse);
|
||||
NpadManager.Initialize(device, inputConfigs, enableKeyboard, enableMouse, enableAutoAssign);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -132,7 +132,7 @@ namespace Ryujinx.Ava
|
||||
SDL2Driver.MainThreadDispatcher = action => Dispatcher.UIThread.InvokeAsync(action, DispatcherPriority.Input);
|
||||
|
||||
ReloadConfig();
|
||||
|
||||
|
||||
WindowScaleFactor = ForceDpiAware.GetWindowScaleFactor();
|
||||
|
||||
// Logging system information.
|
||||
|
||||
@@ -252,6 +252,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
|
||||
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
|
||||
|
||||
_mainWindow.AutoAssignController.ConfigurationUpdated += OnConfigurationUpdated;
|
||||
|
||||
_mainWindow.ViewModel.AppHost?.NpadManager.BlockInputUpdates();
|
||||
|
||||
_isLoaded = false;
|
||||
@@ -365,14 +367,47 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
|
||||
private void HandleOnGamepadDisconnected(string id)
|
||||
{
|
||||
if(ConfigurationState.Instance.Hid.EnableAutoAssign) return;
|
||||
Dispatcher.UIThread.Post(LoadDevices);
|
||||
}
|
||||
|
||||
private void HandleOnGamepadConnected(string id)
|
||||
{
|
||||
if(ConfigurationState.Instance.Hid.EnableAutoAssign) return;
|
||||
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()
|
||||
{
|
||||
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);
|
||||
|
||||
// Atomically replace and signal input change.
|
||||
@@ -890,6 +931,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
|
||||
_mainWindow.InputManager.GamepadDriver.OnGamepadConnected -= HandleOnGamepadConnected;
|
||||
_mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected -= HandleOnGamepadDisconnected;
|
||||
_mainWindow.AutoAssignController.ConfigurationUpdated -= OnConfigurationUpdated;
|
||||
|
||||
_mainWindow.ViewModel.AppHost?.NpadManager.UnblockInputUpdates();
|
||||
|
||||
|
||||
@@ -793,7 +793,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task HandleFirmwareInstallation(string filename)
|
||||
private async Task HandleFirmwareInstallation(string filename)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -125,6 +125,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public bool EnableDockedMode { get; set; }
|
||||
public bool EnableKeyboard { get; set; }
|
||||
public bool EnableMouse { get; set; }
|
||||
public bool EnableAutoAssign { get; set; }
|
||||
public bool DisableInputWhenOutOfFocus { get; set; }
|
||||
|
||||
public int FocusLostActionType { get; set; }
|
||||
@@ -502,6 +503,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
EnableDockedMode = config.System.EnableDockedMode;
|
||||
EnableKeyboard = config.Hid.EnableKeyboard;
|
||||
EnableMouse = config.Hid.EnableMouse;
|
||||
EnableAutoAssign = config.Hid.EnableAutoAssign;
|
||||
DisableInputWhenOutOfFocus = config.Hid.DisableInputWhenOutOfFocus;
|
||||
|
||||
// Keyboard Hotkeys
|
||||
@@ -607,6 +609,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
config.System.EnableDockedMode.Value = EnableDockedMode;
|
||||
config.Hid.EnableKeyboard.Value = EnableKeyboard;
|
||||
config.Hid.EnableMouse.Value = EnableMouse;
|
||||
bool activatingAutoAssign = EnableAutoAssign && !config.Hid.EnableAutoAssign;
|
||||
config.Hid.EnableAutoAssign.Value = EnableAutoAssign;
|
||||
config.Hid.DisableInputWhenOutOfFocus.Value = DisableInputWhenOutOfFocus;
|
||||
|
||||
// Keyboard Hotkeys
|
||||
@@ -629,7 +633,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
|
||||
config.System.DramSize.Value = DramSize;
|
||||
config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
|
||||
config.System.IgnoreControllerApplet.Value = IgnoreApplet;
|
||||
config.System.IgnoreControllerApplet.Value = (EnableAutoAssign) || IgnoreApplet;
|
||||
|
||||
// CPU
|
||||
config.System.EnablePtc.Value = EnablePptc;
|
||||
@@ -707,7 +711,14 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
MainWindow.UpdateGraphicsConfig();
|
||||
RyujinxApp.MainWindow.ViewModel.VSyncModeSettingChanged();
|
||||
|
||||
SaveSettingsEvent?.Invoke();
|
||||
if(activatingAutoAssign)
|
||||
{
|
||||
RyujinxApp.MainWindow.AutoAssignController.RefreshControllers();
|
||||
}
|
||||
else
|
||||
{
|
||||
SaveSettingsEvent?.Invoke();
|
||||
}
|
||||
|
||||
GameListNeedsRefresh = false;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,12 @@
|
||||
<TextBlock
|
||||
Text="{ext:Locale SettingsTabInputDirectMouseAccess}" />
|
||||
</CheckBox>
|
||||
<CheckBox
|
||||
ToolTip.Tip="{ext:Locale AutoAssignTooltip}"
|
||||
IsChecked="{Binding EnableAutoAssign}">
|
||||
<TextBlock
|
||||
Text="{ext:Locale SettingsTabInputAutoAssign}" />
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -133,6 +133,12 @@
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageBrazilianPortuguese}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageSwedish}" />
|
||||
</ComboBoxItem>
|
||||
<ComboBoxItem>
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemSystemLanguageNorwegian}" />
|
||||
</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
<StackPanel
|
||||
@@ -309,6 +315,7 @@
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemIgnoreMissingServices}" />
|
||||
</CheckBox>
|
||||
<CheckBox
|
||||
IsEnabled="{Binding !EnableAutoAssign}"
|
||||
IsChecked="{Binding IgnoreApplet}"
|
||||
ToolTip.Tip="{ext:Locale IgnoreControllerAppletTooltip}">
|
||||
<TextBlock Text="{ext:Locale SettingsTabSystemIgnoreControllerApplet}" />
|
||||
|
||||
@@ -64,6 +64,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; }
|
||||
|
||||
@@ -110,6 +111,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
if (Program.PreviewerDetached)
|
||||
{
|
||||
InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver());
|
||||
AutoAssignController = new AutoAssignController(InputManager, ViewModel);
|
||||
|
||||
_ = this.GetObservable(IsActiveProperty).Subscribe(it => ViewModel.IsActive = it);
|
||||
this.ScalingChanged += OnScalingChanged;
|
||||
@@ -139,24 +141,8 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
NotificationHelper.SetNotificationManager(this);
|
||||
|
||||
Executor.ExecuteBackgroundAsync(async () =>
|
||||
{
|
||||
await ShowIntelMacWarningAsync();
|
||||
FilePath firmwarePath = CommandLineState.FirmwareToInstallPathArg;
|
||||
if (firmwarePath is not null)
|
||||
{
|
||||
if ((firmwarePath.ExistsAsFile && firmwarePath.Extension is "xci" or "zip") ||
|
||||
firmwarePath.ExistsAsDirectory)
|
||||
{
|
||||
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||
ViewModel.HandleFirmwareInstallation(firmwarePath));
|
||||
CommandLineState.FirmwareToInstallPathArg = null;
|
||||
}
|
||||
else
|
||||
Logger.Notice.Print(LogClass.UI, "Invalid firmware type provided. Path must be a directory, or a .zip or .xci file.");
|
||||
}
|
||||
});
|
||||
|
||||
Executor.ExecuteBackgroundAsync(ShowIntelMacWarningAsync);
|
||||
}
|
||||
|
||||
private void OnScalingChanged(object sender, EventArgs e)
|
||||
@@ -189,12 +175,17 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
List<LdnGameData> ldnGameDataArray = e.LdnData.ToList();
|
||||
ViewModel.LdnData.Clear();
|
||||
foreach (ApplicationData application in ViewModel.Applications.Where(it => it.HasControlHolder))
|
||||
{
|
||||
ref ApplicationControlProperty controlHolder = ref application.ControlHolder.Value;
|
||||
|
||||
ViewModel.LdnData[application.IdString] = e.LdnData.Where(ref controlHolder);
|
||||
|
||||
ViewModel.LdnData[application.IdString] =
|
||||
LdnGameData.GetArrayForApp(
|
||||
ldnGameDataArray,
|
||||
ref controlHolder
|
||||
);
|
||||
|
||||
UpdateApplicationWithLdnData(application);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
{
|
||||
public class ApplicationLibrary
|
||||
{
|
||||
public const string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
|
||||
public Language DesiredLanguage { get; set; }
|
||||
public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
|
||||
public event Action<LdnGameDataReceivedEventArgs> LdnGameDataReceived;
|
||||
@@ -825,6 +826,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
|
||||
public async Task RefreshLdn()
|
||||
{
|
||||
|
||||
if (ConfigurationState.Instance.Multiplayer.Mode == MultiplayerMode.LdnRyu)
|
||||
{
|
||||
try
|
||||
@@ -832,22 +834,33 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
string ldnWebHost = ConfigurationState.Instance.Multiplayer.LdnServer;
|
||||
if (string.IsNullOrEmpty(ldnWebHost))
|
||||
{
|
||||
ldnWebHost = SharedConstants.DefaultLanPlayWebHost;
|
||||
ldnWebHost = DefaultLanPlayWebHost;
|
||||
}
|
||||
|
||||
IEnumerable<LdnGameData> ldnGameDataArray = Array.Empty<LdnGameData>();
|
||||
using HttpClient httpClient = new();
|
||||
string ldnGameDataArrayString = await httpClient.GetStringAsync($"https://{ldnWebHost}/api/public_games");
|
||||
LdnGameData[] ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData).ToArray();
|
||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs(ldnGameDataArray));
|
||||
return;
|
||||
ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData);
|
||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs
|
||||
{
|
||||
LdnData = ldnGameDataArray
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, $"Failed to fetch the public games JSON from the API. Player and game count in the game list will be unavailable.\n{ex.Message}");
|
||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs
|
||||
{
|
||||
LdnData = Array.Empty<LdnGameData>()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
LdnGameDataReceived?.Invoke(LdnGameDataReceivedEventArgs.Empty);
|
||||
else
|
||||
{
|
||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs
|
||||
{
|
||||
LdnData = Array.Empty<LdnGameData>()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Replace the currently stored DLC state for the game with the provided DLC state.
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
public IEnumerable<string> Players { get; set; }
|
||||
|
||||
public static Array GetArrayForApp(
|
||||
LdnGameData[] receivedData, ref ApplicationControlProperty acp)
|
||||
IEnumerable<LdnGameData> receivedData, ref ApplicationControlProperty acp)
|
||||
{
|
||||
LibHac.Common.FixedArrays.Array8<ulong> communicationId = acp.LocalCommunicationId;
|
||||
|
||||
@@ -40,10 +40,4 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
public int GameCount => _ldnDatas.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public static class LdnGameDataHelper
|
||||
{
|
||||
public static LdnGameData.Array Where(this LdnGameData[] unfilteredDatas, ref ApplicationControlProperty acp)
|
||||
=> LdnGameData.GetArrayForApp(unfilteredDatas, ref acp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,6 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
||||
{
|
||||
public class LdnGameDataReceivedEventArgs : EventArgs
|
||||
{
|
||||
public static new readonly LdnGameDataReceivedEventArgs Empty = new(null);
|
||||
|
||||
public LdnGameDataReceivedEventArgs(LdnGameData[] ldnData)
|
||||
{
|
||||
LdnData = ldnData ?? [];
|
||||
}
|
||||
|
||||
|
||||
public LdnGameData[] LdnData { get; set; }
|
||||
public IEnumerable<LdnGameData> LdnData { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Gommon;
|
||||
using Ryujinx.Common.Logging;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -14,7 +13,6 @@ namespace Ryujinx.Ava.Utilities
|
||||
public static string OverrideBackendThreading { get; private set; }
|
||||
public static string OverrideHideCursor { get; private set; }
|
||||
public static string BaseDirPathArg { get; private set; }
|
||||
public static FilePath FirmwareToInstallPathArg { get; set; }
|
||||
public static string Profile { get; private set; }
|
||||
public static string LaunchPathArg { get; private set; }
|
||||
public static string LaunchApplicationId { get; private set; }
|
||||
@@ -43,19 +41,6 @@ namespace Ryujinx.Ava.Utilities
|
||||
|
||||
BaseDirPathArg = args[++i];
|
||||
|
||||
arguments.Add(arg);
|
||||
arguments.Add(args[i]);
|
||||
break;
|
||||
case "--install-firmware":
|
||||
if (i + 1 >= args.Length)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
FirmwareToInstallPathArg = new FilePath(args[++i]);
|
||||
|
||||
arguments.Add(arg);
|
||||
arguments.Add(args[i]);
|
||||
break;
|
||||
|
||||
@@ -389,6 +389,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
/// </summary>
|
||||
public bool EnableMouse { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enable or disable automatic controller assignment for players
|
||||
/// </summary>
|
||||
public bool EnableAutoAssign { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
||||
/// </summary>
|
||||
|
||||
@@ -141,6 +141,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
|
||||
Hid.EnableKeyboard.Value = cff.EnableKeyboard;
|
||||
Hid.EnableMouse.Value = cff.EnableMouse;
|
||||
Hid.EnableAutoAssign.Value = cff.EnableAutoAssign;
|
||||
Hid.DisableInputWhenOutOfFocus.Value = cff.DisableInputWhenOutOfFocus;
|
||||
Hid.Hotkeys.Value = cff.Hotkeys;
|
||||
Hid.InputConfig.Value = cff.InputConfig ?? [];
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using ARMeilleure;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.Ava.Utilities.Configuration.System;
|
||||
using Ryujinx.Ava.Utilities.Configuration.UI;
|
||||
using Ryujinx.Common;
|
||||
@@ -449,6 +448,11 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
/// </summary>
|
||||
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>
|
||||
/// Enable/disable the ability to control Ryujinx when it's not the currently focused window.
|
||||
/// </summary>
|
||||
@@ -475,6 +479,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
{
|
||||
EnableKeyboard = new ReactiveObject<bool>();
|
||||
EnableMouse = new ReactiveObject<bool>();
|
||||
EnableAutoAssign = new ReactiveObject<bool>();
|
||||
DisableInputWhenOutOfFocus = new ReactiveObject<bool>();
|
||||
Hotkeys = new ReactiveObject<KeyboardHotkeys>();
|
||||
InputConfig = new ReactiveObject<List<InputConfig>>();
|
||||
@@ -648,14 +653,6 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
/// </summary>
|
||||
public ReactiveObject<string> LdnServer { get; private set; }
|
||||
|
||||
public string GetLdnServer()
|
||||
{
|
||||
string ldnServer = LdnServer;
|
||||
return string.IsNullOrEmpty(ldnServer)
|
||||
? SharedConstants.DefaultLanPlayHost
|
||||
: ldnServer;
|
||||
}
|
||||
|
||||
public MultiplayerSection()
|
||||
{
|
||||
LanInterfaceId = new ReactiveObject<string>();
|
||||
|
||||
@@ -133,6 +133,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
ShowConsole = UI.ShowConsole,
|
||||
EnableKeyboard = Hid.EnableKeyboard,
|
||||
EnableMouse = Hid.EnableMouse,
|
||||
EnableAutoAssign = Hid.EnableAutoAssign,
|
||||
DisableInputWhenOutOfFocus = Hid.DisableInputWhenOutOfFocus,
|
||||
Hotkeys = Hid.Hotkeys,
|
||||
InputConfig = Hid.InputConfig,
|
||||
@@ -249,6 +250,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
||||
UI.WindowStartup.WindowMaximized.Value = false;
|
||||
Hid.EnableKeyboard.Value = false;
|
||||
Hid.EnableMouse.Value = false;
|
||||
Hid.EnableAutoAssign.Value = false;
|
||||
Hid.DisableInputWhenOutOfFocus.Value = false;
|
||||
Hid.Hotkeys.Value = new KeyboardHotkeys
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user