115 lines
3.8 KiB
C#
115 lines
3.8 KiB
C#
|
|
using System;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using Microsoft.Xna.Framework.Input;
|
||
|
|
|
||
|
|
namespace FNAF_Clone.Input;
|
||
|
|
|
||
|
|
|
||
|
|
public static class InputManager {
|
||
|
|
private static Dictionary<Keys, List<(KeypressHandler, InputListenerHook)>> keyPressListeners = new();
|
||
|
|
private static Dictionary<Keys, List<(KeypressHandler, InputListenerHook)>> keyHoldListeners = new(); // The bool is for enabling/disabling that method
|
||
|
|
private static Dictionary<Keys, List<(KeypressHandler, InputListenerHook)>> keyReleaseListeners = new();
|
||
|
|
|
||
|
|
private static KeyboardState oldState = Keyboard.GetState();
|
||
|
|
private static KeyboardState newState;
|
||
|
|
|
||
|
|
// public static ConcurrentQueue<Action> inputEventQueue = new();
|
||
|
|
|
||
|
|
public delegate void KeypressHandler(KeyboardState state);
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
// public static void StartListening() {
|
||
|
|
// processInputThread.Start();
|
||
|
|
// Console.WriteLine("Started listening for input");
|
||
|
|
// }
|
||
|
|
|
||
|
|
public static void NextInputCycle() {
|
||
|
|
Queue<KeypressHandler> inputEventQueue = new();
|
||
|
|
|
||
|
|
// Read
|
||
|
|
|
||
|
|
newState = Keyboard.GetState();
|
||
|
|
Keys[] pressed = newState.GetPressedKeys();
|
||
|
|
Keys[] pressedLastFrame = oldState.GetPressedKeys();
|
||
|
|
|
||
|
|
Array.ForEach(pressed, key => {
|
||
|
|
if (oldState.IsKeyUp(key)){
|
||
|
|
if (keyPressListeners.TryGetValue(key, out var pressHandlers)){
|
||
|
|
pressHandlers.ForEach(t => {
|
||
|
|
if (t.Item2.Enabled){
|
||
|
|
inputEventQueue.Enqueue(t.Item1);
|
||
|
|
}
|
||
|
|
if (t.Item2.RemoveOnNextTrigger){
|
||
|
|
pressHandlers.Remove(t);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (keyHoldListeners.TryGetValue(key, out var holdHandlers)){
|
||
|
|
holdHandlers.ForEach(t => {
|
||
|
|
if (t.Item2.Enabled){
|
||
|
|
inputEventQueue.Enqueue(t.Item1);
|
||
|
|
}
|
||
|
|
if (t.Item2.RemoveOnNextTrigger){
|
||
|
|
holdHandlers.Remove(t);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
Array.ForEach(pressedLastFrame, key => {
|
||
|
|
if (!keyReleaseListeners.ContainsKey(key)){
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (newState.IsKeyUp(key)){
|
||
|
|
if (keyReleaseListeners.TryGetValue(key, out var releaseHandlers))
|
||
|
|
releaseHandlers.ForEach(t => {
|
||
|
|
if (t.Item2.Enabled){
|
||
|
|
inputEventQueue.Enqueue(t.Item1);
|
||
|
|
}
|
||
|
|
if (t.Item2.RemoveOnNextTrigger){
|
||
|
|
releaseHandlers.Remove(t);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
});
|
||
|
|
oldState = newState;
|
||
|
|
|
||
|
|
// Execute
|
||
|
|
|
||
|
|
foreach (KeypressHandler handler in inputEventQueue){
|
||
|
|
handler(newState);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// private static Thread processInputThread = new(() => {
|
||
|
|
//
|
||
|
|
// });
|
||
|
|
|
||
|
|
public static void AddListener(Keys key, KeypressHandler action, InputTiming timing, InputListenerHook hook) {
|
||
|
|
Dictionary<Keys, List<(KeypressHandler, InputListenerHook)>> workingDict;
|
||
|
|
|
||
|
|
switch (timing){
|
||
|
|
case InputTiming.PRESS:
|
||
|
|
workingDict = keyPressListeners;
|
||
|
|
break;
|
||
|
|
case InputTiming.HOLD:
|
||
|
|
workingDict = keyHoldListeners;
|
||
|
|
break;
|
||
|
|
case InputTiming.RELEASE:
|
||
|
|
workingDict = keyReleaseListeners;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
throw new ArgumentOutOfRangeException(nameof(timing), timing, null);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!workingDict.ContainsKey(key)){
|
||
|
|
workingDict.Add(key, new());
|
||
|
|
}
|
||
|
|
|
||
|
|
workingDict[key].Add((action, hook));
|
||
|
|
}
|
||
|
|
}
|