NpadController.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. using Ryujinx.Common;
  2. using Ryujinx.Common.Configuration.Hid;
  3. using Ryujinx.Common.Configuration.Hid.Controller;
  4. using Ryujinx.Common.Configuration.Hid.Controller.Motion;
  5. using Ryujinx.Common.Logging;
  6. using Ryujinx.HLE.HOS.Services.Hid;
  7. using System;
  8. using System.Collections.Concurrent;
  9. using System.Numerics;
  10. using System.Runtime.CompilerServices;
  11. using CemuHookClient = Ryujinx.Input.Motion.CemuHook.Client;
  12. using ConfigControllerType = Ryujinx.Common.Configuration.Hid.ControllerType;
  13. namespace Ryujinx.Input.HLE
  14. {
  15. public class NpadController : IDisposable
  16. {
  17. private class HLEButtonMappingEntry
  18. {
  19. public readonly GamepadButtonInputId DriverInputId;
  20. public readonly ControllerKeys HLEInput;
  21. public HLEButtonMappingEntry(GamepadButtonInputId driverInputId, ControllerKeys hleInput)
  22. {
  23. DriverInputId = driverInputId;
  24. HLEInput = hleInput;
  25. }
  26. }
  27. private static readonly HLEButtonMappingEntry[] _hleButtonMapping = new HLEButtonMappingEntry[]
  28. {
  29. new HLEButtonMappingEntry(GamepadButtonInputId.A, ControllerKeys.A),
  30. new HLEButtonMappingEntry(GamepadButtonInputId.B, ControllerKeys.B),
  31. new HLEButtonMappingEntry(GamepadButtonInputId.X, ControllerKeys.X),
  32. new HLEButtonMappingEntry(GamepadButtonInputId.Y, ControllerKeys.Y),
  33. new HLEButtonMappingEntry(GamepadButtonInputId.LeftStick, ControllerKeys.LStick),
  34. new HLEButtonMappingEntry(GamepadButtonInputId.RightStick, ControllerKeys.RStick),
  35. new HLEButtonMappingEntry(GamepadButtonInputId.LeftShoulder, ControllerKeys.L),
  36. new HLEButtonMappingEntry(GamepadButtonInputId.RightShoulder, ControllerKeys.R),
  37. new HLEButtonMappingEntry(GamepadButtonInputId.LeftTrigger, ControllerKeys.Zl),
  38. new HLEButtonMappingEntry(GamepadButtonInputId.RightTrigger, ControllerKeys.Zr),
  39. new HLEButtonMappingEntry(GamepadButtonInputId.DpadUp, ControllerKeys.DpadUp),
  40. new HLEButtonMappingEntry(GamepadButtonInputId.DpadDown, ControllerKeys.DpadDown),
  41. new HLEButtonMappingEntry(GamepadButtonInputId.DpadLeft, ControllerKeys.DpadLeft),
  42. new HLEButtonMappingEntry(GamepadButtonInputId.DpadRight, ControllerKeys.DpadRight),
  43. new HLEButtonMappingEntry(GamepadButtonInputId.Minus, ControllerKeys.Minus),
  44. new HLEButtonMappingEntry(GamepadButtonInputId.Plus, ControllerKeys.Plus),
  45. new HLEButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger0, ControllerKeys.SlLeft),
  46. new HLEButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger0, ControllerKeys.SrLeft),
  47. new HLEButtonMappingEntry(GamepadButtonInputId.SingleLeftTrigger1, ControllerKeys.SlRight),
  48. new HLEButtonMappingEntry(GamepadButtonInputId.SingleRightTrigger1, ControllerKeys.SrRight),
  49. };
  50. private class HLEKeyboardMappingEntry
  51. {
  52. public readonly Key TargetKey;
  53. public readonly byte Target;
  54. public HLEKeyboardMappingEntry(Key targetKey, byte target)
  55. {
  56. TargetKey = targetKey;
  57. Target = target;
  58. }
  59. }
  60. private static readonly HLEKeyboardMappingEntry[] KeyMapping = new HLEKeyboardMappingEntry[]
  61. {
  62. new HLEKeyboardMappingEntry(Key.A, 0x4),
  63. new HLEKeyboardMappingEntry(Key.B, 0x5),
  64. new HLEKeyboardMappingEntry(Key.C, 0x6),
  65. new HLEKeyboardMappingEntry(Key.D, 0x7),
  66. new HLEKeyboardMappingEntry(Key.E, 0x8),
  67. new HLEKeyboardMappingEntry(Key.F, 0x9),
  68. new HLEKeyboardMappingEntry(Key.G, 0xA),
  69. new HLEKeyboardMappingEntry(Key.H, 0xB),
  70. new HLEKeyboardMappingEntry(Key.I, 0xC),
  71. new HLEKeyboardMappingEntry(Key.J, 0xD),
  72. new HLEKeyboardMappingEntry(Key.K, 0xE),
  73. new HLEKeyboardMappingEntry(Key.L, 0xF),
  74. new HLEKeyboardMappingEntry(Key.M, 0x10),
  75. new HLEKeyboardMappingEntry(Key.N, 0x11),
  76. new HLEKeyboardMappingEntry(Key.O, 0x12),
  77. new HLEKeyboardMappingEntry(Key.P, 0x13),
  78. new HLEKeyboardMappingEntry(Key.Q, 0x14),
  79. new HLEKeyboardMappingEntry(Key.R, 0x15),
  80. new HLEKeyboardMappingEntry(Key.S, 0x16),
  81. new HLEKeyboardMappingEntry(Key.T, 0x17),
  82. new HLEKeyboardMappingEntry(Key.U, 0x18),
  83. new HLEKeyboardMappingEntry(Key.V, 0x19),
  84. new HLEKeyboardMappingEntry(Key.W, 0x1A),
  85. new HLEKeyboardMappingEntry(Key.X, 0x1B),
  86. new HLEKeyboardMappingEntry(Key.Y, 0x1C),
  87. new HLEKeyboardMappingEntry(Key.Z, 0x1D),
  88. new HLEKeyboardMappingEntry(Key.Number1, 0x1E),
  89. new HLEKeyboardMappingEntry(Key.Number2, 0x1F),
  90. new HLEKeyboardMappingEntry(Key.Number3, 0x20),
  91. new HLEKeyboardMappingEntry(Key.Number4, 0x21),
  92. new HLEKeyboardMappingEntry(Key.Number5, 0x22),
  93. new HLEKeyboardMappingEntry(Key.Number6, 0x23),
  94. new HLEKeyboardMappingEntry(Key.Number7, 0x24),
  95. new HLEKeyboardMappingEntry(Key.Number8, 0x25),
  96. new HLEKeyboardMappingEntry(Key.Number9, 0x26),
  97. new HLEKeyboardMappingEntry(Key.Number0, 0x27),
  98. new HLEKeyboardMappingEntry(Key.Enter, 0x28),
  99. new HLEKeyboardMappingEntry(Key.Escape, 0x29),
  100. new HLEKeyboardMappingEntry(Key.BackSpace, 0x2A),
  101. new HLEKeyboardMappingEntry(Key.Tab, 0x2B),
  102. new HLEKeyboardMappingEntry(Key.Space, 0x2C),
  103. new HLEKeyboardMappingEntry(Key.Minus, 0x2D),
  104. new HLEKeyboardMappingEntry(Key.Plus, 0x2E),
  105. new HLEKeyboardMappingEntry(Key.BracketLeft, 0x2F),
  106. new HLEKeyboardMappingEntry(Key.BracketRight, 0x30),
  107. new HLEKeyboardMappingEntry(Key.BackSlash, 0x31),
  108. new HLEKeyboardMappingEntry(Key.Tilde, 0x32),
  109. new HLEKeyboardMappingEntry(Key.Semicolon, 0x33),
  110. new HLEKeyboardMappingEntry(Key.Quote, 0x34),
  111. new HLEKeyboardMappingEntry(Key.Grave, 0x35),
  112. new HLEKeyboardMappingEntry(Key.Comma, 0x36),
  113. new HLEKeyboardMappingEntry(Key.Period, 0x37),
  114. new HLEKeyboardMappingEntry(Key.Slash, 0x38),
  115. new HLEKeyboardMappingEntry(Key.CapsLock, 0x39),
  116. new HLEKeyboardMappingEntry(Key.F1, 0x3a),
  117. new HLEKeyboardMappingEntry(Key.F2, 0x3b),
  118. new HLEKeyboardMappingEntry(Key.F3, 0x3c),
  119. new HLEKeyboardMappingEntry(Key.F4, 0x3d),
  120. new HLEKeyboardMappingEntry(Key.F5, 0x3e),
  121. new HLEKeyboardMappingEntry(Key.F6, 0x3f),
  122. new HLEKeyboardMappingEntry(Key.F7, 0x40),
  123. new HLEKeyboardMappingEntry(Key.F8, 0x41),
  124. new HLEKeyboardMappingEntry(Key.F9, 0x42),
  125. new HLEKeyboardMappingEntry(Key.F10, 0x43),
  126. new HLEKeyboardMappingEntry(Key.F11, 0x44),
  127. new HLEKeyboardMappingEntry(Key.F12, 0x45),
  128. new HLEKeyboardMappingEntry(Key.PrintScreen, 0x46),
  129. new HLEKeyboardMappingEntry(Key.ScrollLock, 0x47),
  130. new HLEKeyboardMappingEntry(Key.Pause, 0x48),
  131. new HLEKeyboardMappingEntry(Key.Insert, 0x49),
  132. new HLEKeyboardMappingEntry(Key.Home, 0x4A),
  133. new HLEKeyboardMappingEntry(Key.PageUp, 0x4B),
  134. new HLEKeyboardMappingEntry(Key.Delete, 0x4C),
  135. new HLEKeyboardMappingEntry(Key.End, 0x4D),
  136. new HLEKeyboardMappingEntry(Key.PageDown, 0x4E),
  137. new HLEKeyboardMappingEntry(Key.Right, 0x4F),
  138. new HLEKeyboardMappingEntry(Key.Left, 0x50),
  139. new HLEKeyboardMappingEntry(Key.Down, 0x51),
  140. new HLEKeyboardMappingEntry(Key.Up, 0x52),
  141. new HLEKeyboardMappingEntry(Key.NumLock, 0x53),
  142. new HLEKeyboardMappingEntry(Key.KeypadDivide, 0x54),
  143. new HLEKeyboardMappingEntry(Key.KeypadMultiply, 0x55),
  144. new HLEKeyboardMappingEntry(Key.KeypadSubtract, 0x56),
  145. new HLEKeyboardMappingEntry(Key.KeypadAdd, 0x57),
  146. new HLEKeyboardMappingEntry(Key.KeypadEnter, 0x58),
  147. new HLEKeyboardMappingEntry(Key.Keypad1, 0x59),
  148. new HLEKeyboardMappingEntry(Key.Keypad2, 0x5A),
  149. new HLEKeyboardMappingEntry(Key.Keypad3, 0x5B),
  150. new HLEKeyboardMappingEntry(Key.Keypad4, 0x5C),
  151. new HLEKeyboardMappingEntry(Key.Keypad5, 0x5D),
  152. new HLEKeyboardMappingEntry(Key.Keypad6, 0x5E),
  153. new HLEKeyboardMappingEntry(Key.Keypad7, 0x5F),
  154. new HLEKeyboardMappingEntry(Key.Keypad8, 0x60),
  155. new HLEKeyboardMappingEntry(Key.Keypad9, 0x61),
  156. new HLEKeyboardMappingEntry(Key.Keypad0, 0x62),
  157. new HLEKeyboardMappingEntry(Key.KeypadDecimal, 0x63),
  158. new HLEKeyboardMappingEntry(Key.F13, 0x68),
  159. new HLEKeyboardMappingEntry(Key.F14, 0x69),
  160. new HLEKeyboardMappingEntry(Key.F15, 0x6A),
  161. new HLEKeyboardMappingEntry(Key.F16, 0x6B),
  162. new HLEKeyboardMappingEntry(Key.F17, 0x6C),
  163. new HLEKeyboardMappingEntry(Key.F18, 0x6D),
  164. new HLEKeyboardMappingEntry(Key.F19, 0x6E),
  165. new HLEKeyboardMappingEntry(Key.F20, 0x6F),
  166. new HLEKeyboardMappingEntry(Key.F21, 0x70),
  167. new HLEKeyboardMappingEntry(Key.F22, 0x71),
  168. new HLEKeyboardMappingEntry(Key.F23, 0x72),
  169. new HLEKeyboardMappingEntry(Key.F24, 0x73),
  170. new HLEKeyboardMappingEntry(Key.ControlLeft, 0xE0),
  171. new HLEKeyboardMappingEntry(Key.ShiftLeft, 0xE1),
  172. new HLEKeyboardMappingEntry(Key.AltLeft, 0xE2),
  173. new HLEKeyboardMappingEntry(Key.WinLeft, 0xE3),
  174. new HLEKeyboardMappingEntry(Key.ControlRight, 0xE4),
  175. new HLEKeyboardMappingEntry(Key.ShiftRight, 0xE5),
  176. new HLEKeyboardMappingEntry(Key.AltRight, 0xE6),
  177. new HLEKeyboardMappingEntry(Key.WinRight, 0xE7),
  178. };
  179. private static readonly HLEKeyboardMappingEntry[] KeyModifierMapping = new HLEKeyboardMappingEntry[]
  180. {
  181. new HLEKeyboardMappingEntry(Key.ControlLeft, 0),
  182. new HLEKeyboardMappingEntry(Key.ShiftLeft, 1),
  183. new HLEKeyboardMappingEntry(Key.AltLeft, 2),
  184. new HLEKeyboardMappingEntry(Key.WinLeft, 3),
  185. new HLEKeyboardMappingEntry(Key.ControlRight, 4),
  186. new HLEKeyboardMappingEntry(Key.ShiftRight, 5),
  187. new HLEKeyboardMappingEntry(Key.AltRight, 6),
  188. new HLEKeyboardMappingEntry(Key.WinRight, 7),
  189. new HLEKeyboardMappingEntry(Key.CapsLock, 8),
  190. new HLEKeyboardMappingEntry(Key.ScrollLock, 9),
  191. new HLEKeyboardMappingEntry(Key.NumLock, 10),
  192. };
  193. private bool _isValid;
  194. private string _id;
  195. private MotionInput _leftMotionInput;
  196. private MotionInput _rightMotionInput;
  197. private IGamepad _gamepad;
  198. private InputConfig _config;
  199. public IGamepadDriver GamepadDriver { get; private set; }
  200. public GamepadStateSnapshot State { get; private set; }
  201. public string Id => _id;
  202. private CemuHookClient _cemuHookClient;
  203. public NpadController(CemuHookClient cemuHookClient)
  204. {
  205. State = default;
  206. _id = null;
  207. _isValid = false;
  208. _cemuHookClient = cemuHookClient;
  209. }
  210. public bool UpdateDriverConfiguration(IGamepadDriver gamepadDriver, InputConfig config)
  211. {
  212. GamepadDriver = gamepadDriver;
  213. _gamepad?.Dispose();
  214. _id = config.Id;
  215. _gamepad = GamepadDriver.GetGamepad(_id);
  216. _isValid = _gamepad != null;
  217. UpdateUserConfiguration(config);
  218. return _isValid;
  219. }
  220. public void UpdateUserConfiguration(InputConfig config)
  221. {
  222. if (config is StandardControllerInputConfig controllerConfig)
  223. {
  224. bool needsMotionInputUpdate = _config == null || (_config is StandardControllerInputConfig oldControllerConfig &&
  225. (oldControllerConfig.Motion.EnableMotion != controllerConfig.Motion.EnableMotion) &&
  226. (oldControllerConfig.Motion.MotionBackend != controllerConfig.Motion.MotionBackend));
  227. if (needsMotionInputUpdate)
  228. {
  229. UpdateMotionInput(controllerConfig.Motion);
  230. }
  231. }
  232. else
  233. {
  234. // Non-controller doesn't have motions.
  235. _leftMotionInput = null;
  236. }
  237. _config = config;
  238. if (_isValid)
  239. {
  240. _gamepad.SetConfiguration(config);
  241. }
  242. }
  243. private void UpdateMotionInput(MotionConfigController motionConfig)
  244. {
  245. if (motionConfig.MotionBackend != MotionInputBackendType.CemuHook)
  246. {
  247. _leftMotionInput = new MotionInput();
  248. }
  249. else
  250. {
  251. _leftMotionInput = null;
  252. }
  253. }
  254. public void Update()
  255. {
  256. if (_isValid && GamepadDriver != null)
  257. {
  258. State = _gamepad.GetMappedStateSnapshot();
  259. if (_config is StandardControllerInputConfig controllerConfig && controllerConfig.Motion.EnableMotion)
  260. {
  261. if (controllerConfig.Motion.MotionBackend == MotionInputBackendType.GamepadDriver)
  262. {
  263. if (_gamepad.Features.HasFlag(GamepadFeaturesFlag.Motion))
  264. {
  265. Vector3 accelerometer = _gamepad.GetMotionData(MotionInputId.Accelerometer);
  266. Vector3 gyroscope = _gamepad.GetMotionData(MotionInputId.Gyroscope);
  267. accelerometer = new Vector3(accelerometer.X, -accelerometer.Z, accelerometer.Y);
  268. gyroscope = new Vector3(gyroscope.X, -gyroscope.Z, gyroscope.Y);
  269. _leftMotionInput.Update(accelerometer, gyroscope, (ulong)PerformanceCounter.ElapsedNanoseconds / 1000, controllerConfig.Motion.Sensitivity, (float)controllerConfig.Motion.GyroDeadzone);
  270. if (controllerConfig.ControllerType == ConfigControllerType.JoyconPair)
  271. {
  272. _rightMotionInput = _leftMotionInput;
  273. }
  274. }
  275. }
  276. else if (controllerConfig.Motion.MotionBackend == MotionInputBackendType.CemuHook && controllerConfig.Motion is CemuHookMotionConfigController cemuControllerConfig)
  277. {
  278. int clientId = (int)controllerConfig.PlayerIndex;
  279. // First of all ensure we are registered
  280. _cemuHookClient.RegisterClient(clientId, cemuControllerConfig.DsuServerHost, cemuControllerConfig.DsuServerPort);
  281. // Then request and retrieve the data
  282. _cemuHookClient.RequestData(clientId, cemuControllerConfig.Slot);
  283. _cemuHookClient.TryGetData(clientId, cemuControllerConfig.Slot, out _leftMotionInput);
  284. if (controllerConfig.ControllerType == ConfigControllerType.JoyconPair)
  285. {
  286. if (!cemuControllerConfig.MirrorInput)
  287. {
  288. _cemuHookClient.RequestData(clientId, cemuControllerConfig.AltSlot);
  289. _cemuHookClient.TryGetData(clientId, cemuControllerConfig.AltSlot, out _rightMotionInput);
  290. }
  291. else
  292. {
  293. _rightMotionInput = _leftMotionInput;
  294. }
  295. }
  296. }
  297. }
  298. }
  299. else
  300. {
  301. // Reset states
  302. State = default;
  303. _leftMotionInput = null;
  304. }
  305. }
  306. public GamepadInput GetHLEInputState()
  307. {
  308. GamepadInput state = new GamepadInput();
  309. // First update all buttons
  310. foreach (HLEButtonMappingEntry entry in _hleButtonMapping)
  311. {
  312. if (State.IsPressed(entry.DriverInputId))
  313. {
  314. state.Buttons |= entry.HLEInput;
  315. }
  316. }
  317. if (_gamepad is IKeyboard)
  318. {
  319. (float leftAxisX, float leftAxisY) = State.GetStick(StickInputId.Left);
  320. (float rightAxisX, float rightAxisY) = State.GetStick(StickInputId.Right);
  321. state.LStick = new JoystickPosition
  322. {
  323. Dx = ClampAxis(leftAxisX),
  324. Dy = ClampAxis(leftAxisY)
  325. };
  326. state.RStick = new JoystickPosition
  327. {
  328. Dx = ClampAxis(rightAxisX),
  329. Dy = ClampAxis(rightAxisY)
  330. };
  331. }
  332. else if (_config is StandardControllerInputConfig controllerConfig)
  333. {
  334. (float leftAxisX, float leftAxisY) = State.GetStick(StickInputId.Left);
  335. (float rightAxisX, float rightAxisY) = State.GetStick(StickInputId.Right);
  336. state.LStick = ClampToCircle(ApplyDeadzone(leftAxisX, leftAxisY, controllerConfig.DeadzoneLeft), controllerConfig.RangeLeft);
  337. state.RStick = ClampToCircle(ApplyDeadzone(rightAxisX, rightAxisY, controllerConfig.DeadzoneRight), controllerConfig.RangeRight);
  338. }
  339. return state;
  340. }
  341. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  342. private static JoystickPosition ApplyDeadzone(float x, float y, float deadzone)
  343. {
  344. float magnitudeClamped = Math.Min(MathF.Sqrt(x * x + y * y), 1f);
  345. if (magnitudeClamped <= deadzone)
  346. {
  347. return new JoystickPosition() {Dx = 0, Dy = 0};
  348. }
  349. return new JoystickPosition()
  350. {
  351. Dx = ClampAxis((x / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone))),
  352. Dy = ClampAxis((y / magnitudeClamped) * ((magnitudeClamped - deadzone) / (1 - deadzone)))
  353. };
  354. }
  355. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  356. private static short ClampAxis(float value)
  357. {
  358. if (Math.Sign(value) < 0)
  359. {
  360. return (short)Math.Max(value * -short.MinValue, short.MinValue);
  361. }
  362. return (short)Math.Min(value * short.MaxValue, short.MaxValue);
  363. }
  364. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  365. private static JoystickPosition ClampToCircle(JoystickPosition position, float range)
  366. {
  367. Vector2 point = new Vector2(position.Dx, position.Dy) * range;
  368. if (point.Length() > short.MaxValue)
  369. {
  370. point = point / point.Length() * short.MaxValue;
  371. }
  372. return new JoystickPosition
  373. {
  374. Dx = (int)point.X,
  375. Dy = (int)point.Y
  376. };
  377. }
  378. public SixAxisInput GetHLEMotionState(bool isJoyconRightPair = false)
  379. {
  380. float[] orientationForHLE = new float[9];
  381. Vector3 gyroscope;
  382. Vector3 accelerometer;
  383. Vector3 rotation;
  384. MotionInput motionInput = _leftMotionInput;
  385. if (isJoyconRightPair)
  386. {
  387. if (_rightMotionInput == null)
  388. {
  389. return default;
  390. }
  391. motionInput = _rightMotionInput;
  392. }
  393. if (motionInput != null)
  394. {
  395. gyroscope = Truncate(motionInput.Gyroscrope * 0.0027f, 3);
  396. accelerometer = Truncate(motionInput.Accelerometer, 3);
  397. rotation = Truncate(motionInput.Rotation * 0.0027f, 3);
  398. Matrix4x4 orientation = motionInput.GetOrientation();
  399. orientationForHLE[0] = Math.Clamp(orientation.M11, -1f, 1f);
  400. orientationForHLE[1] = Math.Clamp(orientation.M12, -1f, 1f);
  401. orientationForHLE[2] = Math.Clamp(orientation.M13, -1f, 1f);
  402. orientationForHLE[3] = Math.Clamp(orientation.M21, -1f, 1f);
  403. orientationForHLE[4] = Math.Clamp(orientation.M22, -1f, 1f);
  404. orientationForHLE[5] = Math.Clamp(orientation.M23, -1f, 1f);
  405. orientationForHLE[6] = Math.Clamp(orientation.M31, -1f, 1f);
  406. orientationForHLE[7] = Math.Clamp(orientation.M32, -1f, 1f);
  407. orientationForHLE[8] = Math.Clamp(orientation.M33, -1f, 1f);
  408. }
  409. else
  410. {
  411. gyroscope = new Vector3();
  412. accelerometer = new Vector3();
  413. rotation = new Vector3();
  414. }
  415. return new SixAxisInput()
  416. {
  417. Accelerometer = accelerometer,
  418. Gyroscope = gyroscope,
  419. Rotation = rotation,
  420. Orientation = orientationForHLE
  421. };
  422. }
  423. private static Vector3 Truncate(Vector3 value, int decimals)
  424. {
  425. float power = MathF.Pow(10, decimals);
  426. value.X = float.IsNegative(value.X) ? MathF.Ceiling(value.X * power) / power : MathF.Floor(value.X * power) / power;
  427. value.Y = float.IsNegative(value.Y) ? MathF.Ceiling(value.Y * power) / power : MathF.Floor(value.Y * power) / power;
  428. value.Z = float.IsNegative(value.Z) ? MathF.Ceiling(value.Z * power) / power : MathF.Floor(value.Z * power) / power;
  429. return value;
  430. }
  431. public KeyboardInput? GetHLEKeyboardInput()
  432. {
  433. if (_gamepad is IKeyboard keyboard)
  434. {
  435. KeyboardStateSnapshot keyboardState = keyboard.GetKeyboardStateSnapshot();
  436. KeyboardInput hidKeyboard = new KeyboardInput
  437. {
  438. Modifier = 0,
  439. Keys = new ulong[0x4]
  440. };
  441. foreach (HLEKeyboardMappingEntry entry in KeyMapping)
  442. {
  443. ulong value = keyboardState.IsPressed(entry.TargetKey) ? 1UL : 0UL;
  444. hidKeyboard.Keys[entry.Target / 0x40] |= (value << (entry.Target % 0x40));
  445. }
  446. foreach (HLEKeyboardMappingEntry entry in KeyModifierMapping)
  447. {
  448. int value = keyboardState.IsPressed(entry.TargetKey) ? 1 : 0;
  449. hidKeyboard.Modifier |= value << entry.Target;
  450. }
  451. return hidKeyboard;
  452. }
  453. return null;
  454. }
  455. protected virtual void Dispose(bool disposing)
  456. {
  457. if (disposing)
  458. {
  459. _gamepad?.Dispose();
  460. }
  461. }
  462. public void Dispose()
  463. {
  464. Dispose(true);
  465. }
  466. public void UpdateRumble(ConcurrentQueue<(VibrationValue, VibrationValue)> queue)
  467. {
  468. if (queue.TryDequeue(out (VibrationValue, VibrationValue) dualVibrationValue))
  469. {
  470. if (_config is StandardControllerInputConfig controllerConfig && controllerConfig.Rumble.EnableRumble)
  471. {
  472. VibrationValue leftVibrationValue = dualVibrationValue.Item1;
  473. VibrationValue rightVibrationValue = dualVibrationValue.Item2;
  474. float low = Math.Min(1f, (float)((rightVibrationValue.AmplitudeLow * 0.85 + rightVibrationValue.AmplitudeHigh * 0.15) * controllerConfig.Rumble.StrongRumble));
  475. float high = Math.Min(1f, (float)((leftVibrationValue.AmplitudeLow * 0.15 + leftVibrationValue.AmplitudeHigh * 0.85) * controllerConfig.Rumble.WeakRumble));
  476. _gamepad.Rumble(low, high, uint.MaxValue);
  477. Logger.Debug?.Print(LogClass.Hid, $"Effect for {controllerConfig.PlayerIndex} " +
  478. $"L.low.amp={leftVibrationValue.AmplitudeLow}, " +
  479. $"L.high.amp={leftVibrationValue.AmplitudeHigh}, " +
  480. $"R.low.amp={rightVibrationValue.AmplitudeLow}, " +
  481. $"R.high.amp={rightVibrationValue.AmplitudeHigh} " +
  482. $"--> ({low}, {high})");
  483. }
  484. }
  485. }
  486. }
  487. }