From de9e93606a2f49458184ccd08bcc34bdee9e8d07 Mon Sep 17 00:00:00 2001 From: madwind Date: Tue, 31 Dec 2024 11:08:32 +0800 Subject: [PATCH] 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); + } } }