mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
support removing key bindings
This commit is contained in:
parent
e12390b08b
commit
71d2be5f76
@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Worldgen wildlife density modifier in features.ron
|
- Worldgen wildlife density modifier in features.ron
|
||||||
- Rivers now make ambient sounds (again)
|
- Rivers now make ambient sounds (again)
|
||||||
- Added a setting to see own speech bubbles
|
- Added a setting to see own speech bubbles
|
||||||
|
- Added an option to allow players to remove keybindings
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
"main.connecting": "Connecting",
|
"main.connecting": "Connecting",
|
||||||
"main.creating_world": "Creating world",
|
"main.creating_world": "Creating world",
|
||||||
"main.tip": "Tip:",
|
"main.tip": "Tip:",
|
||||||
|
"main.unbound_key_tip": "unbound",
|
||||||
|
|
||||||
// Welcome notice that appears the first time Veloren is started
|
// Welcome notice that appears the first time Veloren is started
|
||||||
"main.notice": r#"Welcome to the alpha version of Veloren!
|
"main.notice": r#"Welcome to the alpha version of Veloren!
|
||||||
|
@ -22,6 +22,7 @@ widget_ids! {
|
|||||||
window_r,
|
window_r,
|
||||||
window_scrollbar,
|
window_scrollbar,
|
||||||
reset_controls_button,
|
reset_controls_button,
|
||||||
|
keybinding_mode_button,
|
||||||
controls_alignment_rectangle,
|
controls_alignment_rectangle,
|
||||||
controls_texts[],
|
controls_texts[],
|
||||||
controls_buttons[],
|
controls_buttons[],
|
||||||
@ -178,7 +179,11 @@ impl<'a> Widget for Controls<'a> {
|
|||||||
.set(button_id, ui)
|
.set(button_id, ui)
|
||||||
.was_clicked()
|
.was_clicked()
|
||||||
{
|
{
|
||||||
|
if self.global_state.window.keybinding_mode {
|
||||||
events.push(ChangeBinding(game_input));
|
events.push(ChangeBinding(game_input));
|
||||||
|
} else {
|
||||||
|
events.push(RemoveBinding(game_input));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Set the previous id to the current one for the next cycle
|
// Set the previous id to the current one for the next cycle
|
||||||
previous_element_id = Some(text_id);
|
previous_element_id = Some(text_id);
|
||||||
@ -204,6 +209,27 @@ impl<'a> Widget for Controls<'a> {
|
|||||||
previous_element_id = Some(state.ids.reset_controls_button)
|
previous_element_id = Some(state.ids.reset_controls_button)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let toggle_widget = Button::new()
|
||||||
|
.label(if self.global_state.window.keybinding_mode {
|
||||||
|
"remap"
|
||||||
|
} else {
|
||||||
|
"clear"
|
||||||
|
})
|
||||||
|
.label_color(TEXT_COLOR)
|
||||||
|
.label_font_id(self.fonts.cyri.conrod_id)
|
||||||
|
.label_font_size(self.fonts.cyri.scale(15))
|
||||||
|
.w(100.0)
|
||||||
|
.rgba(0.0, 0.0, 0.0, 0.0)
|
||||||
|
.border_rgba(0.0, 0.0, 0.0, 255.0)
|
||||||
|
.label_y(Relative::Scalar(1.0));
|
||||||
|
if toggle_widget
|
||||||
|
.top_right_with_margins_on(state.ids.window, 10.0, 15.0)
|
||||||
|
.set(state.ids.keybinding_mode_button, ui)
|
||||||
|
.was_clicked()
|
||||||
|
{
|
||||||
|
events.push(ToggleKeybindingMode);
|
||||||
|
}
|
||||||
|
|
||||||
// Add an empty text widget to simulate some bottom margin, because conrod sucks
|
// Add an empty text widget to simulate some bottom margin, because conrod sucks
|
||||||
if let Some(prev_id) = previous_element_id {
|
if let Some(prev_id) = previous_element_id {
|
||||||
Rectangle::fill_with([1.0, 1.0], color::TRANSPARENT)
|
Rectangle::fill_with([1.0, 1.0], color::TRANSPARENT)
|
||||||
|
@ -114,8 +114,14 @@ impl Screen {
|
|||||||
if let Ok(game_input) = GameInput::from_str(&tip[start + 1..end]) {
|
if let Ok(game_input) = GameInput::from_str(&tip[start + 1..end]) {
|
||||||
new_tip.push_str(&tip[last_index..start]);
|
new_tip.push_str(&tip[last_index..start]);
|
||||||
new_tip.push_str(
|
new_tip.push_str(
|
||||||
controls.keybindings[&game_input]
|
match controls.keybindings.get(&game_input) {
|
||||||
.display_string(key_layout)
|
Some(Some(key_mouse)) => {
|
||||||
|
key_mouse.display_string(key_layout)
|
||||||
|
},
|
||||||
|
Some(None) => i18n.get("main.unbound_key_tip").to_string(),
|
||||||
|
None => ControlSettings::default_binding(game_input)
|
||||||
|
.display_string(key_layout),
|
||||||
|
}
|
||||||
.as_str(),
|
.as_str(),
|
||||||
);
|
);
|
||||||
last_index = end + 1;
|
last_index = end + 1;
|
||||||
|
@ -39,6 +39,8 @@ pub enum Chat {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Control {
|
pub enum Control {
|
||||||
ChangeBinding(GameInput),
|
ChangeBinding(GameInput),
|
||||||
|
RemoveBinding(GameInput),
|
||||||
|
ToggleKeybindingMode,
|
||||||
ResetKeyBindings,
|
ResetKeyBindings,
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -249,6 +251,12 @@ impl SettingsChange {
|
|||||||
Control::ChangeBinding(game_input) => {
|
Control::ChangeBinding(game_input) => {
|
||||||
global_state.window.set_keybinding_mode(game_input);
|
global_state.window.set_keybinding_mode(game_input);
|
||||||
},
|
},
|
||||||
|
Control::RemoveBinding(game_input) => {
|
||||||
|
settings.controls.remove_binding(game_input);
|
||||||
|
},
|
||||||
|
Control::ToggleKeybindingMode => {
|
||||||
|
global_state.window.toggle_keybinding_mode();
|
||||||
|
},
|
||||||
Control::ResetKeyBindings => {
|
Control::ResetKeyBindings => {
|
||||||
settings.controls = ControlSettings::default();
|
settings.controls = ControlSettings::default();
|
||||||
},
|
},
|
||||||
|
@ -8,16 +8,16 @@ use winit::event::{MouseButton, VirtualKeyCode};
|
|||||||
// post-deserializing the inverse_keybindings hashmap
|
// post-deserializing the inverse_keybindings hashmap
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct ControlSettingsSerde {
|
struct ControlSettingsSerde {
|
||||||
keybindings: HashMap<GameInput, KeyMouse>,
|
keybindings: HashMap<GameInput, Option<KeyMouse>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ControlSettings> for ControlSettingsSerde {
|
impl From<ControlSettings> for ControlSettingsSerde {
|
||||||
fn from(control_settings: ControlSettings) -> Self {
|
fn from(control_settings: ControlSettings) -> Self {
|
||||||
let mut user_bindings: HashMap<GameInput, KeyMouse> = HashMap::new();
|
let mut user_bindings: HashMap<GameInput, Option<KeyMouse>> = HashMap::new();
|
||||||
// Do a delta between default() ControlSettings and the argument, and let
|
// Do a delta between default() ControlSettings and the argument, and let
|
||||||
// keybindings be only the custom keybindings chosen by the user.
|
// keybindings be only the custom keybindings chosen by the user.
|
||||||
for (k, v) in control_settings.keybindings {
|
for (k, v) in control_settings.keybindings {
|
||||||
if ControlSettings::default_binding(k) != v {
|
if Some(ControlSettings::default_binding(k)) != v {
|
||||||
// Keybinding chosen by the user
|
// Keybinding chosen by the user
|
||||||
user_bindings.insert(k, v);
|
user_bindings.insert(k, v);
|
||||||
}
|
}
|
||||||
@ -32,7 +32,7 @@ impl From<ControlSettings> for ControlSettingsSerde {
|
|||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
#[serde(from = "ControlSettingsSerde", into = "ControlSettingsSerde")]
|
#[serde(from = "ControlSettingsSerde", into = "ControlSettingsSerde")]
|
||||||
pub struct ControlSettings {
|
pub struct ControlSettings {
|
||||||
pub keybindings: HashMap<GameInput, KeyMouse>,
|
pub keybindings: HashMap<GameInput, Option<KeyMouse>>,
|
||||||
pub inverse_keybindings: HashMap<KeyMouse, HashSet<GameInput>>, // used in event loop
|
pub inverse_keybindings: HashMap<KeyMouse, HashSet<GameInput>>, // used in event loop
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,8 +40,11 @@ impl From<ControlSettingsSerde> for ControlSettings {
|
|||||||
fn from(control_serde: ControlSettingsSerde) -> Self {
|
fn from(control_serde: ControlSettingsSerde) -> Self {
|
||||||
let user_keybindings = control_serde.keybindings;
|
let user_keybindings = control_serde.keybindings;
|
||||||
let mut control_settings = ControlSettings::default();
|
let mut control_settings = ControlSettings::default();
|
||||||
for (k, v) in user_keybindings {
|
for (k, maybe_v) in user_keybindings {
|
||||||
control_settings.modify_binding(k, v);
|
match maybe_v {
|
||||||
|
Some(v) => control_settings.modify_binding(k, v),
|
||||||
|
None => control_settings.remove_binding(k),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
control_settings
|
control_settings
|
||||||
}
|
}
|
||||||
@ -58,8 +61,19 @@ const MIDDLE_CLICK_KEY: KeyMouse = KeyMouse::Key(VirtualKeyCode::Grave);
|
|||||||
const MIDDLE_CLICK_KEY: KeyMouse = KeyMouse::Mouse(MouseButton::Middle);
|
const MIDDLE_CLICK_KEY: KeyMouse = KeyMouse::Mouse(MouseButton::Middle);
|
||||||
|
|
||||||
impl ControlSettings {
|
impl ControlSettings {
|
||||||
|
pub fn remove_binding(&mut self, game_input: GameInput) {
|
||||||
|
if let Some(inverse) = self
|
||||||
|
.keybindings
|
||||||
|
.insert(game_input, None)
|
||||||
|
.flatten()
|
||||||
|
.and_then(|key_mouse| self.inverse_keybindings.get_mut(&key_mouse))
|
||||||
|
{
|
||||||
|
inverse.remove(&game_input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_binding(&self, game_input: GameInput) -> Option<KeyMouse> {
|
pub fn get_binding(&self, game_input: GameInput) -> Option<KeyMouse> {
|
||||||
self.keybindings.get(&game_input).copied()
|
self.keybindings.get(&game_input).copied().flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_associated_game_inputs(&self, key_mouse: &KeyMouse) -> Option<&HashSet<GameInput>> {
|
pub fn get_associated_game_inputs(&self, key_mouse: &KeyMouse) -> Option<&HashSet<GameInput>> {
|
||||||
@ -67,7 +81,7 @@ impl ControlSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_binding(&mut self, game_input: GameInput, key_mouse: KeyMouse) {
|
pub fn insert_binding(&mut self, game_input: GameInput, key_mouse: KeyMouse) {
|
||||||
self.keybindings.insert(game_input, key_mouse);
|
self.keybindings.insert(game_input, Some(key_mouse));
|
||||||
self.inverse_keybindings
|
self.inverse_keybindings
|
||||||
.entry(key_mouse)
|
.entry(key_mouse)
|
||||||
.or_default()
|
.or_default()
|
||||||
@ -89,7 +103,7 @@ impl ControlSettings {
|
|||||||
.or_default()
|
.or_default()
|
||||||
.insert(game_input);
|
.insert(game_input);
|
||||||
// For the GameInput->KeyMouse hashmap, just overwrite the value
|
// For the GameInput->KeyMouse hashmap, just overwrite the value
|
||||||
self.keybindings.insert(game_input, key_mouse);
|
self.keybindings.insert(game_input, Some(key_mouse));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if this key is used for multiple GameInputs that aren't
|
/// Return true if this key is used for multiple GameInputs that aren't
|
||||||
|
@ -385,6 +385,8 @@ pub struct Window {
|
|||||||
needs_refresh_resize: bool,
|
needs_refresh_resize: bool,
|
||||||
keypress_map: HashMap<GameInput, winit::event::ElementState>,
|
keypress_map: HashMap<GameInput, winit::event::ElementState>,
|
||||||
pub remapping_keybindings: Option<GameInput>,
|
pub remapping_keybindings: Option<GameInput>,
|
||||||
|
//true for remapping keybinds, false for clearing keybinds
|
||||||
|
pub keybinding_mode: bool,
|
||||||
events: Vec<Event>,
|
events: Vec<Event>,
|
||||||
pub focused: bool,
|
pub focused: bool,
|
||||||
gilrs: Option<Gilrs>,
|
gilrs: Option<Gilrs>,
|
||||||
@ -486,6 +488,7 @@ impl Window {
|
|||||||
needs_refresh_resize: false,
|
needs_refresh_resize: false,
|
||||||
keypress_map,
|
keypress_map,
|
||||||
remapping_keybindings: None,
|
remapping_keybindings: None,
|
||||||
|
keybinding_mode: true,
|
||||||
events: Vec::new(),
|
events: Vec::new(),
|
||||||
focused: true,
|
focused: true,
|
||||||
gilrs,
|
gilrs,
|
||||||
@ -1329,6 +1332,8 @@ impl Window {
|
|||||||
self.remapping_keybindings = Some(game_input);
|
self.remapping_keybindings = Some(game_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn toggle_keybinding_mode(&mut self) { self.keybinding_mode = !self.keybinding_mode; }
|
||||||
|
|
||||||
pub fn window(&self) -> &winit::window::Window { &self.window }
|
pub fn window(&self) -> &winit::window::Window { &self.window }
|
||||||
|
|
||||||
pub fn modifiers(&self) -> winit::event::ModifiersState { self.modifiers }
|
pub fn modifiers(&self) -> winit::event::ModifiersState { self.modifiers }
|
||||||
|
Loading…
Reference in New Issue
Block a user