using Engine.Input; namespace PresenterConsole; public class ConsoleInputHandler : IInputHandler { private readonly HashSet _currentKeys = []; private readonly HashSet _previousKeys = []; private ConsoleModifiers _currentModifiers; private ConsoleModifiers _previousModifiers; public void Update(double deltaTime) { // Save previous state _previousKeys.Clear(); foreach (var key in _currentKeys) { _previousKeys.Add(key); } _previousModifiers = _currentModifiers; // Clear current state _currentKeys.Clear(); _currentModifiers = 0; // Read keys while (Console.KeyAvailable) { var keyInfo = Console.ReadKey(intercept: true); _currentKeys.Add(keyInfo.Key); _currentModifiers |= keyInfo.Modifiers; } } public bool IsKeyPressed(KeyCode keyCode) { if (IsModifierKey(keyCode)) return IsModifierActive(keyCode); return _currentKeys.Contains(ConvertToConsoleKey(keyCode)); } public bool IsKeyJustPressed(KeyCode keyCode) { if (IsModifierKey(keyCode)) return IsModifierActive(keyCode) && !WasModifierActive(keyCode); var consoleKey = ConvertToConsoleKey(keyCode); return _currentKeys.Contains(consoleKey) && !_previousKeys.Contains(consoleKey); } public bool IsKeyRepeat(KeyCode keyCode) { if (IsModifierKey(keyCode)) return IsModifierActive(keyCode) && WasModifierActive(keyCode); var consoleKey = ConvertToConsoleKey(keyCode); return _currentKeys.Contains(consoleKey) && _previousKeys.Contains(consoleKey); } public bool IsMouseButtonPressed(MouseButton button) { return false; } public bool IsMouseButtonJustPressed(MouseButton button) { return false; } private static bool IsModifierKey(KeyCode keyCode) => keyCode is KeyCode.Ctrl or KeyCode.Backspace or KeyCode.Shift; private bool IsModifierActive(KeyCode keyCode) => keyCode switch { KeyCode.Ctrl => (_currentModifiers & ConsoleModifiers.Control) != 0, KeyCode.Alt => (_currentModifiers & ConsoleModifiers.Alt) != 0, KeyCode.Shift => (_currentModifiers & ConsoleModifiers.Shift) != 0, _ => false }; private bool WasModifierActive(KeyCode keyCode) => keyCode switch { KeyCode.Ctrl => (_previousModifiers & ConsoleModifiers.Control) != 0, KeyCode.Alt => (_previousModifiers & ConsoleModifiers.Alt) != 0, KeyCode.Shift => (_previousModifiers & ConsoleModifiers.Shift) != 0, _ => false }; private static ConsoleKey ConvertToConsoleKey(KeyCode keyCode) => keyCode switch { KeyCode.A => ConsoleKey.A, KeyCode.B => ConsoleKey.B, KeyCode.C => ConsoleKey.C, KeyCode.D => ConsoleKey.D, KeyCode.E => ConsoleKey.E, KeyCode.F => ConsoleKey.F, KeyCode.G => ConsoleKey.G, KeyCode.H => ConsoleKey.H, KeyCode.I => ConsoleKey.I, KeyCode.J => ConsoleKey.J, KeyCode.K => ConsoleKey.K, KeyCode.L => ConsoleKey.L, KeyCode.M => ConsoleKey.M, KeyCode.N => ConsoleKey.N, KeyCode.O => ConsoleKey.O, KeyCode.P => ConsoleKey.P, KeyCode.Q => ConsoleKey.Q, KeyCode.R => ConsoleKey.R, KeyCode.S => ConsoleKey.S, KeyCode.T => ConsoleKey.T, KeyCode.U => ConsoleKey.U, KeyCode.V => ConsoleKey.V, KeyCode.W => ConsoleKey.W, KeyCode.X => ConsoleKey.X, KeyCode.Y => ConsoleKey.Y, KeyCode.Z => ConsoleKey.Z, KeyCode.Enter => ConsoleKey.Enter, KeyCode.Escape => ConsoleKey.Escape, KeyCode.Space => ConsoleKey.Spacebar, KeyCode.Tab => ConsoleKey.Tab, KeyCode.Backspace => ConsoleKey.Backspace, KeyCode.Up => ConsoleKey.UpArrow, KeyCode.Down => ConsoleKey.DownArrow, KeyCode.Left => ConsoleKey.LeftArrow, KeyCode.Right => ConsoleKey.RightArrow, _ => throw new ArgumentOutOfRangeException(nameof(keyCode), $"No mapping defined for {keyCode}") }; }