Input.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. using Microsoft.Xna.Framework;
  2. using Microsoft.Xna.Framework.Input;
  3. namespace FF8
  4. {
  5. public enum Buttons { Up, Down, Left, Right, Okay, Cancel, Exit, Switch, Menu, Back, Start, X, Y, B, A, L1, L2, L3, R1, R2, R3, Select, LeftStickX, LeftStickY, RightStickX, RightStickY, MouseX, MouseY, MouseXjoy, MouseYjoy, MouseLeft, MouseMiddle, MouseRight, Mouse4, Mouse5, MouseWheelup, MouseWheeldown }
  6. internal class Input
  7. {
  8. //store current input states;
  9. private static GamePadState m_gp_state = new GamePadState();
  10. private static KeyboardState m_kb_state = new KeyboardState();
  11. private static MouseState m_m_state = new MouseState();
  12. //properties to assign current input states and back up last input states on the fly.
  13. protected static GamePadState CurrentGPState { get => m_gp_state; set { LastGPState = m_gp_state; m_gp_state = value; } }
  14. protected static KeyboardState CurrentKBState { get => m_kb_state; set { LastKBState = m_kb_state; m_kb_state = value; } }
  15. protected static MouseState CurrentMState { get => m_m_state; set { LastMState = m_m_state; m_m_state = value; } }
  16. //last states
  17. protected static GamePadState LastGPState { get; private set; } = new GamePadState();
  18. protected static KeyboardState LastKBState { get; private set; } = new KeyboardState();
  19. protected static MouseState LastMState { get; private set; }
  20. private static bool bLimitInput;
  21. private static int msDelay = 0;
  22. private static readonly int msDelayLimit = 100;
  23. public static bool GetInputDelayed(Keys key)
  24. {
  25. //if (bLimitInput)
  26. // bLimitInput = (msDelay += Memory.gameTime.ElapsedGameTime.Milliseconds) < msDelayLimit;
  27. if (Keyboard.GetState().IsKeyDown(key) && !bLimitInput)
  28. {
  29. ResetInputLimit();
  30. return true;
  31. }
  32. return false;
  33. }
  34. public static void Update()
  35. {
  36. CurrentGPState = GamePad.GetState(PlayerIndex.One, GamePadDeadZone.Circular);
  37. CurrentKBState = Keyboard.GetState();
  38. CurrentMState = Mouse.GetState();
  39. LockMouse();
  40. CheckInputLimit();
  41. }
  42. private static void CheckInputLimit()
  43. {
  44. if (bLimitInput)
  45. {
  46. bLimitInput = (msDelay += Memory.gameTime.ElapsedGameTime.Milliseconds) < msDelayLimit;
  47. }
  48. }
  49. public static void ResetInputLimit()
  50. {
  51. msDelay = 0;
  52. bLimitInput = true;
  53. }
  54. private static bool IsPressed(Keys k, bool dblinput = false)
  55. {
  56. //This function checks if the key on KB is pressed
  57. //if dblinput is false it makes sure the key wasn't pressed last time.
  58. bool boolRT = CurrentKBState.IsKeyDown(k);
  59. boolRT = !dblinput ? boolRT && LastKBState.IsKeyUp(k) : boolRT && !bLimitInput;
  60. return boolRT;
  61. }
  62. private static bool IsPressed(Buttons b, bool dblinput = false)
  63. {
  64. //This function checks if the button on controller is pressed
  65. //if dblinput is false it makes sure the button wasn't pressed last time.
  66. bool boolRT = false;
  67. if (CurrentGPState.IsConnected)
  68. {
  69. switch (b)
  70. {
  71. case Buttons.Up:
  72. boolRT = CurrentGPState.DPad.Up == ButtonState.Pressed;
  73. break;
  74. case Buttons.Down:
  75. boolRT = CurrentGPState.DPad.Down == ButtonState.Pressed;
  76. break;
  77. case Buttons.Left:
  78. boolRT = CurrentGPState.DPad.Left == ButtonState.Pressed;
  79. break;
  80. case Buttons.Right:
  81. boolRT = CurrentGPState.DPad.Right == ButtonState.Pressed;
  82. break;
  83. case Buttons.B:
  84. boolRT = CurrentGPState.Buttons.B == ButtonState.Pressed;
  85. break;
  86. case Buttons.A:
  87. boolRT = CurrentGPState.Buttons.A == ButtonState.Pressed;
  88. break;
  89. case Buttons.Y:
  90. boolRT = CurrentGPState.Buttons.Y == ButtonState.Pressed;
  91. break;
  92. case Buttons.X:
  93. boolRT = CurrentGPState.Buttons.X == ButtonState.Pressed;
  94. break;
  95. case Buttons.L1:
  96. boolRT = CurrentGPState.Buttons.LeftShoulder == ButtonState.Pressed;
  97. break;
  98. case Buttons.L2:
  99. case Buttons.R2:
  100. boolRT = Analog(b) >= 0.25f; // treating the trigger like a button ignoring .25
  101. break;
  102. case Buttons.L3:
  103. boolRT = CurrentGPState.Buttons.LeftStick == ButtonState.Pressed;
  104. break;
  105. case Buttons.R1:
  106. boolRT = CurrentGPState.Buttons.RightShoulder == ButtonState.Pressed;
  107. break;
  108. case Buttons.R3:
  109. boolRT = CurrentGPState.Buttons.RightStick == ButtonState.Pressed;
  110. break;
  111. case Buttons.Start:
  112. boolRT = CurrentGPState.Buttons.Start == ButtonState.Pressed;
  113. break;
  114. case Buttons.Back:
  115. boolRT = CurrentGPState.Buttons.Back == ButtonState.Pressed;
  116. break;
  117. // this would be used as a test to see if stick is currently used.
  118. // not ment to control anything.
  119. case Buttons.LeftStickX:
  120. case Buttons.LeftStickY:
  121. case Buttons.RightStickX:
  122. case Buttons.RightStickY:
  123. boolRT = Analog(b) != 0.0f;
  124. break;
  125. }
  126. if (Memory.IsActive)
  127. {
  128. switch (b)
  129. {
  130. case Buttons.MouseXjoy:
  131. case Buttons.MouseYjoy:
  132. boolRT = Analog(b) != 0.0f;
  133. break;
  134. case Buttons.MouseX:
  135. case Buttons.MouseY:
  136. boolRT = Analog(b) != Analog(b, true);
  137. break;
  138. case Buttons.MouseLeft:
  139. boolRT = CurrentMState.LeftButton == ButtonState.Pressed;
  140. break;
  141. case Buttons.MouseMiddle:
  142. boolRT = CurrentMState.MiddleButton == ButtonState.Pressed;
  143. break;
  144. case Buttons.MouseRight:
  145. boolRT = CurrentMState.RightButton == ButtonState.Pressed;
  146. break;
  147. case Buttons.Mouse4:
  148. boolRT = CurrentMState.XButton1 == ButtonState.Pressed;
  149. break;
  150. case Buttons.Mouse5:
  151. boolRT = CurrentMState.XButton2 == ButtonState.Pressed;
  152. break;
  153. case Buttons.MouseWheelup:
  154. boolRT = CurrentMState.ScrollWheelValue > LastMState.ScrollWheelValue;
  155. break;
  156. case Buttons.MouseWheeldown:
  157. boolRT = CurrentMState.ScrollWheelValue < LastMState.ScrollWheelValue;
  158. break;
  159. }
  160. }
  161. if (!dblinput && boolRT)
  162. {
  163. switch (b)
  164. {
  165. case Buttons.Up:
  166. boolRT = LastGPState.DPad.Up == ButtonState.Released;
  167. break;
  168. case Buttons.Down:
  169. boolRT = LastGPState.DPad.Down == ButtonState.Released;
  170. break;
  171. case Buttons.Left:
  172. boolRT = LastGPState.DPad.Left == ButtonState.Released;
  173. break;
  174. case Buttons.Right:
  175. boolRT = LastGPState.DPad.Right == ButtonState.Released;
  176. break;
  177. case Buttons.B:
  178. boolRT = LastGPState.Buttons.B == ButtonState.Released;
  179. break;
  180. case Buttons.A:
  181. boolRT = LastGPState.Buttons.A == ButtonState.Released;
  182. break;
  183. case Buttons.Y:
  184. boolRT = LastGPState.Buttons.Y == ButtonState.Released;
  185. break;
  186. case Buttons.X:
  187. boolRT = LastGPState.Buttons.X == ButtonState.Released;
  188. break;
  189. case Buttons.L1:
  190. boolRT = LastGPState.Buttons.LeftShoulder == ButtonState.Released;
  191. break;
  192. case Buttons.L2:
  193. case Buttons.R2:
  194. boolRT = Analog(b, true) < 0.25f; // treating the trigger like a button ignoring .25
  195. break;
  196. case Buttons.L3:
  197. boolRT = LastGPState.Buttons.LeftStick == ButtonState.Released;
  198. break;
  199. case Buttons.R1:
  200. boolRT = LastGPState.Buttons.RightShoulder == ButtonState.Released;
  201. break;
  202. case Buttons.R3:
  203. boolRT = LastGPState.Buttons.RightStick == ButtonState.Released;
  204. break;
  205. case Buttons.Start:
  206. boolRT = LastGPState.Buttons.Start == ButtonState.Released;
  207. break;
  208. case Buttons.Back:
  209. boolRT = LastGPState.Buttons.Back == ButtonState.Released;
  210. break;
  211. // this would be used as a test to see if stick was released previously
  212. // not ment to control anything.
  213. case Buttons.LeftStickX:
  214. case Buttons.LeftStickY:
  215. case Buttons.RightStickX:
  216. case Buttons.RightStickY:
  217. boolRT = Analog(b, true) == 0.0f;
  218. break;
  219. }
  220. if (Memory.IsActive)
  221. {
  222. switch (b)
  223. {
  224. case Buttons.MouseXjoy:
  225. case Buttons.MouseYjoy:
  226. boolRT = Analog(b, true) == 0.0f;
  227. break;
  228. case Buttons.MouseLeft:
  229. boolRT = LastMState.LeftButton == ButtonState.Released;
  230. break;
  231. case Buttons.MouseMiddle:
  232. boolRT = LastMState.MiddleButton == ButtonState.Released;
  233. break;
  234. case Buttons.MouseRight:
  235. boolRT = LastMState.RightButton == ButtonState.Released;
  236. break;
  237. case Buttons.Mouse4:
  238. boolRT = LastMState.XButton1 == ButtonState.Released;
  239. break;
  240. case Buttons.Mouse5:
  241. boolRT = LastMState.XButton2 == ButtonState.Released;
  242. break;
  243. }
  244. }
  245. }
  246. else
  247. {
  248. boolRT = boolRT && !bLimitInput;
  249. }
  250. }
  251. if (boolRT)
  252. {
  253. }
  254. return boolRT;
  255. }
  256. public static float Distance(float speed)
  257. {
  258. // no input throttle but still take the max speed * time;
  259. // for non analog controls
  260. return speed * Memory.gameTime.ElapsedGameTime.Milliseconds;
  261. }
  262. public static float Distance(Buttons b, float speed, bool last = false)
  263. {
  264. // (speed * stickvalue) * time = distance
  265. // idea is you get the distance traveled per ms value
  266. // the speed being the max speed. your sticks value being the throttle.
  267. return (speed * Analog(b, last)) * Memory.gameTime.ElapsedGameTime.Milliseconds;
  268. }
  269. public static float Analog(Buttons b, bool last = false)
  270. {
  271. //get output from analog controls
  272. //mousexjoy and mouseyjoy attempt to convert mouse input to a joystick like input 1.0f to -1.0f
  273. float tmp = 0f;
  274. if (last)
  275. {
  276. switch (b)
  277. {
  278. case Buttons.LeftStickX:
  279. return LastGPState.ThumbSticks.Left.X;
  280. case Buttons.LeftStickY:
  281. return LastGPState.ThumbSticks.Left.Y;
  282. case Buttons.RightStickX:
  283. return LastGPState.ThumbSticks.Right.X;
  284. case Buttons.RightStickY:
  285. return LastGPState.ThumbSticks.Right.Y;
  286. case Buttons.L2:
  287. return LastGPState.Triggers.Left;
  288. case Buttons.R2:
  289. return LastGPState.Triggers.Right;
  290. }
  291. if (Memory.IsActive)
  292. {
  293. switch (b)
  294. {
  295. case Buttons.MouseX:
  296. return LastMState.X;
  297. case Buttons.MouseY:
  298. return LastMState.Y;
  299. case Buttons.MouseXjoy:
  300. tmp = (LastMState.X - Memory.graphics.GraphicsDevice.Viewport.Bounds.Width / 2) / (50f);
  301. return MathHelper.Clamp(tmp, -1f, 1f);
  302. case Buttons.MouseYjoy:
  303. tmp = (Memory.graphics.GraphicsDevice.Viewport.Bounds.Height / 2 - LastMState.Y) / (50f);
  304. return MathHelper.Clamp(tmp, -1f, 1f);
  305. }
  306. }
  307. }
  308. else
  309. {
  310. switch (b)
  311. {
  312. case Buttons.LeftStickX:
  313. return CurrentGPState.ThumbSticks.Left.X;
  314. case Buttons.LeftStickY:
  315. return CurrentGPState.ThumbSticks.Left.Y;
  316. case Buttons.RightStickX:
  317. return CurrentGPState.ThumbSticks.Right.X;
  318. case Buttons.RightStickY:
  319. return CurrentGPState.ThumbSticks.Right.Y;
  320. case Buttons.L2:
  321. return CurrentGPState.Triggers.Left;
  322. case Buttons.R2:
  323. return CurrentGPState.Triggers.Right;
  324. }
  325. if (Memory.IsActive)
  326. {
  327. switch (b)
  328. {
  329. case Buttons.MouseX:
  330. return LastMState.X;
  331. case Buttons.MouseY:
  332. return LastMState.Y;
  333. case Buttons.MouseXjoy:
  334. tmp = (CurrentMState.X - Memory.graphics.GraphicsDevice.Viewport.Bounds.Width / 2) / (50f);
  335. return MathHelper.Clamp(tmp, -1f, 1f);
  336. case Buttons.MouseYjoy:
  337. tmp = (Memory.graphics.GraphicsDevice.Viewport.Bounds.Height / 2 - CurrentMState.Y) / (50f);
  338. return MathHelper.Clamp(tmp, -1f, 1f);
  339. }
  340. }
  341. }
  342. return 0.0f;
  343. }
  344. public static MouseLockMode CurrentMode;
  345. public static bool OverrideLockMouse { get; set; } = false;
  346. public enum MouseLockMode
  347. {
  348. Center,
  349. Screen
  350. }
  351. public static void LockMouse()
  352. {
  353. if (Memory.IsActive && OverrideLockMouse) // check for focus to allow for tabbing out with out taking over mouse.
  354. {
  355. if (CurrentMode == MouseLockMode.Center) //center mouse in screen after grabbing state, release mouse if alt tabbed out.
  356. {
  357. Mouse.SetPosition(Memory.graphics.GraphicsDevice.Viewport.Bounds.Width / 2, Memory.graphics.GraphicsDevice.Viewport.Bounds.Height / 2);
  358. }
  359. else if (CurrentMode == MouseLockMode.Screen) //alt lock that clamps to viewport every frame. would be useful if using mouse to navigate menus and stuff.
  360. {
  361. //there is a better way to clamp as if you move mouse fast enough it will escape for a short time.
  362. Mouse.SetPosition(
  363. MathHelper.Clamp(CurrentMState.X, 0, Memory.graphics.GraphicsDevice.Viewport.Bounds.Width),
  364. MathHelper.Clamp(CurrentMState.Y, 0, Memory.graphics.GraphicsDevice.Viewport.Bounds.Height));
  365. }
  366. }
  367. }
  368. public static Point MouseLocation { get => new Point(CurrentMState.X, CurrentMState.Y); }
  369. public static bool Button(Keys k, bool dblinput = false)
  370. {
  371. return IsPressed(k, dblinput); // fail over to IsPressed
  372. }
  373. public static bool Button(Buttons b, bool dblinput = false)
  374. {
  375. // To add support for controller I was extracting the boolean bits from the if statements.
  376. // Maybe it could be a scheme in future. When these are configureable.
  377. // This function mostly translates the function to the button(s) or key(s).
  378. switch (b)
  379. {
  380. case Buttons.Up:
  381. return (IsPressed(Keys.Up, true) || IsPressed(Buttons.MouseWheelup) || IsPressed(Keys.W, true) || (CurrentGPState.IsConnected && (IsPressed(b, true) || Analog(Buttons.LeftStickY) > 0.0f))) && !bLimitInput;
  382. case Buttons.Down:
  383. return (IsPressed(Keys.Down, true) || IsPressed(Buttons.MouseWheeldown) || IsPressed(Keys.S, true) || (CurrentGPState.IsConnected && (IsPressed(b, true) || Analog(Buttons.LeftStickY) < 0.0f))) && !bLimitInput;
  384. case Buttons.Left:
  385. return (IsPressed(Keys.Left, true) || IsPressed(Keys.A, true) || (CurrentGPState.IsConnected && (IsPressed(b, true) || Analog(Buttons.LeftStickX) < 0.0f))) && !bLimitInput;
  386. case Buttons.Right:
  387. return (IsPressed(Keys.Right, true) || IsPressed(Keys.D, true) || (CurrentGPState.IsConnected && (IsPressed(b, true) || Analog(Buttons.LeftStickX) > 0.0f))) && !bLimitInput;
  388. case Buttons.Okay:
  389. return IsPressed(Keys.Enter, dblinput) || IsPressed(Buttons.B, dblinput) || IsPressed(Buttons.MouseLeft);
  390. case Buttons.Cancel:
  391. return IsPressed(Keys.Back, dblinput) || IsPressed(Buttons.A, dblinput) || IsPressed(Buttons.MouseRight);
  392. case Buttons.Menu:
  393. return IsPressed(Keys.PageUp, dblinput) || IsPressed(Buttons.Y, dblinput);
  394. case Buttons.Switch:
  395. return IsPressed(Keys.PageDown, dblinput) || IsPressed(Buttons.X, dblinput);
  396. case Buttons.Start:
  397. return IsPressed(Keys.Home, dblinput) || IsPressed(Buttons.Start, dblinput);
  398. case Buttons.Select:
  399. return IsPressed(Keys.End, dblinput) || IsPressed(Buttons.Back, dblinput);
  400. case Buttons.Exit:
  401. return IsPressed(Keys.Escape, dblinput);
  402. default:
  403. return IsPressed(b, dblinput); // fail over to IsPressed if no custom input is avalible above
  404. }
  405. }
  406. }
  407. }