NpadController.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. using OpenTK;
  2. using OpenTK.Input;
  3. using Ryujinx.HLE.Input;
  4. using System;
  5. namespace Ryujinx.UI.Input
  6. {
  7. public enum ControllerInputId
  8. {
  9. Invalid,
  10. LStick,
  11. RStick,
  12. LShoulder,
  13. RShoulder,
  14. LTrigger,
  15. RTrigger,
  16. LJoystick,
  17. RJoystick,
  18. DPadUp,
  19. DPadDown,
  20. DPadLeft,
  21. DPadRight,
  22. Start,
  23. Back,
  24. A,
  25. B,
  26. X,
  27. Y
  28. }
  29. public struct NpadControllerLeft
  30. {
  31. public ControllerInputId Stick;
  32. public ControllerInputId StickButton;
  33. public ControllerInputId DPadUp;
  34. public ControllerInputId DPadDown;
  35. public ControllerInputId DPadLeft;
  36. public ControllerInputId DPadRight;
  37. public ControllerInputId ButtonMinus;
  38. public ControllerInputId ButtonL;
  39. public ControllerInputId ButtonZl;
  40. }
  41. public struct NpadControllerRight
  42. {
  43. public ControllerInputId Stick;
  44. public ControllerInputId StickButton;
  45. public ControllerInputId ButtonA;
  46. public ControllerInputId ButtonB;
  47. public ControllerInputId ButtonX;
  48. public ControllerInputId ButtonY;
  49. public ControllerInputId ButtonPlus;
  50. public ControllerInputId ButtonR;
  51. public ControllerInputId ButtonZr;
  52. }
  53. public class NpadController
  54. {
  55. /// <summary>
  56. /// Enables or disables controller support
  57. /// </summary>
  58. public bool Enabled { get; private set; }
  59. /// <summary>
  60. /// Controller Device Index
  61. /// </summary>
  62. public int Index { get; private set; }
  63. /// <summary>
  64. /// Controller Analog Stick Deadzone
  65. /// </summary>
  66. public float Deadzone { get; private set; }
  67. /// <summary>
  68. /// Controller Trigger Threshold
  69. /// </summary>
  70. public float TriggerThreshold { get; private set; }
  71. /// <summary>
  72. /// Left JoyCon Controller Bindings
  73. /// </summary>
  74. public NpadControllerLeft LeftJoycon { get; private set; }
  75. /// <summary>
  76. /// Right JoyCon Controller Bindings
  77. /// </summary>
  78. public NpadControllerRight RightJoycon { get; private set; }
  79. public NpadController(
  80. bool enabled,
  81. int index,
  82. float deadzone,
  83. float triggerThreshold,
  84. NpadControllerLeft leftJoycon,
  85. NpadControllerRight rightJoycon)
  86. {
  87. Enabled = enabled;
  88. Index = index;
  89. Deadzone = deadzone;
  90. TriggerThreshold = triggerThreshold;
  91. LeftJoycon = leftJoycon;
  92. RightJoycon = rightJoycon;
  93. }
  94. public void SetEnabled(bool enabled)
  95. {
  96. Enabled = enabled;
  97. }
  98. public HidControllerButtons GetButtons()
  99. {
  100. if (!Enabled)
  101. {
  102. return 0;
  103. }
  104. GamePadState gpState = GamePad.GetState(Index);
  105. HidControllerButtons buttons = 0;
  106. if (IsPressed(gpState, LeftJoycon.DPadUp)) buttons |= HidControllerButtons.DpadUp;
  107. if (IsPressed(gpState, LeftJoycon.DPadDown)) buttons |= HidControllerButtons.DpadDown;
  108. if (IsPressed(gpState, LeftJoycon.DPadLeft)) buttons |= HidControllerButtons.DpadLeft;
  109. if (IsPressed(gpState, LeftJoycon.DPadRight)) buttons |= HidControllerButtons.DPadRight;
  110. if (IsPressed(gpState, LeftJoycon.StickButton)) buttons |= HidControllerButtons.StickLeft;
  111. if (IsPressed(gpState, LeftJoycon.ButtonMinus)) buttons |= HidControllerButtons.Minus;
  112. if (IsPressed(gpState, LeftJoycon.ButtonL)) buttons |= HidControllerButtons.L;
  113. if (IsPressed(gpState, LeftJoycon.ButtonZl)) buttons |= HidControllerButtons.Zl;
  114. if (IsPressed(gpState, RightJoycon.ButtonA)) buttons |= HidControllerButtons.A;
  115. if (IsPressed(gpState, RightJoycon.ButtonB)) buttons |= HidControllerButtons.B;
  116. if (IsPressed(gpState, RightJoycon.ButtonX)) buttons |= HidControllerButtons.X;
  117. if (IsPressed(gpState, RightJoycon.ButtonY)) buttons |= HidControllerButtons.Y;
  118. if (IsPressed(gpState, RightJoycon.StickButton)) buttons |= HidControllerButtons.StickRight;
  119. if (IsPressed(gpState, RightJoycon.ButtonPlus)) buttons |= HidControllerButtons.Plus;
  120. if (IsPressed(gpState, RightJoycon.ButtonR)) buttons |= HidControllerButtons.R;
  121. if (IsPressed(gpState, RightJoycon.ButtonZr)) buttons |= HidControllerButtons.Zr;
  122. return buttons;
  123. }
  124. public (short, short) GetLeftStick()
  125. {
  126. if (!Enabled)
  127. {
  128. return (0, 0);
  129. }
  130. return GetStick(LeftJoycon.Stick);
  131. }
  132. public (short, short) GetRightStick()
  133. {
  134. if (!Enabled)
  135. {
  136. return (0, 0);
  137. }
  138. return GetStick(RightJoycon.Stick);
  139. }
  140. private (short, short) GetStick(ControllerInputId joystick)
  141. {
  142. GamePadState gpState = GamePad.GetState(Index);
  143. switch (joystick)
  144. {
  145. case ControllerInputId.LJoystick:
  146. return ApplyDeadzone(gpState.ThumbSticks.Left);
  147. case ControllerInputId.RJoystick:
  148. return ApplyDeadzone(gpState.ThumbSticks.Right);
  149. default:
  150. return (0, 0);
  151. }
  152. }
  153. private (short, short) ApplyDeadzone(Vector2 axis)
  154. {
  155. return (ClampAxis(MathF.Abs(axis.X) > Deadzone ? axis.X : 0f),
  156. ClampAxis(MathF.Abs(axis.Y) > Deadzone ? axis.Y : 0f));
  157. }
  158. private static short ClampAxis(float value)
  159. {
  160. if (value <= -short.MaxValue)
  161. {
  162. return -short.MaxValue;
  163. }
  164. else
  165. {
  166. return (short)(value * short.MaxValue);
  167. }
  168. }
  169. private bool IsPressed(GamePadState gpState, ControllerInputId button)
  170. {
  171. switch (button)
  172. {
  173. case ControllerInputId.A: return gpState.Buttons.A == ButtonState.Pressed;
  174. case ControllerInputId.B: return gpState.Buttons.B == ButtonState.Pressed;
  175. case ControllerInputId.X: return gpState.Buttons.X == ButtonState.Pressed;
  176. case ControllerInputId.Y: return gpState.Buttons.Y == ButtonState.Pressed;
  177. case ControllerInputId.LStick: return gpState.Buttons.LeftStick == ButtonState.Pressed;
  178. case ControllerInputId.RStick: return gpState.Buttons.RightStick == ButtonState.Pressed;
  179. case ControllerInputId.LShoulder: return gpState.Buttons.LeftShoulder == ButtonState.Pressed;
  180. case ControllerInputId.RShoulder: return gpState.Buttons.RightShoulder == ButtonState.Pressed;
  181. case ControllerInputId.DPadUp: return gpState.DPad.Up == ButtonState.Pressed;
  182. case ControllerInputId.DPadDown: return gpState.DPad.Down == ButtonState.Pressed;
  183. case ControllerInputId.DPadLeft: return gpState.DPad.Left == ButtonState.Pressed;
  184. case ControllerInputId.DPadRight: return gpState.DPad.Right == ButtonState.Pressed;
  185. case ControllerInputId.Start: return gpState.Buttons.Start == ButtonState.Pressed;
  186. case ControllerInputId.Back: return gpState.Buttons.Back == ButtonState.Pressed;
  187. case ControllerInputId.LTrigger: return gpState.Triggers.Left >= TriggerThreshold;
  188. case ControllerInputId.RTrigger: return gpState.Triggers.Right >= TriggerThreshold;
  189. //Using thumbsticks as buttons is not common, but it would be nice not to ignore them
  190. case ControllerInputId.LJoystick:
  191. return gpState.ThumbSticks.Left.X >= Deadzone ||
  192. gpState.ThumbSticks.Left.Y >= Deadzone;
  193. case ControllerInputId.RJoystick:
  194. return gpState.ThumbSticks.Right.X >= Deadzone ||
  195. gpState.ThumbSticks.Right.Y >= Deadzone;
  196. default:
  197. return false;
  198. }
  199. }
  200. }
  201. }