using System; using System.Collections.Generic; using Microsoft.Xna.Framework.Input; using Engine.Core; using Engine.Systems.Input; namespace Engine.Integration.MonoGame; public class KeyboardInputs : Behaviour, IButtonInputs, IUpdate { public IButtonInputs.InputEvent OnAnyButtonPressed { get; } = new(); public IButtonInputs.InputEvent OnAnyButtonReleased { get; } = new(); private readonly Dictionary.InputEvent> OnPressed = new(256); private readonly Dictionary.InputEvent> OnReleased = new(256); private int cachePressedCurrentlyCount = 0; private readonly Keys[] cachePressedCurrently = new Keys[256]; private int cachePressedPreviouslyCount = 0; private readonly Keys[] cachePressedPreviously = new Keys[256]; public void RegisterOnPress(Keys key, IButtonInputs.InputEvent.EventHandler callback) { if (!OnPressed.TryGetValue(key, out IButtonInputs.InputEvent? delegateCallback)) { delegateCallback = new(); OnPressed.Add(key, delegateCallback); } delegateCallback.AddListener(callback); } public void UnregisterOnPress(Keys key, IButtonInputs.InputEvent.EventHandler callback) { if (OnPressed.TryGetValue(key, out IButtonInputs.InputEvent? delegateCallback)) delegateCallback.RemoveListener(callback); } public void RegisterOnRelease(Keys key, IButtonInputs.InputEvent.EventHandler callback) { if (!OnReleased.TryGetValue(key, out IButtonInputs.InputEvent? delegateCallback)) { delegateCallback = new(); OnReleased.Add(key, delegateCallback); } delegateCallback.AddListener(callback); } public void UnregisterOnRelease(Keys key, IButtonInputs.InputEvent.EventHandler callback) { if (OnReleased.TryGetValue(key, out IButtonInputs.InputEvent? delegateCallback)) delegateCallback.RemoveListener(callback); } public void Update() { KeyboardState keyboardState = Keyboard.GetState(); keyboardState.GetPressedKeys(cachePressedCurrently); cachePressedCurrentlyCount = keyboardState.GetPressedKeyCount(); for (int i = 0; i < cachePressedCurrentlyCount; i++) { Keys currentlyPressedKey = cachePressedCurrently[i]; if (WasPressed(currentlyPressedKey)) continue; if (OnPressed.TryGetValue(currentlyPressedKey, out IButtonInputs.InputEvent? callback)) callback?.Invoke(this, new(currentlyPressedKey)); OnAnyButtonPressed?.Invoke(this, new(currentlyPressedKey)); } for (int i = 0; i < cachePressedPreviouslyCount; i++) { Keys previouslyPressedKey = cachePressedPreviously[i]; if (IsPressed(previouslyPressedKey)) continue; if (OnReleased.TryGetValue(previouslyPressedKey, out IButtonInputs.InputEvent? callback)) callback?.Invoke(this, new(previouslyPressedKey)); OnAnyButtonReleased?.Invoke(this, new(previouslyPressedKey)); } Array.Copy(cachePressedCurrently, cachePressedPreviously, cachePressedCurrentlyCount); cachePressedPreviouslyCount = cachePressedCurrentlyCount; } public bool IsPressed(Keys key) { for (int i = 0; i < cachePressedCurrentlyCount; i++) if (cachePressedCurrently[i] == key) return true; return false; } private bool WasPressed(Keys key) { for (int i = 0; i < cachePressedPreviouslyCount; i++) if (cachePressedPreviously[i] == key) return true; return false; } }