From 2200dac64fe9aa400ee842aa472845e4c9f1656b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Hamil?= Date: Sun, 25 Aug 2024 23:47:09 +0300 Subject: [PATCH] Handheld Gyro --- Directory.Packages.props | 3 +- Ryujinx.sln | 11 ++++++ .../JsonMotionConfigControllerConverter.cs | 2 ++ .../Motion/MotionInputBackendType.cs | 1 + src/Ryujinx.Gtk3/Ryujinx.Gtk3.csproj | 1 + src/Ryujinx.Gtk3/UI/MainWindow.cs | 3 +- .../UI/Windows/ControllerWindow.cs | 16 ++++++++- .../UI/Windows/ControllerWindow.glade | 14 ++++++++ src/Ryujinx.Headless.SDL2/Program.cs | 3 +- .../Ryujinx.Headless.SDL2.csproj | 1 + .../Ryujinx.Input.SDL3.csproj | 13 +++++++ src/Ryujinx.Input.SDL3/SDL3MotionDriver.cs | 35 +++++++++++++++++++ src/Ryujinx.Input/HLE/InputManager.cs | 6 ++-- src/Ryujinx.Input/HLE/NpadController.cs | 16 ++++++++- src/Ryujinx.Input/HLE/NpadManager.cs | 6 ++-- src/Ryujinx.Input/IHandheld.cs | 8 +++++ src/Ryujinx/Assets/Locales/en_US.json | 1 + src/Ryujinx/Ryujinx.csproj | 1 + .../UI/Models/Input/GamepadInputConfig.cs | 5 +-- .../ViewModels/Input/MotionInputViewModel.cs | 19 ++++++++++ .../UI/Views/Input/MotionInputView.axaml | 11 ++++++ .../UI/Views/Input/MotionInputView.axaml.cs | 2 ++ src/Ryujinx/UI/Windows/MainWindow.axaml.cs | 3 +- 23 files changed, 169 insertions(+), 12 deletions(-) create mode 100644 src/Ryujinx.Input.SDL3/Ryujinx.Input.SDL3.csproj create mode 100644 src/Ryujinx.Input.SDL3/SDL3MotionDriver.cs create mode 100644 src/Ryujinx.Input/IHandheld.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index e722dd8838..8fb1c261f8 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,6 +3,7 @@ true + @@ -49,4 +50,4 @@ - \ No newline at end of file + diff --git a/Ryujinx.sln b/Ryujinx.sln index b8304164d5..976bc82b4f 100644 --- a/Ryujinx.sln +++ b/Ryujinx.sln @@ -87,6 +87,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon", "src\Ryuj EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D796F12C-217B-4BBF-A131-B6DCB72C6282}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Input.SDL3", "src\Ryujinx.Input.SDL3\Ryujinx.Input.SDL3.csproj", "{3BF24278-547D-42C2-9D43-182B978F54DD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -249,6 +253,10 @@ Global {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU + {3BF24278-547D-42C2-9D43-182B978F54DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3BF24278-547D-42C2-9D43-182B978F54DD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3BF24278-547D-42C2-9D43-182B978F54DD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3BF24278-547D-42C2-9D43-182B978F54DD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -256,4 +264,7 @@ Global GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {110169B3-3328-4730-8AB0-BA05BEF75C1A} EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {3BF24278-547D-42C2-9D43-182B978F54DD} = {D796F12C-217B-4BBF-A131-B6DCB72C6282} + EndGlobalSection EndGlobal diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/Motion/JsonMotionConfigControllerConverter.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/Motion/JsonMotionConfigControllerConverter.cs index 40f067aea3..4f218c0d25 100644 --- a/src/Ryujinx.Common/Configuration/Hid/Controller/Motion/JsonMotionConfigControllerConverter.cs +++ b/src/Ryujinx.Common/Configuration/Hid/Controller/Motion/JsonMotionConfigControllerConverter.cs @@ -56,6 +56,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion return motionBackendType switch { MotionInputBackendType.GamepadDriver => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardMotionConfigController), + MotionInputBackendType.Handheld => JsonSerializer.Deserialize(ref reader, _serializerContext.StandardMotionConfigController), MotionInputBackendType.CemuHook => JsonSerializer.Deserialize(ref reader, _serializerContext.CemuHookMotionConfigController), _ => throw new InvalidOperationException($"Unknown backend type {motionBackendType}"), }; @@ -66,6 +67,7 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion switch (value.MotionBackend) { case MotionInputBackendType.GamepadDriver: + case MotionInputBackendType.Handheld: JsonSerializer.Serialize(writer, value as StandardMotionConfigController, _serializerContext.StandardMotionConfigController); break; case MotionInputBackendType.CemuHook: diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/Motion/MotionInputBackendType.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/Motion/MotionInputBackendType.cs index fd8391289c..fd09b25d83 100644 --- a/src/Ryujinx.Common/Configuration/Hid/Controller/Motion/MotionInputBackendType.cs +++ b/src/Ryujinx.Common/Configuration/Hid/Controller/Motion/MotionInputBackendType.cs @@ -9,5 +9,6 @@ namespace Ryujinx.Common.Configuration.Hid.Controller.Motion Invalid, GamepadDriver, CemuHook, + Handheld, } } diff --git a/src/Ryujinx.Gtk3/Ryujinx.Gtk3.csproj b/src/Ryujinx.Gtk3/Ryujinx.Gtk3.csproj index b4453f9d79..23f3317837 100644 --- a/src/Ryujinx.Gtk3/Ryujinx.Gtk3.csproj +++ b/src/Ryujinx.Gtk3/Ryujinx.Gtk3.csproj @@ -36,6 +36,7 @@ + diff --git a/src/Ryujinx.Gtk3/UI/MainWindow.cs b/src/Ryujinx.Gtk3/UI/MainWindow.cs index 66c0afae03..787121f5c4 100644 --- a/src/Ryujinx.Gtk3/UI/MainWindow.cs +++ b/src/Ryujinx.Gtk3/UI/MainWindow.cs @@ -26,6 +26,7 @@ using Ryujinx.Input.GTK3; using Ryujinx.Input.HLE; using Ryujinx.Input.SDL2; using Ryujinx.Modules; +using Ryujinx.SDL3; using Ryujinx.UI.App.Common; using Ryujinx.UI.Applet; using Ryujinx.UI.Common; @@ -339,7 +340,7 @@ namespace Ryujinx.UI Task.Run(RefreshFirmwareLabel); - InputManager = new InputManager(new GTK3KeyboardDriver(this), new SDL2GamepadDriver()); + InputManager = new InputManager(new GTK3KeyboardDriver(this), new SDL2GamepadDriver(), new SDL3MotionDriver()); } private void UpdateMultiplayerLanInterfaceId(object sender, ReactiveEventArgs args) diff --git a/src/Ryujinx.Gtk3/UI/Windows/ControllerWindow.cs b/src/Ryujinx.Gtk3/UI/Windows/ControllerWindow.cs index d0b8266f42..fa2231ce9c 100644 --- a/src/Ryujinx.Gtk3/UI/Windows/ControllerWindow.cs +++ b/src/Ryujinx.Gtk3/UI/Windows/ControllerWindow.cs @@ -47,6 +47,7 @@ namespace Ryujinx.UI.Windows [GUI] Adjustment _gyroDeadzone; [GUI] CheckButton _enableMotion; [GUI] CheckButton _enableCemuHook; + [GUI] CheckButton _enableHandheld; [GUI] CheckButton _mirrorInput; [GUI] Entry _dsuServerHost; [GUI] Entry _dsuServerPort; @@ -185,6 +186,7 @@ namespace Ryujinx.UI.Windows _rSl.Clicked += Button_Pressed; _rSr.Clicked += Button_Pressed; _enableCemuHook.Clicked += CemuHookCheckButtonPressed; + _enableHandheld.Clicked += HandheldCheckButtonPressed; // Setup current values. UpdateInputDeviceList(); @@ -202,6 +204,11 @@ namespace Ryujinx.UI.Windows _mainWindow.RendererWidget?.NpadManager.BlockInputUpdates(); } + private void HandheldCheckButtonPressed(object sender, EventArgs e) + { + UpdateCemuHookSpecificFieldsVisibility(); + } + private void CemuHookCheckButtonPressed(object sender, EventArgs e) { UpdateCemuHookSpecificFieldsVisibility(); @@ -291,8 +298,13 @@ namespace Ryujinx.UI.Windows private void UpdateCemuHookSpecificFieldsVisibility() { + if (_enableHandheld.Active) + { + _enableCemuHook.Active = false; + } if (_enableCemuHook.Active) { + _enableHandheld.Active = false; _dsuServerHostBox.Show(); _dsuServerPortBox.Show(); _motionControllerSlot.Show(); @@ -429,6 +441,7 @@ namespace Ryujinx.UI.Windows _mirrorInput.Active = false; _enableMotion.Active = false; _enableCemuHook.Active = false; + _enableHandheld.Active = false; _slotNumber.Value = 0; _altSlotNumber.Value = 0; _sensitivity.Value = 100; @@ -528,6 +541,7 @@ namespace Ryujinx.UI.Windows _gyroDeadzone.Value = controllerConfig.Motion.GyroDeadzone; _enableMotion.Active = controllerConfig.Motion.EnableMotion; _enableCemuHook.Active = controllerConfig.Motion.MotionBackend == MotionInputBackendType.CemuHook; + _enableHandheld.Active = controllerConfig.Motion.MotionBackend == MotionInputBackendType.Handheld; // If both stick ranges are 0 (usually indicative of an outdated profile load) then both sticks will be set to 1.0. if (_controllerRangeLeft.Value <= 0.0 && _controllerRangeRight.Value <= 0.0) @@ -688,7 +702,7 @@ namespace Ryujinx.UI.Windows { motionConfig = new StandardMotionConfigController { - MotionBackend = MotionInputBackendType.GamepadDriver, + MotionBackend = _enableHandheld.Active ? MotionInputBackendType.Handheld : MotionInputBackendType.GamepadDriver, EnableMotion = _enableMotion.Active, Sensitivity = (int)_sensitivity.Value, GyroDeadzone = _gyroDeadzone.Value, diff --git a/src/Ryujinx.Gtk3/UI/Windows/ControllerWindow.glade b/src/Ryujinx.Gtk3/UI/Windows/ControllerWindow.glade index e433f5cc46..c148abe10b 100644 --- a/src/Ryujinx.Gtk3/UI/Windows/ControllerWindow.glade +++ b/src/Ryujinx.Gtk3/UI/Windows/ControllerWindow.glade @@ -1867,6 +1867,20 @@ 1 + + + Use Handheld compatible motion + True + True + False + True + + + False + True + 2 + + Use CemuHook compatible motion diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs index 85aff67129..fe3df16682 100644 --- a/src/Ryujinx.Headless.SDL2/Program.cs +++ b/src/Ryujinx.Headless.SDL2/Program.cs @@ -28,6 +28,7 @@ using Ryujinx.Input; using Ryujinx.Input.HLE; using Ryujinx.Input.SDL2; using Ryujinx.SDL2.Common; +using Ryujinx.SDL3; using Silk.NET.Vulkan; using System; using System.Collections.Generic; @@ -339,7 +340,7 @@ namespace Ryujinx.Headless.SDL2 _accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, option.UserProfile); _userChannelPersistence = new UserChannelPersistence(); - _inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver()); + _inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver(), new SDL3MotionDriver()); GraphicsConfig.EnableShaderCache = true; diff --git a/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj b/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj index 6102295444..b046d05846 100644 --- a/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj +++ b/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj @@ -24,6 +24,7 @@ + diff --git a/src/Ryujinx.Input.SDL3/Ryujinx.Input.SDL3.csproj b/src/Ryujinx.Input.SDL3/Ryujinx.Input.SDL3.csproj new file mode 100644 index 0000000000..a3b94f7400 --- /dev/null +++ b/src/Ryujinx.Input.SDL3/Ryujinx.Input.SDL3.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + true + + + + + + + + diff --git a/src/Ryujinx.Input.SDL3/SDL3MotionDriver.cs b/src/Ryujinx.Input.SDL3/SDL3MotionDriver.cs new file mode 100644 index 0000000000..77530cb3b4 --- /dev/null +++ b/src/Ryujinx.Input.SDL3/SDL3MotionDriver.cs @@ -0,0 +1,35 @@ +using Ryujinx.Input; +using SDL3; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using static SDL3.SDL3; + +namespace Ryujinx.SDL3; +public unsafe class SDL3MotionDriver : IHandheld +{ + private Dictionary sensors; + public SDL3MotionDriver() + { + SDL_Init(SDL_InitFlags.Sensor); + sensors = SDL_GetSensors().ToArray().ToDictionary(SDL_GetSensorTypeForID, SDL_OpenSensor); + } + + public Vector3 GetMotionData(MotionInputId gyroscope) + { + var data = stackalloc float[3]; + + switch (gyroscope) + { + case MotionInputId.Gyroscope: + SDL_GetSensorData(sensors[SDL_SensorType.Gyro], data, 3); + return new Vector3(data[0], data[1], data[2]) * (180 / MathF.PI); + case MotionInputId.Accelerometer: + SDL_GetSensorData(sensors[SDL_SensorType.Accel], data, 3); + return new Vector3(data[0], data[1], data[2]) / SDL_STANDARD_GRAVITY; + default: + return Vector3.Zero; + } + } +} diff --git a/src/Ryujinx.Input/HLE/InputManager.cs b/src/Ryujinx.Input/HLE/InputManager.cs index 7111f55025..f02f60e705 100644 --- a/src/Ryujinx.Input/HLE/InputManager.cs +++ b/src/Ryujinx.Input/HLE/InputManager.cs @@ -7,9 +7,11 @@ namespace Ryujinx.Input.HLE public IGamepadDriver KeyboardDriver { get; private set; } public IGamepadDriver GamepadDriver { get; private set; } public IGamepadDriver MouseDriver { get; private set; } + public IHandheld Handheld { get; private set; } - public InputManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver) + public InputManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IHandheld handheld) { + Handheld = handheld; KeyboardDriver = keyboardDriver; GamepadDriver = gamepadDriver; } @@ -23,7 +25,7 @@ namespace Ryujinx.Input.HLE public NpadManager CreateNpadManager() { - return new NpadManager(KeyboardDriver, GamepadDriver, MouseDriver); + return new NpadManager(KeyboardDriver, GamepadDriver, MouseDriver, Handheld); } public TouchScreenManager CreateTouchScreenManager() diff --git a/src/Ryujinx.Input/HLE/NpadController.cs b/src/Ryujinx.Input/HLE/NpadController.cs index 3807452838..4dcac605ea 100644 --- a/src/Ryujinx.Input/HLE/NpadController.cs +++ b/src/Ryujinx.Input/HLE/NpadController.cs @@ -215,12 +215,14 @@ namespace Ryujinx.Input.HLE public string Id { get; private set; } private readonly CemuHookClient _cemuHookClient; + private readonly IHandheld _handheld; - public NpadController(CemuHookClient cemuHookClient) + public NpadController(CemuHookClient cemuHookClient, IHandheld handheld) { State = default; Id = null; _cemuHookClient = cemuHookClient; + _handheld = handheld; } public bool UpdateDriverConfiguration(IGamepadDriver gamepadDriver, InputConfig config) @@ -284,6 +286,18 @@ namespace Ryujinx.Input.HLE if (_config is StandardControllerInputConfig controllerConfig && controllerConfig.Motion.EnableMotion) { + if (controllerConfig.Motion.MotionBackend == MotionInputBackendType.Handheld) + { + Vector3 accelerometer = _handheld.GetMotionData(MotionInputId.Accelerometer); + Vector3 gyroscope = _handheld.GetMotionData(MotionInputId.Gyroscope); + + accelerometer = new Vector3(accelerometer.X, -accelerometer.Z, accelerometer.Y); + gyroscope = new Vector3(gyroscope.X, -gyroscope.Z, gyroscope.Y); + + _leftMotionInput.Update(accelerometer, gyroscope, (ulong)PerformanceCounter.ElapsedNanoseconds / 1000, controllerConfig.Motion.Sensitivity, (float)controllerConfig.Motion.GyroDeadzone); + _rightMotionInput = _leftMotionInput; + } + if (controllerConfig.Motion.MotionBackend == MotionInputBackendType.GamepadDriver) { if (gamepad.Features.HasFlag(GamepadFeaturesFlag.Motion)) diff --git a/src/Ryujinx.Input/HLE/NpadManager.cs b/src/Ryujinx.Input/HLE/NpadManager.cs index 1dc87358d5..2feb24ca31 100644 --- a/src/Ryujinx.Input/HLE/NpadManager.cs +++ b/src/Ryujinx.Input/HLE/NpadManager.cs @@ -29,6 +29,7 @@ namespace Ryujinx.Input.HLE private readonly IGamepadDriver _keyboardDriver; private readonly IGamepadDriver _gamepadDriver; private readonly IGamepadDriver _mouseDriver; + private readonly IHandheld _handheld; private bool _isDisposed; private List _inputConfig; @@ -36,7 +37,7 @@ namespace Ryujinx.Input.HLE private bool _enableMouse; private Switch _device; - public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IGamepadDriver mouseDriver) + public NpadManager(IGamepadDriver keyboardDriver, IGamepadDriver gamepadDriver, IGamepadDriver mouseDriver, IHandheld handheld) { _controllers = new NpadController[MaxControllers]; _cemuHookClient = new CemuHookClient(this); @@ -44,6 +45,7 @@ namespace Ryujinx.Input.HLE _keyboardDriver = keyboardDriver; _gamepadDriver = gamepadDriver; _mouseDriver = mouseDriver; + _handheld = handheld; _inputConfig = new List(); _gamepadDriver.OnGamepadConnected += HandleOnGamepadConnected; @@ -137,7 +139,7 @@ namespace Ryujinx.Input.HLE } else { - controller = new(_cemuHookClient); + controller = new(_cemuHookClient, _handheld); } bool isValid = DriverConfigurationUpdate(ref controller, inputConfigEntry); diff --git a/src/Ryujinx.Input/IHandheld.cs b/src/Ryujinx.Input/IHandheld.cs new file mode 100644 index 0000000000..debec3f5a8 --- /dev/null +++ b/src/Ryujinx.Input/IHandheld.cs @@ -0,0 +1,8 @@ +using System.Numerics; + +namespace Ryujinx.Input; + +public interface IHandheld +{ + Vector3 GetMotionData(MotionInputId gyroscope); +} diff --git a/src/Ryujinx/Assets/Locales/en_US.json b/src/Ryujinx/Assets/Locales/en_US.json index 74e18056ba..d6f3820d21 100644 --- a/src/Ryujinx/Assets/Locales/en_US.json +++ b/src/Ryujinx/Assets/Locales/en_US.json @@ -264,6 +264,7 @@ "ControllerSettingsTriggerThreshold": "Trigger Threshold:", "ControllerSettingsMotion": "Motion", "ControllerSettingsMotionUseCemuhookCompatibleMotion": "Use CemuHook compatible motion", + "ControllerSettingsMotionUseHandheldCompatibleMotion": "Use Handheld compatible motion", "ControllerSettingsMotionControllerSlot": "Controller Slot:", "ControllerSettingsMotionMirrorInput": "Mirror Input", "ControllerSettingsMotionRightJoyConSlot": "Right JoyCon Slot:", diff --git a/src/Ryujinx/Ryujinx.csproj b/src/Ryujinx/Ryujinx.csproj index 6718b7fcc4..d0d35921b0 100644 --- a/src/Ryujinx/Ryujinx.csproj +++ b/src/Ryujinx/Ryujinx.csproj @@ -61,6 +61,7 @@ + diff --git a/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs b/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs index 833670bdc4..eea0bd88e4 100644 --- a/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs +++ b/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs @@ -9,6 +9,7 @@ namespace Ryujinx.Ava.UI.Models.Input public class GamepadInputConfig : BaseModel { public bool EnableCemuHookMotion { get; set; } + public bool EnableHandheldMotion { get; set; } public string DsuServerHost { get; set; } public int DsuServerPort { get; set; } public int Slot { get; set; } @@ -465,7 +466,7 @@ namespace Ryujinx.Ava.UI.Models.Input EnableMotion = controllerInput.Motion.EnableMotion; GyroDeadzone = controllerInput.Motion.GyroDeadzone; Sensitivity = controllerInput.Motion.Sensitivity; - + EnableHandheldMotion = controllerInput.Motion.MotionBackend == MotionInputBackendType.Handheld; if (controllerInput.Motion is CemuHookMotionConfigController cemuHook) { EnableCemuHookMotion = true; @@ -568,7 +569,7 @@ namespace Ryujinx.Ava.UI.Models.Input config.Motion = new StandardMotionConfigController { EnableMotion = EnableMotion, - MotionBackend = MotionInputBackendType.GamepadDriver, + MotionBackend = EnableHandheldMotion ? MotionInputBackendType.Handheld : MotionInputBackendType.GamepadDriver, GyroDeadzone = GyroDeadzone, Sensitivity = Sensitivity, }; diff --git a/src/Ryujinx/UI/ViewModels/Input/MotionInputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/MotionInputViewModel.cs index c9ed8f2d46..1590965a2c 100644 --- a/src/Ryujinx/UI/ViewModels/Input/MotionInputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/MotionInputViewModel.cs @@ -85,9 +85,28 @@ namespace Ryujinx.Ava.UI.ViewModels.Input get => _enableCemuHookMotion; set { + if (value) + { + EnableHandheldMotion = false; + } _enableCemuHookMotion = value; OnPropertyChanged(); } } + + private bool _enableHandheldMotion; + public bool EnableHandheldMotion + { + get => _enableHandheldMotion; + set + { + if (value) + { + EnableCemuHookMotion = false; + } + _enableHandheldMotion = value; + OnPropertyChanged(); + } + } } } diff --git a/src/Ryujinx/UI/Views/Input/MotionInputView.axaml b/src/Ryujinx/UI/Views/Input/MotionInputView.axaml index 0d018e297a..0d2c9cce8d 100644 --- a/src/Ryujinx/UI/Views/Input/MotionInputView.axaml +++ b/src/Ryujinx/UI/Views/Input/MotionInputView.axaml @@ -61,6 +61,17 @@ Margin="5, 0" Text="{Binding GyroDeadzone, StringFormat=\{0:0.00\}}" /> + + + + diff --git a/src/Ryujinx/UI/Views/Input/MotionInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/MotionInputView.axaml.cs index 2304364b67..a429dded78 100644 --- a/src/Ryujinx/UI/Views/Input/MotionInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/MotionInputView.axaml.cs @@ -29,6 +29,7 @@ namespace Ryujinx.Ava.UI.Views.Input Sensitivity = config.Sensitivity, GyroDeadzone = config.GyroDeadzone, EnableCemuHookMotion = config.EnableCemuHookMotion, + EnableHandheldMotion = config.EnableHandheldMotion, }; InitializeComponent(); @@ -57,6 +58,7 @@ namespace Ryujinx.Ava.UI.Views.Input config.DsuServerHost = content._viewModel.DsuServerHost; config.DsuServerPort = content._viewModel.DsuServerPort; config.EnableCemuHookMotion = content._viewModel.EnableCemuHookMotion; + config.EnableHandheldMotion = content._viewModel.EnableHandheldMotion; config.MirrorInput = content._viewModel.MirrorInput; }; diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs index 348412e78c..2ef0ef0090 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs @@ -20,6 +20,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.Input.HLE; using Ryujinx.Input.SDL2; using Ryujinx.Modules; +using Ryujinx.SDL3; using Ryujinx.UI.App.Common; using Ryujinx.UI.Common; using Ryujinx.UI.Common.Configuration; @@ -89,7 +90,7 @@ namespace Ryujinx.Ava.UI.Windows if (Program.PreviewerDetached) { - InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver()); + InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver(), new SDL3MotionDriver()); this.GetObservable(IsActiveProperty).Subscribe(IsActiveChanged); this.ScalingChanged += OnScalingChanged;