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);
+ }
}
}