From de9e93606a2f49458184ccd08bcc34bdee9e8d07 Mon Sep 17 00:00:00 2001 From: madwind Date: Tue, 31 Dec 2024 11:08:32 +0800 Subject: [PATCH 1/3] Display position to help set the deadzone. --- .../Input/ControllerInputViewModel.cs | 28 ++++++ .../UI/Views/Input/ControllerInputView.axaml | 10 ++- .../Views/Input/ControllerInputView.axaml.cs | 89 ++++++++++++++++++- 3 files changed, 122 insertions(+), 5 deletions(-) diff --git a/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs index 6ee79a371..cf99241fe 100644 --- a/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs @@ -7,6 +7,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input public class ControllerInputViewModel : BaseModel { private GamepadInputConfig _config; + public GamepadInputConfig Config { get => _config; @@ -18,6 +19,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input } private bool _isLeft; + public bool IsLeft { get => _isLeft; @@ -30,6 +32,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input } private bool _isRight; + public bool IsRight { get => _isRight; @@ -44,6 +47,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input public bool HasSides => IsLeft ^ IsRight; private SvgImage _image; + public SvgImage Image { get => _image; @@ -55,6 +59,30 @@ namespace Ryujinx.Ava.UI.ViewModels.Input } public readonly InputViewModel ParentModel; + + private string _leftStickPosition; + + public string LeftStickPosition + { + get => _leftStickPosition; + set + { + _leftStickPosition = value; + OnPropertyChanged(); + } + } + + private string _rightStickPosition; + + public string RightStickPosition + { + get => _rightStickPosition; + set + { + _rightStickPosition = value; + OnPropertyChanged(); + } + } public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config) { diff --git a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml index 7daf23eb6..544b1e766 100644 --- a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml +++ b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml @@ -15,7 +15,9 @@ x:DataType="viewModels:ControllerInputViewModel" x:CompileBindings="True" mc:Ignorable="d" - Focusable="True"> + Focusable="True" + Unloaded="Control_OnUnloaded" + > @@ -183,6 +185,9 @@ + + @@ -237,5 +242,81 @@ namespace Ryujinx.Ava.UI.Views.Input _currentAssigner?.Cancel(); _currentAssigner = null; } + + private void Control_OnUnloaded(object sender, RoutedEventArgs e) + { + _isRunning = false; + } + + + private async void StartUpdatingData() + { + while (_isRunning) + { + var viewModel = (DataContext as ControllerInputViewModel); + if (viewModel != null) + { + IGamepad gamepad = viewModel.ParentModel.SelectedGamepad; + var config = viewModel.Config; + + if (config.LeftJoystick != StickInputId.Unbound) + { + var stickInputId = (Ryujinx.Input.StickInputId)(int)config.LeftJoystick; + (float leftAxisX, float leftAxisY) = + gamepad.GetStick(stickInputId); + viewModel.LeftStickPosition = + ClampToCircle(ApplyDeadzone(leftAxisX, leftAxisY, config.DeadzoneLeft), config.RangeLeft) + .ToString(); + } + + if (config.RightJoystick != StickInputId.Unbound) + { + var stickInputId = (Ryujinx.Input.StickInputId)(int)config.RightJoystick; + (float rightAxisX, float rightAxisY) = gamepad.GetStick(stickInputId); + viewModel.RightStickPosition = + ClampToCircle(ApplyDeadzone(rightAxisX, rightAxisY, config.DeadzoneRight), + config.RangeRight).ToString(); + } + } + + await Task.Delay(100); + } + } + + private static (int x, int y) ClampToCircle((int x, int y) postion, float range) + { + Vector2 point = new Vector2(postion.x, postion.y) * range; + + if (point.Length() > short.MaxValue) + { + point = point / point.Length() * short.MaxValue; + } + + return ((int)point.X, (int)point.Y); + } + + private static (short x, short y) ApplyDeadzone(float x, float y, float deadzone) + { + float magnitudeClamped = Math.Min(MathF.Sqrt(x * x + y * y), 1f); + + if (magnitudeClamped <= deadzone) + { + return (0, 0); + } + + return (ClampAxis((x / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone))), + ClampAxis((y / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone)))); + } + + + private static short ClampAxis(float value) + { + if (Math.Sign(value) < 0) + { + return (short)Math.Max(value * -short.MinValue, short.MinValue); + } + + return (short)Math.Min(value * short.MaxValue, short.MaxValue); + } } } From 6945a05e45738f75b72fc2fc93345f3777ded26f Mon Sep 17 00:00:00 2001 From: madwind Date: Fri, 3 Jan 2025 17:01:02 +0800 Subject: [PATCH 2/3] restore single joy-con svg --- src/Ryujinx/Assets/Icons/Controller_JoyConLeft_Settings.svg | 1 + .../Assets/Icons/Controller_JoyConRight_Settings.svg | 1 + src/Ryujinx/Ryujinx.csproj | 6 +++++- src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs | 4 ++-- 4 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 src/Ryujinx/Assets/Icons/Controller_JoyConLeft_Settings.svg create mode 100644 src/Ryujinx/Assets/Icons/Controller_JoyConRight_Settings.svg diff --git a/src/Ryujinx/Assets/Icons/Controller_JoyConLeft_Settings.svg b/src/Ryujinx/Assets/Icons/Controller_JoyConLeft_Settings.svg new file mode 100644 index 000000000..03585e656 --- /dev/null +++ b/src/Ryujinx/Assets/Icons/Controller_JoyConLeft_Settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Ryujinx/Assets/Icons/Controller_JoyConRight_Settings.svg b/src/Ryujinx/Assets/Icons/Controller_JoyConRight_Settings.svg new file mode 100644 index 000000000..f4f125148 --- /dev/null +++ b/src/Ryujinx/Assets/Icons/Controller_JoyConRight_Settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Ryujinx/Ryujinx.csproj b/src/Ryujinx/Ryujinx.csproj index 9d23b0909..eaab5e33f 100644 --- a/src/Ryujinx/Ryujinx.csproj +++ b/src/Ryujinx/Ryujinx.csproj @@ -125,6 +125,8 @@ + + @@ -143,6 +145,8 @@ + + @@ -161,4 +165,4 @@ - \ No newline at end of file + diff --git a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs index 74b8681d5..f6a8a6dea 100644 --- a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs @@ -37,8 +37,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input private const string Disabled = "disabled"; private const string ProControllerResource = "Ryujinx/Assets/Icons/Controller_ProCon.svg"; private const string JoyConPairResource = "Ryujinx/Assets/Icons/Controller_JoyConPair.svg"; - private const string JoyConLeftResource = "Ryujinx/Assets/Icons/Controller_JoyConLeft.svg"; - private const string JoyConRightResource = "Ryujinx/Assets/Icons/Controller_JoyConRight.svg"; + private const string JoyConLeftResource = "Ryujinx/Assets/Icons/Controller_JoyConLeft_Settings.svg"; + private const string JoyConRightResource = "Ryujinx/Assets/Icons/Controller_JoyConRight_Settings.svg"; private const string KeyboardString = "keyboard"; private const string ControllerString = "controller"; private readonly MainWindow _mainWindow; From 270c5bd815fa4780e4a6ff6de01139b8b9d324b4 Mon Sep 17 00:00:00 2001 From: madwind Date: Fri, 3 Jan 2025 17:03:59 +0800 Subject: [PATCH 3/3] add public method: GetJoystickPosition --- src/Ryujinx.Input/HLE/NpadController.cs | 5 ++ .../Views/Input/ControllerInputView.axaml.cs | 90 ++++++------------- 2 files changed, 33 insertions(+), 62 deletions(-) diff --git a/src/Ryujinx.Input/HLE/NpadController.cs b/src/Ryujinx.Input/HLE/NpadController.cs index 53426f71a..ca672bdc5 100644 --- a/src/Ryujinx.Input/HLE/NpadController.cs +++ b/src/Ryujinx.Input/HLE/NpadController.cs @@ -392,6 +392,11 @@ namespace Ryujinx.Input.HLE return state; } + + public static JoystickPosition GetJoystickPosition(float x, float y, float deadzone, float range) + { + return ClampToCircle(ApplyDeadzone(x, y,deadzone), range); + } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static JoystickPosition ApplyDeadzone(float x, float y, float deadzone) diff --git a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs index a17876554..3a5907b24 100644 --- a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs +++ b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml.cs @@ -9,8 +9,7 @@ using Ryujinx.Ava.UI.ViewModels.Input; using Ryujinx.Common.Configuration.Hid.Controller; using Ryujinx.Input; using Ryujinx.Input.Assigner; -using System; -using System.Numerics; +using Ryujinx.Input.HLE; using System.Threading.Tasks; using StickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId; @@ -249,74 +248,41 @@ namespace Ryujinx.Ava.UI.Views.Input } - private async void StartUpdatingData() + private void StartUpdatingData() { - while (_isRunning) + Task.Run(async () => { - var viewModel = (DataContext as ControllerInputViewModel); - if (viewModel != null) + while (_isRunning) { - IGamepad gamepad = viewModel.ParentModel.SelectedGamepad; - var config = viewModel.Config; - - if (config.LeftJoystick != StickInputId.Unbound) + var viewModel = (DataContext as ControllerInputViewModel); + if (viewModel != null) { - var stickInputId = (Ryujinx.Input.StickInputId)(int)config.LeftJoystick; - (float leftAxisX, float leftAxisY) = - gamepad.GetStick(stickInputId); - viewModel.LeftStickPosition = - ClampToCircle(ApplyDeadzone(leftAxisX, leftAxisY, config.DeadzoneLeft), config.RangeLeft) + IGamepad gamepad = viewModel.ParentModel.SelectedGamepad; + var config = viewModel.Config; + + if (config.LeftJoystick != StickInputId.Unbound) + { + var stickInputId = (Ryujinx.Input.StickInputId)(int)config.LeftJoystick; + (float leftAxisX, float leftAxisY) = + gamepad.GetStick(stickInputId); + viewModel.LeftStickPosition = NpadController.GetJoystickPosition(leftAxisX, leftAxisY, + config.DeadzoneLeft, config.RangeLeft) .ToString(); + } + + if (config.RightJoystick != StickInputId.Unbound) + { + var stickInputId = (Ryujinx.Input.StickInputId)(int)config.RightJoystick; + (float rightAxisX, float rightAxisY) = gamepad.GetStick(stickInputId); + viewModel.RightStickPosition = NpadController + .GetJoystickPosition(rightAxisX, rightAxisY, config.DeadzoneRight, config.RangeRight) + .ToString(); + } } - if (config.RightJoystick != StickInputId.Unbound) - { - var stickInputId = (Ryujinx.Input.StickInputId)(int)config.RightJoystick; - (float rightAxisX, float rightAxisY) = gamepad.GetStick(stickInputId); - viewModel.RightStickPosition = - ClampToCircle(ApplyDeadzone(rightAxisX, rightAxisY, config.DeadzoneRight), - config.RangeRight).ToString(); - } + await Task.Delay(100); } - - await Task.Delay(100); - } - } - - private static (int x, int y) ClampToCircle((int x, int y) postion, float range) - { - Vector2 point = new Vector2(postion.x, postion.y) * range; - - if (point.Length() > short.MaxValue) - { - point = point / point.Length() * short.MaxValue; - } - - return ((int)point.X, (int)point.Y); - } - - private static (short x, short y) ApplyDeadzone(float x, float y, float deadzone) - { - float magnitudeClamped = Math.Min(MathF.Sqrt(x * x + y * y), 1f); - - if (magnitudeClamped <= deadzone) - { - return (0, 0); - } - - return (ClampAxis((x / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone))), - ClampAxis((y / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone)))); - } - - - private static short ClampAxis(float value) - { - if (Math.Sign(value) < 0) - { - return (short)Math.Max(value * -short.MinValue, short.MinValue); - } - - return (short)Math.Min(value * short.MaxValue, short.MaxValue); + }); } } }