Added support for mouse input. Removed redundant keyboard state paramater for KeypressHandler, replaced with static field updated every frame.

This commit is contained in:
Perry 2026-01-15 19:49:49 +01:00
parent a2b524ee04
commit 182ebfc31c

View file

@ -1,23 +1,37 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Transactions;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Input;
namespace MonoGameLibrary.Input; namespace MonoGameLibrary.Input;
public static class InputManager { public static class InputManager {
private static Dictionary<Keys, List<InputEntry>> keyPressListeners = new(); private static Dictionary<Keys, List<KeyboardInputEntry>> keyPressListeners = new();
private static Dictionary<Keys, List<InputEntry>> keyHoldListeners = new(); // The bool is for enabling/disabling that method private static Dictionary<Keys, List<KeyboardInputEntry>> keyHoldListeners = new(); // The bool is for enabling/disabling that method
private static Dictionary<Keys, List<InputEntry>> keyReleaseListeners = new(); private static Dictionary<Keys, List<KeyboardInputEntry>> keyReleaseListeners = new();
private static Dictionary<string, InputEntry> labelDict = new(); private static Dictionary<string, InputEntry> labelDict = new();
private static KeyboardState oldState = Keyboard.GetState(); private static KeyboardState oldKBState = Keyboard.GetState();
private static KeyboardState newState; private static KeyboardState newKBState;
public static KeyboardState KeyboardState => newKBState;
private static MouseState oldMouseState = Mouse.GetState();
private static MouseState newMouseState;
public static MouseState MouseState => newMouseState;
private static Dictionary<MouseButton, List<MouseInputEntry>> mousePressListeners = new();
private static Dictionary<MouseButton, List<MouseInputEntry>> mouseHoldListeners = new();
private static Dictionary<MouseButton, List<MouseInputEntry>> mouseReleaseListeners = new();
// public static ConcurrentQueue<Action> inputEventQueue = new(); // public static ConcurrentQueue<Action> inputEventQueue = new();
public delegate void KeypressHandler(KeyboardState state); public delegate void KeypressHandler();
public delegate void MouseHandler();
private static int nextUnnamedId = 0; private static int nextUnnamedId = 0;
@ -32,14 +46,14 @@ public static class InputManager {
public static void NextInputCycle() { public static void NextInputCycle() {
Queue<KeypressHandler> inputEventQueue = new(); Queue<KeypressHandler> inputEventQueue = new();
// Read // Read Keyboard
newState = Keyboard.GetState(); newKBState = Keyboard.GetState();
Keys[] pressed = newState.GetPressedKeys(); Keys[] pressed = newKBState.GetPressedKeys();
Keys[] pressedLastFrame = oldState.GetPressedKeys(); Keys[] pressedLastFrame = oldKBState.GetPressedKeys();
Array.ForEach(pressed, key => { Array.ForEach(pressed, key => {
if (oldState.IsKeyUp(key)){ if (oldKBState.IsKeyUp(key)){
if (keyPressListeners.TryGetValue(key, out var pressHandlers)){ if (keyPressListeners.TryGetValue(key, out var pressHandlers)){
pressHandlers.ForEach(t => { pressHandlers.ForEach(t => {
if (t.Enabled){ if (t.Enabled){
@ -69,7 +83,7 @@ public static class InputManager {
return; return;
} }
if (newState.IsKeyUp(key)){ if (newKBState.IsKeyUp(key)){
if (keyReleaseListeners.TryGetValue(key, out var releaseHandlers)) if (keyReleaseListeners.TryGetValue(key, out var releaseHandlers))
releaseHandlers.ForEach(t => { releaseHandlers.ForEach(t => {
if (t.Enabled){ if (t.Enabled){
@ -81,12 +95,47 @@ public static class InputManager {
}); });
} }
}); });
oldState = newState; oldKBState = newKBState;
// Read Mouse
newMouseState = Mouse.GetState();
List<MouseInputEntry> mouseHandlers = new List<MouseInputEntry>();
foreach (var button in ((MouseButton type, ButtonState current, ButtonState old)[])[
(MouseButton.LEFT, newMouseState.LeftButton, oldMouseState.LeftButton),
(MouseButton.RIGHT, newMouseState.RightButton, oldMouseState.RightButton),
(MouseButton.MIDDLE, newMouseState.MiddleButton, oldMouseState.MiddleButton)
])
{
if (button.current == ButtonState.Pressed){
if (button.old == ButtonState.Released){
mousePressListeners.TryGetValue(button.type, out var pressHandlers);
mouseHandlers.AddRange(pressHandlers ?? new List<MouseInputEntry>());
}
mouseHoldListeners.TryGetValue(button.type, out var holdHandlers);
mouseHandlers.AddRange(holdHandlers ?? new List<MouseInputEntry>());
}
else if (button.old == ButtonState.Pressed){
if (button.current == ButtonState.Released){
mouseReleaseListeners.TryGetValue(button.type, out var releaseHandlers);
mouseHandlers.AddRange(releaseHandlers ?? new List<MouseInputEntry>());
}
}
}
mouseHandlers.ForEach(entry => inputEventQueue.Enqueue(entry.Action));
oldMouseState = newMouseState;
// Execute // Execute
foreach (KeypressHandler handler in inputEventQueue){ foreach (KeypressHandler handler in inputEventQueue){
handler(newState); handler();
} }
} }
@ -98,17 +147,31 @@ public static class InputManager {
if (label.StartsWith("!")){ if (label.StartsWith("!")){
throw new ArgumentException("Label cannot start with !"); throw new ArgumentException("Label cannot start with !");
} }
InputEntry entry = new (label, key, action, timing, hook); KeyboardInputEntry entry = new (label, key, action, timing, hook);
_addListener(entry); _addListenerKB(entry);
} }
public static void AddListener(Keys key, KeypressHandler action, InputTiming timing, InputListenerHook hook) { public static void AddListener(Keys key, KeypressHandler action, InputTiming timing, InputListenerHook hook) {
InputEntry entry = new ($"!{Enum.GetName(typeof(Keys), key)}Handler{nextUnnamedId++}", key, action, timing, hook); KeyboardInputEntry entry = new ($"!{Enum.GetName(typeof(Keys), key)}Handler{nextUnnamedId++}", key, action, timing, hook);
_addListener(entry); _addListenerKB(entry);
} }
private static void _addListener(InputEntry entry) { public static void AddListener(string label, MouseButton button, KeypressHandler action, InputTiming timing, InputListenerHook hook) {
Dictionary<Keys, List<InputEntry>> workingDict; if (label.StartsWith("!")){
throw new ArgumentException("Label cannot start with !");
}
MouseInputEntry entry = new (label, button, action, timing, hook);
_addListenerMouse(entry);
}
public static void AddListener(MouseButton button, KeypressHandler action, InputTiming timing,
InputListenerHook hook) {
MouseInputEntry entry = new ($"!{Enum.GetName(typeof(MouseButton), button)}Handler{nextUnnamedId++}", button, action, timing, hook);
_addListenerMouse(entry);
}
private static void _addListenerKB(KeyboardInputEntry entry) {
Dictionary<Keys, List<KeyboardInputEntry>> workingDict;
switch (entry.Timing){ switch (entry.Timing){
case InputTiming.PRESS: case InputTiming.PRESS:
@ -133,27 +196,76 @@ public static class InputManager {
labelDict.Add(entry.Label, entry); labelDict.Add(entry.Label, entry);
} }
private static void _addListenerMouse(MouseInputEntry entry) {
Dictionary<MouseButton, List<MouseInputEntry>> workingDict;
switch (entry.Timing){
case InputTiming.PRESS:
workingDict = mousePressListeners;
break;
case InputTiming.HOLD:
workingDict = mouseHoldListeners;
break;
case InputTiming.RELEASE:
workingDict = mouseReleaseListeners;
break;
default:
throw new ArgumentOutOfRangeException(nameof(entry.Timing), entry.Timing, null);
}
if (!workingDict.ContainsKey(entry.Button)){
workingDict.Add(entry.Button, new());
}
workingDict[entry.Button].Add(entry);
labelDict.Add(entry.Label, entry);
}
public static InputEntry GetEntry(string label) { public static InputEntry GetEntry(string label) {
return labelDict[label]; return labelDict[label];
} }
public class InputEntry { public abstract class InputEntry {
public string Label; public string Label;
public Keys Key;
public KeypressHandler Action; public KeypressHandler Action;
public InputTiming Timing; public InputTiming Timing;
public InputListenerHook Hook; public InputListenerHook Hook;
public bool Enabled => Hook.Enabled; public bool Enabled => Hook.Enabled;
public InputEntry(string label, Keys key, KeypressHandler action, InputTiming timing, InputListenerHook hook) { public InputEntry(string label, KeypressHandler action, InputTiming timing, InputListenerHook hook) {
Key = key;
Action = action; Action = action;
Timing = timing; Timing = timing;
Hook = hook; Hook = hook;
Label = label; Label = label;
} }
} }
public class KeyboardInputEntry : InputEntry {
public Keys Key;
public KeyboardInputEntry(string label, Keys key, KeypressHandler action, InputTiming timing, InputListenerHook hook) : base(label, action, timing, hook) {
Key = key;
}
}
public class MouseInputEntry : InputEntry {
public MouseButton Button;
public MouseInputEntry(string label, MouseButton button, KeypressHandler action, InputTiming timing, InputListenerHook hook) : base(label, action, timing, hook) {
Button = button;
}
}
public enum MouseButton {
RIGHT,
LEFT,
MIDDLE
}
// private static List<InputEntry> inputQueue = new(); // private static List<InputEntry> inputQueue = new();
} }