Files
Voile/Voile/Source/Input/InputSystem.cs

296 lines
8.1 KiB
C#

using System.Diagnostics.CodeAnalysis;
using System.Numerics;
using Voile.Utils;
namespace Voile.Input
{
/// <summary>
/// A system providing means for collecting user input, as well as defining custom <see cref="InputAction"/> list.
/// </summary>
public abstract class InputSystem : IStartableSystem, IDisposable
{
/// <summary>
/// The list of all available input mappings, custom and built-in.
/// </summary>
public static IReadOnlyDictionary<string, List<IInputAction>> InputMappings => inputMappings;
public void Start()
{
inputMappings = new Dictionary<string, List<IInputAction>>();
CreateDefaultMappings();
}
/// <summary>
/// Forces this input system to poll all of its inputs during current frame.<br />
/// Some backends require inputs to be polled once per specific interval. Override this method to implement this behavior.
/// </summary>
public virtual void Poll() { }
public void Shutdown() => Dispose();
public void Dispose() => GC.SuppressFinalize(this);
public bool Handled { get => _handled; set => _handled = value; }
public bool IsActionDown(string action)
{
List<IInputAction>? mappings;
if (TryGetInputMappings(action, out mappings))
{
foreach (IInputAction inputAction in mappings)
if (inputAction.IsDown(this)) return true;
}
return false;
}
public bool IsActionPressed(string action)
{
List<IInputAction>? mappings;
if (TryGetInputMappings(action, out mappings))
{
foreach (IInputAction inputAction in mappings)
if (inputAction.IsPressed(this)) return true;
}
return false;
}
public bool IsActionReleased(string action)
{
List<IInputAction>? mappings;
if (TryGetInputMappings(action, out mappings))
{
foreach (IInputAction inputAction in mappings)
if (inputAction.IsReleased(this)) return true;
}
return false;
}
public Vector2 GetInputDirection(KeyboardKey leftKey, KeyboardKey rightKey, KeyboardKey upKey, KeyboardKey downKey)
{
Vector2 dir = Vector2.Zero;
if (IsKeyboardKeyDown(leftKey))
dir.X -= 1;
if (IsKeyboardKeyDown(rightKey))
dir.X += 1;
if (IsKeyboardKeyDown(upKey))
dir.Y -= 1;
if (IsKeyboardKeyDown(downKey))
dir.Y += 1;
return dir == Vector2.Zero ? Vector2.Zero : Vector2.Normalize(dir);
}
public Vector2 GetInputDirection(string leftAction, string rightAction, string upAction, string downAction)
{
Vector2 dir = Vector2.Zero;
if (IsActionDown(leftAction))
dir.X -= 1;
if (IsActionDown(rightAction))
dir.X += 1;
if (IsActionDown(upAction))
dir.Y -= 1;
if (IsActionDown(downAction))
dir.Y += 1;
return dir == Vector2.Zero ? Vector2.Zero : Vector2.Normalize(dir);
}
public abstract bool IsKeyboardKeyDown(KeyboardKey key);
public abstract bool KeyboardKeyJustPressed(KeyboardKey key);
public abstract bool KeyboardKeyJustReleased(KeyboardKey key);
public abstract int GetCharPressed();
public abstract bool IsMousePressed(MouseButton button);
public abstract bool IsMouseButtonDown(MouseButton button);
public abstract bool IsMouseButtonReleased(MouseButton button);
public abstract float GetMouseWheelMovement();
public abstract void SetMousePosition(Vector2 position);
public abstract Vector2 GetMousePosition();
public abstract void HideCursor();
public abstract void ShowCursor();
public abstract bool IsCursorHidden();
public void SetAsHandled() => _handled = true;
public void AddInputMapping(string actionName, IEnumerable<IInputAction> inputActions)
{
inputMappings.Add(actionName, inputActions.ToList());
}
private void CreateDefaultMappings()
{
AddInputMapping("up", [
new KeyInputAction(KeyboardKey.W),
new KeyInputAction(KeyboardKey.Up),
]);
AddInputMapping("down", [
new KeyInputAction(KeyboardKey.S),
new KeyInputAction(KeyboardKey.Down),
]);
AddInputMapping("left", [
new KeyInputAction(KeyboardKey.A),
new KeyInputAction(KeyboardKey.Left),
]);
AddInputMapping("right", [
new KeyInputAction(KeyboardKey.D),
new KeyInputAction(KeyboardKey.Right),
]);
AddInputMapping("accept", [
new KeyInputAction(KeyboardKey.Enter),
]);
AddInputMapping("cancel", [
new KeyInputAction(KeyboardKey.Backspace),
]);
}
protected bool TryGetInputMappings(string forAction, [NotNullWhen(true)] out List<IInputAction>? inputActions)
{
inputActions = null;
if (inputMappings.TryGetValue(forAction, out var actions))
{
inputActions = actions;
return true;
}
_logger.Error($"The action \"{forAction}\" is not present in the input mappings!");
return false;
}
protected static Dictionary<string, List<IInputAction>> inputMappings = new();
private bool _handled;
private Logger _logger = new(nameof(InputSystem));
}
public enum KeyboardKey
{
Null = 0,
Back = 4,
VolumeUp = 24,
VolumeDown = 25,
Spacebar = 32,
Apostrophe = 39,
Comma = 44,
Minus = 45,
Period = 46,
Slash = 47,
Zero = 48,
One = 49,
Two = 50,
Three = 51,
Four = 52,
Five = 53,
Six = 54,
Seven = 55,
Eight = 56,
Nine = 57,
Semicolon = 59,
Equal = 61,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
Menu = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
LeftBracket = 91,
Backslash = 92,
RightBracket = 93,
Grave = 96,
Escape = 256,
Enter = 257,
Tab = 258,
Backspace = 259,
Insert = 260,
Delete = 261,
Right = 262,
Left = 263,
Down = 264,
Up = 265,
PageUp = 266,
PageDown = 267,
Home = 268,
End = 269,
CapsLock = 280,
ScrollLock = 281,
NumLock = 282,
PrintScreen = 283,
Pause = 284,
F1 = 290,
F2 = 291,
F3 = 292,
F4 = 293,
F5 = 294,
F6 = 295,
F7 = 296,
F8 = 297,
F9 = 298,
F10 = 299,
F11 = 300,
F12 = 301,
KP0 = 320,
KP1 = 321,
KP2 = 322,
KP3 = 323,
KP4 = 324,
KP5 = 325,
KP6 = 326,
KP7 = 327,
KP8 = 328,
KP9 = 329,
KPDecimal = 330,
KPDivide = 331,
KPMultiply = 332,
KPSubstract = 333,
KPAdd = 334,
KPEnter = 335,
KPEqual = 336,
LeftShift = 340,
LeftControl = 341,
LeftAlt = 342,
LeftSuper = 343,
RightShift = 344,
RightControl = 345,
RightAlt = 346,
RightSuper = 347,
KBMenu = 348
}
[Flags]
public enum MouseButton
{
Left = 0,
Right = 1,
Middle = 2,
}
}