Skip to content

Commit 8d90167

Browse files
authored
Merge pull request #1254 from dotnet/feature/input-isscancodepressed
Add IKeyboard function to check scancode pressed state
2 parents 9001b79 + 6c3bfe6 commit 8d90167

File tree

8 files changed

+126
-45
lines changed

8 files changed

+126
-45
lines changed

src/Input/Silk.NET.Input.Common/Interfaces/IKeyboard.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ public interface IKeyboard : IInputDevice
2828
/// <returns>Whether or not the key is pressed.</returns>
2929
bool IsKeyPressed(Key key);
3030

31+
/// <summary>
32+
/// Checks if a specific scancode is pressed.
33+
/// </summary>
34+
/// <param name="scancode">The scancode to check.</param>
35+
/// <returns>Whether or not the scancode is pressed.</returns>
36+
bool IsScancodePressed(int scancode);
37+
3138
/// <summary>
3239
/// Called when a key is pressed.
3340
/// </summary>

src/Input/Silk.NET.Input.Common/PublicAPI/net5.0/PublicAPI.Shipped.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ Silk.NET.Input.IKeyboard.ClipboardText.get -> string!
112112
Silk.NET.Input.IKeyboard.ClipboardText.set -> void
113113
Silk.NET.Input.IKeyboard.EndInput() -> void
114114
Silk.NET.Input.IKeyboard.IsKeyPressed(Silk.NET.Input.Key key) -> bool
115+
Silk.NET.Input.IKeyboard.IsScancodePressed(int scancode) -> bool
115116
Silk.NET.Input.IKeyboard.KeyChar -> System.Action<Silk.NET.Input.IKeyboard!, char>?
116117
Silk.NET.Input.IKeyboard.KeyDown -> System.Action<Silk.NET.Input.IKeyboard!, Silk.NET.Input.Key, int>?
117118
Silk.NET.Input.IKeyboard.KeyUp -> System.Action<Silk.NET.Input.IKeyboard!, Silk.NET.Input.Key, int>?

src/Input/Silk.NET.Input.Common/PublicAPI/netcoreapp3.1/PublicAPI.Shipped.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ Silk.NET.Input.IKeyboard.ClipboardText.get -> string!
112112
Silk.NET.Input.IKeyboard.ClipboardText.set -> void
113113
Silk.NET.Input.IKeyboard.EndInput() -> void
114114
Silk.NET.Input.IKeyboard.IsKeyPressed(Silk.NET.Input.Key key) -> bool
115+
Silk.NET.Input.IKeyboard.IsScancodePressed(int scancode) -> bool
115116
Silk.NET.Input.IKeyboard.KeyChar -> System.Action<Silk.NET.Input.IKeyboard!, char>?
116117
Silk.NET.Input.IKeyboard.KeyDown -> System.Action<Silk.NET.Input.IKeyboard!, Silk.NET.Input.Key, int>?
117118
Silk.NET.Input.IKeyboard.KeyUp -> System.Action<Silk.NET.Input.IKeyboard!, Silk.NET.Input.Key, int>?

src/Input/Silk.NET.Input.Common/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ Silk.NET.Input.IKeyboard.ClipboardText.get -> string!
112112
Silk.NET.Input.IKeyboard.ClipboardText.set -> void
113113
Silk.NET.Input.IKeyboard.EndInput() -> void
114114
Silk.NET.Input.IKeyboard.IsKeyPressed(Silk.NET.Input.Key key) -> bool
115+
Silk.NET.Input.IKeyboard.IsScancodePressed(int scancode) -> bool
115116
Silk.NET.Input.IKeyboard.KeyChar -> System.Action<Silk.NET.Input.IKeyboard!, char>?
116117
Silk.NET.Input.IKeyboard.KeyDown -> System.Action<Silk.NET.Input.IKeyboard!, Silk.NET.Input.Key, int>?
117118
Silk.NET.Input.IKeyboard.KeyUp -> System.Action<Silk.NET.Input.IKeyboard!, Silk.NET.Input.Key, int>?

src/Input/Silk.NET.Input.Common/PublicAPI/netstandard2.1/PublicAPI.Shipped.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ Silk.NET.Input.IKeyboard.ClipboardText.get -> string!
112112
Silk.NET.Input.IKeyboard.ClipboardText.set -> void
113113
Silk.NET.Input.IKeyboard.EndInput() -> void
114114
Silk.NET.Input.IKeyboard.IsKeyPressed(Silk.NET.Input.Key key) -> bool
115+
Silk.NET.Input.IKeyboard.IsScancodePressed(int scancode) -> bool
115116
Silk.NET.Input.IKeyboard.KeyChar -> System.Action<Silk.NET.Input.IKeyboard!, char>?
116117
Silk.NET.Input.IKeyboard.KeyDown -> System.Action<Silk.NET.Input.IKeyboard!, Silk.NET.Input.Key, int>?
117118
Silk.NET.Input.IKeyboard.KeyUp -> System.Action<Silk.NET.Input.IKeyboard!, Silk.NET.Input.Key, int>?

src/Input/Silk.NET.Input.Glfw/GlfwKeyboard.cs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ internal class GlfwKeyboard : IKeyboard, IGlfwSubscriber
1818
private unsafe WindowHandle* _handle;
1919
private GlfwCallbacks.CharCallback? _char;
2020
private GlfwCallbacks.KeyCallback? _key;
21+
private List<int> _scancodesDown = new List<int>();
22+
2123
public string Name { get; } = "Silk.NET Keyboard (via GLFW)";
2224
public int Index { get; } = 0;
2325
public bool IsConnected { get; } = true;
@@ -31,6 +33,8 @@ public unsafe string ClipboardText
3133
public unsafe bool IsKeyPressed
3234
(Key key) => GlfwProvider.GLFW.Value.GetKey(_handle, ConvertKey(key)) == (int) InputAction.Press;
3335

36+
public unsafe bool IsScancodePressed(int scancode) => _scancodesDown.Contains(scancode);
37+
3438
public event Action<IKeyboard, Key, int>? KeyDown;
3539
public event Action<IKeyboard, Key, int>? KeyUp;
3640
public event Action<IKeyboard, char>? KeyChar;
@@ -49,13 +53,22 @@ public unsafe void Subscribe(GlfwEvents events)
4953
_handle = events.Handle;
5054
events.Char += _char = (_, c) => KeyChar?.Invoke(this, (char) c);
5155
events.Key += _key = (_, key, code, action, mods) =>
52-
(action switch
56+
{
57+
Action<IKeyboard, Key, int>? evt = null;
58+
switch(action)
5359
{
54-
InputAction.Press => KeyDown,
55-
InputAction.Release => KeyUp,
56-
InputAction.Repeat => null,
57-
_ => null
58-
})?.Invoke(this, ConvertKey(key), code);
60+
case InputAction.Press:
61+
evt = KeyDown;
62+
_scancodesDown.Add(code);
63+
break;
64+
case InputAction.Release:
65+
evt = KeyUp;
66+
_scancodesDown.Remove(code);
67+
break;
68+
}
69+
70+
evt?.Invoke(this, ConvertKey(key), code);
71+
};
5972
}
6073

6174
public void Unsubscribe(GlfwEvents events)

src/Input/Silk.NET.Input.Sdl/SdlKeyboard.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Silk.NET.Input.Sdl
99
internal partial class SdlKeyboard : IKeyboard, ISdlDevice
1010
{
1111
private readonly SdlInputContext _ctx;
12-
private List<Key> _keysDown = new List<Key>();
12+
private List<Scancode> _scancodesDown = new List<Scancode>();
1313

1414
public SdlKeyboard(SdlInputContext ctx)
1515
{
@@ -27,7 +27,8 @@ public string ClipboardText
2727
get => _ctx.Sdl.GetClipboardTextS();
2828
set => _ctx.Sdl.SetClipboardText(value);
2929
}
30-
public bool IsKeyPressed(Key key) => _keysDown.Contains(key);
30+
public bool IsKeyPressed(Key key) => _scancodesDown.Any(x => _keyMap.TryGetValue(x, out Key skey) && key == skey);
31+
public bool IsScancodePressed(int scancode) => _scancodesDown.Contains((Scancode) scancode);
3132
public event Action<IKeyboard, Key, int>? KeyDown;
3233
public event Action<IKeyboard, Key, int>? KeyUp;
3334
public event Action<IKeyboard, char>? KeyChar;
@@ -46,13 +47,13 @@ public unsafe void DoEvent(Event @event)
4647
if (_keyMap.TryGetValue(@event.Key.Keysym.Scancode, out var key))
4748
{
4849
keyDown = key;
49-
_keysDown.Add(keyDown);
5050
}
5151
else
5252
{
5353
keyDown = Key.Unknown;
5454
}
5555

56+
_scancodesDown.Add(@event.Key.Keysym.Scancode);
5657
KeyDown?.Invoke(this, keyDown, (int) @event.Key.Keysym.Scancode);
5758
}
5859

@@ -66,13 +67,13 @@ public unsafe void DoEvent(Event @event)
6667
if (_keyMap.TryGetValue(@event.Key.Keysym.Scancode, out var key))
6768
{
6869
keyUp = key;
69-
_keysDown.Remove(keyUp);
7070
}
7171
else
7272
{
7373
keyUp = Key.Unknown;
7474
}
7575

76+
_scancodesDown.Remove(@event.Key.Keysym.Scancode);
7677
KeyUp?.Invoke(this, keyUp, (int) @event.Key.Keysym.Scancode);
7778
}
7879

src/Lab/Experiments/InputTest/Program.cs

Lines changed: 91 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Diagnostics;
34
using System.Drawing;
45
using System.Linq;
@@ -33,10 +34,15 @@ private static void Run(string[]? args = null)
3334
window.Run();
3435
}
3536

37+
static Key[] _allKeys = Enum.GetValues(typeof(Key)).Cast<Key>().Where(x => x != Key.Unknown).ToArray();
38+
static List<Key> _keysDown = new List<Key>();
39+
static List<int> _scancodesDown = new List<int>();
40+
3641
public static Action OnLoad(IView window) =>
3742
() =>
3843
{
3944
var input = window.CreateInput();
45+
window.Update += OnUpdate(input);
4046
input.ConnectionChanged += DoConnect;
4147
Console.WriteLine("Now, go press buttons in the window and you'll see the feedback here.");
4248
foreach (var gamepad in input.Gamepads)
@@ -69,44 +75,66 @@ public static Action OnLoad(IView window) =>
6975
//};
7076
};
7177

72-
private static void GamepadOnTriggerMoved(IGamepad g, Trigger t)
78+
public static Action<double> OnUpdate(IInputContext input) =>
79+
(dt) =>
80+
{
81+
foreach (Key k in _allKeys)
82+
{
83+
// This should really be separated into different keyboards, but since all current backends
84+
// just report a single keyboard we'll leave this test as is for now.
85+
if (_keysDown.Contains(k) != input.Keyboards.Any(x => x.IsKeyPressed(k)))
86+
{
87+
Console.WriteLine($"[ERROR] IsKeyPressed() and event mismatch! Key {k}");
88+
}
89+
}
90+
91+
for (int s = 0; s < 256; s++)
92+
{
93+
if (_scancodesDown.Contains(s) != input.Keyboards.Any(x => x.IsScancodePressed(s)))
94+
{
95+
Console.WriteLine($"[ERROR] IsScancodePressed() and event mismatch! Scancode {s}");
96+
}
97+
}
98+
};
99+
100+
private static void GamepadOnTriggerMoved(IGamepad gamepad, Trigger trigger)
73101
{
74-
Console.WriteLine($"G{g.Index}> {t.Index} trigger moved: {t.Position}");
102+
Console.WriteLine($"G{gamepad.Index}> {trigger.Index} trigger moved: {trigger.Position}");
75103
}
76104

77-
private static void GamepadOnThumbstickMoved(IGamepad g, Thumbstick t)
105+
private static void GamepadOnThumbstickMoved(IGamepad gamepad, Thumbstick thumbstick)
78106
{
79-
Console.WriteLine($"G{g.Index}> {t.Index} thumbstick moved: ({t.X}, {t.Y})");
107+
Console.WriteLine($"G{gamepad.Index}> {thumbstick.Index} thumbstick moved: ({thumbstick.X}, {thumbstick.Y})");
80108
}
81109

82-
private static void JoystickOnHatMoved(IJoystick arg1, Hat arg2)
110+
private static void JoystickOnHatMoved(IJoystick joystick, Hat hat)
83111
{
84-
Console.WriteLine($"J{arg1.Index}> {arg2.Index} hat moved: {arg2.Position}");
112+
Console.WriteLine($"J{joystick.Index}> {hat.Index} hat moved: {hat.Position}");
85113
}
86114

87-
private static void JoystickOnAxisMoved(IJoystick arg1, Axis arg2)
115+
private static void JoystickOnAxisMoved(IJoystick joystick, Axis axis)
88116
{
89-
Console.WriteLine($"J{arg1.Index}> {arg2.Index} axis moved: {arg2.Position}");
117+
Console.WriteLine($"J{joystick.Index}> {axis.Index} axis moved: {axis.Position}");
90118
}
91119

92-
private static void JoystickOnButtonUp(IJoystick arg1, Button arg2)
120+
private static void JoystickOnButtonUp(IJoystick joystick, Button button)
93121
{
94-
Console.WriteLine($"J{arg1.Index}> {arg2.Name} down.");
122+
Console.WriteLine($"J{joystick.Index}> {button.Name} down.");
95123
}
96124

97-
private static void JoystickOnButtonDown(IJoystick arg1, Button arg2)
125+
private static void JoystickOnButtonDown(IJoystick joystick, Button button)
98126
{
99-
Console.WriteLine($"J{arg1.Index}> {arg2.Name} down.");
127+
Console.WriteLine($"J{joystick.Index}> {button.Name} down.");
100128
}
101129

102-
private static void InputGamepadOnButtonDown(IGamepad arg1, Button arg2)
130+
private static void InputGamepadOnButtonDown(IGamepad gamepad, Button button)
103131
{
104-
Console.WriteLine($"G{arg1.Index}> {arg2.Name} down. {(int) arg2.Name}");
132+
Console.WriteLine($"G{gamepad.Index}> {button.Name} down. {(int) button.Name}");
105133
}
106134

107-
private static void InputGamepadOnButtonUp(IGamepad arg1, Button arg2)
135+
private static void InputGamepadOnButtonUp(IGamepad gamepad, Button button)
108136
{
109-
Console.WriteLine($"G{arg1.Index}> {arg2.Name} up.");
137+
Console.WriteLine($"G{gamepad.Index}> {button.Name} up.");
110138
}
111139

112140
public static unsafe void DoConnect(IInputDevice device, bool isConnected)
@@ -214,49 +242,77 @@ public static unsafe void DoConnect(IInputDevice device, bool isConnected)
214242
}
215243
}
216244

217-
private static void KeyboardOnKeyChar(IKeyboard arg1, char arg2)
245+
private static void KeyboardOnKeyChar(IKeyboard keyboard, char c)
218246
{
219-
Console.WriteLine($"K{arg1.Index}> {arg2} received.");
247+
Console.WriteLine($"K{keyboard.Index}> {c} received.");
220248
}
221249

222-
private static void MouseOnMouseMove(IMouse arg1, Vector2 arg2)
250+
private static void MouseOnMouseMove(IMouse mouse, Vector2 pos)
223251
{
224-
Console.WriteLine($"M{arg1.Index}> Moved: {arg2}");
252+
Console.WriteLine($"M{mouse.Index}> Moved: {pos}");
225253
}
226254

227-
private static void MouseOnScroll(IMouse arg1, ScrollWheel arg2)
255+
private static void MouseOnScroll(IMouse mouse, ScrollWheel sw)
228256
{
229-
Console.WriteLine($"K{arg1.Index}> Scrolled: ({arg2.X}, {arg2.Y})");
257+
Console.WriteLine($"K{mouse.Index}> Scrolled: ({sw.X}, {sw.Y})");
230258
}
231259

232-
private static void MouseOnMouseDown(IMouse arg1, MouseButton arg2)
260+
private static void MouseOnMouseDown(IMouse mouse, MouseButton button)
233261
{
234-
Console.WriteLine($"M{arg1.Index}> {arg2} down.");
262+
Console.WriteLine($"M{mouse.Index}> {button} down.");
235263
}
236264

237-
private static void MouseOnMouseUp(IMouse arg1, MouseButton arg2)
265+
private static void MouseOnMouseUp(IMouse mouse, MouseButton button)
238266
{
239-
Console.WriteLine($"M{arg1.Index}> {arg2} up.");
267+
Console.WriteLine($"M{mouse.Index}> {button} up.");
240268
}
241269

242-
private static void MouseOnClick(IMouse arg1, MouseButton arg2, Vector2 pos)
270+
private static void MouseOnClick(IMouse mouse, MouseButton button, Vector2 pos)
243271
{
244-
Console.WriteLine($"M{arg1.Index}> {arg2} single click.");
272+
Console.WriteLine($"M{mouse.Index}> {button} single click.");
245273
}
246274

247-
private static void MouseOnDoubleClick(IMouse arg1, MouseButton arg2, Vector2 pos)
275+
private static void MouseOnDoubleClick(IMouse mouse, MouseButton button, Vector2 pos)
248276
{
249-
Console.WriteLine($"M{arg1.Index}> {arg2} double click.");
277+
Console.WriteLine($"M{mouse.Index}> {button} double click.");
250278
}
251279

252-
private static void KeyboardOnKeyUp(IKeyboard arg1, Key arg2, int _)
280+
private static void KeyboardOnKeyUp(IKeyboard keyboard, Key key, int scancode)
253281
{
254-
Console.WriteLine($"K{arg1.Index}> {arg2} up.");
282+
Console.WriteLine($"K{keyboard.Index}> key={key} scancode={scancode} up.");
283+
284+
if (key != Key.Unknown)
285+
{
286+
int keyIndex = _keysDown.IndexOf(key);
287+
if (keyIndex < 0)
288+
Console.WriteLine($"[ERROR] Double key up detected? K{keyboard.Index}> {key} up.");
289+
else
290+
_keysDown.RemoveAt(keyIndex);
291+
}
292+
293+
int scancodeIndex = _scancodesDown.IndexOf(scancode);
294+
if (scancodeIndex < 0)
295+
Console.WriteLine($"[ERROR] Double scancode up detected? K{keyboard.Index}> {scancode} up.");
296+
else
297+
_scancodesDown.RemoveAt(scancodeIndex);
255298
}
256299

257-
private static void KeyboardOnKeyDown(IKeyboard arg1, Key arg2, int _)
300+
private static void KeyboardOnKeyDown(IKeyboard keyboard, Key key, int scancode)
258301
{
259-
Console.WriteLine($"K{arg1.Index}> {arg2} down.");
302+
Console.WriteLine($"K{keyboard.Index}> key={key} scancode={scancode} down.");
303+
304+
if (key != Key.Unknown)
305+
{
306+
if (_keysDown.Contains(key))
307+
Console.WriteLine($"[ERROR] Double key down detected? K{keyboard.Index}> {key} down.");
308+
else
309+
_keysDown.Add(key);
310+
}
311+
312+
if (_scancodesDown.Contains(scancode))
313+
Console.WriteLine($"[ERROR] Double scancode down detected? K{keyboard.Index}> {scancode} down.");
314+
else
315+
_scancodesDown.Add(scancode);
260316
}
261317
}
262-
}
318+
}

0 commit comments

Comments
 (0)