Setup entry point + integrated moonworks stuff
This commit is contained in:
7
Nerfed.Runtime/Input/ButtonState.cs
Normal file
7
Nerfed.Runtime/Input/ButtonState.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Nerfed.Runtime;
|
||||
|
||||
public enum ButtonState
|
||||
{
|
||||
Released,
|
||||
Pressed
|
||||
}
|
224
Nerfed.Runtime/Input/Devices/GamePad.cs
Normal file
224
Nerfed.Runtime/Input/Devices/GamePad.cs
Normal file
@ -0,0 +1,224 @@
|
||||
using SDL2;
|
||||
|
||||
namespace Nerfed.Runtime;
|
||||
|
||||
public class GamePad
|
||||
{
|
||||
private const int maxGamePads = 4;
|
||||
private static readonly GamePad[] gamePads = new GamePad[maxGamePads];
|
||||
private static readonly GamePad dummy = new GamePad();
|
||||
|
||||
public IntPtr Handle { get; private set; }
|
||||
public bool IsConnected => Handle != IntPtr.Zero;
|
||||
public int JoystickInstanceId { get; private set; } = -1;
|
||||
|
||||
private readonly ButtonState[] buttonStates;
|
||||
private readonly ButtonState[] lastButtonStates;
|
||||
|
||||
static GamePad()
|
||||
{
|
||||
for (int i = 0; i < maxGamePads; i++)
|
||||
{
|
||||
gamePads[i] = new GamePad();
|
||||
}
|
||||
}
|
||||
|
||||
private GamePad()
|
||||
{
|
||||
int gamePadButtonCount = Enum.GetValues<GamePadButton>().Length;
|
||||
buttonStates = new ButtonState[gamePadButtonCount];
|
||||
lastButtonStates = new ButtonState[gamePadButtonCount];
|
||||
}
|
||||
|
||||
public bool IsButtonDown(GamePadButton button)
|
||||
{
|
||||
return buttonStates[(int)button] == ButtonState.Pressed;
|
||||
}
|
||||
|
||||
private void Register(IntPtr handle)
|
||||
{
|
||||
Handle = handle;
|
||||
IntPtr joystickHandle = SDL.SDL_GameControllerGetJoystick(handle);
|
||||
JoystickInstanceId = SDL.SDL_JoystickInstanceID(joystickHandle);
|
||||
Log.Info("Controller connected");
|
||||
}
|
||||
|
||||
private void UnRegister()
|
||||
{
|
||||
Handle = IntPtr.Zero;
|
||||
JoystickInstanceId = -1;
|
||||
Log.Info("Controller disconnected");
|
||||
}
|
||||
|
||||
public static GamePad Get(int slot)
|
||||
{
|
||||
return slot >= 0 && slot < maxGamePads ? gamePads[slot] : dummy;
|
||||
}
|
||||
|
||||
internal static void Update()
|
||||
{
|
||||
for (int i = 0; i < maxGamePads; i++)
|
||||
{
|
||||
GamePad gamePad = gamePads[i];
|
||||
if (gamePad.IsConnected)
|
||||
{
|
||||
Array.Copy(gamePad.buttonStates, gamePad.lastButtonStates, gamePad.buttonStates.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void ProcessEvent(ref SDL.SDL_Event ev)
|
||||
{
|
||||
switch (ev.type)
|
||||
{
|
||||
case SDL.SDL_EventType.SDL_CONTROLLERDEVICEADDED:
|
||||
ProcessDeviceAdded(ref ev.cdevice);
|
||||
break;
|
||||
case SDL.SDL_EventType.SDL_CONTROLLERDEVICEREMOVED:
|
||||
ProcessDeviceRemoved(ref ev.cdevice);
|
||||
break;
|
||||
case SDL.SDL_EventType.SDL_CONTROLLERBUTTONDOWN:
|
||||
ProcessButtonDown(ref ev.cbutton);
|
||||
break;
|
||||
case SDL.SDL_EventType.SDL_CONTROLLERBUTTONUP:
|
||||
ProcessButtonUp(ref ev.cbutton);
|
||||
break;
|
||||
case SDL.SDL_EventType.SDL_CONTROLLERAXISMOTION:
|
||||
ProcessAxisMotion(ref ev.caxis);
|
||||
break;
|
||||
case SDL.SDL_EventType.SDL_CONTROLLERTOUCHPADDOWN:
|
||||
ProcessTouchPadDown(ref ev.ctouchpad);
|
||||
break;
|
||||
case SDL.SDL_EventType.SDL_CONTROLLERTOUCHPADUP:
|
||||
ProcessTouchPadUp(ref ev.ctouchpad);
|
||||
break;
|
||||
case SDL.SDL_EventType.SDL_CONTROLLERTOUCHPADMOTION:
|
||||
ProcessTouchPadMotion(ref ev.ctouchpad);
|
||||
break;
|
||||
case SDL.SDL_EventType.SDL_CONTROLLERSENSORUPDATE:
|
||||
ProcessSensorUpdate(ref ev.sensor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessDeviceAdded(ref SDL.SDL_ControllerDeviceEvent ev)
|
||||
{
|
||||
int index = ev.which;
|
||||
if (SDL.SDL_IsGameController(index) == SDL.SDL_bool.SDL_TRUE)
|
||||
{
|
||||
int slot = -1;
|
||||
for (int i = 0; i < maxGamePads; i++)
|
||||
{
|
||||
if (!gamePads[i].IsConnected)
|
||||
{
|
||||
slot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (slot == -1)
|
||||
{
|
||||
Log.Warning("Too many gamepads connected");
|
||||
return;
|
||||
}
|
||||
|
||||
IntPtr handle = SDL.SDL_GameControllerOpen(index);
|
||||
if (handle == IntPtr.Zero)
|
||||
{
|
||||
Log.Error($"Failed to open gamepad: {SDL.SDL_GetError()}");
|
||||
return;
|
||||
}
|
||||
|
||||
gamePads[slot].Register(handle);
|
||||
}
|
||||
}
|
||||
|
||||
private static GamePad GetByJoystickId(int joystickId)
|
||||
{
|
||||
for (int slot = 0; slot < maxGamePads; slot++)
|
||||
{
|
||||
GamePad gamePad = gamePads[slot];
|
||||
if (gamePad.IsConnected && gamePad.JoystickInstanceId == joystickId)
|
||||
{
|
||||
return gamePad;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void ProcessDeviceRemoved(ref SDL.SDL_ControllerDeviceEvent ev)
|
||||
{
|
||||
GamePad gamePad = GetByJoystickId(ev.which);
|
||||
gamePad?.UnRegister();
|
||||
}
|
||||
|
||||
private static void ProcessButtonDown(ref SDL.SDL_ControllerButtonEvent ev)
|
||||
{
|
||||
if (TryConvertButton(ev.button, out GamePadButton button))
|
||||
{
|
||||
GamePad gamePad = GetByJoystickId(ev.which);
|
||||
gamePad.buttonStates[(int)button] = ButtonState.Pressed;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessButtonUp(ref SDL.SDL_ControllerButtonEvent ev)
|
||||
{
|
||||
if (TryConvertButton(ev.button, out GamePadButton button))
|
||||
{
|
||||
GamePad gamePad = GetByJoystickId(ev.which);
|
||||
gamePad.buttonStates[(int)button] = ButtonState.Released;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessAxisMotion(ref SDL.SDL_ControllerAxisEvent ev)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static void ProcessTouchPadDown(ref SDL.SDL_ControllerTouchpadEvent ev)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static void ProcessTouchPadUp(ref SDL.SDL_ControllerTouchpadEvent ev)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static void ProcessTouchPadMotion(ref SDL.SDL_ControllerTouchpadEvent ev)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static void ProcessSensorUpdate(ref SDL.SDL_SensorEvent ev)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static bool TryConvertButton(byte rawButton, out GamePadButton button)
|
||||
{
|
||||
GamePadButton? result = rawButton switch
|
||||
{
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_A => GamePadButton.A,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_B => GamePadButton.B,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_X => GamePadButton.X,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_Y => GamePadButton.Y,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_BACK => GamePadButton.Back,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_START => GamePadButton.Start,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSTICK => GamePadButton.LeftStick,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSTICK => GamePadButton.RightStick,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_LEFTSHOULDER => GamePadButton.LeftShoulder,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_RIGHTSHOULDER => GamePadButton.RightShoulder,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_UP => GamePadButton.DPadUp,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_DOWN => GamePadButton.DPadDown,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_LEFT => GamePadButton.DPadLeft,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_RIGHT => GamePadButton.DPadRight,
|
||||
(byte)SDL.SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_TOUCHPAD => GamePadButton.BigButton,
|
||||
_ => null
|
||||
};
|
||||
|
||||
button = result.GetValueOrDefault();
|
||||
return result.HasValue;
|
||||
}
|
||||
}
|
295
Nerfed.Runtime/Input/Devices/Keyboard.cs
Normal file
295
Nerfed.Runtime/Input/Devices/Keyboard.cs
Normal file
@ -0,0 +1,295 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using SDL2;
|
||||
|
||||
namespace Nerfed.Runtime;
|
||||
|
||||
public static class Keyboard
|
||||
{
|
||||
private static readonly List<char> textInput = new List<char>();
|
||||
|
||||
private const int maxPressedKeys = 8;
|
||||
private static readonly List<Key> keys = new List<Key>(maxPressedKeys);
|
||||
private static readonly List<Key> lastKeys = new List<Key>(maxPressedKeys);
|
||||
|
||||
/// <summary>
|
||||
/// True if the key was pressed or continued to be held down this frame.
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsKeyDown(Key key)
|
||||
{
|
||||
return HasKey(keys, key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if the key was pressed this frame.
|
||||
/// </summary>
|
||||
public static bool IsKeyPressed(Key key)
|
||||
{
|
||||
return HasKey(keys, key) && !HasKey(lastKeys, key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if the key was released or continued to be released this frame.
|
||||
/// </summary>
|
||||
public static bool IsKeyUp(Key key)
|
||||
{
|
||||
return !HasKey(keys, key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if the key was released this frame.
|
||||
/// </summary>
|
||||
public static bool IsKeyReleased(Key key)
|
||||
{
|
||||
return !HasKey(keys, key) && HasKey(lastKeys, key);
|
||||
}
|
||||
|
||||
public static ReadOnlySpan<Key> GetPressedKeys()
|
||||
{
|
||||
return CollectionsMarshal.AsSpan(keys);
|
||||
}
|
||||
|
||||
public static ReadOnlySpan<char> GetTextInput()
|
||||
{
|
||||
return CollectionsMarshal.AsSpan(textInput);
|
||||
}
|
||||
|
||||
internal static void Update()
|
||||
{
|
||||
textInput.Clear();
|
||||
|
||||
lastKeys.Clear();
|
||||
if (keys.Count > 0)
|
||||
{
|
||||
lastKeys.AddRange(keys);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool HasKey(List<Key> list, Key key)
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (keys[i] == key)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static void ProcessEvent(ref SDL.SDL_Event ev)
|
||||
{
|
||||
switch (ev.type)
|
||||
{
|
||||
case SDL.SDL_EventType.SDL_TEXTINPUT:
|
||||
ProcessTextInputEvent(ref ev.text);
|
||||
break;
|
||||
case SDL.SDL_EventType.SDL_KEYDOWN:
|
||||
ProcessKeyDownEvent(ref ev.key);
|
||||
break;
|
||||
case SDL.SDL_EventType.SDL_KEYUP:
|
||||
ProcessKeyUpEvent(ref ev.key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe void ProcessTextInputEvent(ref SDL.SDL_TextInputEvent evt)
|
||||
{
|
||||
// Based on the SDL2# LPUtf8StrMarshaler
|
||||
int MeasureStringLength(byte* ptr)
|
||||
{
|
||||
int bytes;
|
||||
for (bytes = 0; *ptr != 0; ptr += 1, bytes += 1) ;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
fixed (byte* textPtr = evt.text)
|
||||
{
|
||||
int bytes = MeasureStringLength(textPtr);
|
||||
if (bytes > 0)
|
||||
{
|
||||
/* UTF8 will never encode more characters
|
||||
* than bytes in a string, so bytes is a
|
||||
* suitable upper estimate of size needed
|
||||
*/
|
||||
char* charsBuffer = stackalloc char[bytes];
|
||||
int chars = Encoding.UTF8.GetChars(
|
||||
textPtr,
|
||||
bytes,
|
||||
charsBuffer,
|
||||
bytes
|
||||
);
|
||||
|
||||
if (chars > 0)
|
||||
{
|
||||
textInput.AddRange(new ReadOnlySpan<char>(charsBuffer, chars));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessKeyDownEvent(ref SDL.SDL_KeyboardEvent ev)
|
||||
{
|
||||
Key key = ConvertScancode(ev.keysym.scancode);
|
||||
SetKeyState(key, KeyState.Down);
|
||||
}
|
||||
|
||||
private static void ProcessKeyUpEvent(ref SDL.SDL_KeyboardEvent ev)
|
||||
{
|
||||
Key key = ConvertScancode(ev.keysym.scancode);
|
||||
SetKeyState(key, KeyState.Up);
|
||||
}
|
||||
|
||||
public static void SetKeyState(Key key, KeyState state)
|
||||
{
|
||||
if (keys.Count >= maxPressedKeys)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == KeyState.Down)
|
||||
{
|
||||
if (!keys.Contains(key))
|
||||
{
|
||||
keys.Add(key);
|
||||
}
|
||||
}
|
||||
else if (state == KeyState.Up)
|
||||
{
|
||||
keys.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
private static Key ConvertScancode(SDL.SDL_Scancode scancode)
|
||||
{
|
||||
switch (scancode)
|
||||
{
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_A: return Key.A;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_B: return Key.B;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_C: return Key.C;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_D: return Key.D;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_E: return Key.E;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F: return Key.F;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_G: return Key.G;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_H: return Key.H;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_I: return Key.I;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_J: return Key.J;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_K: return Key.K;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_L: return Key.L;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_M: return Key.M;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_N: return Key.N;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_O: return Key.O;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_P: return Key.P;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_Q: return Key.Q;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_R: return Key.R;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_S: return Key.S;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_T: return Key.T;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_U: return Key.U;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_V: return Key.V;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_W: return Key.W;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_X: return Key.X;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_Y: return Key.Y;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_Z: return Key.Z;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_1: return Key.D1;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_2: return Key.D2;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_3: return Key.D3;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_4: return Key.D4;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_5: return Key.D5;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_6: return Key.D6;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_7: return Key.D7;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_8: return Key.D8;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_9: return Key.D9;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_0: return Key.D0;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_RETURN: return Key.Enter;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_ESCAPE: return Key.Escape;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_BACKSPACE: return Key.Backspace;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_TAB: return Key.Tab;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_SPACE: return Key.Space;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_MINUS: return Key.Minus;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_EQUALS: return Key.Equals;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_LEFTBRACKET: return Key.LeftBracket;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_RIGHTBRACKET: return Key.RightBracket;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_BACKSLASH: return Key.Backslash;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_SEMICOLON: return Key.Semicolon;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_APOSTROPHE: return Key.Apostrophe;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_GRAVE: return Key.Tilde;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_COMMA: return Key.Comma;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_PERIOD: return Key.Period;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_SLASH: return Key.Slash;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_CAPSLOCK: return Key.CapsLock;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F1: return Key.F1;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F2: return Key.F2;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F3: return Key.F3;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F4: return Key.F4;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F5: return Key.F5;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F6: return Key.F6;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F7: return Key.F7;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F8: return Key.F8;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F9: return Key.F9;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F10: return Key.F10;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F11: return Key.F11;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F12: return Key.F12;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_PRINTSCREEN: return Key.PrintScreen;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_SCROLLLOCK: return Key.Scroll;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_PAUSE: return Key.Pause;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_INSERT: return Key.Insert;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_HOME: return Key.Home;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_PAGEUP: return Key.PageUp;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_DELETE: return Key.Delete;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_END: return Key.End;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_PAGEDOWN: return Key.PageDown;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_RIGHT: return Key.Right;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_LEFT: return Key.Left;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_DOWN: return Key.Down;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_UP: return Key.Up;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_NUMLOCKCLEAR: return Key.NumLock;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_DIVIDE: return Key.Divide;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_MULTIPLY: return Key.Multiply;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_MINUS: return Key.Subtract;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_PLUS: return Key.Add;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_ENTER: return Key.Enter;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_1: return Key.NumPad1;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_2: return Key.NumPad2;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_3: return Key.NumPad3;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_4: return Key.NumPad4;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_5: return Key.NumPad5;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_6: return Key.NumPad6;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_7: return Key.NumPad7;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_8: return Key.NumPad8;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_9: return Key.NumPad9;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_0: return Key.NumPad0;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_PERIOD: return Key.Period;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_APPLICATION: return Key.Apps;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_EQUALS: return Key.Equals;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F13: return Key.F13;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F14: return Key.F14;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F15: return Key.F15;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F16: return Key.F16;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F17: return Key.F17;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F18: return Key.F18;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F19: return Key.F19;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F20: return Key.F20;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F21: return Key.F21;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F22: return Key.F22;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F23: return Key.F23;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_F24: return Key.F24;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_EXECUTE: return Key.Execute;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_HELP: return Key.Help;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_MENU: return Key.Apps;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_SELECT: return Key.Select;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_KP_COMMA: return Key.Comma;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_LCTRL: return Key.LeftControl;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_LSHIFT: return Key.LeftShift;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_LALT: return Key.LeftAlt;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_LGUI: return Key.LeftSuper;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_RCTRL: return Key.RightControl;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_RSHIFT: return Key.RightShift;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_RALT: return Key.RightAlt;
|
||||
case SDL.SDL_Scancode.SDL_SCANCODE_RGUI: return Key.RightSuper;
|
||||
default: return Key.None;
|
||||
}
|
||||
}
|
||||
}
|
132
Nerfed.Runtime/Input/Devices/Mouse.cs
Normal file
132
Nerfed.Runtime/Input/Devices/Mouse.cs
Normal file
@ -0,0 +1,132 @@
|
||||
using System.Numerics;
|
||||
using SDL2;
|
||||
|
||||
namespace Nerfed.Runtime;
|
||||
|
||||
internal static class Mouse
|
||||
{
|
||||
public static Vector2 Position { get; private set; }
|
||||
|
||||
private static readonly ButtonState[] buttonStates;
|
||||
private static readonly ButtonState[] lastButtonStates;
|
||||
private static int wheelX;
|
||||
private static int wheelY;
|
||||
|
||||
static Mouse()
|
||||
{
|
||||
int numButtons = Enum.GetValues<MouseButton>().Length;
|
||||
buttonStates = new ButtonState[numButtons];
|
||||
lastButtonStates = new ButtonState[numButtons];
|
||||
}
|
||||
|
||||
/// /// <summary>
|
||||
/// True if the button is pressed or continued to be held this frame.
|
||||
/// </summary>
|
||||
public static bool IsButtonDown(MouseButton button)
|
||||
{
|
||||
return buttonStates[(int)button] == ButtonState.Pressed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if the button is pressed this frame.
|
||||
/// </summary>
|
||||
public static bool IsButtonPressed(MouseButton button)
|
||||
{
|
||||
return buttonStates[(int)button] == ButtonState.Pressed && lastButtonStates[(int)button] == ButtonState.Released;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if the button is released or continued to be released this frame.
|
||||
/// </summary>
|
||||
/// <param name="button"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsButtonUp(MouseButton button)
|
||||
{
|
||||
return buttonStates[(int)button] == ButtonState.Released;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True if the button is released this frame.
|
||||
/// </summary>
|
||||
public static bool IsButtonReleased(MouseButton button)
|
||||
{
|
||||
return buttonStates[(int)button] == ButtonState.Released && lastButtonStates[(int)button] == ButtonState.Pressed;
|
||||
}
|
||||
|
||||
public static int GetWheel()
|
||||
{
|
||||
return wheelY;
|
||||
}
|
||||
|
||||
public static int GetWheelHorizontal()
|
||||
{
|
||||
return wheelX;
|
||||
}
|
||||
|
||||
internal static void Update()
|
||||
{
|
||||
Array.Copy(buttonStates, lastButtonStates, buttonStates.Length);
|
||||
}
|
||||
|
||||
internal static void ProcessEvent(ref SDL.SDL_Event ev)
|
||||
{
|
||||
switch (ev.type)
|
||||
{
|
||||
case SDL.SDL_EventType.SDL_MOUSEBUTTONDOWN:
|
||||
ProcessButtonDownEvent(ref ev.button);
|
||||
break;
|
||||
case SDL.SDL_EventType.SDL_MOUSEBUTTONUP:
|
||||
ProcessButtonUpEvent(ref ev.button);
|
||||
break;
|
||||
case SDL.SDL_EventType.SDL_MOUSEWHEEL:
|
||||
ProcessWheelEvent(ref ev.wheel);
|
||||
break;
|
||||
case SDL.SDL_EventType.SDL_MOUSEMOTION:
|
||||
ProcessMotionEvent(ref ev.motion);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessButtonDownEvent(ref SDL.SDL_MouseButtonEvent ev)
|
||||
{
|
||||
if (TryConvertButton(ev.button, out MouseButton button))
|
||||
{
|
||||
buttonStates[(int)button] = ButtonState.Pressed;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessButtonUpEvent(ref SDL.SDL_MouseButtonEvent ev)
|
||||
{
|
||||
if (TryConvertButton(ev.button, out MouseButton button))
|
||||
{
|
||||
buttonStates[(int)button] = ButtonState.Released;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ProcessWheelEvent(ref SDL.SDL_MouseWheelEvent ev)
|
||||
{
|
||||
wheelX += ev.x;
|
||||
wheelY += ev.y;
|
||||
}
|
||||
|
||||
private static void ProcessMotionEvent(ref SDL.SDL_MouseMotionEvent ev)
|
||||
{
|
||||
Position = new Vector2(ev.x, ev.y);
|
||||
}
|
||||
|
||||
private static bool TryConvertButton(byte rawButton, out MouseButton button)
|
||||
{
|
||||
MouseButton? result = rawButton switch
|
||||
{
|
||||
(byte)SDL.SDL_BUTTON_LEFT => MouseButton.Left,
|
||||
(byte)SDL.SDL_BUTTON_MIDDLE => MouseButton.Middle,
|
||||
(byte)SDL.SDL_BUTTON_RIGHT => MouseButton.Right,
|
||||
(byte)SDL.SDL_BUTTON_X1 => MouseButton.XButton1,
|
||||
(byte)SDL.SDL_BUTTON_X2 => MouseButton.XButton2,
|
||||
_ => null
|
||||
};
|
||||
|
||||
button = result.GetValueOrDefault();
|
||||
return result.HasValue;
|
||||
}
|
||||
}
|
11
Nerfed.Runtime/Input/GamePadAxis.cs
Normal file
11
Nerfed.Runtime/Input/GamePadAxis.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Nerfed.Runtime;
|
||||
|
||||
public enum GamePadAxis
|
||||
{
|
||||
LeftTrigger,
|
||||
RightTrigger,
|
||||
LeftThumbStickX,
|
||||
LeftThumbStickY,
|
||||
RightThumbStickX,
|
||||
RightThumbStickY
|
||||
}
|
20
Nerfed.Runtime/Input/GamePadButton.cs
Normal file
20
Nerfed.Runtime/Input/GamePadButton.cs
Normal file
@ -0,0 +1,20 @@
|
||||
namespace Nerfed.Runtime;
|
||||
|
||||
public enum GamePadButton
|
||||
{
|
||||
Start,
|
||||
A,
|
||||
B,
|
||||
X,
|
||||
Y,
|
||||
DPadLeft,
|
||||
DPadRight,
|
||||
DPadUp,
|
||||
DPadDown,
|
||||
RightShoulder,
|
||||
LeftShoulder,
|
||||
LeftStick,
|
||||
RightStick,
|
||||
Back,
|
||||
BigButton
|
||||
}
|
127
Nerfed.Runtime/Input/Key.cs
Normal file
127
Nerfed.Runtime/Input/Key.cs
Normal file
@ -0,0 +1,127 @@
|
||||
namespace Nerfed.Runtime;
|
||||
|
||||
public enum Key : int // must be int32 (see KeyboardState)
|
||||
{
|
||||
None,
|
||||
Backspace,
|
||||
Tab,
|
||||
Enter,
|
||||
CapsLock,
|
||||
Escape,
|
||||
Space,
|
||||
PageUp,
|
||||
PageDown,
|
||||
End,
|
||||
Home,
|
||||
Left,
|
||||
Up,
|
||||
Right,
|
||||
Down,
|
||||
Select,
|
||||
Execute,
|
||||
PrintScreen,
|
||||
Insert,
|
||||
Delete,
|
||||
Help,
|
||||
D0,
|
||||
D1,
|
||||
D2,
|
||||
D3,
|
||||
D4,
|
||||
D5,
|
||||
D6,
|
||||
D7,
|
||||
D8,
|
||||
D9,
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
LeftSuper,
|
||||
RightSuper,
|
||||
Apps,
|
||||
NumPad0,
|
||||
NumPad1,
|
||||
NumPad2,
|
||||
NumPad3,
|
||||
NumPad4,
|
||||
NumPad5,
|
||||
NumPad6,
|
||||
NumPad7,
|
||||
NumPad8,
|
||||
NumPad9,
|
||||
Multiply,
|
||||
Add,
|
||||
Separator,
|
||||
Subtract,
|
||||
Decimal,
|
||||
Divide,
|
||||
F1,
|
||||
F2,
|
||||
F3,
|
||||
F4,
|
||||
F5,
|
||||
F6,
|
||||
F7,
|
||||
F8,
|
||||
F9,
|
||||
F10,
|
||||
F11,
|
||||
F12,
|
||||
F13,
|
||||
F14,
|
||||
F15,
|
||||
F16,
|
||||
F17,
|
||||
F18,
|
||||
F19,
|
||||
F20,
|
||||
F21,
|
||||
F22,
|
||||
F23,
|
||||
F24,
|
||||
NumLock,
|
||||
Scroll,
|
||||
LeftShift,
|
||||
RightShift,
|
||||
LeftControl,
|
||||
RightControl,
|
||||
LeftAlt,
|
||||
RightAlt,
|
||||
Semicolon,
|
||||
Equals,
|
||||
Comma,
|
||||
Minus,
|
||||
Period,
|
||||
Slash,
|
||||
Tilde,
|
||||
LeftBracket,
|
||||
Backslash,
|
||||
RightBracket,
|
||||
Apostrophe,
|
||||
Pause,
|
||||
|
||||
Count
|
||||
}
|
7
Nerfed.Runtime/Input/KeyState.cs
Normal file
7
Nerfed.Runtime/Input/KeyState.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace Nerfed.Runtime;
|
||||
|
||||
public enum KeyState
|
||||
{
|
||||
Up,
|
||||
Down
|
||||
}
|
10
Nerfed.Runtime/Input/MouseButton.cs
Normal file
10
Nerfed.Runtime/Input/MouseButton.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace Nerfed.Runtime;
|
||||
|
||||
public enum MouseButton
|
||||
{
|
||||
Left,
|
||||
Middle,
|
||||
Right,
|
||||
XButton1,
|
||||
XButton2
|
||||
}
|
14
Nerfed.Runtime/Input/MouseState.cs
Normal file
14
Nerfed.Runtime/Input/MouseState.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.Numerics;
|
||||
|
||||
namespace Nerfed.Runtime;
|
||||
|
||||
public struct MouseState
|
||||
{
|
||||
public Vector2 position;
|
||||
public ButtonState left;
|
||||
public ButtonState middle;
|
||||
public ButtonState right;
|
||||
public ButtonState x1;
|
||||
public ButtonState x2;
|
||||
public int wheel;
|
||||
}
|
Reference in New Issue
Block a user