-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve keyboard input with Input<ScanCode> #2052
Comments
Key Codes are layout-dependent. Scan Codes are layout-independent. I think we should improve our keyboard APIs to encourage good practices:
So I would suggest the following:
These changes should result in a much cleaner keyboard input API that encourages good practices and is easy to use correctly. |
To me this isn't necessarily clear cut. Game input generally cares about the "shape" of the keyboard (ex: WASD movement or the position of the arrow keys). ScanCode is closer to the ground truth of the "shape". But it also isnt the ground truth because we live in a world with different physical keyboard layouts. By adopting ScanCode as our standard for game inputs, we are essentially saying that non-qwerty-scancode-aligned keyboard owners need to remap all of the defaults a game provides (or have the game provide alternative mappings for each layout they want to support). This feels pretty english-centric to me. Using ScanCode for input will likely result in better outcomes, but it isn't a complete solution:
Semi-related Bevy conversation: #782 |
As part of this, would Bevy need a portable mechanism to translate a EDIT: hmm, this is the same use case as #1995 which is now closed, but as far as I can see #805 only added a |
Hmm ... what? This seems backwards to me? What is a "non-qwerty-scancode-aligned keyboard"? I thought the scan codes represent the physical keys and are the same on every keyboard? If you are referring to my suggestion about naming the enum variants after QWERTY, I can see the point, but those are just internal enum values. I suggest using the matching KeyCode for text display to users / as part of UI. Game inputs should use scan codes, precisely so that they are not "english-centric". That way they will work regardless of whether i switch my keyboard to QWERTY, Dvorak, or Russian. The current KeyCode-based API is english-centric, because it makes it inconvenient to use non-qwerty (or worse, non-latin) layouts.
Of course some people have special nonstandard keyboards (like the various ergonomic keyboards with weird physical arrangement of keys), but those people are going to have to customize/remap their game inputs anyway. |
This is what I was contesting. I understand that scan code is the raw event sent from the keyboard and doesn't directly correlate to a letter (this is the OS's job, which is what produces KeyCode and is virtual-keyboard-layout dependent). I have only ever used "qwerty" keyboards, but I am currently under the impression that international keyboards exist (such as this azerty keyboard) with scan codes that don't line up with the physical positions of qwerty keyboard scancodes. This is confounded by the fact that other azerty keyboards apparently do use qwerty scan codes (and rely on the OS to configure an azerty layout). I was under the impression that the W3C KeyboardEvent.code spec was designed to combat this by providing abstract non-scancode values. But maybe they also assume scancode positions are constant and they just 1:1 map scancode to new names.
If these are truly "non-standard" in terms of "an overwhelming majority of the world uses the same scan code positions", then I'm totally cool with using scancodes because we can't support every fringe thing that exists. I just want to make sure we aren't alienating some significant portion of the world's population. I'm definitely not an expert here, but I'd like some way to quantify the actual situation. Something like "windows / mac / linux all assume physical scancode positions are stable as defined by some standard X and only 0.1% of the population uses standard Y". edit: adjusted qwerty scancode link to something that uses hex values for parity with the other example |
The USB HID spec for keyboards is based off the physical layout of a QWERTY keyboard so I think any enumeration should use the spec's defined values where applicable. [See Keyboard / Keypad page (0x07) on pdf page 82]: |
Fun news! on macOS, the scan codes provided by winit don't seem to be the real scan codes, but the virtual key codes macOS is using... https://developer.apple.com/documentation/coregraphics/cgkeycode my "q" key have a scan code of... 0 |
Ugh, why does macOS always ... uhm ... "think different" |
I tried running Bevy with rust-windowing/winit#1890 (macOS impl for rust-windowing/winit#753) and events are much better for keyboard 👍 example event:
It seems done for Windows (rust-windowing/winit#1788), in review for macOS (rust-windowing/winit#1890), draft for web (rust-windowing/winit#1888) and under work for Linux. Unless we are ready to implement something temporary, I think we should wait for this to be done on winit side. |
Wow that api is so much better. And yeah the scancodes for mac (even in the new impl) are completely out of sync with what I expect them to be. Sounds like the "physical_key" api is the way to go. Relevant bit from the api redesign issue: Which is basically what the W3C decided to roll with for their new keyboard api for the web. Unfortunately this is the sort of thing that could drag on for a long time (iirc winit's eventloop 2.0 started midway through 2018 and winit 20.0 dropped at the start of 2020). We should try to help them if possible. Bevy contributors motivated to make input better (faster) should consider reaching out in this issue: rust-windowing/winit#1806 |
Heh, rust-windowing/winit#753 has been open for well over two years now, so I hope we don't end up spending too much time getting this across the finish line. Any help on this matter would be appreciated. The Linux impl should have a PR up later this week (hopefully), so what would be most helpful is help with code review, preferably from someone familiar with X11 and/or Wayland, as both these platforms (effectively) lack maintainers. I'm sure @ArturKovacs would also appreciate another pair of eyes (and more testing) on the macOS impl. |
and now rust-windowing/winit#1932 is up for anyone on Linux to test 🎉 |
Are there any updates on this? |
I'm not sure I understand this discussion fully, I too also need a way to show the user which keys he has selected, in a controls panel. I did this simple thing. Is this bad?
|
This issue is not about that. This issue is about being able to handle keyboard input in a way that does not break for users with multiple keyboard layouts set in the OS. For instance, I have a Workman (previously Dvorak), QWERTY (because i need it to test stuff that assumes everyone is using qwerty, like Bevy currently), and a Cyrillic layout (for Bulgarian/Ukrainian/Russian). French users use AZERTY. Etc... Currently, Bevy does not work properly, because key codes come from the currently active layout. If a game uses WASD for movement, and I play the game, I have to switch to qwerty, or the keys will be in the wrong places (physically). If I have a keybinding (like Alt-Shift or something) for switching layouts, there is a risk I might accidentally press it while in game, causing the keyboard input to get messed up in the middle of gameplay. The solution to this are "scan codes". Scan codes identify the physical key on the keyboard, regardless of the software layout set in the OS. In Bevy, scan codes are only available when using keyboard events, not when using the Further, scan codes are only represented as opaque integers, not a friendly enum like |
# Objective - I wanted to have controls independent from keyboard layout and found that bevy doesn't have a proper implementation for that ## Solution - I created a `ScanCode` enum with two hundreds scan codes and updated `keyboard_input_system` to include and update `ResMut<Input<ScanCode>>` - closes both #2052 and #862 Co-authored-by: Bleb1k <[email protected]>
# Objective - I wanted to have controls independent from keyboard layout and found that bevy doesn't have a proper implementation for that ## Solution - I created a `ScanCode` enum with two hundreds scan codes and updated `keyboard_input_system` to include and update `ResMut<Input<ScanCode>>` - closes both bevyengine#2052 and bevyengine#862 Co-authored-by: Bleb1k <[email protected]>
# Objective - I wanted to have controls independent from keyboard layout and found that bevy doesn't have a proper implementation for that ## Solution - I created a `ScanCode` enum with two hundreds scan codes and updated `keyboard_input_system` to include and update `ResMut<Input<ScanCode>>` - closes both bevyengine#2052 and bevyengine#862 Co-authored-by: Bleb1k <[email protected]>
# Objective - I wanted to have controls independent from keyboard layout and found that bevy doesn't have a proper implementation for that ## Solution - I created a `ScanCode` enum with two hundreds scan codes and updated `keyboard_input_system` to include and update `ResMut<Input<ScanCode>>` - closes both bevyengine#2052 and bevyengine#862 Co-authored-by: Bleb1k <[email protected]>
This was added in #5495. Closing. |
# Objective - I wanted to have controls independent from keyboard layout and found that bevy doesn't have a proper implementation for that ## Solution - I created a `ScanCode` enum with two hundreds scan codes and updated `keyboard_input_system` to include and update `ResMut<Input<ScanCode>>` - closes both bevyengine#2052 and bevyengine#862 Co-authored-by: Bleb1k <[email protected]>
What problem does this solve or what need does it fill?
Right now, getting the status of raw keys is difficult. An
Input<ScanCode>
would make this simpler.What solution would you like?
Add a
Input<ScanCode>
resource by default in bevy_input, and change the ScanCode type to be an enum where the keys are represented as the key they correspond to on a standard QWERTY keyboard.What alternative(s) have you considered?
Do nothing, or do this partially.
Additional context
Started discussion in discord
The text was updated successfully, but these errors were encountered: