diff --git a/src/Input/Axis.cs b/src/Input/Axis.cs index acef4a06..3fba7bca 100644 --- a/src/Input/Axis.cs +++ b/src/Input/Axis.cs @@ -1,15 +1,38 @@ +using System; +using MoonWorks.Math; +using SDL2; + namespace MoonWorks.Input { public class Axis { + IntPtr GamepadHandle; + SDL.SDL_GameControllerAxis SDL_Axis; + + public AxisCode Code { get; private set; } + /// /// An axis value between -1 and 1. /// public float Value { get; private set; } - internal void Update(float value) + public Axis( + IntPtr gamepadHandle, + AxisCode code, + SDL.SDL_GameControllerAxis sdlAxis + ) { + GamepadHandle = gamepadHandle; + SDL_Axis = sdlAxis; + Code = code; + } + + internal void Update() { - Value = value; + Value = MathHelper.Normalize( + SDL.SDL_GameControllerGetAxis(GamepadHandle, SDL_Axis), + short.MinValue, short.MaxValue, + -1, 1 + ); } } } diff --git a/src/Input/AxisButtonCode.cs b/src/Input/AxisButtonCode.cs new file mode 100644 index 00000000..cd8c92c9 --- /dev/null +++ b/src/Input/AxisButtonCode.cs @@ -0,0 +1,14 @@ +namespace MoonWorks.Input +{ + public enum AxisButtonCode + { + LeftX_Left, + LeftX_Right, + LeftY_Up, + LeftY_Down, + RightX_Left, + RightX_Right, + RightY_Up, + RightY_Down + } +} diff --git a/src/Input/ButtonCode.cs b/src/Input/ButtonCode.cs index c28b9aff..d6070815 100644 --- a/src/Input/ButtonCode.cs +++ b/src/Input/ButtonCode.cs @@ -1,7 +1,7 @@ namespace MoonWorks.Input { // Enum values are equivalent to the SDL GameControllerButton value. - public enum ButtonCode + public enum GamepadButtonCode { A, B, diff --git a/src/Input/ButtonIdentifier.cs b/src/Input/ButtonIdentifier.cs deleted file mode 100644 index 7a31922f..00000000 --- a/src/Input/ButtonIdentifier.cs +++ /dev/null @@ -1,59 +0,0 @@ -namespace MoonWorks.Input -{ - // Blittable identifier that can be used for button state lookups. - public struct ButtonIdentifier : System.IEquatable - { - public DeviceKind DeviceKind { get; } - public int Index { get; } // 1-4 for gamepads, 0 otherwise - public int Code { get; } - - public ButtonIdentifier(Gamepad gamepad, ButtonCode buttonCode) - { - DeviceKind = DeviceKind.Gamepad; - Index = gamepad.Index; - Code = (int) buttonCode; - } - - public ButtonIdentifier(KeyCode keyCode) - { - DeviceKind = DeviceKind.Keyboard; - Index = 0; - Code = (int) keyCode; - } - - public ButtonIdentifier(MouseButtonCode mouseCode) - { - DeviceKind = DeviceKind.Mouse; - 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/ButtonState.cs b/src/Input/ButtonState.cs index 270f6b9a..0d137436 100644 --- a/src/Input/ButtonState.cs +++ b/src/Input/ButtonState.cs @@ -9,7 +9,7 @@ public bool IsDown => ButtonStatus == ButtonStatus.Pressed || ButtonStatus == ButtonStatus.Held; public bool IsReleased => ButtonStatus == ButtonStatus.Released; - public ButtonState(ButtonStatus buttonStatus) + internal ButtonState(ButtonStatus buttonStatus) { ButtonStatus = buttonStatus; } diff --git a/src/Input/Gamepad.cs b/src/Input/Gamepad.cs index 16a8e6c2..4e432e7e 100644 --- a/src/Input/Gamepad.cs +++ b/src/Input/Gamepad.cs @@ -10,39 +10,57 @@ namespace MoonWorks.Input internal IntPtr Handle; internal int Index; - public Button A { get; } = new Button(); - public Button B { get; } = new Button(); - public Button X { get; } = new Button(); - public Button Y { get; } = new Button(); - public Button Back { get; } = new Button(); - public Button Guide { get; } = new Button(); - public Button Start { get; } = new Button(); - public Button LeftStick { get; } = new Button(); - public Button RightStick { get; } = new Button(); - public Button LeftShoulder { get; } = new Button(); - public Button RightShoulder { get; } = new Button(); - public Button DpadUp { get; } = new Button(); - public Button DpadDown { get; } = new Button(); - public Button DpadLeft { get; } = new Button(); - public Button DpadRight { get; } = new Button(); + public GamepadButton A { get; } + public GamepadButton B { get; } + public GamepadButton X { get; } + public GamepadButton Y { get; } + public GamepadButton Back { get; } + public GamepadButton Guide { get; } + public GamepadButton Start { get; } + public GamepadButton LeftStick { get; } + public GamepadButton RightStick { get; } + public GamepadButton LeftShoulder { get; } + public GamepadButton RightShoulder { get; } + public GamepadButton DpadUp { get; } + public GamepadButton DpadDown { get; } + public GamepadButton DpadLeft { get; } + public GamepadButton DpadRight { get; } - public Axis LeftX { get; } = new Axis(); - public Axis LeftY { get; } = new Axis(); - public Axis RightX { get; } = new Axis(); - public Axis RightY { get; } = new Axis(); + public Axis LeftX { get; } + public Axis LeftY { get; } + public Axis RightX { get; } + public Axis RightY { get; } - public Trigger TriggerLeft { get; } = new Trigger(); - public Trigger TriggerRight { get; } = new Trigger(); + public AxisButton LeftXLeft { get; } + public AxisButton LeftXRight { get; } + public AxisButton LeftYUp { get; } + public AxisButton LeftYDown { get; } + + public AxisButton RightXLeft { get; } + public AxisButton RightXRight { get; } + public AxisButton RightYUp { get; } + public AxisButton RightYDown { get; } + + public Trigger TriggerLeft { get; } + public Trigger TriggerRight { get; } + + public TriggerButton TriggerLeftButton { get; } + public TriggerButton TriggerRightButton { get; } public bool IsDummy => Handle == IntPtr.Zero; public bool AnyPressed { get; private set; } - public ButtonCode AnyPressedButtonCode { get; private set; } + public VirtualButton AnyPressedButton { get; private set; } - private Dictionary EnumToButton; + private Dictionary EnumToButton; private Dictionary EnumToAxis; private Dictionary EnumToTrigger; + private Dictionary AxisButtonCodeToAxisButton; + private Dictionary TriggerCodeToTriggerButton; + + private VirtualButton[] VirtualButtons; + internal Gamepad(IntPtr handle, int index) { Handle = handle; @@ -50,7 +68,48 @@ namespace MoonWorks.Input AnyPressed = false; - EnumToButton = new Dictionary + A = new GamepadButton(handle, GamepadButtonCode.A, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_A); + B = new GamepadButton(handle, GamepadButtonCode.B, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_B); + X = new GamepadButton(handle, GamepadButtonCode.X, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_X); + Y = new GamepadButton(handle, GamepadButtonCode.Y, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_Y); + + Back = new GamepadButton(handle, GamepadButtonCode.Back, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_BACK); + Guide = new GamepadButton(handle, GamepadButtonCode.Guide, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_GUIDE); + Start = new GamepadButton(handle, GamepadButtonCode.Start, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_START); + + LeftStick = new GamepadButton(handle, GamepadButtonCode.LeftStick, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSTICK); + RightStick = new GamepadButton(handle, GamepadButtonCode.RightStick, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSTICK); + + LeftShoulder = new GamepadButton(handle, GamepadButtonCode.LeftShoulder, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSHOULDER); + RightShoulder = new GamepadButton(handle, GamepadButtonCode.RightShoulder, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); + + DpadUp = new GamepadButton(handle, GamepadButtonCode.DpadUp, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_UP); + DpadDown = new GamepadButton(handle, GamepadButtonCode.DpadDown, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_DOWN); + DpadLeft = new GamepadButton(handle, GamepadButtonCode.DpadLeft, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_LEFT); + DpadRight = new GamepadButton(handle, GamepadButtonCode.DpadRight, SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_RIGHT); + + LeftX = new Axis(handle, AxisCode.LeftX, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTX); + LeftY = new Axis(handle, AxisCode.LeftY, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_LEFTY); + RightX = new Axis(handle, AxisCode.RightX, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_RIGHTX); + RightY = new Axis(handle, AxisCode.RightY, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_RIGHTY); + + LeftXLeft = new AxisButton(LeftX, false); + LeftXRight = new AxisButton(LeftX, true); + LeftYUp = new AxisButton(LeftY, false); + LeftYDown = new AxisButton(LeftY, true); + + RightXLeft = new AxisButton(RightX, false); + RightXRight = new AxisButton(RightX, true); + RightYUp = new AxisButton(RightY, false); + RightYDown = new AxisButton(RightY, true); + + TriggerLeft = new Trigger(handle, TriggerCode.Left, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERLEFT); + TriggerRight = new Trigger(handle, TriggerCode.Right, SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERRIGHT); + + TriggerLeftButton = new TriggerButton(TriggerLeft); + TriggerRightButton = new TriggerButton(TriggerRight); + + EnumToButton = new Dictionary { { SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_A, A }, { SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_B, B }, @@ -82,6 +141,47 @@ namespace MoonWorks.Input { SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERLEFT, TriggerLeft }, { SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERRIGHT, TriggerRight } }; + + AxisButtonCodeToAxisButton = new Dictionary + { + { AxisButtonCode.LeftX_Left, LeftXLeft }, + { AxisButtonCode.LeftX_Right, LeftXRight }, + { AxisButtonCode.LeftY_Down, LeftYDown }, + { AxisButtonCode.LeftY_Up, LeftYUp }, + { AxisButtonCode.RightX_Left, RightXLeft }, + { AxisButtonCode.RightX_Right, RightXRight }, + { AxisButtonCode.RightY_Up, RightYUp }, + { AxisButtonCode.RightY_Down, RightYDown } + }; + + VirtualButtons = new VirtualButton[] + { + A, + B, + X, + Y, + Back, + Guide, + Start, + LeftStick, + RightStick, + LeftShoulder, + RightShoulder, + DpadUp, + DpadDown, + DpadLeft, + DpadRight, + LeftXLeft, + LeftXRight, + LeftYUp, + LeftYDown, + RightXLeft, + RightXRight, + RightYUp, + RightYDown, + TriggerLeftButton, + TriggerRightButton + }; } internal void Update() @@ -90,31 +190,42 @@ namespace MoonWorks.Input if (!IsDummy) { - foreach (var (sdlEnum, button) in EnumToButton) + foreach (var button in EnumToButton.Values) { - var pressed = CheckPressed(sdlEnum); - button.Update(pressed); + button.Update(); + } + foreach (var axis in EnumToAxis.Values) + { + axis.Update(); + } + + foreach (var trigger in EnumToTrigger.Values) + { + trigger.Update(); + } + + LeftXLeft.Update(); + LeftXRight.Update(); + LeftYUp.Update(); + LeftYDown.Update(); + RightXLeft.Update(); + RightXRight.Update(); + RightYUp.Update(); + RightYDown.Update(); + + TriggerLeftButton.Update(); + TriggerRightButton.Update(); + + foreach (var button in VirtualButtons) + { if (button.IsPressed) { AnyPressed = true; - AnyPressedButtonCode = (ButtonCode) sdlEnum; + AnyPressedButton = button; + break; } } - - foreach (var (sdlEnum, axis) in EnumToAxis) - { - var sdlAxisValue = SDL.SDL_GameControllerGetAxis(Handle, sdlEnum); - var axisValue = MathHelper.Normalize(sdlAxisValue, short.MinValue, short.MaxValue, -1, 1); - axis.Update(axisValue); - } - - foreach (var (sdlEnum, trigger) in EnumToTrigger) - { - var sdlAxisValue = SDL.SDL_GameControllerGetAxis(Handle, sdlEnum); - var axisValue = MathHelper.Normalize(sdlAxisValue, 0, short.MaxValue, 0, 1); - trigger.Update(axisValue); - } } } @@ -131,44 +242,19 @@ namespace MoonWorks.Input ) == 0; } - /// - /// True if the button is pressed or held. - /// - public bool IsDown(ButtonCode buttonCode) + public GamepadButton Button(GamepadButtonCode buttonCode) { - return EnumToButton[(SDL.SDL_GameControllerButton) buttonCode].IsDown; + return EnumToButton[(SDL.SDL_GameControllerButton) buttonCode]; } - /// - /// True if the button was pressed this exact frame. - /// - public bool IsPressed(ButtonCode buttonCode) + public AxisButton Button(AxisButtonCode axisButtonCode) { - return EnumToButton[(SDL.SDL_GameControllerButton) buttonCode].IsPressed; + return AxisButtonCodeToAxisButton[axisButtonCode]; } - /// - /// True if the button has been continuously held for more than one frame. - /// - public bool IsHeld(ButtonCode buttonCode) + public TriggerButton Button(TriggerCode triggerCode) { - return EnumToButton[(SDL.SDL_GameControllerButton) buttonCode].IsHeld; - } - - /// - /// True if the button is not pressed. - /// - public bool IsReleased(ButtonCode buttonCode) - { - return EnumToButton[(SDL.SDL_GameControllerButton) buttonCode].IsReleased; - } - - /// - /// Obtains the button state given a ButtonCode. - /// - public ButtonState ButtonState(ButtonCode buttonCode) - { - return EnumToButton[(SDL.SDL_GameControllerButton) buttonCode].State; + return TriggerCodeToTriggerButton[triggerCode]; } /// diff --git a/src/Input/Input.cs b/src/Input/Input.cs index c41178fb..739a641f 100644 --- a/src/Input/Input.cs +++ b/src/Input/Input.cs @@ -15,7 +15,7 @@ namespace MoonWorks.Input public static event Action TextInput; public bool AnyPressed { get; private set; } - public ButtonIdentifier AnyPressedButton { get; private set; } + public VirtualButton AnyPressedButton { get; private set; } internal Inputs() { @@ -49,7 +49,7 @@ namespace MoonWorks.Input if (Keyboard.AnyPressed) { AnyPressed = true; - AnyPressedButton = new ButtonIdentifier(Keyboard.AnyPressedKeyCode); + AnyPressedButton = Keyboard.AnyPressedButton; } Mouse.Update(); @@ -57,7 +57,7 @@ namespace MoonWorks.Input if (Mouse.AnyPressed) { AnyPressed = true; - AnyPressedButton = new ButtonIdentifier(Mouse.AnyPressedButtonCode); + AnyPressedButton = Mouse.AnyPressedButton; } foreach (var gamepad in gamepads) @@ -67,7 +67,7 @@ namespace MoonWorks.Input if (gamepad.AnyPressed) { AnyPressed = true; - AnyPressedButton = new ButtonIdentifier(gamepad, gamepad.AnyPressedButtonCode); + AnyPressedButton = gamepad.AnyPressedButton; } } } @@ -82,31 +82,6 @@ namespace MoonWorks.Input return gamepads[slot]; } - public ButtonState ButtonState(ButtonIdentifier identifier) - { - if (identifier.DeviceKind == DeviceKind.Gamepad) - { - var gamepad = GetGamepad(identifier.Index); - return gamepad.ButtonState((ButtonCode) identifier.Code); - } - else if (identifier.DeviceKind == DeviceKind.Keyboard) - { - return Keyboard.ButtonState((KeyCode) identifier.Code); - } - else if (identifier.DeviceKind == DeviceKind.Mouse) - { - 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!"); - } - } - internal static void OnTextInput(char c) { if (TextInput != null) diff --git a/src/Input/Keyboard.cs b/src/Input/Keyboard.cs index 1c31a7dc..ac660186 100644 --- a/src/Input/Keyboard.cs +++ b/src/Input/Keyboard.cs @@ -8,9 +8,11 @@ namespace MoonWorks.Input public class Keyboard { public bool AnyPressed { get; private set; } - public KeyCode AnyPressedKeyCode { get; private set; } + public KeyboardButton AnyPressedButton { get; private set; } - private Button[] Keys { get; } + public IntPtr State { get; private set; } + + private KeyboardButton[] Keys { get; } private int numKeys; private static readonly char[] TextInputCharacters = new char[] @@ -39,10 +41,10 @@ namespace MoonWorks.Input { SDL.SDL_GetKeyboardState(out numKeys); - Keys = new Button[numKeys]; + Keys = new KeyboardButton[numKeys]; foreach (KeyCode keycode in Enum.GetValues(typeof(KeyCode))) { - Keys[(int) keycode] = new Button(); + Keys[(int) keycode] = new KeyboardButton(this, keycode); } } @@ -50,14 +52,14 @@ namespace MoonWorks.Input { AnyPressed = false; - IntPtr keyboardState = SDL.SDL_GetKeyboardState(out _); + State = SDL.SDL_GetKeyboardState(out _); foreach (int keycode in Enum.GetValues(typeof(KeyCode))) { - var keyDown = Conversions.ByteToBool(Marshal.ReadByte(keyboardState, keycode)); - Keys[keycode].Update(keyDown); + var button = Keys[keycode]; + button.Update(); - if (keyDown) + if (button.IsPressed) { if (TextInputBindings.TryGetValue((KeyCode) keycode, out var textIndex)) { @@ -67,12 +69,9 @@ namespace MoonWorks.Input { Inputs.OnTextInput(TextInputCharacters[6]); } - } - if (Keys[keycode].IsPressed) - { AnyPressed = true; - AnyPressedKeyCode = (KeyCode) keycode; + AnyPressedButton = button; } } } @@ -97,7 +96,7 @@ namespace MoonWorks.Input return Keys[(int) keycode].IsReleased; } - public Button Button(KeyCode keycode) + public KeyboardButton Button(KeyCode keycode) { return Keys[(int) keycode]; } diff --git a/src/Input/Mouse.cs b/src/Input/Mouse.cs index ea803e31..3ee65bc9 100644 --- a/src/Input/Mouse.cs +++ b/src/Input/Mouse.cs @@ -5,9 +5,9 @@ namespace MoonWorks.Input { public class Mouse { - public Button LeftButton { get; } = new Button(); - public Button MiddleButton { get; } = new Button(); - public Button RightButton { get; } = new Button(); + public MouseButton LeftButton { get; } + public MouseButton MiddleButton { get; } + public MouseButton RightButton { get; } public int X { get; private set; } public int Y { get; private set; } @@ -17,7 +17,9 @@ namespace MoonWorks.Input public int Wheel { get; internal set; } public bool AnyPressed { get; private set; } - public MouseButtonCode AnyPressedButtonCode { get; private set; } + public MouseButton AnyPressedButton { get; private set; } + + public uint ButtonMask { get; private set; } private bool relativeMode; public bool RelativeMode @@ -34,31 +36,37 @@ namespace MoonWorks.Input } } - private readonly Dictionary CodeToButton; - private readonly Dictionary MaskToButtonCode; + private readonly Dictionary CodeToButton; + + private IEnumerable Buttons + { + get + { + yield return LeftButton; + yield return MiddleButton; + yield return RightButton; + } + } public Mouse() { - CodeToButton = new Dictionary + LeftButton = new MouseButton(this, MouseButtonCode.Left, SDL.SDL_BUTTON_LMASK); + MiddleButton = new MouseButton(this, MouseButtonCode.Middle, SDL.SDL_BUTTON_MMASK); + RightButton = new MouseButton(this, MouseButtonCode.Right, SDL.SDL_BUTTON_RMASK); + + CodeToButton = new Dictionary { { MouseButtonCode.Left, LeftButton }, { 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); + ButtonMask = SDL.SDL_GetMouseState(out var x, out var y); var _ = SDL.SDL_GetRelativeMouseState(out var deltaX, out var deltaY); X = x; @@ -66,16 +74,18 @@ namespace MoonWorks.Input DeltaX = deltaX; DeltaY = deltaY; - foreach (var (mask, buttonCode) in MaskToButtonCode) + LeftButton.Update(); + MiddleButton.Update(); + RightButton.Update(); + + foreach (var button in Buttons) { - var pressed = IsPressed(buttonMask, mask); - var button = CodeToButton[buttonCode]; - button.Update(pressed); + button.Update(); if (button.IsPressed) { AnyPressed = true; - AnyPressedButtonCode = buttonCode; + AnyPressedButton = button; } } } @@ -84,10 +94,5 @@ namespace MoonWorks.Input { return CodeToButton[buttonCode].State; } - - private bool IsPressed(uint buttonMask, uint buttonFlag) - { - return (buttonMask & buttonFlag) != 0; - } } } diff --git a/src/Input/Trigger.cs b/src/Input/Trigger.cs index 58b151d9..4a8c826b 100644 --- a/src/Input/Trigger.cs +++ b/src/Input/Trigger.cs @@ -1,15 +1,38 @@ +using System; +using MoonWorks.Math; +using SDL2; + namespace MoonWorks.Input { public class Trigger { + public IntPtr GamepadHandle; + public SDL.SDL_GameControllerAxis SDL_Axis; + + public TriggerCode Code { get; } + /// /// A trigger value between 0 and 1. /// public float Value { get; private set; } - internal void Update(float value) + public Trigger( + IntPtr gamepadHandle, + TriggerCode code, + SDL.SDL_GameControllerAxis sdlAxis + ) { + GamepadHandle = gamepadHandle; + Code = code; + SDL_Axis = sdlAxis; + } + + internal void Update() { - Value = value; + Value = MathHelper.Normalize( + SDL.SDL_GameControllerGetAxis(GamepadHandle, SDL_Axis), + 0, short.MaxValue, + 0, 1 + ); } } } diff --git a/src/Input/Button.cs b/src/Input/VirtualButton.cs similarity index 73% rename from src/Input/Button.cs rename to src/Input/VirtualButton.cs index 7826d07b..4f9efc25 100644 --- a/src/Input/Button.cs +++ b/src/Input/VirtualButton.cs @@ -1,8 +1,8 @@ namespace MoonWorks.Input { - public class Button + public abstract class VirtualButton { - public ButtonState State { get; private set; } + public ButtonState State { get; protected set; } /// /// True if the button is pressed or held. @@ -24,9 +24,11 @@ namespace MoonWorks.Input /// public bool IsReleased => State.IsReleased; - internal void Update(bool isPressed) + internal virtual void Update() { - State = State.Update(isPressed); + State = State.Update(CheckPressed()); } + + internal abstract bool CheckPressed(); } } diff --git a/src/Input/VirtualButtons/AxisButton.cs b/src/Input/VirtualButtons/AxisButton.cs new file mode 100644 index 00000000..92e244a7 --- /dev/null +++ b/src/Input/VirtualButtons/AxisButton.cs @@ -0,0 +1,73 @@ +namespace MoonWorks.Input +{ + public class AxisButton : VirtualButton + { + public Axis Parent { get; } + public AxisButtonCode Code { get; } + + private float threshold = 0.9f; + public float Threshold + { + get => threshold; + set => threshold = System.Math.Clamp(value, 0, 1); + } + + private int Sign; + + internal AxisButton(Axis parent, bool positive) + { + Parent = parent; + Sign = positive ? 1 : -1; + + if (parent.Code == AxisCode.LeftX) + { + if (positive) + { + Code = AxisButtonCode.LeftX_Right; + } + else + { + Code = AxisButtonCode.LeftX_Left; + } + } + else if (parent.Code == AxisCode.LeftY) + { + if (positive) + { + Code = AxisButtonCode.LeftY_Up; + } + else + { + Code = AxisButtonCode.LeftY_Down; + } + } + else if (parent.Code == AxisCode.RightX) + { + if (positive) + { + Code = AxisButtonCode.RightX_Right; + } + else + { + Code = AxisButtonCode.RightX_Left; + } + } + else if (parent.Code == AxisCode.RightY) + { + if (positive) + { + Code = AxisButtonCode.RightY_Up; + } + else + { + Code = AxisButtonCode.RightY_Down; + } + } + } + + internal override bool CheckPressed() + { + return Sign * Parent.Value >= threshold; + } + } +} diff --git a/src/Input/VirtualButtons/GamepadButton.cs b/src/Input/VirtualButtons/GamepadButton.cs new file mode 100644 index 00000000..344ee5b4 --- /dev/null +++ b/src/Input/VirtualButtons/GamepadButton.cs @@ -0,0 +1,25 @@ +using System; +using SDL2; + +namespace MoonWorks.Input +{ + public class GamepadButton : VirtualButton + { + IntPtr GamepadHandle; + SDL.SDL_GameControllerButton SDL_Button; + + public GamepadButtonCode Code { get; private set; } + + internal GamepadButton(IntPtr gamepadHandle, GamepadButtonCode code, SDL.SDL_GameControllerButton sdlButton) + { + GamepadHandle = gamepadHandle; + Code = code; + SDL_Button = sdlButton; + } + + internal override bool CheckPressed() + { + return MoonWorks.Conversions.ByteToBool(SDL.SDL_GameControllerGetButton(GamepadHandle, SDL_Button)); + } + } +} diff --git a/src/Input/VirtualButtons/KeyboardButton.cs b/src/Input/VirtualButtons/KeyboardButton.cs new file mode 100644 index 00000000..733ee77d --- /dev/null +++ b/src/Input/VirtualButtons/KeyboardButton.cs @@ -0,0 +1,21 @@ +using System.Runtime.InteropServices; + +namespace MoonWorks.Input +{ + public class KeyboardButton : VirtualButton + { + Keyboard Parent; + KeyCode KeyCode; + + internal KeyboardButton(Keyboard parent, KeyCode keyCode) + { + Parent = parent; + KeyCode = keyCode; + } + + internal override bool CheckPressed() + { + return Conversions.ByteToBool(Marshal.ReadByte(Parent.State, (int) KeyCode)); + } + } +} diff --git a/src/Input/VirtualButtons/MouseButton.cs b/src/Input/VirtualButtons/MouseButton.cs new file mode 100644 index 00000000..4637114d --- /dev/null +++ b/src/Input/VirtualButtons/MouseButton.cs @@ -0,0 +1,22 @@ +namespace MoonWorks.Input +{ + public class MouseButton : VirtualButton + { + Mouse Parent; + uint ButtonMask; + + public MouseButtonCode Code { get; private set; } + + internal MouseButton(Mouse parent, MouseButtonCode code, uint buttonMask) + { + Parent = parent; + Code = code; + ButtonMask = buttonMask; + } + + internal override bool CheckPressed() + { + return (Parent.ButtonMask & ButtonMask) != 0; + } + } +} diff --git a/src/Input/VirtualButtons/TriggerButton.cs b/src/Input/VirtualButtons/TriggerButton.cs new file mode 100644 index 00000000..f0a93cb4 --- /dev/null +++ b/src/Input/VirtualButtons/TriggerButton.cs @@ -0,0 +1,25 @@ +namespace MoonWorks.Input +{ + public class TriggerButton : VirtualButton + { + public Trigger Parent { get; } + public TriggerCode Code => Parent.Code; + + private float threshold = 0.7f; + public float Threshold + { + get => threshold; + set => threshold = System.Math.Clamp(value, 0, 1); + } + + internal TriggerButton(Trigger parent) + { + Parent = parent; + } + + internal override bool CheckPressed() + { + return Parent.Value >= Threshold; + } + } +}