Gondwana Game Engine Development (master) - 2.6.1
Gondwana is a cross-platform 2.5D game and rendering engine written in C#/.NET 8. It provides fine-grained control over rendering, timing, and scene composition, with built-in support for parallax, z-ordering, pixel overhang, collision detection, and particle effects. Gondwana targets desktop and web platforms using SkiaSharp for graphics and pluggable audio backends for desktop and browser targets.
Loading...
Searching...
No Matches
KeyboardEventPoller.cs
1using System.Collections.Concurrent;
2using System.Collections.ObjectModel;
3
5
9public sealed class KeyboardEventPoller
10{
14 public static KeyboardEventPoller? Instance { get; private set; }
15
24 public static void Initialize(IKeyboardAdapter adapter)
25 {
26 Instance = new KeyboardEventPoller(adapter);
27 }
28
35 public event Action<KeyDownEventArgs>? KeyDown;
36
37 // Hot path uses int key codes.
38 private readonly Dictionary<int, KeyEventConfiguration> _keyConfigs = new();
39 private readonly Dictionary<int, bool> _previousPressed = new();
40
41 // Apply monitoring changes on the engine thread to avoid ToList() allocations.
42 private readonly ConcurrentQueue<Action> _pendingOps = new();
43
44 private KeyboardEventPoller() { }
45
47 {
48 Adapter = adapter;
49 }
50
54 public IKeyboardAdapter? Adapter { get; private set; }
55
59 public bool PauseAllKeyEvents { get; set; }
60
66 internal void PollForEvents(long tick)
67 {
69 return;
70
71 var adapter = Adapter;
72 if (adapter is null)
73 return;
74
75 // Apply any pending adds/removes on the engine thread.
76 while (_pendingOps.TryDequeue(out var op))
77 op();
78
79 var mods = adapter.CurrentKeyboardModifiers;
80
81 foreach (var kvp in _keyConfigs)
82 {
83 int keyCode = kvp.Key;
84 var config = kvp.Value;
85
86 bool currentlyPressed = adapter.IsDown(keyCode);
87 bool previouslyPressed = _previousPressed.TryGetValue(keyCode, out var prev) && prev;
88
89 // Transition: not pressed -> pressed
90 if (currentlyPressed && !previouslyPressed)
91 {
92 _previousPressed[keyCode] = true;
93 config._lastEventTick = tick;
94
95 KeyDown?.Invoke(new KeyDownEventArgs(config, mods, KeyAction.Pressed));
96 continue;
97 }
98
99 // Still pressed -> maybe repeated (throttled)
100 if (currentlyPressed && previouslyPressed)
101 {
102 if (!config.IsPaused && config.ReadyForNextEvent(tick))
103 {
104 config._lastEventTick = tick;
105 KeyDown?.Invoke(new KeyDownEventArgs(config, mods, KeyAction.Repeated));
106 }
107 continue;
108 }
109
110 // Transition: pressed -> not pressed
111 if (!currentlyPressed && previouslyPressed)
112 {
113 _previousPressed[keyCode] = false;
114 KeyDown?.Invoke(new KeyDownEventArgs(config, mods, KeyAction.Released));
115 }
116
117 // not pressed && not previously pressed => nothing
118 }
119 }
120
129 public void StartMonitoringKey(int keyCode, string? displayName = null, double timeBetweenEvents = -1, bool isPaused = false)
130 {
131 _pendingOps.Enqueue(() =>
132 {
133 if (timeBetweenEvents < 0)
134 timeBetweenEvents = Engine.Instance.Configuration.TimeBetweenKeyboardEvents;
135
136 var name = string.IsNullOrWhiteSpace(displayName) ? keyCode.ToString() : displayName;
137 var config = new KeyEventConfiguration(name, timeBetweenEvents, isPaused);
138
139 _keyConfigs[keyCode] = config;
140
141 var adapter = Adapter;
142 _previousPressed[keyCode] = adapter?.IsDown(keyCode) ?? false;
143 });
144 }
145
155 public void StopMonitoringKey(int keyCode)
156 {
157 _pendingOps.Enqueue(() =>
158 {
159 _keyConfigs.Remove(keyCode);
160 _previousPressed.Remove(keyCode);
161 });
162 }
163
173 public void StopMonitoringKey(string key)
174 {
175 if (int.TryParse(key, out int code))
176 StopMonitoringKey(code);
177 }
178
186 {
187 _pendingOps.Enqueue(() =>
188 {
189 _keyConfigs.Clear();
190 _previousPressed.Clear();
191 });
192 }
193
197 public IReadOnlyDictionary<int, KeyEventConfiguration> AllKeyConfigs =>
198 new ReadOnlyDictionary<int, KeyEventConfiguration>(_keyConfigs);
199}
Represents the core game engine singleton responsible for managing the main update loop,...
Definition Engine.cs:36
static Engine Instance
Gets the singleton instance of the Engine.
Definition Engine.cs:49
EngineConfiguration Configuration
Gets the current engine configuration settings.
Definition Engine.cs:928
Provides data for keyboard key events, including information about the key that was pressed,...
Represents the configuration for keyboard key events, including key identification and timing control...
Cross-platform singleton keyboard handler with throttling and manual input state feeding.
void StopMonitoringAllKeys()
Unregisters all keys from event monitoring, clearing all key configurations and state tracking....
bool PauseAllKeyEvents
Pauses all key events globally.
IReadOnlyDictionary< int, KeyEventConfiguration > AllKeyConfigs
Exposes monitored key configurations. Treat as engine-thread-only unless you add external synchroniza...
void StopMonitoringKey(int keyCode)
Unregisters a specific key from event monitoring by its platform-agnostic key code....
void StopMonitoringKey(string key)
Unregisters a specific key from event monitoring by parsing its string representation....
static void Initialize(IKeyboardAdapter adapter)
Initializes the singleton instance of the KeyboardEventPoller with the specified keyboard adapter....
Action< KeyDownEventArgs >? KeyDown
Occurs when a monitored keyboard key is pressed, released, or repeated based on its configuration and...
void StartMonitoringKey(int keyCode, string? displayName=null, double timeBetweenEvents=-1, bool isPaused=false)
Primary API: monitor by platform-agnostic key code. Platform layers (WinForms, SDL,...
IKeyboardAdapter? Adapter
Gets the current keyboard adapter in use.
static ? KeyboardEventPoller Instance
Singleton instance of the KeyboardEventPoller class.
Represents an adapter for keyboard input, providing access to the currently pressed keys and active m...
KeyAction
Represents the type of action performed on a keyboard key, indicating whether the key was pressed,...
Definition KeyAction.cs:10