forked from MoonsideGames/MoonWorks
160 lines
3.6 KiB
C#
160 lines
3.6 KiB
C#
using SDL2;
|
|
using System;
|
|
|
|
namespace MoonWorks.Input
|
|
{
|
|
/// <summary>
|
|
/// The main container class for all input tracking.
|
|
/// Your Game class will automatically have a reference to this class.
|
|
/// </summary>
|
|
public class Inputs
|
|
{
|
|
public const int MAX_GAMEPADS = 4;
|
|
|
|
/// <summary>
|
|
/// The reference to the Keyboard input abstraction.
|
|
/// </summary>
|
|
public Keyboard Keyboard { get; }
|
|
|
|
/// <summary>
|
|
/// The reference to the Mouse input abstraction.
|
|
/// </summary>
|
|
public Mouse Mouse { get; }
|
|
|
|
Gamepad[] Gamepads;
|
|
|
|
public static event Action<char> TextInput;
|
|
|
|
/// <summary>
|
|
/// True if any input on any input device is active. Useful for input remapping.
|
|
/// </summary>
|
|
public bool AnyPressed { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Contains a reference to an arbitrary VirtualButton that was pressed this frame. Useful for input remapping.
|
|
/// </summary>
|
|
public VirtualButton AnyPressedButton { get; private set; }
|
|
|
|
internal Inputs()
|
|
{
|
|
Keyboard = new Keyboard();
|
|
Mouse = new Mouse();
|
|
|
|
Gamepads = new Gamepad[MAX_GAMEPADS];
|
|
|
|
// initialize dummy controllers
|
|
for (var slot = 0; slot < MAX_GAMEPADS; slot += 1)
|
|
{
|
|
Gamepads[slot] = new Gamepad(IntPtr.Zero, slot);
|
|
}
|
|
}
|
|
|
|
// Assumes that SDL_PumpEvents has been called!
|
|
internal void Update()
|
|
{
|
|
AnyPressed = false;
|
|
AnyPressedButton = default; // DeviceKind.None
|
|
|
|
Keyboard.Update();
|
|
|
|
if (Keyboard.AnyPressed)
|
|
{
|
|
AnyPressed = true;
|
|
AnyPressedButton = Keyboard.AnyPressedButton;
|
|
}
|
|
|
|
Mouse.Update();
|
|
|
|
if (Mouse.AnyPressed)
|
|
{
|
|
AnyPressed = true;
|
|
AnyPressedButton = Mouse.AnyPressedButton;
|
|
}
|
|
|
|
foreach (var gamepad in Gamepads)
|
|
{
|
|
gamepad.Update();
|
|
|
|
if (gamepad.AnyPressed)
|
|
{
|
|
AnyPressed = true;
|
|
AnyPressedButton = gamepad.AnyPressedButton;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if a gamepad is currently connected in the given slot.
|
|
/// </summary>
|
|
/// <param name="slot">Range: 0-3</param>
|
|
/// <returns></returns>
|
|
public bool GamepadExists(int slot)
|
|
{
|
|
if (slot < 0 || slot >= MAX_GAMEPADS)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return !Gamepads[slot].IsDummy;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a gamepad associated with the given slot.
|
|
/// The first n slots are guaranteed to occupied with gamepads if they are connected.
|
|
/// If a gamepad does not exist for the given slot, a dummy object with all inputs in default state will be returned.
|
|
/// You can check if a gamepad is connected in a slot with the GamepadExists function.
|
|
/// </summary>
|
|
/// <param name="slot">Range: 0-3</param>
|
|
public Gamepad GetGamepad(int slot)
|
|
{
|
|
return Gamepads[slot];
|
|
}
|
|
|
|
internal void AddGamepad(int index)
|
|
{
|
|
for (var slot = 0; slot < MAX_GAMEPADS; slot += 1)
|
|
{
|
|
if (!GamepadExists(slot))
|
|
{
|
|
var openResult = SDL.SDL_GameControllerOpen(index);
|
|
if (openResult == 0)
|
|
{
|
|
Logger.LogError("Error opening gamepad!");
|
|
Logger.LogError(SDL.SDL_GetError());
|
|
}
|
|
else
|
|
{
|
|
Gamepads[slot].Register(openResult);
|
|
Logger.LogInfo($"Gamepad added to slot {slot}!");
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
Logger.LogInfo("Too many gamepads already!");
|
|
}
|
|
|
|
internal void RemoveGamepad(int joystickInstanceID)
|
|
{
|
|
for (int slot = 0; slot < MAX_GAMEPADS; slot += 1)
|
|
{
|
|
if (joystickInstanceID == Gamepads[slot].JoystickInstanceID)
|
|
{
|
|
SDL.SDL_GameControllerClose(Gamepads[slot].Handle);
|
|
Gamepads[slot].Unregister();
|
|
Logger.LogInfo($"Removing gamepad from slot {slot}!");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
internal static void OnTextInput(char c)
|
|
{
|
|
if (TextInput != null)
|
|
{
|
|
TextInput(c);
|
|
}
|
|
}
|
|
}
|
|
}
|