Skip to content
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

Keyboard keycode to qwerty char #782

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 211 additions & 1 deletion crates/bevy_input/src/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ pub enum KeyCode {
NumpadAdd,
Apostrophe,
Apps,
Asterix,
Asterisk,
Plus,
At,
Ax,
Expand Down Expand Up @@ -253,3 +253,213 @@ pub enum KeyCode {
Paste,
Cut,
}

impl KeyCode {
/// Converts a key into its textual char representation on a QWERTY keyboard depending on the provided shift status.
///
/// Calls [`KeyCode::to_qwerty_char_with_shift`] if shift is down, or [`KeyCode::to_qwerty_char_without_shift`] if shift isn't down.
///
/// Returns `None` if the key has no valid textual mapping on a QWERTY keyboard with the provided shift status.
///
/// # Examples
///
/// ```
/// # use bevy_input::prelude::KeyCode;
/// #
/// let c1 = KeyCode::Slash.to_qwerty_char(false);
/// assert_eq!(c1, Some('/'));
///
/// let c2 = KeyCode::Slash.to_qwerty_char(true);
/// assert_eq!(c2, Some('?'));
///
/// let c3 = KeyCode::End.to_qwerty_char(true);
/// assert_eq!(c3, None);
/// ```
pub fn to_qwerty_char(self, shift_down: bool) -> Option<char> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think calling this qwerty isn't quite correct. It seems like this would work equally well on an AZERTY keyboard. How about just to_char()?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The chars don't match for Key1 to Key0 between azerty and qwerty.
For example, with azerty you have to press shift to get the number

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arg gotcha gotcha. in that case idk if hard-coding qwerty is the right answer. I don't want to optimize bevy apis for specific regions.

Maybe we should just create a new event for ReceivedCharacter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Realistically, the "correct" approach would be to have different keysets/locales which you run key codes through and which each have conversions. Localization in general is a remarkably complex problem...

Because of this, I was imagining this as a sort of "stop-gap" solution until the proper work would be done.

But looking at that winit event you linked, implementing a new input thing which hooks into that event to supply direct text would likely be the better and more cross-platform solution...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably remove this method. We don't need two ways to get characters with/without shift.

How about just to_char() and to_char_with_shift()

if shift_down {
self.to_qwerty_char_with_shift()
} else {
self.to_qwerty_char_without_shift()
}
}

/// Converts a key into its textual char representation on a QWERTY keyboard when shift is not pressed.
///
/// Returns `None` if the key has no valid textual mapping on a QWERTY keyboard without shift pressed.
///
/// # Examples
///
/// ```
/// # use bevy_input::prelude::KeyCode;
/// #
/// let c1 = KeyCode::Slash.to_qwerty_char_without_shift();
/// assert_eq!(c1, Some('/'))
/// ```
/// This will cause the slash key to return an actual forward slash character (`/`).
/// To get the question mark character (`?`), which is associated with the same key,
/// you must use [`KeyCode::to_qwerty_char_with_shift`].
///
/// ```
/// # use bevy_input::prelude::KeyCode;
/// #
/// let c2 = KeyCode::End.to_qwerty_char_without_shift();
/// assert_eq!(c2, None);
/// ```
/// Since the End key has no textual representation, the function returns `None`.
pub fn to_qwerty_char_without_shift(self) -> Option<char> {
let out = match self {
KeyCode::Key1 => '1',
KeyCode::Key2 => '2',
KeyCode::Key3 => '3',
KeyCode::Key4 => '4',
KeyCode::Key5 => '5',
KeyCode::Key6 => '6',
KeyCode::Key7 => '7',
KeyCode::Key8 => '8',
KeyCode::Key9 => '9',
KeyCode::Key0 => '0',

KeyCode::A => 'a',
KeyCode::B => 'b',
KeyCode::C => 'c',
KeyCode::D => 'd',
KeyCode::E => 'e',
KeyCode::F => 'f',
KeyCode::G => 'g',
KeyCode::H => 'h',
KeyCode::I => 'i',
KeyCode::J => 'j',
KeyCode::K => 'k',
KeyCode::L => 'l',
KeyCode::M => 'm',
KeyCode::N => 'n',
KeyCode::O => 'o',
KeyCode::P => 'p',
KeyCode::Q => 'q',
KeyCode::R => 'r',
KeyCode::S => 's',
KeyCode::T => 't',
KeyCode::U => 'u',
KeyCode::V => 'v',
KeyCode::W => 'w',
KeyCode::X => 'x',
KeyCode::Y => 'y',
KeyCode::Z => 'z',

KeyCode::Numpad0 => '0',
KeyCode::Numpad1 => '1',
KeyCode::Numpad2 => '2',
KeyCode::Numpad3 => '3',
KeyCode::Numpad4 => '4',
KeyCode::Numpad5 => '5',
KeyCode::Numpad6 => '6',
KeyCode::Numpad7 => '7',
KeyCode::Numpad8 => '8',
KeyCode::Numpad9 => '9',

KeyCode::NumpadAdd => '+',
KeyCode::Apostrophe => '\'',
KeyCode::Backslash => '\\',
KeyCode::Comma => ',',
KeyCode::NumpadDecimal => '.',
KeyCode::NumpadDivide => '/',
KeyCode::Equals => '=',
KeyCode::Grave => '`',
KeyCode::LBracket => '[',
KeyCode::Minus => '-',
KeyCode::Period => '.',
KeyCode::RBracket => ']',
KeyCode::Semicolon => ';',
KeyCode::Slash => '/',
KeyCode::Tab => '\t',

_ => return None,
};

Some(out)
}

/// Converts a key into its textual char representation on a QWERTY keyboard when shift is pressed.
///
/// Returns `None` if the key has no valid textual mapping on a QWERTY keyboard with shift pressed.
///
/// # Examples
///
/// ```
/// # use bevy_input::prelude::KeyCode;
/// #
/// let c1 = KeyCode::Slash.to_qwerty_char_with_shift();
/// assert_eq!(c1, Some('?'));
/// ```
/// This will cause the slash key to return a question mark character (`?`).
/// To get the actual forward slash character (`/`), which is associated with the same key,
/// you must use [`KeyCode::to_qwerty_char_without_shift`].
///
/// ```
/// # use bevy_input::prelude::KeyCode;
/// #
/// let c2 = KeyCode::End.to_qwerty_char_with_shift();
/// assert_eq!(c2, None);
/// ```
/// Since the End key has no textual representation, the function returns `None`.
pub fn to_qwerty_char_with_shift(self) -> Option<char> {
let out = match self {
KeyCode::Key1 => '!',
KeyCode::Key2 => '@',
KeyCode::Key3 => '#',
KeyCode::Key4 => '$',
KeyCode::Key5 => '%',
KeyCode::Key6 => '^',
KeyCode::Key7 => '&',
KeyCode::Key8 => '*',
KeyCode::Key9 => '(',
KeyCode::Key0 => ')',

KeyCode::A => 'A',
KeyCode::B => 'B',
KeyCode::C => 'C',
KeyCode::D => 'D',
KeyCode::E => 'E',
KeyCode::F => 'F',
KeyCode::G => 'G',
KeyCode::H => 'H',
KeyCode::I => 'I',
KeyCode::J => 'J',
KeyCode::K => 'K',
KeyCode::L => 'L',
KeyCode::M => 'M',
KeyCode::N => 'N',
KeyCode::O => 'O',
KeyCode::P => 'P',
KeyCode::Q => 'Q',
KeyCode::R => 'R',
KeyCode::S => 'S',
KeyCode::T => 'T',
KeyCode::U => 'U',
KeyCode::V => 'V',
KeyCode::W => 'W',
KeyCode::X => 'X',
KeyCode::Y => 'Y',
KeyCode::Z => 'Z',

KeyCode::NumpadAdd => '+',
KeyCode::Apostrophe => '"',
KeyCode::Backslash => '|',
KeyCode::Comma => '<',
KeyCode::NumpadDivide => '/',
KeyCode::Equals => '+',
KeyCode::Grave => '~',
KeyCode::LBracket => '{',
KeyCode::Minus => '_',
KeyCode::Period => '>',
KeyCode::RBracket => '}',
KeyCode::Semicolon => ':',
KeyCode::Slash => '?',
KeyCode::Tab => '\t',

_ => return None,
};

Some(out)
}
}
2 changes: 1 addition & 1 deletion crates/bevy_winit/src/converters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ pub fn convert_virtual_key_code(virtual_key_code: winit::event::VirtualKeyCode)
winit::event::VirtualKeyCode::NumpadAdd => KeyCode::NumpadAdd,
winit::event::VirtualKeyCode::Apostrophe => KeyCode::Apostrophe,
winit::event::VirtualKeyCode::Apps => KeyCode::Apps,
winit::event::VirtualKeyCode::Asterisk => KeyCode::Asterix,
winit::event::VirtualKeyCode::Asterisk => KeyCode::Asterisk,
winit::event::VirtualKeyCode::Plus => KeyCode::Plus,
winit::event::VirtualKeyCode::At => KeyCode::At,
winit::event::VirtualKeyCode::Ax => KeyCode::Ax,
Expand Down