Client LuaCsForBarotrauma
BarotraumaClient/ClientSource/PlayerInput.cs
1 using System.Collections.Generic;
2 using Microsoft.Xna.Framework;
3 using Microsoft.Xna.Framework.Input;
4 using System;
5 #if WINDOWS
6 using System.Runtime.InteropServices;
7 #endif
8 
9 namespace Barotrauma
10 {
11  public enum MouseButton
12  {
13  None = -1,
14  PrimaryMouse = 0,
15  SecondaryMouse = 1,
16  MiddleMouse = 2,
17  MouseButton4 = 3,
18  MouseButton5 = 4,
19  MouseWheelUp = 5,
20  MouseWheelDown = 6
21  }
22 
23  public class KeyOrMouse
24  {
25  public readonly Keys Key;
26 
27  private LocalizedString name;
28 
30  {
31  get
32  {
33  if (name == null) { name = GetName(); }
34  return name;
35  }
36  }
37 
38  public MouseButton MouseButton { get; private set; }
39 
40  public static implicit operator KeyOrMouse(Keys key) { return new KeyOrMouse(key); }
41  public static implicit operator KeyOrMouse(MouseButton mouseButton) { return new KeyOrMouse(mouseButton); }
42 
43  public KeyOrMouse(Keys keyBinding)
44  {
45  this.Key = keyBinding;
46  this.MouseButton = MouseButton.None;
47  }
48 
49  public KeyOrMouse(MouseButton mouseButton)
50  {
51  this.Key = Keys.None;
52  this.MouseButton = mouseButton;
53  }
54 
55  public bool IsDown()
56  {
57  switch (MouseButton)
58  {
59  case MouseButton.None:
60  if (Key == Keys.None) { return false; }
61  return PlayerInput.KeyDown(Key);
62  case MouseButton.PrimaryMouse:
64  case MouseButton.SecondaryMouse:
66  case MouseButton.MiddleMouse:
67  return PlayerInput.MidButtonHeld();
68  case MouseButton.MouseButton4:
70  case MouseButton.MouseButton5:
72  case MouseButton.MouseWheelUp: // No real way of "holding" a mouse wheel key, but then again it makes no sense to bind the key to this kind of task.
74  case MouseButton.MouseWheelDown:
76  }
77 
78  return false;
79  }
80 
81  public bool IsHit()
82  {
83  switch (MouseButton)
84  {
85  case MouseButton.None:
86  if (Key == Keys.None) { return false; }
87  return PlayerInput.KeyHit(Key);
88  case MouseButton.PrimaryMouse:
90  case MouseButton.SecondaryMouse:
92  case MouseButton.MiddleMouse:
94  case MouseButton.MouseButton4:
96  case MouseButton.MouseButton5:
98  case MouseButton.MouseWheelUp:
100  case MouseButton.MouseWheelDown:
102  }
103 
104  return false;
105  }
106 
107  public override bool Equals(object obj)
108  {
109  if (obj is KeyOrMouse keyOrMouse)
110  {
111  return this == keyOrMouse;
112  }
113  else
114  {
115  return false;
116  }
117  }
118 
119  public static bool operator ==(KeyOrMouse a, KeyOrMouse b)
120  {
121  if (a is null)
122  {
123  return b is null;
124  }
125  else if (a.MouseButton != MouseButton.None)
126  {
127  return !(b is null) && a.MouseButton == b.MouseButton;
128  }
129  else
130  {
131  return !(b is null) && a.Key.Equals(b.Key);
132  }
133  }
134 
135  public static bool operator !=(KeyOrMouse a, KeyOrMouse b)
136  {
137  return !(a == b);
138  }
139 
140  public static bool operator ==(KeyOrMouse keyOrMouse, Keys key)
141  {
142  if (keyOrMouse.MouseButton != MouseButton.None) { return false; }
143  return keyOrMouse.Key == key;
144  }
145 
146  public static bool operator !=(KeyOrMouse keyOrMouse, Keys key)
147  {
148  return !(keyOrMouse == key);
149  }
150 
151  public static bool operator ==(Keys key, KeyOrMouse keyOrMouse)
152  {
153  return keyOrMouse == key;
154  }
155 
156  public static bool operator !=(Keys key, KeyOrMouse keyOrMouse)
157  {
158  return keyOrMouse != key;
159  }
160 
161  public static bool operator ==(KeyOrMouse keyOrMouse, MouseButton mb)
162  {
163  return keyOrMouse.MouseButton == mb && keyOrMouse.Key == Keys.None;
164  }
165 
166  public static bool operator !=(KeyOrMouse keyOrMouse, MouseButton mb)
167  {
168  return !(keyOrMouse == mb);
169  }
170 
171  public static bool operator ==(MouseButton mb, KeyOrMouse keyOrMouse)
172  {
173  return keyOrMouse == mb;
174  }
175 
176  public static bool operator !=(MouseButton mb, KeyOrMouse keyOrMouse)
177  {
178  return keyOrMouse != mb;
179  }
180 
181  public override string ToString()
182  {
183  switch (MouseButton)
184  {
185  case MouseButton.None:
186  return Key.ToString();
187  default:
188  return MouseButton.ToString();
189  }
190  }
191 
192  public override int GetHashCode()
193  {
194  var hashCode = int.MinValue;
195  hashCode = hashCode * -1521134295 + Key.GetHashCode();
196  hashCode = hashCode * -1521134295 + EqualityComparer<int?>.Default.GetHashCode((int)MouseButton);
197  return hashCode;
198  }
199 
201  {
202  if (PlayerInput.NumberKeys.Contains(Key))
203  {
204  return Key.ToString().Substring(1, 1);
205  }
206  if (MouseButton != MouseButton.None)
207  {
208  switch (MouseButton)
209  {
210  case MouseButton.PrimaryMouse:
212  case MouseButton.SecondaryMouse:
214  default:
215  return TextManager.Get($"Input.{MouseButton}");
216  }
217  }
218  else
219  {
220  return Key.ToString();
221  }
222  }
223  }
224 
225  public class PlayerInput
226  {
227  static MouseState mouseState, oldMouseState;
228  static MouseState latestMouseState; //the absolute latest state, do NOT use for player interaction
229  static KeyboardState keyboardState, oldKeyboardState;
230 
231  static double timeSincePrimaryClick;
232  static Point lastPrimaryClickPosition;
233 
234  static double timeSinceSecondaryClick;
235  static Point lastSecondaryClickPosition;
236 
237  const float DoubleClickDelay = 0.4f;
238  public static float MaxDoubleClickDistance
239  {
240  get { return Math.Max(15.0f * Math.Max(GameMain.GraphicsHeight / 1920.0f, GameMain.GraphicsHeight / 1080.0f), 10.0f); }
241  }
242 
243  static bool primaryDoubleClicked;
244  static bool secondaryDoubleClicked;
245 
246  static bool allowInput;
247  static bool wasWindowActive;
248 
249  public static readonly List<Keys> NumberKeys = new List<Keys> { Keys.D0, Keys.D1, Keys.D2, Keys.D3, Keys.D4, Keys.D5, Keys.D6, Keys.D7, Keys.D8, Keys.D9 };
250 
251 #if WINDOWS
252  [DllImport("user32.dll")]
253  static extern int GetSystemMetrics(int smIndex);
254  private const int SM_SWAPBUTTON = 23;
255 
256  public static bool MouseButtonsSwapped()
257  {
258  return GetSystemMetrics(SM_SWAPBUTTON) != 0;
259  }
260 #else
261  public static bool MouseButtonsSwapped()
262  {
263  return false; //TODO: implement on other platforms?
264  }
265 #endif
266 
267  public static readonly LocalizedString PrimaryMouseLabel = TextManager.Get($"Input.{(!MouseButtonsSwapped() ? "Left" : "Right")}Mouse");
268  public static readonly LocalizedString SecondaryMouseLabel = TextManager.Get($"Input.{(!MouseButtonsSwapped() ? "Right" : "Left")}Mouse");
269 
270  public static Vector2 MousePosition
271  {
272  get { return new Vector2(mouseState.Position.X, mouseState.Position.Y); }
273  }
274 
275  public static Vector2 LatestMousePosition
276  {
277  get { return new Vector2(latestMouseState.Position.X, latestMouseState.Position.Y); }
278  }
279 
280  public static bool MouseInsideWindow
281  {
282  get { return new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight).Contains(MousePosition); }
283  }
284 
285  public static Vector2 MouseSpeed
286  {
287  get
288  {
289  return AllowInput ? MousePosition - new Vector2(oldMouseState.X, oldMouseState.Y) : Vector2.Zero;
290  }
291  }
292 
293  private static bool AllowInput
294  {
295  get { return GameMain.WindowActive && allowInput; }
296  }
297 
298  public static Vector2 MouseSpeedPerSecond { get; private set; }
299 
300  public static KeyboardState GetKeyboardState
301  {
302  get { return keyboardState; }
303  }
304 
305  public static KeyboardState GetOldKeyboardState
306  {
307  get { return oldKeyboardState; }
308  }
309 
310  public static int ScrollWheelSpeed
311  {
312  get { return AllowInput ? mouseState.ScrollWheelValue - oldMouseState.ScrollWheelValue : 0; }
313 
314  }
315 
316  public static bool PrimaryMouseButtonHeld()
317  {
318  return AllowInput && mouseState.LeftButton == ButtonState.Pressed;
319  }
320 
321  public static bool PrimaryMouseButtonDown()
322  {
323  return AllowInput &&
324  oldMouseState.LeftButton == ButtonState.Released &&
325  mouseState.LeftButton == ButtonState.Pressed;
326  }
327 
328  public static bool PrimaryMouseButtonReleased()
329  {
330  return AllowInput && mouseState.LeftButton == ButtonState.Released;
331  }
332 
333 
334  public static bool PrimaryMouseButtonClicked()
335  {
336  return (AllowInput &&
337  oldMouseState.LeftButton == ButtonState.Pressed
338  && mouseState.LeftButton == ButtonState.Released);
339  }
340 
341  public static bool SecondaryMouseButtonHeld()
342  {
343  return AllowInput && mouseState.RightButton == ButtonState.Pressed;
344  }
345 
346  public static bool SecondaryMouseButtonDown()
347  {
348  return AllowInput &&
349  oldMouseState.RightButton == ButtonState.Released &&
350  mouseState.RightButton == ButtonState.Pressed;
351  }
352 
353  public static bool SecondaryMouseButtonReleased()
354  {
355  return AllowInput && mouseState.RightButton == ButtonState.Released;
356  }
357 
358  public static bool SecondaryMouseButtonClicked()
359  {
360  return (AllowInput &&
361  oldMouseState.RightButton == ButtonState.Pressed
362  && mouseState.RightButton == ButtonState.Released);
363  }
364 
365  public static bool MidButtonClicked()
366  {
367  return (AllowInput &&
368  oldMouseState.MiddleButton == ButtonState.Pressed
369  && mouseState.MiddleButton == ButtonState.Released);
370  }
371 
372  public static bool MidButtonHeld()
373  {
374  return AllowInput && mouseState.MiddleButton == ButtonState.Pressed;
375  }
376 
377  public static bool Mouse4ButtonClicked()
378  {
379  return (AllowInput &&
380  oldMouseState.XButton1 == ButtonState.Pressed
381  && mouseState.XButton1 == ButtonState.Released);
382  }
383 
384  public static bool Mouse4ButtonHeld()
385  {
386  return AllowInput && mouseState.XButton1 == ButtonState.Pressed;
387  }
388 
389  public static bool Mouse5ButtonClicked()
390  {
391  return (AllowInput &&
392  oldMouseState.XButton2 == ButtonState.Pressed
393  && mouseState.XButton2 == ButtonState.Released);
394  }
395 
396  public static bool Mouse5ButtonHeld()
397  {
398  return AllowInput && mouseState.XButton2 == ButtonState.Pressed;
399  }
400 
401  public static bool MouseWheelUpClicked()
402  {
403  return (AllowInput && ScrollWheelSpeed > 0);
404  }
405 
406  public static bool MouseWheelDownClicked()
407  {
408  return (AllowInput && ScrollWheelSpeed < 0);
409  }
410 
411  public static bool DoubleClicked()
412  {
413  return AllowInput && primaryDoubleClicked;
414  }
415 
416  public static bool SecondaryDoubleClicked()
417  {
418  return AllowInput && secondaryDoubleClicked;
419  }
420 
421  public static bool KeyHit(InputType inputType)
422  {
423  return AllowInput && GameSettings.CurrentConfig.KeyMap.Bindings[inputType].IsHit();
424  }
425 
426  public static bool KeyDown(InputType inputType)
427  {
428  return AllowInput && GameSettings.CurrentConfig.KeyMap.Bindings[inputType].IsDown();
429  }
430 
431  public static bool KeyUp(InputType inputType)
432  {
433  return AllowInput && !GameSettings.CurrentConfig.KeyMap.Bindings[inputType].IsDown();
434  }
435 
436  public static bool KeyHit(Keys button)
437  {
438  return AllowInput && oldKeyboardState.IsKeyUp(button) && keyboardState.IsKeyDown(button);
439  }
440 
441  public static bool InventoryKeyHit(int index)
442  {
443  if (index == -1) return false;
444  return AllowInput && GameSettings.CurrentConfig.InventoryKeyMap.Bindings[index].IsHit();
445  }
446 
447  public static bool KeyDown(Keys button)
448  {
449  return AllowInput && keyboardState.IsKeyDown(button);
450  }
451 
452  public static bool KeyUp(Keys button)
453  {
454  return AllowInput && keyboardState.IsKeyUp(button);
455  }
456 
457  public static bool IsShiftDown()
458  {
459  return KeyDown(Keys.LeftShift) || KeyDown(Keys.RightShift);
460  }
461 
462  public static bool IsCtrlDown()
463  {
464 #if !OSX
465  return KeyDown(Keys.LeftControl) || KeyDown(Keys.RightControl);
466 #else
467  return KeyDown(Keys.LeftWindows) || KeyDown(Keys.RightWindows);
468 #endif
469  }
470 
471  public static bool IsAltDown()
472  {
473  return KeyDown(Keys.LeftAlt) || KeyDown(Keys.RightAlt);
474  }
475 
476  public static void Update(double deltaTime)
477  {
478  timeSincePrimaryClick += deltaTime;
479  timeSinceSecondaryClick += deltaTime;
480 
481  if (!GameMain.WindowActive)
482  {
483  wasWindowActive = false;
484  return;
485  }
486 
487  //window was not active during the previous frame -> ignore inputs from this frame
488  if (!wasWindowActive)
489  {
490  wasWindowActive = true;
491  allowInput = false;
492  }
493  else
494  {
495  allowInput = true;
496  }
497 
498  GameMain.LuaCs.Hook.Call("keyUpdate", deltaTime);
499 
500  oldMouseState = mouseState;
501  mouseState = latestMouseState;
502  UpdateVariable();
503 
504  oldKeyboardState = keyboardState;
505  keyboardState = Keyboard.GetState();
506 
507  MouseSpeedPerSecond = MouseSpeed / (float)deltaTime;
508 
509  // Split into two to not accept drag & drop releasing as part of a double-click
510  primaryDoubleClicked = false;
512  {
513  primaryDoubleClicked = UpdateDoubleClicking(ref lastPrimaryClickPosition, ref timeSincePrimaryClick);
514  }
515 
517  {
518  lastPrimaryClickPosition = mouseState.Position;
519  }
520 
521  secondaryDoubleClicked = false;
523  {
524  secondaryDoubleClicked = UpdateDoubleClicking(ref lastSecondaryClickPosition, ref timeSinceSecondaryClick);
525  }
526 
528  {
529  lastSecondaryClickPosition = mouseState.Position;
530  }
531 
532  bool UpdateDoubleClicking(ref Point lastClickPosition, ref double timeSinceClick)
533  {
534  bool doubleClicked = false;
535  float dist = (mouseState.Position - lastClickPosition).ToVector2().Length();
536 
537  if (timeSinceClick < DoubleClickDelay && dist < MaxDoubleClickDistance)
538  {
539  doubleClicked = true;
540  timeSinceClick = DoubleClickDelay;
541  }
542  else if (timeSinceClick < DoubleClickDelay)
543  {
544  lastClickPosition = mouseState.Position;
545  }
546  if (!doubleClicked && dist < MaxDoubleClickDistance)
547  {
548  timeSinceClick = 0.0;
549  }
550 
551  return doubleClicked;
552  }
553  }
554 
555  public static void UpdateVariable()
556  {
557  //do NOT use this for actual interaction with the game, this is to be used for debugging and rendering ONLY
558 
559  latestMouseState = Mouse.GetState();
560  }
561  }
562 }
static int GraphicsWidth
Definition: GameMain.cs:162
static int GraphicsHeight
Definition: GameMain.cs:168
static bool WindowActive
Definition: GameMain.cs:174
static LuaCsSetup LuaCs
Definition: GameMain.cs:26
static bool operator==(KeyOrMouse a, KeyOrMouse b)
static bool operator!=(KeyOrMouse a, KeyOrMouse b)
object Call(string name, params object[] args)
static readonly LocalizedString PrimaryMouseLabel
static readonly LocalizedString SecondaryMouseLabel
static bool KeyDown(InputType inputType)