forked from Mirror/Ryujinx
ava: Cleanup Input classes (#4042)
* ava: Cleanup Input classes This PR just cleanup all Input classes for consistencies. * Addresses TSRBerry's feedback
This commit is contained in:
parent
40311310d1
commit
2372c194f1
7 changed files with 112 additions and 128 deletions
|
@ -4,7 +4,6 @@ using Ryujinx.Input;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
using ConfigKey = Ryujinx.Common.Configuration.Hid.Key;
|
using ConfigKey = Ryujinx.Common.Configuration.Hid.Key;
|
||||||
using Key = Ryujinx.Input.Key;
|
using Key = Ryujinx.Input.Key;
|
||||||
|
|
||||||
|
@ -14,30 +13,37 @@ namespace Ryujinx.Ava.Input
|
||||||
{
|
{
|
||||||
private readonly List<ButtonMappingEntry> _buttonsUserMapping;
|
private readonly List<ButtonMappingEntry> _buttonsUserMapping;
|
||||||
private readonly AvaloniaKeyboardDriver _driver;
|
private readonly AvaloniaKeyboardDriver _driver;
|
||||||
|
|
||||||
private readonly object _userMappingLock = new();
|
|
||||||
|
|
||||||
private StandardKeyboardInputConfig _configuration;
|
private StandardKeyboardInputConfig _configuration;
|
||||||
|
|
||||||
private bool HasConfiguration => _configuration != null;
|
private readonly object _userMappingLock = new();
|
||||||
|
|
||||||
public string Id { get; }
|
public string Id { get; }
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
|
||||||
public bool IsConnected => true;
|
public bool IsConnected => true;
|
||||||
|
|
||||||
public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None;
|
public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None;
|
||||||
|
|
||||||
|
private class ButtonMappingEntry
|
||||||
|
{
|
||||||
|
public readonly Key From;
|
||||||
|
public readonly GamepadButtonInputId To;
|
||||||
|
|
||||||
|
public ButtonMappingEntry(GamepadButtonInputId to, Key from)
|
||||||
|
{
|
||||||
|
To = to;
|
||||||
|
From = from;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public AvaloniaKeyboard(AvaloniaKeyboardDriver driver, string id, string name)
|
public AvaloniaKeyboard(AvaloniaKeyboardDriver driver, string id, string name)
|
||||||
{
|
{
|
||||||
|
_buttonsUserMapping = new List<ButtonMappingEntry>();
|
||||||
|
|
||||||
_driver = driver;
|
_driver = driver;
|
||||||
Id = id;
|
Id = id;
|
||||||
Name = name;
|
Name = name;
|
||||||
_buttonsUserMapping = new List<ButtonMappingEntry>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() { }
|
|
||||||
|
|
||||||
public KeyboardStateSnapshot GetKeyboardStateSnapshot()
|
public KeyboardStateSnapshot GetKeyboardStateSnapshot()
|
||||||
{
|
{
|
||||||
return IKeyboard.GetStateSnapshot(this);
|
return IKeyboard.GetStateSnapshot(this);
|
||||||
|
@ -50,7 +56,7 @@ namespace Ryujinx.Ava.Input
|
||||||
|
|
||||||
lock (_userMappingLock)
|
lock (_userMappingLock)
|
||||||
{
|
{
|
||||||
if (!HasConfiguration)
|
if (_configuration == null)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +68,7 @@ namespace Ryujinx.Ava.Input
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not touch state of the button already pressed
|
// NOTE: Do not touch state of the button already pressed.
|
||||||
if (!result.IsPressed(entry.To))
|
if (!result.IsPressed(entry.To))
|
||||||
{
|
{
|
||||||
result.SetPressed(entry.To, rawState.IsPressed(entry.From));
|
result.SetPressed(entry.To, rawState.IsPressed(entry.From));
|
||||||
|
@ -114,7 +120,7 @@ namespace Ryujinx.Ava.Input
|
||||||
|
|
||||||
_buttonsUserMapping.Clear();
|
_buttonsUserMapping.Clear();
|
||||||
|
|
||||||
// Left joycon
|
// Left JoyCon
|
||||||
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftStick, (Key)_configuration.LeftJoyconStick.StickButton));
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftStick, (Key)_configuration.LeftJoyconStick.StickButton));
|
||||||
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadUp, (Key)_configuration.LeftJoycon.DpadUp));
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadUp, (Key)_configuration.LeftJoycon.DpadUp));
|
||||||
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadDown, (Key)_configuration.LeftJoycon.DpadDown));
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadDown, (Key)_configuration.LeftJoycon.DpadDown));
|
||||||
|
@ -126,7 +132,7 @@ namespace Ryujinx.Ava.Input
|
||||||
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger0, (Key)_configuration.LeftJoycon.ButtonSr));
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger0, (Key)_configuration.LeftJoycon.ButtonSr));
|
||||||
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger0, (Key)_configuration.LeftJoycon.ButtonSl));
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger0, (Key)_configuration.LeftJoycon.ButtonSl));
|
||||||
|
|
||||||
// Finally right joycon
|
// Right JoyCon
|
||||||
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightStick, (Key)_configuration.RightJoyconStick.StickButton));
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightStick, (Key)_configuration.RightJoyconStick.StickButton));
|
||||||
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.A, (Key)_configuration.RightJoycon.ButtonA));
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.A, (Key)_configuration.RightJoycon.ButtonA));
|
||||||
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.B, (Key)_configuration.RightJoycon.ButtonB));
|
_buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.B, (Key)_configuration.RightJoycon.ButtonB));
|
||||||
|
@ -190,16 +196,6 @@ namespace Ryujinx.Ava.Input
|
||||||
_driver?.ResetKeys();
|
_driver?.ResetKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ButtonMappingEntry
|
public void Dispose() { }
|
||||||
{
|
|
||||||
public readonly Key From;
|
|
||||||
public readonly GamepadButtonInputId To;
|
|
||||||
|
|
||||||
public ButtonMappingEntry(GamepadButtonInputId to, Key from)
|
|
||||||
{
|
|
||||||
To = to;
|
|
||||||
From = from;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,6 @@ using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Input;
|
using Ryujinx.Input;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using AvaKey = Avalonia.Input.Key;
|
using AvaKey = Avalonia.Input.Key;
|
||||||
using Key = Ryujinx.Input.Key;
|
using Key = Ryujinx.Input.Key;
|
||||||
|
|
||||||
|
@ -20,8 +19,7 @@ namespace Ryujinx.Ava.Input
|
||||||
public event EventHandler<KeyEventArgs> KeyRelease;
|
public event EventHandler<KeyEventArgs> KeyRelease;
|
||||||
public event EventHandler<string> TextInput;
|
public event EventHandler<string> TextInput;
|
||||||
|
|
||||||
public string DriverName => "Avalonia";
|
public string DriverName => "AvaloniaKeyboardDriver";
|
||||||
|
|
||||||
public ReadOnlySpan<string> GamepadsIds => _keyboardIdentifers;
|
public ReadOnlySpan<string> GamepadsIds => _keyboardIdentifers;
|
||||||
|
|
||||||
public AvaloniaKeyboardDriver(Control control)
|
public AvaloniaKeyboardDriver(Control control)
|
||||||
|
@ -51,11 +49,6 @@ namespace Ryujinx.Ava.Input
|
||||||
remove { }
|
remove { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Dispose(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IGamepad GetGamepad(string id)
|
public IGamepad GetGamepad(string id)
|
||||||
{
|
{
|
||||||
if (!_keyboardIdentifers[0].Equals(id))
|
if (!_keyboardIdentifers[0].Equals(id))
|
||||||
|
@ -77,8 +70,6 @@ namespace Ryujinx.Ava.Input
|
||||||
|
|
||||||
protected void OnKeyPress(object sender, KeyEventArgs args)
|
protected void OnKeyPress(object sender, KeyEventArgs args)
|
||||||
{
|
{
|
||||||
AvaKey key = args.Key;
|
|
||||||
|
|
||||||
_pressedKeys.Add(args.Key);
|
_pressedKeys.Add(args.Key);
|
||||||
|
|
||||||
KeyPressed?.Invoke(this, args);
|
KeyPressed?.Invoke(this, args);
|
||||||
|
@ -98,7 +89,7 @@ namespace Ryujinx.Ava.Input
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AvaloniaMappingHelper.TryGetAvaKey(key, out var nativeKey);
|
AvaloniaKeyboardMappingHelper.TryGetAvaKey(key, out var nativeKey);
|
||||||
|
|
||||||
return _pressedKeys.Contains(nativeKey);
|
return _pressedKeys.Contains(nativeKey);
|
||||||
}
|
}
|
||||||
|
@ -107,5 +98,10 @@ namespace Ryujinx.Ava.Input
|
||||||
{
|
{
|
||||||
_pressedKeys.Clear();
|
_pressedKeys.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@ using AvaKey = Avalonia.Input.Key;
|
||||||
|
|
||||||
namespace Ryujinx.Ava.Input
|
namespace Ryujinx.Ava.Input
|
||||||
{
|
{
|
||||||
internal static class AvaloniaMappingHelper
|
internal static class AvaloniaKeyboardMappingHelper
|
||||||
{
|
{
|
||||||
private static readonly AvaKey[] _keyMapping = new AvaKey[(int)Key.Count]
|
private static readonly AvaKey[] _keyMapping = new AvaKey[(int)Key.Count]
|
||||||
{
|
{
|
||||||
|
@ -149,11 +149,11 @@ namespace Ryujinx.Ava.Input
|
||||||
|
|
||||||
private static readonly Dictionary<AvaKey, Key> _avaKeyMapping;
|
private static readonly Dictionary<AvaKey, Key> _avaKeyMapping;
|
||||||
|
|
||||||
static AvaloniaMappingHelper()
|
static AvaloniaKeyboardMappingHelper()
|
||||||
{
|
{
|
||||||
var inputKeys = Enum.GetValues(typeof(Key));
|
var inputKeys = Enum.GetValues(typeof(Key));
|
||||||
|
|
||||||
// Avalonia.Input.Key is not contiguous and quite large, so use a dictionary instead of an array.
|
// NOTE: Avalonia.Input.Key is not contiguous and quite large, so use a dictionary instead of an array.
|
||||||
_avaKeyMapping = new Dictionary<AvaKey, Key>();
|
_avaKeyMapping = new Dictionary<AvaKey, Key>();
|
||||||
|
|
||||||
foreach (var key in inputKeys)
|
foreach (var key in inputKeys)
|
||||||
|
@ -167,15 +167,13 @@ namespace Ryujinx.Ava.Input
|
||||||
|
|
||||||
public static bool TryGetAvaKey(Key key, out AvaKey avaKey)
|
public static bool TryGetAvaKey(Key key, out AvaKey avaKey)
|
||||||
{
|
{
|
||||||
var keyExist = (int)key < _keyMapping.Length;
|
avaKey = AvaKey.None;
|
||||||
|
|
||||||
|
bool keyExist = (int)key < _keyMapping.Length;
|
||||||
if (keyExist)
|
if (keyExist)
|
||||||
{
|
{
|
||||||
avaKey = _keyMapping[(int)key];
|
avaKey = _keyMapping[(int)key];
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
avaKey = AvaKey.None;
|
|
||||||
}
|
|
||||||
|
|
||||||
return keyExist;
|
return keyExist;
|
||||||
}
|
}
|
|
@ -10,14 +10,11 @@ namespace Ryujinx.Ava.Input
|
||||||
{
|
{
|
||||||
private AvaloniaMouseDriver _driver;
|
private AvaloniaMouseDriver _driver;
|
||||||
|
|
||||||
public GamepadFeaturesFlag Features => throw new NotImplementedException();
|
|
||||||
|
|
||||||
public string Id => "0";
|
public string Id => "0";
|
||||||
|
|
||||||
public string Name => "AvaloniaMouse";
|
public string Name => "AvaloniaMouse";
|
||||||
|
|
||||||
public bool IsConnected => true;
|
public bool IsConnected => true;
|
||||||
|
public GamepadFeaturesFlag Features => throw new NotImplementedException();
|
||||||
public bool[] Buttons => _driver.PressedButtons;
|
public bool[] Buttons => _driver.PressedButtons;
|
||||||
|
|
||||||
public AvaloniaMouse(AvaloniaMouseDriver driver)
|
public AvaloniaMouse(AvaloniaMouseDriver driver)
|
||||||
|
|
|
@ -17,10 +17,12 @@ namespace Ryujinx.Ava.Input
|
||||||
private readonly Window _window;
|
private readonly Window _window;
|
||||||
|
|
||||||
public bool[] PressedButtons { get; }
|
public bool[] PressedButtons { get; }
|
||||||
|
|
||||||
public Vector2 CurrentPosition { get; private set; }
|
public Vector2 CurrentPosition { get; private set; }
|
||||||
public Vector2 Scroll { get; private set; }
|
public Vector2 Scroll { get; private set; }
|
||||||
|
|
||||||
|
public string DriverName => "AvaloniaMouseDriver";
|
||||||
|
public ReadOnlySpan<string> GamepadsIds => new[] { "0" };
|
||||||
|
|
||||||
public AvaloniaMouseDriver(Window window, Control parent)
|
public AvaloniaMouseDriver(Window window, Control parent)
|
||||||
{
|
{
|
||||||
_widget = parent;
|
_widget = parent;
|
||||||
|
@ -39,7 +41,20 @@ namespace Ryujinx.Ava.Input
|
||||||
PressedButtons = new bool[(int)MouseButton.Count];
|
PressedButtons = new bool[(int)MouseButton.Count];
|
||||||
|
|
||||||
_size = new Size((int)parent.Bounds.Width, (int)parent.Bounds.Height);
|
_size = new Size((int)parent.Bounds.Width, (int)parent.Bounds.Height);
|
||||||
parent.GetObservable(Control.BoundsProperty).Subscribe(Resized);
|
|
||||||
|
parent.GetObservable(Visual.BoundsProperty).Subscribe(Resized);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action<string> OnGamepadConnected
|
||||||
|
{
|
||||||
|
add { }
|
||||||
|
remove { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Action<string> OnGamepadDisconnected
|
||||||
|
{
|
||||||
|
add { }
|
||||||
|
remove { }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Resized(Rect rect)
|
private void Resized(Rect rect)
|
||||||
|
@ -59,14 +74,12 @@ namespace Ryujinx.Ava.Input
|
||||||
|
|
||||||
private void Parent_PointerPressEvent(object o, PointerPressedEventArgs args)
|
private void Parent_PointerPressEvent(object o, PointerPressedEventArgs args)
|
||||||
{
|
{
|
||||||
var pointerProperties = args.GetCurrentPoint(_widget).Properties;
|
PressedButtons[(int)args.GetCurrentPoint(_widget).Properties.PointerUpdateKind] = true;
|
||||||
|
|
||||||
PressedButtons[(int)pointerProperties.PointerUpdateKind] = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Parent_PointerMovedEvent(object o, PointerEventArgs args)
|
private void Parent_PointerMovedEvent(object o, PointerEventArgs args)
|
||||||
{
|
{
|
||||||
var position = args.GetPosition(_widget);
|
Point position = args.GetPosition(_widget);
|
||||||
|
|
||||||
CurrentPosition = new Vector2((float)position.X, (float)position.Y);
|
CurrentPosition = new Vector2((float)position.X, (float)position.Y);
|
||||||
}
|
}
|
||||||
|
@ -96,22 +109,6 @@ namespace Ryujinx.Ava.Input
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string DriverName => "Avalonia";
|
|
||||||
|
|
||||||
public event Action<string> OnGamepadConnected
|
|
||||||
{
|
|
||||||
add { }
|
|
||||||
remove { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public event Action<string> OnGamepadDisconnected
|
|
||||||
{
|
|
||||||
add { }
|
|
||||||
remove { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReadOnlySpan<string> GamepadsIds => new[] { "0" };
|
|
||||||
|
|
||||||
public IGamepad GetGamepad(string id)
|
public IGamepad GetGamepad(string id)
|
||||||
{
|
{
|
||||||
return new AvaloniaMouse(this);
|
return new AvaloniaMouse(this);
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace Ryujinx.Ava.Ui.Applet
|
||||||
|
|
||||||
private void AvaloniaDynamicTextInputHandler_KeyRelease(object sender, Avalonia.Input.KeyEventArgs e)
|
private void AvaloniaDynamicTextInputHandler_KeyRelease(object sender, Avalonia.Input.KeyEventArgs e)
|
||||||
{
|
{
|
||||||
var key = (HidKey)AvaloniaMappingHelper.ToInputKey(e.Key);
|
var key = (HidKey)AvaloniaKeyboardMappingHelper.ToInputKey(e.Key);
|
||||||
|
|
||||||
if (!(KeyReleasedEvent?.Invoke(key)).GetValueOrDefault(true))
|
if (!(KeyReleasedEvent?.Invoke(key)).GetValueOrDefault(true))
|
||||||
{
|
{
|
||||||
|
@ -88,7 +88,7 @@ namespace Ryujinx.Ava.Ui.Applet
|
||||||
|
|
||||||
private void AvaloniaDynamicTextInputHandler_KeyPressed(object sender, KeyEventArgs e)
|
private void AvaloniaDynamicTextInputHandler_KeyPressed(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
var key = (HidKey)AvaloniaMappingHelper.ToInputKey(e.Key);
|
var key = (HidKey)AvaloniaKeyboardMappingHelper.ToInputKey(e.Key);
|
||||||
|
|
||||||
if (!(KeyPressedEvent?.Invoke(key)).GetValueOrDefault(true))
|
if (!(KeyPressedEvent?.Invoke(key)).GetValueOrDefault(true))
|
||||||
{
|
{
|
||||||
|
|
|
@ -883,17 +883,17 @@ namespace Ryujinx.Ava.Ui.ViewModels
|
||||||
|
|
||||||
public void LoadConfigurableHotKeys()
|
public void LoadConfigurableHotKeys()
|
||||||
{
|
{
|
||||||
if (AvaloniaMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi, out var showUiKey))
|
if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi, out var showUiKey))
|
||||||
{
|
{
|
||||||
ShowUiKey = new KeyGesture(showUiKey, KeyModifiers.None);
|
ShowUiKey = new KeyGesture(showUiKey, KeyModifiers.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AvaloniaMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot, out var screenshotKey))
|
if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot, out var screenshotKey))
|
||||||
{
|
{
|
||||||
ScreenshotKey = new KeyGesture(screenshotKey, KeyModifiers.None);
|
ScreenshotKey = new KeyGesture(screenshotKey, KeyModifiers.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AvaloniaMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause, out var pauseKey))
|
if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause, out var pauseKey))
|
||||||
{
|
{
|
||||||
PauseKey = new KeyGesture(pauseKey, KeyModifiers.None);
|
PauseKey = new KeyGesture(pauseKey, KeyModifiers.None);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue