forked from MoonsideGames/MoonWorks
VirtualButton system
parent
3543f074f4
commit
d07a722fb1
|
@ -1,15 +1,38 @@
|
||||||
|
using System;
|
||||||
|
using MoonWorks.Math;
|
||||||
|
using SDL2;
|
||||||
|
|
||||||
namespace MoonWorks.Input
|
namespace MoonWorks.Input
|
||||||
{
|
{
|
||||||
public class Axis
|
public class Axis
|
||||||
{
|
{
|
||||||
|
IntPtr GamepadHandle;
|
||||||
|
SDL.SDL_GameControllerAxis SDL_Axis;
|
||||||
|
|
||||||
|
public AxisCode Code { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An axis value between -1 and 1.
|
/// An axis value between -1 and 1.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float Value { get; private set; }
|
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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
namespace MoonWorks.Input
|
namespace MoonWorks.Input
|
||||||
{
|
{
|
||||||
// Enum values are equivalent to the SDL GameControllerButton value.
|
// Enum values are equivalent to the SDL GameControllerButton value.
|
||||||
public enum ButtonCode
|
public enum GamepadButtonCode
|
||||||
{
|
{
|
||||||
A,
|
A,
|
||||||
B,
|
B,
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
namespace MoonWorks.Input
|
|
||||||
{
|
|
||||||
// Blittable identifier that can be used for button state lookups.
|
|
||||||
public struct ButtonIdentifier : System.IEquatable<ButtonIdentifier>
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,7 +9,7 @@
|
||||||
public bool IsDown => ButtonStatus == ButtonStatus.Pressed || ButtonStatus == ButtonStatus.Held;
|
public bool IsDown => ButtonStatus == ButtonStatus.Pressed || ButtonStatus == ButtonStatus.Held;
|
||||||
public bool IsReleased => ButtonStatus == ButtonStatus.Released;
|
public bool IsReleased => ButtonStatus == ButtonStatus.Released;
|
||||||
|
|
||||||
public ButtonState(ButtonStatus buttonStatus)
|
internal ButtonState(ButtonStatus buttonStatus)
|
||||||
{
|
{
|
||||||
ButtonStatus = buttonStatus;
|
ButtonStatus = buttonStatus;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,39 +10,57 @@ namespace MoonWorks.Input
|
||||||
internal IntPtr Handle;
|
internal IntPtr Handle;
|
||||||
internal int Index;
|
internal int Index;
|
||||||
|
|
||||||
public Button A { get; } = new Button();
|
public GamepadButton A { get; }
|
||||||
public Button B { get; } = new Button();
|
public GamepadButton B { get; }
|
||||||
public Button X { get; } = new Button();
|
public GamepadButton X { get; }
|
||||||
public Button Y { get; } = new Button();
|
public GamepadButton Y { get; }
|
||||||
public Button Back { get; } = new Button();
|
public GamepadButton Back { get; }
|
||||||
public Button Guide { get; } = new Button();
|
public GamepadButton Guide { get; }
|
||||||
public Button Start { get; } = new Button();
|
public GamepadButton Start { get; }
|
||||||
public Button LeftStick { get; } = new Button();
|
public GamepadButton LeftStick { get; }
|
||||||
public Button RightStick { get; } = new Button();
|
public GamepadButton RightStick { get; }
|
||||||
public Button LeftShoulder { get; } = new Button();
|
public GamepadButton LeftShoulder { get; }
|
||||||
public Button RightShoulder { get; } = new Button();
|
public GamepadButton RightShoulder { get; }
|
||||||
public Button DpadUp { get; } = new Button();
|
public GamepadButton DpadUp { get; }
|
||||||
public Button DpadDown { get; } = new Button();
|
public GamepadButton DpadDown { get; }
|
||||||
public Button DpadLeft { get; } = new Button();
|
public GamepadButton DpadLeft { get; }
|
||||||
public Button DpadRight { get; } = new Button();
|
public GamepadButton DpadRight { get; }
|
||||||
|
|
||||||
public Axis LeftX { get; } = new Axis();
|
public Axis LeftX { get; }
|
||||||
public Axis LeftY { get; } = new Axis();
|
public Axis LeftY { get; }
|
||||||
public Axis RightX { get; } = new Axis();
|
public Axis RightX { get; }
|
||||||
public Axis RightY { get; } = new Axis();
|
public Axis RightY { get; }
|
||||||
|
|
||||||
public Trigger TriggerLeft { get; } = new Trigger();
|
public AxisButton LeftXLeft { get; }
|
||||||
public Trigger TriggerRight { get; } = new Trigger();
|
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 IsDummy => Handle == IntPtr.Zero;
|
||||||
|
|
||||||
public bool AnyPressed { get; private set; }
|
public bool AnyPressed { get; private set; }
|
||||||
public ButtonCode AnyPressedButtonCode { get; private set; }
|
public VirtualButton AnyPressedButton { get; private set; }
|
||||||
|
|
||||||
private Dictionary<SDL.SDL_GameControllerButton, Button> EnumToButton;
|
private Dictionary<SDL.SDL_GameControllerButton, GamepadButton> EnumToButton;
|
||||||
private Dictionary<SDL.SDL_GameControllerAxis, Axis> EnumToAxis;
|
private Dictionary<SDL.SDL_GameControllerAxis, Axis> EnumToAxis;
|
||||||
private Dictionary<SDL.SDL_GameControllerAxis, Trigger> EnumToTrigger;
|
private Dictionary<SDL.SDL_GameControllerAxis, Trigger> EnumToTrigger;
|
||||||
|
|
||||||
|
private Dictionary<AxisButtonCode, AxisButton> AxisButtonCodeToAxisButton;
|
||||||
|
private Dictionary<TriggerCode, TriggerButton> TriggerCodeToTriggerButton;
|
||||||
|
|
||||||
|
private VirtualButton[] VirtualButtons;
|
||||||
|
|
||||||
internal Gamepad(IntPtr handle, int index)
|
internal Gamepad(IntPtr handle, int index)
|
||||||
{
|
{
|
||||||
Handle = handle;
|
Handle = handle;
|
||||||
|
@ -50,7 +68,48 @@ namespace MoonWorks.Input
|
||||||
|
|
||||||
AnyPressed = false;
|
AnyPressed = false;
|
||||||
|
|
||||||
EnumToButton = new Dictionary<SDL.SDL_GameControllerButton, Button>
|
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, GamepadButton>
|
||||||
{
|
{
|
||||||
{ SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_A, A },
|
{ SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_A, A },
|
||||||
{ SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_B, B },
|
{ 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_TRIGGERLEFT, TriggerLeft },
|
||||||
{ SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERRIGHT, TriggerRight }
|
{ SDL.SDL_GameControllerAxis.SDL_CONTROLLER_AXIS_TRIGGERRIGHT, TriggerRight }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AxisButtonCodeToAxisButton = new Dictionary<AxisButtonCode, AxisButton>
|
||||||
|
{
|
||||||
|
{ 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()
|
internal void Update()
|
||||||
|
@ -90,31 +190,42 @@ namespace MoonWorks.Input
|
||||||
|
|
||||||
if (!IsDummy)
|
if (!IsDummy)
|
||||||
{
|
{
|
||||||
foreach (var (sdlEnum, button) in EnumToButton)
|
foreach (var button in EnumToButton.Values)
|
||||||
{
|
{
|
||||||
var pressed = CheckPressed(sdlEnum);
|
button.Update();
|
||||||
button.Update(pressed);
|
}
|
||||||
|
|
||||||
|
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)
|
if (button.IsPressed)
|
||||||
{
|
{
|
||||||
AnyPressed = true;
|
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;
|
) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public GamepadButton Button(GamepadButtonCode buttonCode)
|
||||||
/// True if the button is pressed or held.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsDown(ButtonCode buttonCode)
|
|
||||||
{
|
{
|
||||||
return EnumToButton[(SDL.SDL_GameControllerButton) buttonCode].IsDown;
|
return EnumToButton[(SDL.SDL_GameControllerButton) buttonCode];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public AxisButton Button(AxisButtonCode axisButtonCode)
|
||||||
/// True if the button was pressed this exact frame.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsPressed(ButtonCode buttonCode)
|
|
||||||
{
|
{
|
||||||
return EnumToButton[(SDL.SDL_GameControllerButton) buttonCode].IsPressed;
|
return AxisButtonCodeToAxisButton[axisButtonCode];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public TriggerButton Button(TriggerCode triggerCode)
|
||||||
/// True if the button has been continuously held for more than one frame.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsHeld(ButtonCode buttonCode)
|
|
||||||
{
|
{
|
||||||
return EnumToButton[(SDL.SDL_GameControllerButton) buttonCode].IsHeld;
|
return TriggerCodeToTriggerButton[triggerCode];
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if the button is not pressed.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsReleased(ButtonCode buttonCode)
|
|
||||||
{
|
|
||||||
return EnumToButton[(SDL.SDL_GameControllerButton) buttonCode].IsReleased;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Obtains the button state given a ButtonCode.
|
|
||||||
/// </summary>
|
|
||||||
public ButtonState ButtonState(ButtonCode buttonCode)
|
|
||||||
{
|
|
||||||
return EnumToButton[(SDL.SDL_GameControllerButton) buttonCode].State;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace MoonWorks.Input
|
||||||
public static event Action<char> TextInput;
|
public static event Action<char> TextInput;
|
||||||
|
|
||||||
public bool AnyPressed { get; private set; }
|
public bool AnyPressed { get; private set; }
|
||||||
public ButtonIdentifier AnyPressedButton { get; private set; }
|
public VirtualButton AnyPressedButton { get; private set; }
|
||||||
|
|
||||||
internal Inputs()
|
internal Inputs()
|
||||||
{
|
{
|
||||||
|
@ -49,7 +49,7 @@ namespace MoonWorks.Input
|
||||||
if (Keyboard.AnyPressed)
|
if (Keyboard.AnyPressed)
|
||||||
{
|
{
|
||||||
AnyPressed = true;
|
AnyPressed = true;
|
||||||
AnyPressedButton = new ButtonIdentifier(Keyboard.AnyPressedKeyCode);
|
AnyPressedButton = Keyboard.AnyPressedButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mouse.Update();
|
Mouse.Update();
|
||||||
|
@ -57,7 +57,7 @@ namespace MoonWorks.Input
|
||||||
if (Mouse.AnyPressed)
|
if (Mouse.AnyPressed)
|
||||||
{
|
{
|
||||||
AnyPressed = true;
|
AnyPressed = true;
|
||||||
AnyPressedButton = new ButtonIdentifier(Mouse.AnyPressedButtonCode);
|
AnyPressedButton = Mouse.AnyPressedButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var gamepad in gamepads)
|
foreach (var gamepad in gamepads)
|
||||||
|
@ -67,7 +67,7 @@ namespace MoonWorks.Input
|
||||||
if (gamepad.AnyPressed)
|
if (gamepad.AnyPressed)
|
||||||
{
|
{
|
||||||
AnyPressed = true;
|
AnyPressed = true;
|
||||||
AnyPressedButton = new ButtonIdentifier(gamepad, gamepad.AnyPressedButtonCode);
|
AnyPressedButton = gamepad.AnyPressedButton;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,31 +82,6 @@ namespace MoonWorks.Input
|
||||||
return gamepads[slot];
|
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)
|
internal static void OnTextInput(char c)
|
||||||
{
|
{
|
||||||
if (TextInput != null)
|
if (TextInput != null)
|
||||||
|
|
|
@ -8,9 +8,11 @@ namespace MoonWorks.Input
|
||||||
public class Keyboard
|
public class Keyboard
|
||||||
{
|
{
|
||||||
public bool AnyPressed { get; private set; }
|
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 int numKeys;
|
||||||
|
|
||||||
private static readonly char[] TextInputCharacters = new char[]
|
private static readonly char[] TextInputCharacters = new char[]
|
||||||
|
@ -39,10 +41,10 @@ namespace MoonWorks.Input
|
||||||
{
|
{
|
||||||
SDL.SDL_GetKeyboardState(out numKeys);
|
SDL.SDL_GetKeyboardState(out numKeys);
|
||||||
|
|
||||||
Keys = new Button[numKeys];
|
Keys = new KeyboardButton[numKeys];
|
||||||
foreach (KeyCode keycode in Enum.GetValues(typeof(KeyCode)))
|
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;
|
AnyPressed = false;
|
||||||
|
|
||||||
IntPtr keyboardState = SDL.SDL_GetKeyboardState(out _);
|
State = SDL.SDL_GetKeyboardState(out _);
|
||||||
|
|
||||||
foreach (int keycode in Enum.GetValues(typeof(KeyCode)))
|
foreach (int keycode in Enum.GetValues(typeof(KeyCode)))
|
||||||
{
|
{
|
||||||
var keyDown = Conversions.ByteToBool(Marshal.ReadByte(keyboardState, keycode));
|
var button = Keys[keycode];
|
||||||
Keys[keycode].Update(keyDown);
|
button.Update();
|
||||||
|
|
||||||
if (keyDown)
|
if (button.IsPressed)
|
||||||
{
|
{
|
||||||
if (TextInputBindings.TryGetValue((KeyCode) keycode, out var textIndex))
|
if (TextInputBindings.TryGetValue((KeyCode) keycode, out var textIndex))
|
||||||
{
|
{
|
||||||
|
@ -67,12 +69,9 @@ namespace MoonWorks.Input
|
||||||
{
|
{
|
||||||
Inputs.OnTextInput(TextInputCharacters[6]);
|
Inputs.OnTextInput(TextInputCharacters[6]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Keys[keycode].IsPressed)
|
|
||||||
{
|
|
||||||
AnyPressed = true;
|
AnyPressed = true;
|
||||||
AnyPressedKeyCode = (KeyCode) keycode;
|
AnyPressedButton = button;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +96,7 @@ namespace MoonWorks.Input
|
||||||
return Keys[(int) keycode].IsReleased;
|
return Keys[(int) keycode].IsReleased;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Button Button(KeyCode keycode)
|
public KeyboardButton Button(KeyCode keycode)
|
||||||
{
|
{
|
||||||
return Keys[(int) keycode];
|
return Keys[(int) keycode];
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,9 @@ namespace MoonWorks.Input
|
||||||
{
|
{
|
||||||
public class Mouse
|
public class Mouse
|
||||||
{
|
{
|
||||||
public Button LeftButton { get; } = new Button();
|
public MouseButton LeftButton { get; }
|
||||||
public Button MiddleButton { get; } = new Button();
|
public MouseButton MiddleButton { get; }
|
||||||
public Button RightButton { get; } = new Button();
|
public MouseButton RightButton { get; }
|
||||||
|
|
||||||
public int X { get; private set; }
|
public int X { get; private set; }
|
||||||
public int Y { get; private set; }
|
public int Y { get; private set; }
|
||||||
|
@ -17,7 +17,9 @@ namespace MoonWorks.Input
|
||||||
public int Wheel { get; internal set; }
|
public int Wheel { get; internal set; }
|
||||||
|
|
||||||
public bool AnyPressed { get; private 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;
|
private bool relativeMode;
|
||||||
public bool RelativeMode
|
public bool RelativeMode
|
||||||
|
@ -34,31 +36,37 @@ namespace MoonWorks.Input
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Dictionary<MouseButtonCode, Button> CodeToButton;
|
private readonly Dictionary<MouseButtonCode, MouseButton> CodeToButton;
|
||||||
private readonly Dictionary<uint, MouseButtonCode> MaskToButtonCode;
|
|
||||||
|
private IEnumerable<MouseButton> Buttons
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
yield return LeftButton;
|
||||||
|
yield return MiddleButton;
|
||||||
|
yield return RightButton;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Mouse()
|
public Mouse()
|
||||||
{
|
{
|
||||||
CodeToButton = new Dictionary<MouseButtonCode, Button>
|
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, MouseButton>
|
||||||
{
|
{
|
||||||
{ MouseButtonCode.Left, LeftButton },
|
{ MouseButtonCode.Left, LeftButton },
|
||||||
{ MouseButtonCode.Right, RightButton },
|
{ MouseButtonCode.Right, RightButton },
|
||||||
{ MouseButtonCode.Middle, MiddleButton }
|
{ MouseButtonCode.Middle, MiddleButton }
|
||||||
};
|
};
|
||||||
|
|
||||||
MaskToButtonCode = new Dictionary<uint, MouseButtonCode>
|
|
||||||
{
|
|
||||||
{ SDL.SDL_BUTTON_LMASK, MouseButtonCode.Left },
|
|
||||||
{ SDL.SDL_BUTTON_MMASK, MouseButtonCode.Middle },
|
|
||||||
{ SDL.SDL_BUTTON_RMASK, MouseButtonCode.Right }
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Update()
|
internal void Update()
|
||||||
{
|
{
|
||||||
AnyPressed = false;
|
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);
|
var _ = SDL.SDL_GetRelativeMouseState(out var deltaX, out var deltaY);
|
||||||
|
|
||||||
X = x;
|
X = x;
|
||||||
|
@ -66,16 +74,18 @@ namespace MoonWorks.Input
|
||||||
DeltaX = deltaX;
|
DeltaX = deltaX;
|
||||||
DeltaY = deltaY;
|
DeltaY = deltaY;
|
||||||
|
|
||||||
foreach (var (mask, buttonCode) in MaskToButtonCode)
|
LeftButton.Update();
|
||||||
|
MiddleButton.Update();
|
||||||
|
RightButton.Update();
|
||||||
|
|
||||||
|
foreach (var button in Buttons)
|
||||||
{
|
{
|
||||||
var pressed = IsPressed(buttonMask, mask);
|
button.Update();
|
||||||
var button = CodeToButton[buttonCode];
|
|
||||||
button.Update(pressed);
|
|
||||||
|
|
||||||
if (button.IsPressed)
|
if (button.IsPressed)
|
||||||
{
|
{
|
||||||
AnyPressed = true;
|
AnyPressed = true;
|
||||||
AnyPressedButtonCode = buttonCode;
|
AnyPressedButton = button;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,10 +94,5 @@ namespace MoonWorks.Input
|
||||||
{
|
{
|
||||||
return CodeToButton[buttonCode].State;
|
return CodeToButton[buttonCode].State;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsPressed(uint buttonMask, uint buttonFlag)
|
|
||||||
{
|
|
||||||
return (buttonMask & buttonFlag) != 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,38 @@
|
||||||
|
using System;
|
||||||
|
using MoonWorks.Math;
|
||||||
|
using SDL2;
|
||||||
|
|
||||||
namespace MoonWorks.Input
|
namespace MoonWorks.Input
|
||||||
{
|
{
|
||||||
public class Trigger
|
public class Trigger
|
||||||
{
|
{
|
||||||
|
public IntPtr GamepadHandle;
|
||||||
|
public SDL.SDL_GameControllerAxis SDL_Axis;
|
||||||
|
|
||||||
|
public TriggerCode Code { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A trigger value between 0 and 1.
|
/// A trigger value between 0 and 1.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float Value { get; private set; }
|
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
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
namespace MoonWorks.Input
|
namespace MoonWorks.Input
|
||||||
{
|
{
|
||||||
public class Button
|
public abstract class VirtualButton
|
||||||
{
|
{
|
||||||
public ButtonState State { get; private set; }
|
public ButtonState State { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if the button is pressed or held.
|
/// True if the button is pressed or held.
|
||||||
|
@ -24,9 +24,11 @@ namespace MoonWorks.Input
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsReleased => State.IsReleased;
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue