AvaloniaKeyboard.cs 8.0 KB

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