Added input management, added lables to input handler entries, added filtering by label
This commit is contained in:
parent
7366d5cb22
commit
a2b524ee04
5 changed files with 180 additions and 0 deletions
2
MonoGameLibrary.sln.DotSettings.user
Normal file
2
MonoGameLibrary.sln.DotSettings.user
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AKeys_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa69b121f85054691b2a8d28643003c23136600_003F08_003F1a47fbcb_003FKeys_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>
|
||||
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using MonoGameLibrary.Input;
|
||||
|
||||
namespace MonoGameLibrary;
|
||||
|
||||
|
|
@ -88,4 +89,9 @@ public class Core : Game
|
|||
// Create the sprite batch instance.
|
||||
spriteBatch = new SpriteBatch(graphicsDevice);
|
||||
}
|
||||
|
||||
protected override void Update(GameTime gameTime) {
|
||||
InputManager.NextInputCycle();
|
||||
base.Update(gameTime);
|
||||
}
|
||||
}
|
||||
6
MonoGameLibrary/Input/InputListenerHook.cs
Normal file
6
MonoGameLibrary/Input/InputListenerHook.cs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
namespace MonoGameLibrary.Input;
|
||||
|
||||
public class InputListenerHook(bool enabled, bool oneTimeOnly = false) {
|
||||
public bool Enabled { get; set; } = enabled;
|
||||
public bool RemoveOnNextTrigger { get; set; } = oneTimeOnly;
|
||||
}
|
||||
159
MonoGameLibrary/Input/InputManager.cs
Normal file
159
MonoGameLibrary/Input/InputManager.cs
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
|
||||
namespace MonoGameLibrary.Input;
|
||||
|
||||
|
||||
public static class InputManager {
|
||||
private static Dictionary<Keys, List<InputEntry>> keyPressListeners = new();
|
||||
private static Dictionary<Keys, List<InputEntry>> keyHoldListeners = new(); // The bool is for enabling/disabling that method
|
||||
private static Dictionary<Keys, List<InputEntry>> keyReleaseListeners = new();
|
||||
|
||||
private static Dictionary<string, InputEntry> labelDict = new();
|
||||
|
||||
private static KeyboardState oldState = Keyboard.GetState();
|
||||
private static KeyboardState newState;
|
||||
|
||||
// public static ConcurrentQueue<Action> inputEventQueue = new();
|
||||
|
||||
public delegate void KeypressHandler(KeyboardState state);
|
||||
|
||||
private static int nextUnnamedId = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
// 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.Enabled){
|
||||
inputEventQueue.Enqueue(t.Action);
|
||||
}
|
||||
if (t.Hook.RemoveOnNextTrigger){
|
||||
pressHandlers.Remove(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (keyHoldListeners.TryGetValue(key, out var holdHandlers)){
|
||||
holdHandlers.ForEach(t => {
|
||||
if (t.Enabled){
|
||||
inputEventQueue.Enqueue(t.Action);
|
||||
}
|
||||
if (t.Hook.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.Enabled){
|
||||
inputEventQueue.Enqueue(t.Action);
|
||||
}
|
||||
if (t.Hook.RemoveOnNextTrigger){
|
||||
releaseHandlers.Remove(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
oldState = newState;
|
||||
|
||||
// Execute
|
||||
|
||||
foreach (KeypressHandler handler in inputEventQueue){
|
||||
handler(newState);
|
||||
}
|
||||
}
|
||||
|
||||
// private static Thread processInputThread = new(() => {
|
||||
//
|
||||
// });
|
||||
|
||||
public static void AddListener(string label, Keys key, KeypressHandler action, InputTiming timing, InputListenerHook hook) {
|
||||
if (label.StartsWith("!")){
|
||||
throw new ArgumentException("Label cannot start with !");
|
||||
}
|
||||
InputEntry entry = new (label, key, action, timing, hook);
|
||||
_addListener(entry);
|
||||
}
|
||||
|
||||
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);
|
||||
_addListener(entry);
|
||||
}
|
||||
|
||||
private static void _addListener(InputEntry entry) {
|
||||
Dictionary<Keys, List<InputEntry>> workingDict;
|
||||
|
||||
switch (entry.Timing){
|
||||
case InputTiming.PRESS:
|
||||
workingDict = keyPressListeners;
|
||||
break;
|
||||
case InputTiming.HOLD:
|
||||
workingDict = keyHoldListeners;
|
||||
break;
|
||||
case InputTiming.RELEASE:
|
||||
workingDict = keyReleaseListeners;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(entry.Timing), entry.Timing, null);
|
||||
}
|
||||
|
||||
if (!workingDict.ContainsKey(entry.Key)){
|
||||
workingDict.Add(entry.Key, new());
|
||||
}
|
||||
|
||||
workingDict[entry.Key].Add(entry);
|
||||
|
||||
labelDict.Add(entry.Label, entry);
|
||||
}
|
||||
|
||||
public static InputEntry GetEntry(string label) {
|
||||
return labelDict[label];
|
||||
}
|
||||
|
||||
public class InputEntry {
|
||||
|
||||
public string Label;
|
||||
public Keys Key;
|
||||
public KeypressHandler Action;
|
||||
public InputTiming Timing;
|
||||
public InputListenerHook Hook;
|
||||
|
||||
public bool Enabled => Hook.Enabled;
|
||||
|
||||
public InputEntry(string label, Keys key, KeypressHandler action, InputTiming timing, InputListenerHook hook) {
|
||||
Key = key;
|
||||
Action = action;
|
||||
Timing = timing;
|
||||
Hook = hook;
|
||||
Label = label;
|
||||
}
|
||||
}
|
||||
// private static List<InputEntry> inputQueue = new();
|
||||
}
|
||||
7
MonoGameLibrary/Input/InputTiming.cs
Normal file
7
MonoGameLibrary/Input/InputTiming.cs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
namespace MonoGameLibrary.Input;
|
||||
|
||||
public enum InputTiming {
|
||||
PRESS,
|
||||
HOLD,
|
||||
RELEASE
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue