mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Display keys based off of scancodes
Queries the OS to translate physical keyboard scancodes into Strings that can be shown in the UI. Addresses issues #861 and #354
This commit is contained in:
parent
522e89d57f
commit
0d7d069d41
@ -49,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Bag tooltips only show slots now
|
||||
- Removed infinite armour values from most admin items
|
||||
- Item tooltips during trades will now inform the user of what ctrl-click and shift-click do
|
||||
- International keyboards can now display more key names on Linux and Windows instead of `Unknown`.
|
||||
|
||||
### Removed
|
||||
|
||||
|
47
Cargo.lock
generated
47
Cargo.lock
generated
@ -2570,6 +2570,19 @@ dependencies = [
|
||||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "keyboard-keynames"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6dbe132877d7a0327c4282840703c2cb456312fae930898b5dc126844889626"
|
||||
dependencies = [
|
||||
"wayland-client 0.28.5",
|
||||
"winapi 0.3.9",
|
||||
"winit",
|
||||
"xcb 0.8.2",
|
||||
"xkbcommon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "khronos_api"
|
||||
version = "3.1.0"
|
||||
@ -2820,6 +2833,16 @@ version = "2.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
|
||||
|
||||
[[package]]
|
||||
name = "memmap"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.1.0"
|
||||
@ -5687,6 +5710,7 @@ dependencies = [
|
||||
"image",
|
||||
"inline_tweak",
|
||||
"itertools 0.10.0",
|
||||
"keyboard-keynames",
|
||||
"lazy_static",
|
||||
"native-dialog",
|
||||
"num 0.4.0",
|
||||
@ -6435,7 +6459,7 @@ version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5e937afd03b64b7be4f959cc044e09260a47241b71e56933f37db097bf7859d"
|
||||
dependencies = [
|
||||
"xcb",
|
||||
"xcb 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -6471,6 +6495,16 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xcb"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e917a3f24142e9ff8be2414e36c649d47d6cc2ba81f16201cdef96e533e02de"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xcb"
|
||||
version = "0.9.0"
|
||||
@ -6513,6 +6547,17 @@ dependencies = [
|
||||
"xkbcommon-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xkbcommon"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fda0ea5f7ddabd51deeeda7799bee06274112f577da7dd3d954b8eda731b2fce"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"memmap",
|
||||
"xcb 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xkbcommon-sys"
|
||||
version = "0.7.4"
|
||||
|
@ -45,6 +45,7 @@ iced = {package = "iced_native", git = "https://github.com/hecrj/iced", rev = "8
|
||||
iced_winit = {git = "https://github.com/hecrj/iced", rev = "8d882d787e6b7fd7c2435f42f82933e2ed904edf"}
|
||||
window_clipboard = "0.2"
|
||||
glyph_brush = "0.7.0"
|
||||
keyboard-keynames = "0.1.0"
|
||||
|
||||
# ECS
|
||||
specs = {git = "https://github.com/amethyst/specs.git", rev = "5a9b71035007be0e3574f35184acac1cd4530496"}
|
||||
|
@ -126,6 +126,7 @@ impl<'a> Widget for Buttons<'a> {
|
||||
Some(inv) => inv,
|
||||
None => return None,
|
||||
};
|
||||
let key_layout = &self.global_state.window.key_layout;
|
||||
let localized_strings = self.localized_strings;
|
||||
let arrow_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer
|
||||
|
||||
@ -184,13 +185,13 @@ impl<'a> Widget for Buttons<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Bag)
|
||||
{
|
||||
Text::new(bag.to_string().as_str())
|
||||
Text::new(bag.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.bag, 0.0, 0.0)
|
||||
.font_size(10)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.bag_text_bg, ui);
|
||||
Text::new(bag.to_string().as_str())
|
||||
Text::new(bag.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.bag_text_bg, 1.0, 1.0)
|
||||
.font_size(10)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -245,13 +246,13 @@ impl<'a> Widget for Buttons<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Settings)
|
||||
{
|
||||
Text::new(settings.to_string().as_str())
|
||||
Text::new(settings.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.settings_button, 0.0, 0.0)
|
||||
.font_size(10)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.settings_text_bg, ui);
|
||||
Text::new(settings.to_string().as_str())
|
||||
Text::new(settings.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.settings_text_bg, 1.0, 1.0)
|
||||
.font_size(10)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -283,13 +284,13 @@ impl<'a> Widget for Buttons<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Social)
|
||||
{
|
||||
Text::new(social.to_string().as_str())
|
||||
Text::new(social.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.social_button, 0.0, 0.0)
|
||||
.font_size(10)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.social_text_bg, ui);
|
||||
Text::new(social.to_string().as_str())
|
||||
Text::new(social.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.social_text_bg, 1.0, 1.0)
|
||||
.font_size(10)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -320,13 +321,13 @@ impl<'a> Widget for Buttons<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Map)
|
||||
{
|
||||
Text::new(map.to_string().as_str())
|
||||
Text::new(map.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.map_button, 0.0, 0.0)
|
||||
.font_size(10)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.map_text_bg, ui);
|
||||
Text::new(map.to_string().as_str())
|
||||
Text::new(map.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.map_text_bg, 1.0, 1.0)
|
||||
.font_size(10)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -362,13 +363,13 @@ impl<'a> Widget for Buttons<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Spellbook)
|
||||
{
|
||||
Text::new(spell.to_string().as_str())
|
||||
Text::new(spell.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.spellbook_button, 0.0, 0.0)
|
||||
.font_size(10)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.spellbook_text_bg, ui);
|
||||
Text::new(spell.to_string().as_str())
|
||||
Text::new(spell.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.spellbook_text_bg, 1.0, 1.0)
|
||||
.font_size(10)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -422,13 +423,13 @@ impl<'a> Widget for Buttons<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Crafting)
|
||||
{
|
||||
Text::new(crafting.to_string().as_str())
|
||||
Text::new(crafting.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.crafting_button, 0.0, 0.0)
|
||||
.font_size(10)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.crafting_text_bg, ui);
|
||||
Text::new(crafting.to_string().as_str())
|
||||
Text::new(crafting.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.crafting_text_bg, 1.0, 1.0)
|
||||
.font_size(10)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
|
@ -151,6 +151,7 @@ impl<'a> Widget for Group<'a> {
|
||||
let widget::UpdateArgs { state, ui, .. } = args;
|
||||
let mut events = Vec::new();
|
||||
let localized_strings = self.localized_strings;
|
||||
let key_layout = &self.global_state.window.key_layout;
|
||||
let buff_ani = ((self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8) + 0.5; //Animation timer
|
||||
let debug_on = self.global_state.settings.interface.toggle_debug;
|
||||
let offset = if debug_on { 270.0 } else { 0.0 };
|
||||
@ -802,7 +803,7 @@ impl<'a> Widget for Group<'a> {
|
||||
.settings
|
||||
.controls
|
||||
.get_binding(GameInput::AcceptGroupInvite)
|
||||
.map_or_else(|| "".into(), |key| key.to_string());
|
||||
.map_or_else(|| "".into(), |key| key.display_string(key_layout));
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(90.0, 22.0)
|
||||
.bottom_left_with_margins_on(state.ids.bg, 15.0, 15.0)
|
||||
@ -827,7 +828,7 @@ impl<'a> Widget for Group<'a> {
|
||||
.settings
|
||||
.controls
|
||||
.get_binding(GameInput::DeclineGroupInvite)
|
||||
.map_or_else(|| "".into(), |key| key.to_string());
|
||||
.map_or_else(|| "".into(), |key| key.display_string(key_layout));
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(90.0, 22.0)
|
||||
.bottom_right_with_margins_on(state.ids.bg, 15.0, 15.0)
|
||||
|
@ -953,6 +953,7 @@ impl Hud {
|
||||
let fps = global_state.clock.stats().average_tps;
|
||||
let version = common::util::DISPLAY_VERSION_LONG.clone();
|
||||
let i18n = &*global_state.i18n.read();
|
||||
let key_layout = &global_state.window.key_layout;
|
||||
|
||||
if self.show.ingame {
|
||||
let ecs = client.state().ecs();
|
||||
@ -1389,6 +1390,7 @@ impl Hud {
|
||||
&global_state.settings.controls,
|
||||
// If we're currently set to interact with the item...
|
||||
active,
|
||||
&global_state.window.key_layout,
|
||||
)
|
||||
.x_y(0.0, 100.0)
|
||||
.position_ingame(pos)
|
||||
@ -1434,6 +1436,7 @@ impl Hud {
|
||||
&self.fonts,
|
||||
&global_state.settings.controls,
|
||||
true,
|
||||
&global_state.window.key_layout,
|
||||
)
|
||||
.x_y(0.0, 100.0)
|
||||
.position_ingame(over_pos)
|
||||
@ -1791,21 +1794,19 @@ impl Hud {
|
||||
.mid_top_with_margin_on(self.ids.intro_button, -20.0 + arrow_ani as f64)
|
||||
.color(Some(QUALITY_LEGENDARY))
|
||||
.set(self.ids.tut_arrow, ui_widgets);
|
||||
Text::new(
|
||||
&i18n
|
||||
.get("hud.tutorial_click_here")
|
||||
.replace("{key}", toggle_cursor_key.to_string().as_str()),
|
||||
)
|
||||
Text::new(&i18n.get("hud.tutorial_click_here").replace(
|
||||
"{key}",
|
||||
toggle_cursor_key.display_string(key_layout).as_str(),
|
||||
))
|
||||
.mid_top_with_margin_on(self.ids.tut_arrow, -18.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
.color(BLACK)
|
||||
.set(self.ids.tut_arrow_txt_bg, ui_widgets);
|
||||
Text::new(
|
||||
&i18n
|
||||
.get("hud.tutorial_click_here")
|
||||
.replace("{key}", toggle_cursor_key.to_string().as_str()),
|
||||
)
|
||||
Text::new(&i18n.get("hud.tutorial_click_here").replace(
|
||||
"{key}",
|
||||
toggle_cursor_key.display_string(key_layout).as_str(),
|
||||
))
|
||||
.bottom_right_with_margins_on(self.ids.tut_arrow_txt_bg, 1.0, 1.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(self.fonts.cyri.scale(14))
|
||||
@ -2071,7 +2072,7 @@ impl Hud {
|
||||
Text::new(
|
||||
&i18n
|
||||
.get("hud.press_key_to_toggle_keybindings_fmt")
|
||||
.replace("{key}", help_key.to_string().as_str()),
|
||||
.replace("{key}", help_key.display_string(key_layout).as_str()),
|
||||
)
|
||||
.color(TEXT_COLOR)
|
||||
.down_from(self.ids.num_particles, 5.0)
|
||||
@ -2085,11 +2086,10 @@ impl Hud {
|
||||
.controls
|
||||
.get_binding(GameInput::ToggleDebug)
|
||||
{
|
||||
Text::new(
|
||||
&i18n
|
||||
.get("hud.press_key_to_toggle_debug_info_fmt")
|
||||
.replace("{key}", toggle_debug_key.to_string().as_str()),
|
||||
)
|
||||
Text::new(&i18n.get("hud.press_key_to_toggle_debug_info_fmt").replace(
|
||||
"{key}",
|
||||
toggle_debug_key.display_string(key_layout).as_str(),
|
||||
))
|
||||
.color(TEXT_COLOR)
|
||||
.down_from(self.ids.help_info, 5.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -2102,7 +2102,7 @@ impl Hud {
|
||||
Text::new(
|
||||
&i18n
|
||||
.get("hud.press_key_to_show_keybindings_fmt")
|
||||
.replace("{key}", help_key.to_string().as_str()),
|
||||
.replace("{key}", help_key.display_string(key_layout).as_str()),
|
||||
)
|
||||
.color(TEXT_COLOR)
|
||||
.bottom_left_with_margins_on(ui_widgets.window, 210.0, 10.0)
|
||||
@ -2116,11 +2116,10 @@ impl Hud {
|
||||
.controls
|
||||
.get_binding(GameInput::ToggleDebug)
|
||||
{
|
||||
Text::new(
|
||||
&i18n
|
||||
.get("hud.press_key_to_show_debug_info_fmt")
|
||||
.replace("{key}", toggle_debug_key.to_string().as_str()),
|
||||
)
|
||||
Text::new(&i18n.get("hud.press_key_to_show_debug_info_fmt").replace(
|
||||
"{key}",
|
||||
toggle_debug_key.display_string(key_layout).as_str(),
|
||||
))
|
||||
.color(TEXT_COLOR)
|
||||
.top_left_with_margins_on(ui_widgets.window, 5.0, 5.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -2133,11 +2132,10 @@ impl Hud {
|
||||
.controls
|
||||
.get_binding(GameInput::ToggleLantern)
|
||||
{
|
||||
Text::new(
|
||||
&i18n
|
||||
.get("hud.press_key_to_toggle_lantern_fmt")
|
||||
.replace("{key}", toggle_lantern_key.to_string().as_str()),
|
||||
)
|
||||
Text::new(&i18n.get("hud.press_key_to_toggle_lantern_fmt").replace(
|
||||
"{key}",
|
||||
toggle_lantern_key.display_string(key_layout).as_str(),
|
||||
))
|
||||
.color(TEXT_COLOR)
|
||||
.up_from(self.ids.help_info, 2.0)
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -2259,6 +2257,7 @@ impl Hud {
|
||||
&global_state.i18n,
|
||||
&global_state.settings,
|
||||
&prompt_dialog_settings,
|
||||
&global_state.window.key_layout,
|
||||
)
|
||||
.set(self.ids.prompt_dialog, ui_widgets)
|
||||
{
|
||||
@ -2894,7 +2893,7 @@ impl Hud {
|
||||
if self.show.free_look {
|
||||
let msg = i18n
|
||||
.get("hud.free_look_indicator")
|
||||
.replace("{key}", freelook_key.to_string().as_str());
|
||||
.replace("{key}", freelook_key.display_string(key_layout).as_str());
|
||||
Text::new(&msg)
|
||||
.color(TEXT_BG)
|
||||
.mid_top_with_margin_on(ui_widgets.window, indicator_offset)
|
||||
@ -2937,7 +2936,7 @@ impl Hud {
|
||||
if self.show.camera_clamp {
|
||||
let msg = i18n
|
||||
.get("hud.camera_clamp_indicator")
|
||||
.replace("{key}", cameraclamp_key.to_string().as_str());
|
||||
.replace("{key}", cameraclamp_key.display_string(key_layout).as_str());
|
||||
Text::new(&msg)
|
||||
.color(TEXT_BG)
|
||||
.mid_top_with_margin_on(ui_widgets.window, indicator_offset)
|
||||
|
@ -10,6 +10,7 @@ use conrod_core::{
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub const TEXT_COLOR: Color = Color::Rgba(0.61, 0.61, 0.89, 1.0);
|
||||
use keyboard_keynames::key_layout::KeyLayout;
|
||||
|
||||
widget_ids! {
|
||||
struct Ids {
|
||||
@ -34,6 +35,7 @@ pub struct Overitem<'a> {
|
||||
#[conrod(common_builder)]
|
||||
common: widget::CommonBuilder,
|
||||
active: bool,
|
||||
key_layout: &'a Option<KeyLayout>,
|
||||
}
|
||||
|
||||
impl<'a> Overitem<'a> {
|
||||
@ -44,6 +46,7 @@ impl<'a> Overitem<'a> {
|
||||
fonts: &'a Fonts,
|
||||
controls: &'a ControlSettings,
|
||||
active: bool,
|
||||
key_layout: &'a Option<KeyLayout>,
|
||||
) -> Self {
|
||||
Self {
|
||||
name,
|
||||
@ -53,6 +56,7 @@ impl<'a> Overitem<'a> {
|
||||
controls,
|
||||
common: widget::CommonBuilder::default(),
|
||||
active,
|
||||
key_layout,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -143,7 +147,7 @@ impl<'a> Widget for Overitem<'a> {
|
||||
.depth(self.distance_from_player_sqr + 1.0)
|
||||
.parent(id)
|
||||
.set(state.ids.btn_bg, ui);
|
||||
Text::new(&format!("{}", key_button))
|
||||
Text::new(key_button.display_string(self.key_layout).as_str())
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.font_size(btn_font_size as u32)
|
||||
.color(TEXT_COLOR)
|
||||
|
@ -11,6 +11,7 @@ use conrod_core::{
|
||||
widget::{self, Button, Image, Text},
|
||||
widget_ids, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||
};
|
||||
use keyboard_keynames::key_layout::KeyLayout;
|
||||
|
||||
widget_ids! {
|
||||
struct Ids {
|
||||
@ -34,6 +35,7 @@ pub struct PromptDialog<'a> {
|
||||
localized_strings: &'a AssetHandle<Localization>,
|
||||
settings: &'a Settings,
|
||||
prompt_dialog_settings: &'a PromptDialogSettings,
|
||||
key_layout: &'a Option<KeyLayout>,
|
||||
}
|
||||
|
||||
impl<'a> PromptDialog<'a> {
|
||||
@ -44,6 +46,7 @@ impl<'a> PromptDialog<'a> {
|
||||
localized_strings: &'a AssetHandle<Localization>,
|
||||
settings: &'a Settings,
|
||||
prompt_dialog_settings: &'a PromptDialogSettings,
|
||||
key_layout: &'a Option<KeyLayout>,
|
||||
) -> Self {
|
||||
Self {
|
||||
imgs,
|
||||
@ -52,6 +55,7 @@ impl<'a> PromptDialog<'a> {
|
||||
common: widget::CommonBuilder::default(),
|
||||
settings,
|
||||
prompt_dialog_settings,
|
||||
key_layout,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -88,12 +92,12 @@ impl<'a> Widget for PromptDialog<'a> {
|
||||
.settings
|
||||
.controls
|
||||
.get_binding(GameInput::AcceptGroupInvite)
|
||||
.map_or_else(|| "".into(), |key| key.to_string());
|
||||
.map_or_else(|| "".into(), |key| key.display_string(self.key_layout));
|
||||
let decline_key = self
|
||||
.settings
|
||||
.controls
|
||||
.get_binding(GameInput::DeclineGroupInvite)
|
||||
.map_or_else(|| "".into(), |key| key.to_string());
|
||||
.map_or_else(|| "".into(), |key| key.display_string(self.key_layout));
|
||||
|
||||
// Window
|
||||
Image::new(self.imgs.prompt_top)
|
||||
|
@ -74,6 +74,7 @@ impl<'a> Widget for Controls<'a> {
|
||||
let widget::UpdateArgs { state, ui, .. } = args;
|
||||
|
||||
let mut events = Vec::new();
|
||||
let key_layout = &self.global_state.window.key_layout;
|
||||
|
||||
Rectangle::fill_with(args.rect.dim(), color::TRANSPARENT)
|
||||
.xy(args.rect.xy())
|
||||
@ -125,7 +126,7 @@ impl<'a> Widget for Controls<'a> {
|
||||
)
|
||||
} else if let Some(key) = controls.get_binding(game_input) {
|
||||
(
|
||||
key.to_string(),
|
||||
key.display_string(key_layout),
|
||||
if controls.has_conflicting_bindings(key) {
|
||||
TEXT_BIND_CONFLICT_COLOR
|
||||
} else {
|
||||
|
@ -245,6 +245,7 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani);
|
||||
|
||||
let localized_strings = self.localized_strings;
|
||||
let key_layout = &self.global_state.window.key_layout;
|
||||
|
||||
let slot_offset = 3.0;
|
||||
|
||||
@ -265,7 +266,7 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
Text::new(
|
||||
&localized_strings
|
||||
.get("hud.press_key_to_respawn")
|
||||
.replace("{key}", key.to_string().as_str()),
|
||||
.replace("{key}", key.display_string(key_layout).as_str()),
|
||||
)
|
||||
.mid_bottom_with_margin_on(state.ids.death_message_1_bg, -120.0)
|
||||
.font_size(self.fonts.cyri.scale(30))
|
||||
@ -281,7 +282,7 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
Text::new(
|
||||
&localized_strings
|
||||
.get("hud.press_key_to_respawn")
|
||||
.replace("{key}", key.to_string().as_str()),
|
||||
.replace("{key}", key.display_string(key_layout).as_str()),
|
||||
)
|
||||
.bottom_left_with_margins_on(state.ids.death_message_2_bg, 2.0, 2.0)
|
||||
.font_size(self.fonts.cyri.scale(30))
|
||||
@ -825,13 +826,13 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Slot1)
|
||||
{
|
||||
Text::new(slot1.to_string().as_str())
|
||||
Text::new(slot1.display_string(key_layout).as_str())
|
||||
.top_right_with_margins_on(state.ids.slot1, 3.0, 5.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.slot1_text_bg, ui);
|
||||
Text::new(slot1.to_string().as_str())
|
||||
Text::new(slot1.display_string(key_layout).as_str())
|
||||
.bottom_left_with_margins_on(state.ids.slot1_text_bg, 1.0, 1.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -844,13 +845,13 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Slot2)
|
||||
{
|
||||
Text::new(slot2.to_string().as_str())
|
||||
Text::new(slot2.display_string(key_layout).as_str())
|
||||
.top_right_with_margins_on(state.ids.slot2, 3.0, 5.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.slot2_text_bg, ui);
|
||||
Text::new(slot2.to_string().as_str())
|
||||
Text::new(slot2.display_string(key_layout).as_str())
|
||||
.bottom_left_with_margins_on(state.ids.slot2_text_bg, 1.0, 1.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -863,13 +864,13 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Slot3)
|
||||
{
|
||||
Text::new(slot3.to_string().as_str())
|
||||
Text::new(slot3.display_string(key_layout).as_str())
|
||||
.top_right_with_margins_on(state.ids.slot3, 3.0, 5.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.slot3_text_bg, ui);
|
||||
Text::new(slot3.to_string().as_str())
|
||||
Text::new(slot3.display_string(key_layout).as_str())
|
||||
.bottom_left_with_margins_on(state.ids.slot3_text_bg, 1.0, 1.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -882,13 +883,13 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Slot4)
|
||||
{
|
||||
Text::new(slot4.to_string().as_str())
|
||||
Text::new(slot4.display_string(key_layout).as_str())
|
||||
.top_right_with_margins_on(state.ids.slot4, 3.0, 5.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.slot4_text_bg, ui);
|
||||
Text::new(slot4.to_string().as_str())
|
||||
Text::new(slot4.display_string(key_layout).as_str())
|
||||
.bottom_left_with_margins_on(state.ids.slot4_text_bg, 1.0, 1.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -901,13 +902,13 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Slot5)
|
||||
{
|
||||
Text::new(slot5.to_string().as_str())
|
||||
Text::new(slot5.display_string(key_layout).as_str())
|
||||
.top_right_with_margins_on(state.ids.slot5, 3.0, 5.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.slot5_text_bg, ui);
|
||||
Text::new(slot5.to_string().as_str())
|
||||
Text::new(slot5.display_string(key_layout).as_str())
|
||||
.bottom_left_with_margins_on(state.ids.slot5_text_bg, 1.0, 1.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -920,13 +921,13 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Slot6)
|
||||
{
|
||||
Text::new(slot6.to_string().as_str())
|
||||
Text::new(slot6.display_string(key_layout).as_str())
|
||||
.top_right_with_margins_on(state.ids.slot6, 3.0, 5.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.slot6_text_bg, ui);
|
||||
Text::new(slot6.to_string().as_str())
|
||||
Text::new(slot6.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.slot6_text_bg, 1.0, 1.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -939,13 +940,13 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Slot7)
|
||||
{
|
||||
Text::new(slot7.to_string().as_str())
|
||||
Text::new(slot7.display_string(key_layout).as_str())
|
||||
.top_right_with_margins_on(state.ids.slot7, 3.0, 5.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.slot7_text_bg, ui);
|
||||
Text::new(slot7.to_string().as_str())
|
||||
Text::new(slot7.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.slot7_text_bg, 1.0, 1.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -958,13 +959,13 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Slot8)
|
||||
{
|
||||
Text::new(slot8.to_string().as_str())
|
||||
Text::new(slot8.display_string(key_layout).as_str())
|
||||
.top_right_with_margins_on(state.ids.slot8, 3.0, 5.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.slot8_text_bg, ui);
|
||||
Text::new(slot8.to_string().as_str())
|
||||
Text::new(slot8.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.slot8_text_bg, 1.0, 1.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -977,13 +978,13 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Slot9)
|
||||
{
|
||||
Text::new(slot9.to_string().as_str())
|
||||
Text::new(slot9.display_string(key_layout).as_str())
|
||||
.top_right_with_margins_on(state.ids.slot9, 3.0, 5.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.slot9_text_bg, ui);
|
||||
Text::new(slot9.to_string().as_str())
|
||||
Text::new(slot9.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.slot9_text_bg, 1.0, 1.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
@ -996,13 +997,13 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
.controls
|
||||
.get_binding(GameInput::Slot10)
|
||||
{
|
||||
Text::new(slot10.to_string().as_str())
|
||||
Text::new(slot10.display_string(key_layout).as_str())
|
||||
.top_right_with_margins_on(state.ids.slot10, 3.0, 5.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
.color(BLACK)
|
||||
.set(state.ids.slot10_text_bg, ui);
|
||||
Text::new(slot10.to_string().as_str())
|
||||
Text::new(slot10.display_string(key_layout).as_str())
|
||||
.bottom_right_with_margins_on(state.ids.slot10_text_bg, 1.0, 1.0)
|
||||
.font_size(self.fonts.cyri.scale(8))
|
||||
.font_id(self.fonts.cyri.conrod_id)
|
||||
|
@ -9,9 +9,9 @@ use crossbeam::channel;
|
||||
use gilrs::{EventType, Gilrs};
|
||||
use hashbrown::HashMap;
|
||||
use itertools::Itertools;
|
||||
use keyboard_keynames::key_layout::KeyLayout;
|
||||
use old_school_gfx_glutin_ext::{ContextBuilderExt, WindowInitExt, WindowUpdateExt};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use tracing::{error, info, warn};
|
||||
use vek::*;
|
||||
use winit::monitor::VideoMode;
|
||||
@ -320,11 +320,11 @@ pub enum KeyMouse {
|
||||
ScanKey(winit::event::ScanCode),
|
||||
}
|
||||
|
||||
impl fmt::Display for KeyMouse {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl KeyMouse {
|
||||
pub fn display_string(&self, key_layout: &Option<KeyLayout>) -> String {
|
||||
use self::KeyMouse::*;
|
||||
use winit::event::{MouseButton, VirtualKeyCode::*};
|
||||
write!(f, "{}", match self {
|
||||
let key_string = match self {
|
||||
Key(Key1) => "1",
|
||||
Key(Key2) => "2",
|
||||
Key(Key3) => "3",
|
||||
@ -491,11 +491,20 @@ impl fmt::Display for KeyMouse {
|
||||
Mouse(MouseButton::Left) => "M1",
|
||||
Mouse(MouseButton::Right) => "M2",
|
||||
Mouse(MouseButton::Middle) => "M3",
|
||||
Mouse(MouseButton::Other(button)) =>
|
||||
Mouse(MouseButton::Other(button)) => {
|
||||
// Additional mouse buttons after middle click start at 1
|
||||
return write!(f, "M{}", button + 3),
|
||||
ScanKey(_) => "Unknown",
|
||||
})
|
||||
return format!("M{}", button + 3);
|
||||
},
|
||||
ScanKey(scancode) => {
|
||||
if let Some(layout) = key_layout {
|
||||
return layout.get_key_as_string(*scancode);
|
||||
} else {
|
||||
return format!("Unknown({})", scancode);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
String::from(key_string)
|
||||
}
|
||||
}
|
||||
|
||||
@ -525,6 +534,7 @@ pub struct Window {
|
||||
// Used for screenshots & fullscreen toggle to deduplicate/postpone to after event handler
|
||||
take_screenshot: bool,
|
||||
toggle_fullscreen: bool,
|
||||
pub key_layout: Option<KeyLayout>,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
@ -600,6 +610,18 @@ impl Window {
|
||||
|
||||
let scale_factor = window.window().scale_factor();
|
||||
|
||||
let key_layout = match KeyLayout::new_from_window(window.window()) {
|
||||
Ok(kl) => Some(kl),
|
||||
Err(err) => {
|
||||
warn!(
|
||||
?err,
|
||||
"Failed to construct the scancode to keyname mapper, falling back to \
|
||||
displaying Unknown(<scancode>)."
|
||||
);
|
||||
None
|
||||
},
|
||||
};
|
||||
|
||||
let mut this = Self {
|
||||
renderer: Renderer::new(
|
||||
device,
|
||||
@ -631,6 +653,7 @@ impl Window {
|
||||
message_receiver,
|
||||
take_screenshot: false,
|
||||
toggle_fullscreen: false,
|
||||
key_layout,
|
||||
};
|
||||
|
||||
this.set_fullscreen_mode(settings.graphics.fullscreen);
|
||||
|
Loading…
Reference in New Issue
Block a user