diff --git a/src/Input/ButtonIdentifier.cs b/src/Input/ButtonIdentifier.cs index a1388d3b..7a31922f 100644 --- a/src/Input/ButtonIdentifier.cs +++ b/src/Input/ButtonIdentifier.cs @@ -1,7 +1,7 @@ namespace MoonWorks.Input { // Blittable identifier that can be used for button state lookups. - public struct ButtonIdentifier + public struct ButtonIdentifier : System.IEquatable { public DeviceKind DeviceKind { get; } public int Index { get; } // 1-4 for gamepads, 0 otherwise @@ -27,5 +27,33 @@ namespace MoonWorks.Input Index = 0; Code = (int) mouseCode; } + + public override int GetHashCode() + { + return System.HashCode.Combine(DeviceKind, Index, Code); + } + + public override bool Equals(object obj) + { + return obj is ButtonIdentifier identifier && Equals(identifier); + } + + public bool Equals(ButtonIdentifier identifier) + { + return + DeviceKind == identifier.DeviceKind && + Index == identifier.Index && + Code == identifier.Code; + } + + public static bool operator ==(ButtonIdentifier a, ButtonIdentifier b) + { + return a.Equals(b); + } + + public static bool operator !=(ButtonIdentifier a, ButtonIdentifier b) + { + return !(a == b); + } } } diff --git a/src/Input/DeviceKind.cs b/src/Input/DeviceKind.cs index 58b14b49..1663788a 100644 --- a/src/Input/DeviceKind.cs +++ b/src/Input/DeviceKind.cs @@ -2,8 +2,9 @@ namespace MoonWorks.Input { public enum DeviceKind { + None, Keyboard, Mouse, - Gamepad + Gamepad, } } diff --git a/src/Input/Gamepad.cs b/src/Input/Gamepad.cs index d771e13d..16a8e6c2 100644 --- a/src/Input/Gamepad.cs +++ b/src/Input/Gamepad.cs @@ -36,6 +36,9 @@ namespace MoonWorks.Input public bool IsDummy => Handle == IntPtr.Zero; + public bool AnyPressed { get; private set; } + public ButtonCode AnyPressedButtonCode { get; private set; } + private Dictionary EnumToButton; private Dictionary EnumToAxis; private Dictionary EnumToTrigger; @@ -45,6 +48,8 @@ namespace MoonWorks.Input Handle = handle; Index = index; + AnyPressed = false; + EnumToButton = new Dictionary { { SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_A, A }, @@ -81,11 +86,20 @@ namespace MoonWorks.Input internal void Update() { + AnyPressed = false; + if (!IsDummy) { foreach (var (sdlEnum, button) in EnumToButton) { - button.Update(CheckPressed(sdlEnum)); + var pressed = CheckPressed(sdlEnum); + button.Update(pressed); + + if (button.IsPressed) + { + AnyPressed = true; + AnyPressedButtonCode = (ButtonCode) sdlEnum; + } } foreach (var (sdlEnum, axis) in EnumToAxis) diff --git a/src/Input/Input.cs b/src/Input/Input.cs index 700d4b01..608bc768 100644 --- a/src/Input/Input.cs +++ b/src/Input/Input.cs @@ -14,6 +14,9 @@ namespace MoonWorks.Input public static event Action TextInput; + public bool AnyPressed { get; private set; } + public ButtonIdentifier AnyPressedButton { get; private set; } + internal Inputs() { Keyboard = new Keyboard(); @@ -37,13 +40,34 @@ namespace MoonWorks.Input // Assumes that SDL_PumpEvents has been called! internal void Update() { + AnyPressed = false; + Mouse.Wheel = 0; Keyboard.Update(); + + if (Keyboard.AnyPressed) + { + AnyPressed = true; + AnyPressedButton = new ButtonIdentifier(Keyboard.AnyPressedKeyCode); + } + Mouse.Update(); + if (Mouse.AnyPressed) + { + AnyPressed = true; + AnyPressedButton = new ButtonIdentifier(Mouse.AnyPressedButtonCode); + } + foreach (var gamepad in gamepads) { gamepad.Update(); + + if (gamepad.AnyPressed) + { + AnyPressed = true; + AnyPressedButton = new ButtonIdentifier(gamepad, gamepad.AnyPressedButtonCode); + } } } @@ -72,6 +96,10 @@ namespace MoonWorks.Input { return Mouse.ButtonState((MouseButtonCode) identifier.Code); } + else if (identifier.DeviceKind == DeviceKind.None) + { + return new ButtonState(ButtonStatus.Released); + } else { throw new System.ArgumentException("Invalid button identifier!"); diff --git a/src/Input/Keyboard.cs b/src/Input/Keyboard.cs index b1acdc78..1c31a7dc 100644 --- a/src/Input/Keyboard.cs +++ b/src/Input/Keyboard.cs @@ -7,6 +7,9 @@ namespace MoonWorks.Input { public class Keyboard { + public bool AnyPressed { get; private set; } + public KeyCode AnyPressedKeyCode { get; private set; } + private Button[] Keys { get; } private int numKeys; @@ -45,14 +48,16 @@ namespace MoonWorks.Input internal void Update() { + AnyPressed = false; + IntPtr keyboardState = SDL.SDL_GetKeyboardState(out _); foreach (int keycode in Enum.GetValues(typeof(KeyCode))) { - var keyDown = Marshal.ReadByte(keyboardState, keycode); - Keys[keycode].Update(Conversions.ByteToBool(keyDown)); + var keyDown = Conversions.ByteToBool(Marshal.ReadByte(keyboardState, keycode)); + Keys[keycode].Update(keyDown); - if (Conversions.ByteToBool(keyDown)) + if (keyDown) { if (TextInputBindings.TryGetValue((KeyCode) keycode, out var textIndex)) { @@ -63,6 +68,12 @@ namespace MoonWorks.Input Inputs.OnTextInput(TextInputCharacters[6]); } } + + if (Keys[keycode].IsPressed) + { + AnyPressed = true; + AnyPressedKeyCode = (KeyCode) keycode; + } } } diff --git a/src/Input/Mouse.cs b/src/Input/Mouse.cs index 766b9561..ea803e31 100644 --- a/src/Input/Mouse.cs +++ b/src/Input/Mouse.cs @@ -16,6 +16,9 @@ namespace MoonWorks.Input public int Wheel { get; internal set; } + public bool AnyPressed { get; private set; } + public MouseButtonCode AnyPressedButtonCode { get; private set; } + private bool relativeMode; public bool RelativeMode { @@ -32,6 +35,7 @@ namespace MoonWorks.Input } private readonly Dictionary CodeToButton; + private readonly Dictionary MaskToButtonCode; public Mouse() { @@ -41,10 +45,19 @@ namespace MoonWorks.Input { MouseButtonCode.Right, RightButton }, { MouseButtonCode.Middle, MiddleButton } }; + + MaskToButtonCode = new Dictionary + { + { SDL.SDL_BUTTON_LMASK, MouseButtonCode.Left }, + { SDL.SDL_BUTTON_MMASK, MouseButtonCode.Middle }, + { SDL.SDL_BUTTON_RMASK, MouseButtonCode.Right } + }; } internal void Update() { + AnyPressed = false; + var buttonMask = SDL.SDL_GetMouseState(out var x, out var y); var _ = SDL.SDL_GetRelativeMouseState(out var deltaX, out var deltaY); @@ -53,9 +66,18 @@ namespace MoonWorks.Input DeltaX = deltaX; DeltaY = deltaY; - LeftButton.Update(IsPressed(buttonMask, SDL.SDL_BUTTON_LMASK)); - MiddleButton.Update(IsPressed(buttonMask, SDL.SDL_BUTTON_MMASK)); - RightButton.Update(IsPressed(buttonMask, SDL.SDL_BUTTON_RMASK)); + foreach (var (mask, buttonCode) in MaskToButtonCode) + { + var pressed = IsPressed(buttonMask, mask); + var button = CodeToButton[buttonCode]; + button.Update(pressed); + + if (button.IsPressed) + { + AnyPressed = true; + AnyPressedButtonCode = buttonCode; + } + } } public ButtonState ButtonState(MouseButtonCode buttonCode)