AvaloniaKeyboard.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. using Ryujinx.Common.Configuration.Hid;
  2. using Ryujinx.Common.Configuration.Hid.Keyboard;
  3. using Ryujinx.Common.Logging;
  4. using Ryujinx.Input;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Numerics;
  8. using System.Threading;
  9. using ConfigKey = Ryujinx.Common.Configuration.Hid.Key;
  10. using Key = Ryujinx.Input.Key;
  11. namespace Ryujinx.Ava.Input
  12. {
  13. internal class AvaloniaKeyboard : IKeyboard
  14. {
  15. private readonly List<ButtonMappingEntry> _buttonsUserMapping;
  16. private readonly AvaloniaKeyboardDriver _driver;
  17. private StandardKeyboardInputConfig _configuration;
  18. private readonly Lock _userMappingLock = new();
  19. public string Id { get; }
  20. public string Name { get; }
  21. public bool IsConnected => true;
  22. public GamepadFeaturesFlag Features => GamepadFeaturesFlag.None;
  23. private class ButtonMappingEntry(GamepadButtonInputId to, Key from)
  24. {
  25. public readonly GamepadButtonInputId To = to;
  26. public readonly Key From = from;
  27. }
  28. public AvaloniaKeyboard(AvaloniaKeyboardDriver driver, string id, string name)
  29. {
  30. _buttonsUserMapping = [];
  31. _driver = driver;
  32. Id = id;
  33. Name = name;
  34. }
  35. public KeyboardStateSnapshot GetKeyboardStateSnapshot()
  36. {
  37. return IKeyboard.GetStateSnapshot(this);
  38. }
  39. public GamepadStateSnapshot GetMappedStateSnapshot()
  40. {
  41. KeyboardStateSnapshot rawState = GetKeyboardStateSnapshot();
  42. GamepadStateSnapshot result = default;
  43. lock (_userMappingLock)
  44. {
  45. if (_configuration == null)
  46. {
  47. return result;
  48. }
  49. foreach (ButtonMappingEntry entry in _buttonsUserMapping)
  50. {
  51. if (entry.From == Key.Unknown || entry.From == Key.Unbound || entry.To == GamepadButtonInputId.Unbound)
  52. {
  53. continue;
  54. }
  55. // NOTE: Do not touch state of the button already pressed.
  56. if (!result.IsPressed(entry.To))
  57. {
  58. result.SetPressed(entry.To, rawState.IsPressed(entry.From));
  59. }
  60. }
  61. (short leftStickX, short leftStickY) = GetStickValues(ref rawState, _configuration.LeftJoyconStick);
  62. (short rightStickX, short rightStickY) = GetStickValues(ref rawState, _configuration.RightJoyconStick);
  63. result.SetStick(StickInputId.Left, ConvertRawStickValue(leftStickX), ConvertRawStickValue(leftStickY));
  64. result.SetStick(StickInputId.Right, ConvertRawStickValue(rightStickX), ConvertRawStickValue(rightStickY));
  65. }
  66. return result;
  67. }
  68. public GamepadStateSnapshot GetStateSnapshot()
  69. {
  70. throw new NotSupportedException();
  71. }
  72. public (float, float) GetStick(StickInputId inputId)
  73. {
  74. throw new NotSupportedException();
  75. }
  76. public bool IsPressed(GamepadButtonInputId inputId)
  77. {
  78. throw new NotSupportedException();
  79. }
  80. public bool IsPressed(Key key)
  81. {
  82. try
  83. {
  84. return _driver.IsPressed(key);
  85. }
  86. catch
  87. {
  88. return false;
  89. }
  90. }
  91. public void SetConfiguration(InputConfig configuration)
  92. {
  93. lock (_userMappingLock)
  94. {
  95. _configuration = (StandardKeyboardInputConfig)configuration;
  96. _buttonsUserMapping.Clear();
  97. #pragma warning disable IDE0055 // Disable formatting
  98. // Left JoyCon
  99. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftStick, (Key)_configuration.LeftJoyconStick.StickButton));
  100. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadUp, (Key)_configuration.LeftJoycon.DpadUp));
  101. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadDown, (Key)_configuration.LeftJoycon.DpadDown));
  102. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadLeft, (Key)_configuration.LeftJoycon.DpadLeft));
  103. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.DpadRight, (Key)_configuration.LeftJoycon.DpadRight));
  104. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Minus, (Key)_configuration.LeftJoycon.ButtonMinus));
  105. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftShoulder, (Key)_configuration.LeftJoycon.ButtonL));
  106. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.LeftTrigger, (Key)_configuration.LeftJoycon.ButtonZl));
  107. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger0, (Key)_configuration.LeftJoycon.ButtonSr));
  108. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger0, (Key)_configuration.LeftJoycon.ButtonSl));
  109. // Right JoyCon
  110. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightStick, (Key)_configuration.RightJoyconStick.StickButton));
  111. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.A, (Key)_configuration.RightJoycon.ButtonA));
  112. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.B, (Key)_configuration.RightJoycon.ButtonB));
  113. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.X, (Key)_configuration.RightJoycon.ButtonX));
  114. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Y, (Key)_configuration.RightJoycon.ButtonY));
  115. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.Plus, (Key)_configuration.RightJoycon.ButtonPlus));
  116. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightShoulder, (Key)_configuration.RightJoycon.ButtonR));
  117. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.RightTrigger, (Key)_configuration.RightJoycon.ButtonZr));
  118. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger1, (Key)_configuration.RightJoycon.ButtonSr));
  119. _buttonsUserMapping.Add(new ButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger1, (Key)_configuration.RightJoycon.ButtonSl));
  120. #pragma warning restore IDE0055
  121. }
  122. }
  123. public void SetLed(uint packedRgb)
  124. {
  125. Logger.Info?.Print(LogClass.UI, "SetLed called on an AvaloniaKeyboard");
  126. }
  127. public void SetTriggerThreshold(float triggerThreshold) { }
  128. public void Rumble(float lowFrequency, float highFrequency, uint durationMs) { }
  129. public Vector3 GetMotionData(MotionInputId inputId) => Vector3.Zero;
  130. private static float ConvertRawStickValue(short value)
  131. {
  132. const float ConvertRate = 1.0f / (short.MaxValue + 0.5f);
  133. return value * ConvertRate;
  134. }
  135. private static (short, short) GetStickValues(ref KeyboardStateSnapshot snapshot, JoyconConfigKeyboardStick<ConfigKey> stickConfig)
  136. {
  137. short stickX = 0;
  138. short stickY = 0;
  139. if (snapshot.IsPressed((Key)stickConfig.StickUp))
  140. {
  141. stickY += 1;
  142. }
  143. if (snapshot.IsPressed((Key)stickConfig.StickDown))
  144. {
  145. stickY -= 1;
  146. }
  147. if (snapshot.IsPressed((Key)stickConfig.StickRight))
  148. {
  149. stickX += 1;
  150. }
  151. if (snapshot.IsPressed((Key)stickConfig.StickLeft))
  152. {
  153. stickX -= 1;
  154. }
  155. Vector2 stick = new(stickX, stickY);
  156. stick = Vector2.Normalize(stick);
  157. return ((short)(stick.X * short.MaxValue), (short)(stick.Y * short.MaxValue));
  158. }
  159. public void Clear()
  160. {
  161. _driver?.Clear();
  162. }
  163. public void Dispose() { }
  164. }
  165. }