Skip to main content

veloren_voxygen/settings/
controller.rs

1use crate::{game_input::GameInput, window::MenuInput};
2use gilrs::{Axis as GilAxis, Button as GilButton, ev::Code as GilCode};
3use hashbrown::{HashMap, HashSet};
4use i18n::Localization;
5use serde::{Deserialize, Serialize};
6use strum::{EnumIter, IntoEnumIterator};
7
8#[derive(Serialize, Deserialize)]
9#[serde(default)]
10struct ControllerSettingsSerde {
11    // save as a delta against defaults for efficiency
12    game_button_map: HashMap<GameInput, Option<Button>>,
13    menu_button_map: HashMap<MenuInput, Option<Button>>,
14    game_analog_button_map: HashMap<AnalogButtonGameAction, AnalogButton>,
15    menu_analog_button_map: HashMap<AnalogButtonMenuAction, AnalogButton>,
16    game_axis_map: HashMap<AxisGameAction, Axis>,
17    menu_axis_map: HashMap<AxisMenuAction, Axis>,
18    layer_button_map: HashMap<GameInput, Option<LayerEntry>>,
19    modifier_buttons: Vec<Button>,
20
21    pan_sensitivity: u32,
22    pan_invert_y: bool,
23    axis_deadzones: HashMap<Axis, f32>,
24    button_deadzones: HashMap<AnalogButton, f32>,
25    mouse_emulation_sensitivity: u32,
26    inverted_axes: Vec<Axis>,
27}
28
29impl From<ControllerSettings> for ControllerSettingsSerde {
30    fn from(controller_settings: ControllerSettings) -> Self {
31        // Do a delta between default() ControllerSettings and the argument,
32        // let buttons be only the custom keybindings chosen by the user
33        //
34        // check game buttons
35        let mut button_bindings: HashMap<GameInput, Option<Button>> = HashMap::new();
36        for (k, v) in controller_settings.game_button_map {
37            if ControllerSettings::default_button_binding(k) != v {
38                button_bindings.insert(k, v);
39            }
40        }
41
42        // check game layers
43        let mut layer_bindings: HashMap<GameInput, Option<LayerEntry>> = HashMap::new();
44        for (k, v) in controller_settings.layer_button_map {
45            if ControllerSettings::default_layer_binding(k) != v {
46                layer_bindings.insert(k, v);
47            }
48        }
49
50        // check menu buttons
51        let mut menu_bindings: HashMap<MenuInput, Option<Button>> = HashMap::new();
52        for (k, v) in controller_settings.menu_button_map {
53            if ControllerSettings::default_menu_button_binding(k) != v {
54                menu_bindings.insert(k, v);
55            }
56        }
57
58        // none hashmap values
59        let modifier_buttons = controller_settings.modifier_buttons;
60        let pan_sensitivity = controller_settings.pan_sensitivity;
61        let pan_invert_y = controller_settings.pan_invert_y;
62        let axis_deadzones = controller_settings.axis_deadzones;
63
64        let mouse_emulation_sensitivity = controller_settings.mouse_emulation_sensitivity;
65        let inverted_axes = controller_settings.inverted_axes;
66
67        ControllerSettingsSerde {
68            game_button_map: button_bindings,
69            menu_button_map: menu_bindings,
70            game_analog_button_map: HashMap::new(),
71            menu_analog_button_map: HashMap::new(),
72            game_axis_map: HashMap::new(),
73            menu_axis_map: HashMap::new(),
74            layer_button_map: layer_bindings,
75
76            modifier_buttons,
77            pan_sensitivity,
78            pan_invert_y,
79            axis_deadzones,
80
81            button_deadzones: HashMap::new(),
82            mouse_emulation_sensitivity,
83            inverted_axes,
84        }
85    }
86}
87
88impl Default for ControllerSettingsSerde {
89    fn default() -> Self { ControllerSettings::default().into() }
90}
91
92/// Contains all controller related settings and keymaps
93#[derive(Clone, Debug, Serialize, Deserialize)]
94#[serde(from = "ControllerSettingsSerde", into = "ControllerSettingsSerde")]
95pub struct ControllerSettings {
96    pub game_button_map: HashMap<GameInput, Option<Button>>,
97    pub inverse_game_button_map: HashMap<Button, HashSet<GameInput>>,
98    pub menu_button_map: HashMap<MenuInput, Option<Button>>,
99    pub inverse_menu_button_map: HashMap<Button, HashSet<MenuInput>>,
100    pub game_analog_button_map: HashMap<AnalogButtonGameAction, AnalogButton>,
101    pub inverse_game_analog_button_map: HashMap<AnalogButton, HashSet<AnalogButtonGameAction>>,
102    pub menu_analog_button_map: HashMap<AnalogButtonMenuAction, AnalogButton>,
103    pub inverse_menu_analog_button_map: HashMap<AnalogButton, HashSet<AnalogButtonMenuAction>>,
104    pub game_axis_map: HashMap<AxisGameAction, Axis>,
105    pub inverse_game_axis_map: HashMap<Axis, HashSet<AxisGameAction>>,
106    pub menu_axis_map: HashMap<AxisMenuAction, Axis>,
107    pub inverse_menu_axis_map: HashMap<Axis, HashSet<AxisMenuAction>>,
108    pub layer_button_map: HashMap<GameInput, Option<LayerEntry>>,
109    pub inverse_layer_button_map: HashMap<LayerEntry, HashSet<GameInput>>,
110
111    pub modifier_buttons: Vec<Button>,
112    pub pan_sensitivity: u32,
113    pub pan_invert_y: bool,
114    pub axis_deadzones: HashMap<Axis, f32>,
115    pub button_deadzones: HashMap<AnalogButton, f32>,
116    pub mouse_emulation_sensitivity: u32,
117    pub inverted_axes: Vec<Axis>,
118}
119
120impl From<ControllerSettingsSerde> for ControllerSettings {
121    fn from(controller_serde: ControllerSettingsSerde) -> Self {
122        let button_bindings = controller_serde.game_button_map;
123        let layer_bindings = controller_serde.layer_button_map;
124        let menu_bindings = controller_serde.menu_button_map;
125        let mut controller_settings = ControllerSettings::default();
126        // update button bindings
127        for (k, maybe_v) in button_bindings {
128            match maybe_v {
129                Some(v) => controller_settings.modify_button_binding(k, v),
130                None => controller_settings.remove_button_binding(k),
131            }
132        }
133        // update layer bindings
134        for (k, maybe_v) in layer_bindings {
135            match maybe_v {
136                Some(v) => controller_settings.modify_layer_binding(k, v),
137                None => controller_settings.remove_layer_binding(k),
138            }
139        }
140        // update menu bindings
141        for (k, maybe_v) in menu_bindings {
142            match maybe_v {
143                Some(v) => controller_settings.modify_menu_binding(k, v),
144                None => controller_settings.remove_menu_binding(k),
145            }
146        }
147        controller_settings
148    }
149}
150
151impl ControllerSettings {
152    pub fn apply_axis_deadzone(&self, k: &Axis, input: f32) -> f32 {
153        let threshold = *self.axis_deadzones.get(k).unwrap_or(&0.2);
154
155        // This could be one comparison per handled event faster if threshold was
156        // guaranteed to fall into <0, 1) range
157        let input_abs = input.abs();
158        if input_abs <= threshold || threshold >= 1.0 {
159            0.0
160        } else if threshold <= 0.0 {
161            input
162        } else {
163            (input_abs - threshold) / (1.0 - threshold) * input.signum()
164        }
165    }
166
167    pub fn apply_button_deadzone(&self, k: &AnalogButton, input: f32) -> f32 {
168        let threshold = *self.button_deadzones.get(k).unwrap_or(&0.2);
169
170        // This could be one comparison per handled event faster if threshold was
171        // guaranteed to fall into <0, 1) range
172        if input <= threshold || threshold >= 1.0 {
173            0.0
174        } else if threshold <= 0.0 {
175            input
176        } else {
177            (input - threshold) / (1.0 - threshold)
178        }
179    }
180
181    pub fn remove_button_binding(&mut self, game_input: GameInput) {
182        if let Some(inverse) = self
183            .game_button_map
184            .insert(game_input, None)
185            .flatten()
186            .and_then(|button| self.inverse_game_button_map.get_mut(&button))
187        {
188            inverse.remove(&game_input);
189        }
190    }
191
192    pub fn remove_layer_binding(&mut self, layer_input: GameInput) {
193        if let Some(inverse) = self
194            .layer_button_map
195            .insert(layer_input, None)
196            .flatten()
197            .and_then(|button| self.inverse_layer_button_map.get_mut(&button))
198        {
199            inverse.remove(&layer_input);
200        }
201    }
202
203    pub fn remove_menu_binding(&mut self, menu_input: MenuInput) {
204        if let Some(inverse) = self
205            .menu_button_map
206            .insert(menu_input, None)
207            .flatten()
208            .and_then(|button| self.inverse_menu_button_map.get_mut(&button))
209        {
210            inverse.remove(&menu_input);
211        }
212    }
213
214    pub fn get_associated_game_button_inputs(
215        &self,
216        button: &Button,
217    ) -> Option<&HashSet<GameInput>> {
218        self.inverse_game_button_map.get(button)
219    }
220
221    pub fn get_associated_game_layer_inputs(
222        &self,
223        layers: &LayerEntry,
224    ) -> Option<&HashSet<GameInput>> {
225        self.inverse_layer_button_map.get(layers)
226    }
227
228    pub fn get_associated_game_menu_inputs(&self, button: &Button) -> Option<&HashSet<MenuInput>> {
229        self.inverse_menu_button_map.get(button)
230    }
231
232    pub fn get_game_button_binding(&self, input: GameInput) -> Option<Button> {
233        self.game_button_map.get(&input).cloned().flatten()
234    }
235
236    pub fn get_menu_button_binding(&self, input: MenuInput) -> Option<Button> {
237        self.menu_button_map.get(&input).cloned().flatten()
238    }
239
240    pub fn get_layer_button_binding(&self, input: GameInput) -> Option<LayerEntry> {
241        self.layer_button_map.get(&input).cloned().flatten()
242    }
243
244    pub fn insert_game_button_binding(&mut self, game_input: GameInput, game_button: Button) {
245        if game_button != Button::default() {
246            self.game_button_map.insert(game_input, Some(game_button));
247            self.inverse_game_button_map
248                .entry(game_button)
249                .or_default()
250                .insert(game_input);
251        }
252    }
253
254    pub fn insert_menu_button_binding(&mut self, menu_input: MenuInput, button: Button) {
255        if button != Button::default() {
256            self.menu_button_map.insert(menu_input, Some(button));
257            self.inverse_menu_button_map
258                .entry(button)
259                .or_default()
260                .insert(menu_input);
261        }
262    }
263
264    pub fn insert_game_axis_binding(&mut self, input: AxisGameAction, axis: Axis) {
265        if axis != Axis::default() {
266            self.game_axis_map.insert(input, axis);
267            self.inverse_game_axis_map
268                .entry(axis)
269                .or_default()
270                .insert(input);
271        }
272    }
273
274    pub fn insert_menu_axis_binding(&mut self, input: AxisMenuAction, axis: Axis) {
275        if axis != Axis::default() {
276            self.menu_axis_map.insert(input, axis);
277            self.inverse_menu_axis_map
278                .entry(axis)
279                .or_default()
280                .insert(input);
281        }
282    }
283
284    pub fn insert_layer_button_binding(&mut self, input: GameInput, layer_entry: LayerEntry) {
285        if layer_entry != LayerEntry::default() {
286            self.layer_button_map.insert(input, Some(layer_entry));
287            self.inverse_layer_button_map
288                .entry(layer_entry)
289                .or_default()
290                .insert(input);
291        }
292    }
293
294    pub fn modify_button_binding(&mut self, game_input: GameInput, button: Button) {
295        // for the Button->GameInput hashmap, we first need to remove the GameInput from
296        // the old binding
297        if let Some(old_binding) = self.get_game_button_binding(game_input) {
298            self.inverse_game_button_map
299                .entry(old_binding)
300                .or_default()
301                .remove(&game_input);
302        }
303        // then we add the GameInput to the proper key
304        self.inverse_game_button_map
305            .entry(button)
306            .or_default()
307            .insert(game_input);
308        // for the GameInput->button hashmap, just overwrite the value
309        self.game_button_map.insert(game_input, Some(button));
310    }
311
312    pub fn modify_layer_binding(&mut self, game_input: GameInput, layers: LayerEntry) {
313        // for the LayerEntry->GameInput hashmap, we first need to remove the GameInput
314        // from the old binding
315        if let Some(old_binding) = self.get_layer_button_binding(game_input) {
316            self.inverse_layer_button_map
317                .entry(old_binding)
318                .or_default()
319                .remove(&game_input);
320        }
321        // then we add the GameInput to the proper key
322        self.inverse_layer_button_map
323            .entry(layers)
324            .or_default()
325            .insert(game_input);
326        // for the GameInput->layer hashmap, just overwrite the value
327        self.layer_button_map.insert(game_input, Some(layers));
328    }
329
330    pub fn modify_menu_binding(&mut self, menu_input: MenuInput, button: Button) {
331        // for the Button->GameInput hashmap, we first need to remove the GameInput from
332        // the old binding
333        if let Some(old_binding) = self.get_menu_button_binding(menu_input) {
334            self.inverse_menu_button_map
335                .entry(old_binding)
336                .or_default()
337                .remove(&menu_input);
338        }
339        // then we add the GameInput to the proper key
340        self.inverse_menu_button_map
341            .entry(button)
342            .or_default()
343            .insert(menu_input);
344        // for the MenuInput->button hashmap, just overwrite the value
345        self.menu_button_map.insert(menu_input, Some(button));
346    }
347
348    /// Return true if this button is used for multiple GameInputs that aren't
349    /// expected to be safe to have bound to the same button at the same time
350    pub fn game_button_has_conflicting_bindings(&self, game_button: Button) -> bool {
351        if let Some(game_inputs) = self.inverse_game_button_map.get(&game_button) {
352            for a in game_inputs.iter() {
353                for b in game_inputs.iter() {
354                    if !GameInput::can_share_bindings(*a, *b) {
355                        return true;
356                    }
357                }
358            }
359
360            let layer_entry = LayerEntry {
361                button: game_button,
362                mod1: Button::Simple(GilButton::Unknown),
363                mod2: Button::Simple(GilButton::Unknown),
364            };
365            if let Some(layer_inputs) = self.inverse_layer_button_map.get(&layer_entry) {
366                for a in game_inputs.iter() {
367                    for b in layer_inputs.iter() {
368                        if !GameInput::can_share_bindings(*a, *b) {
369                            return true;
370                        }
371                    }
372                }
373            }
374        }
375        false
376    }
377
378    pub fn menu_button_has_conflicting_bindings(&self, menu_button: Button) -> bool {
379        self.inverse_menu_button_map
380            .get(&menu_button)
381            .is_some_and(|menu_inputs| menu_inputs.len() > 1)
382    }
383
384    /// Return true if this key is used for multiple GameInputs that aren't
385    /// expected to be safe to have bound to the same key at the same time
386    pub fn layer_entry_has_conflicting_bindings(&self, layer_entry: LayerEntry) -> bool {
387        if let Some(layer_inputs) = self.inverse_layer_button_map.get(&layer_entry) {
388            for a in layer_inputs.iter() {
389                for b in layer_inputs.iter() {
390                    if !GameInput::can_share_bindings(*a, *b) {
391                        return true;
392                    }
393                }
394            }
395
396            if layer_entry.mod1 == Button::Simple(GilButton::Unknown)
397                && layer_entry.mod2 == Button::Simple(GilButton::Unknown)
398                && let Some(game_inputs) = self.inverse_game_button_map.get(&layer_entry.button)
399            {
400                for a in layer_inputs.iter() {
401                    for b in game_inputs.iter() {
402                        if !GameInput::can_share_bindings(*a, *b) {
403                            return true;
404                        }
405                    }
406                }
407            }
408        }
409        false
410    }
411
412    pub fn default_game_axis(game_axis: AxisGameAction) -> Option<Axis> {
413        match game_axis {
414            AxisGameAction::MovementX => Some(Axis::Simple(GilAxis::LeftStickX)),
415            AxisGameAction::MovementY => Some(Axis::Simple(GilAxis::LeftStickY)),
416            AxisGameAction::CameraX => Some(Axis::Simple(GilAxis::RightStickX)),
417            AxisGameAction::CameraY => Some(Axis::Simple(GilAxis::RightStickY)),
418        }
419    }
420
421    pub fn default_menu_axis(menu_axis: AxisMenuAction) -> Option<Axis> {
422        match menu_axis {
423            AxisMenuAction::MoveX => Some(Axis::Simple(GilAxis::LeftStickX)),
424            AxisMenuAction::MoveY => Some(Axis::Simple(GilAxis::LeftStickY)),
425            AxisMenuAction::ScrollX => Some(Axis::Simple(GilAxis::RightStickX)),
426            AxisMenuAction::ScrollY => Some(Axis::Simple(GilAxis::RightStickY)),
427        }
428    }
429
430    pub fn default_button_binding(game_input: GameInput) -> Option<Button> {
431        match game_input {
432            GameInput::Primary => Some(Button::Simple(GilButton::RightTrigger2)),
433            GameInput::Secondary => Some(Button::Simple(GilButton::LeftTrigger2)),
434            GameInput::Block => Some(Button::Simple(GilButton::LeftTrigger)),
435            GameInput::Slot1 => Some(Button::Simple(GilButton::Unknown)),
436            GameInput::Slot2 => Some(Button::Simple(GilButton::Unknown)),
437            GameInput::Slot3 => Some(Button::Simple(GilButton::Unknown)),
438            GameInput::Slot4 => Some(Button::Simple(GilButton::Unknown)),
439            GameInput::Slot5 => Some(Button::Simple(GilButton::Unknown)),
440            GameInput::Slot6 => Some(Button::Simple(GilButton::Unknown)),
441            GameInput::Slot7 => Some(Button::Simple(GilButton::Unknown)),
442            GameInput::Slot8 => Some(Button::Simple(GilButton::Unknown)),
443            GameInput::Slot9 => Some(Button::Simple(GilButton::Unknown)),
444            GameInput::Slot10 => Some(Button::Simple(GilButton::Unknown)),
445            GameInput::PreviousSlot => Some(Button::Simple(GilButton::Unknown)),
446            GameInput::NextSlot => Some(Button::Simple(GilButton::Unknown)),
447            GameInput::CurrentSlot => Some(Button::Simple(GilButton::North)),
448            GameInput::ToggleCursor => Some(Button::Simple(GilButton::Unknown)),
449            GameInput::MoveForward => Some(Button::Simple(GilButton::Unknown)),
450            GameInput::MoveBack => Some(Button::Simple(GilButton::Unknown)),
451            GameInput::MoveLeft => Some(Button::Simple(GilButton::Unknown)),
452            GameInput::MoveRight => Some(Button::Simple(GilButton::Unknown)),
453            GameInput::Jump => Some(Button::Simple(GilButton::South)),
454            GameInput::WallJump => Some(Button::Simple(GilButton::South)),
455            GameInput::Sit => Some(Button::Simple(GilButton::Unknown)),
456            GameInput::Crawl => Some(Button::Simple(GilButton::Unknown)),
457            GameInput::Dance => Some(Button::Simple(GilButton::Unknown)),
458            GameInput::Greet => Some(Button::Simple(GilButton::Unknown)),
459            GameInput::Glide => Some(Button::Simple(GilButton::DPadUp)),
460            GameInput::SwimUp => Some(Button::Simple(GilButton::South)),
461            GameInput::SwimDown => Some(Button::Simple(GilButton::West)),
462            GameInput::Fly => Some(Button::Simple(GilButton::Unknown)),
463            GameInput::Sneak => Some(Button::Simple(GilButton::LeftThumb)),
464            GameInput::CancelClimb => Some(Button::Simple(GilButton::East)),
465            GameInput::ToggleLantern => Some(Button::Simple(GilButton::Unknown)),
466            GameInput::Mount => Some(Button::Simple(GilButton::South)),
467            GameInput::StayFollow => Some(Button::Simple(GilButton::Unknown)),
468            GameInput::Chat => Some(Button::Simple(GilButton::Unknown)),
469            GameInput::Command => Some(Button::Simple(GilButton::Unknown)),
470            GameInput::Escape => Some(Button::Simple(GilButton::Start)),
471            GameInput::Map => Some(Button::Simple(GilButton::Select)),
472            GameInput::Inventory => Some(Button::Simple(GilButton::DPadRight)),
473            GameInput::Trade => Some(Button::Simple(GilButton::Unknown)),
474            GameInput::Social => Some(Button::Simple(GilButton::DPadLeft)),
475            GameInput::Crafting => Some(Button::Simple(GilButton::Unknown)),
476            GameInput::Diary => Some(Button::Simple(GilButton::Unknown)),
477            GameInput::Settings => Some(Button::Simple(GilButton::Unknown)),
478            GameInput::Controls => Some(Button::Simple(GilButton::Unknown)),
479            GameInput::ToggleInterface => Some(Button::Simple(GilButton::Unknown)),
480            GameInput::ToggleDebug => Some(Button::Simple(GilButton::Unknown)),
481            #[cfg(feature = "egui-ui")]
482            GameInput::ToggleEguiDebug => Some(Button::Simple(GilButton::Unknown)),
483            GameInput::ToggleChat => Some(Button::Simple(GilButton::Unknown)),
484            GameInput::Fullscreen => Some(Button::Simple(GilButton::Unknown)),
485            GameInput::Screenshot => Some(Button::Simple(GilButton::Unknown)),
486            GameInput::ToggleIngameUi => Some(Button::Simple(GilButton::Unknown)),
487            GameInput::Roll => Some(Button::Simple(GilButton::RightThumb)),
488            GameInput::GiveUp => Some(Button::Simple(GilButton::South)),
489            GameInput::Respawn => Some(Button::Simple(GilButton::South)),
490            GameInput::Interact => Some(Button::Simple(GilButton::West)),
491            GameInput::ToggleWield => Some(Button::Simple(GilButton::East)),
492            GameInput::SwapLoadout => Some(Button::Simple(GilButton::DPadDown)),
493            GameInput::FreeLook => Some(Button::Simple(GilButton::Unknown)),
494            GameInput::AutoWalk => Some(Button::Simple(GilButton::Unknown)),
495            GameInput::ZoomIn => Some(Button::Simple(GilButton::Unknown)),
496            GameInput::ZoomOut => Some(Button::Simple(GilButton::Unknown)),
497            GameInput::ZoomLock => Some(Button::Simple(GilButton::Unknown)),
498            GameInput::CameraClamp => Some(Button::Simple(GilButton::Unknown)),
499            GameInput::CycleCamera => Some(Button::Simple(GilButton::Unknown)),
500            GameInput::Select => Some(Button::Simple(GilButton::Unknown)),
501            GameInput::AcceptGroupInvite => Some(Button::Simple(GilButton::Unknown)),
502            GameInput::DeclineGroupInvite => Some(Button::Simple(GilButton::Unknown)),
503            GameInput::MapZoomIn => Some(Button::Simple(GilButton::Unknown)),
504            GameInput::MapZoomOut => Some(Button::Simple(GilButton::Unknown)),
505            GameInput::MapSetMarker => Some(Button::Simple(GilButton::Unknown)),
506            GameInput::SpectateSpeedBoost => Some(Button::Simple(GilButton::Unknown)),
507            GameInput::SpectateViewpoint => Some(Button::Simple(GilButton::Unknown)),
508            GameInput::MuteMaster => Some(Button::Simple(GilButton::Unknown)),
509            GameInput::MuteInactiveMaster => Some(Button::Simple(GilButton::Unknown)),
510            GameInput::MuteMusic => Some(Button::Simple(GilButton::Unknown)),
511            GameInput::MuteSfx => Some(Button::Simple(GilButton::Unknown)),
512            GameInput::MuteAmbience => Some(Button::Simple(GilButton::Unknown)),
513            GameInput::ToggleWalk => Some(Button::Simple(GilButton::Unknown)),
514        }
515    }
516
517    pub fn default_layer_binding(layer_input: GameInput) -> Option<LayerEntry> {
518        match layer_input {
519            GameInput::Primary => Some(LayerEntry {
520                button: Button::Simple(GilButton::Unknown),
521                mod1: Button::Simple(GilButton::Unknown),
522                mod2: Button::Simple(GilButton::Unknown),
523            }),
524            GameInput::Secondary => Some(LayerEntry {
525                button: Button::Simple(GilButton::Unknown),
526                mod1: Button::Simple(GilButton::Unknown),
527                mod2: Button::Simple(GilButton::Unknown),
528            }),
529            GameInput::Block => Some(LayerEntry {
530                button: Button::Simple(GilButton::Unknown),
531                mod1: Button::Simple(GilButton::Unknown),
532                mod2: Button::Simple(GilButton::Unknown),
533            }),
534            GameInput::Slot1 => Some(LayerEntry {
535                button: Button::Simple(GilButton::Unknown),
536                mod1: Button::Simple(GilButton::Unknown),
537                mod2: Button::Simple(GilButton::Unknown),
538            }),
539            GameInput::Slot2 => Some(LayerEntry {
540                button: Button::Simple(GilButton::Unknown),
541                mod1: Button::Simple(GilButton::Unknown),
542                mod2: Button::Simple(GilButton::Unknown),
543            }),
544            GameInput::Slot3 => Some(LayerEntry {
545                button: Button::Simple(GilButton::Unknown),
546                mod1: Button::Simple(GilButton::Unknown),
547                mod2: Button::Simple(GilButton::Unknown),
548            }),
549            GameInput::Slot4 => Some(LayerEntry {
550                button: Button::Simple(GilButton::Unknown),
551                mod1: Button::Simple(GilButton::Unknown),
552                mod2: Button::Simple(GilButton::Unknown),
553            }),
554            GameInput::Slot5 => Some(LayerEntry {
555                button: Button::Simple(GilButton::Unknown),
556                mod1: Button::Simple(GilButton::Unknown),
557                mod2: Button::Simple(GilButton::Unknown),
558            }),
559            GameInput::Slot6 => Some(LayerEntry {
560                button: Button::Simple(GilButton::Unknown),
561                mod1: Button::Simple(GilButton::Unknown),
562                mod2: Button::Simple(GilButton::Unknown),
563            }),
564            GameInput::Slot7 => Some(LayerEntry {
565                button: Button::Simple(GilButton::Unknown),
566                mod1: Button::Simple(GilButton::Unknown),
567                mod2: Button::Simple(GilButton::Unknown),
568            }),
569            GameInput::Slot8 => Some(LayerEntry {
570                button: Button::Simple(GilButton::Unknown),
571                mod1: Button::Simple(GilButton::Unknown),
572                mod2: Button::Simple(GilButton::Unknown),
573            }),
574            GameInput::Slot9 => Some(LayerEntry {
575                button: Button::Simple(GilButton::Unknown),
576                mod1: Button::Simple(GilButton::Unknown),
577                mod2: Button::Simple(GilButton::Unknown),
578            }),
579            GameInput::Slot10 => Some(LayerEntry {
580                button: Button::Simple(GilButton::Unknown),
581                mod1: Button::Simple(GilButton::Unknown),
582                mod2: Button::Simple(GilButton::Unknown),
583            }),
584            GameInput::PreviousSlot => Some(LayerEntry {
585                button: Button::Simple(GilButton::West),
586                mod1: Button::Simple(GilButton::RightTrigger),
587                mod2: Button::Simple(GilButton::Unknown),
588            }),
589            GameInput::NextSlot => Some(LayerEntry {
590                button: Button::Simple(GilButton::East),
591                mod1: Button::Simple(GilButton::RightTrigger),
592                mod2: Button::Simple(GilButton::Unknown),
593            }),
594            GameInput::CurrentSlot => Some(LayerEntry {
595                button: Button::Simple(GilButton::Unknown),
596                mod1: Button::Simple(GilButton::Unknown),
597                mod2: Button::Simple(GilButton::Unknown),
598            }),
599            GameInput::ToggleCursor => Some(LayerEntry {
600                button: Button::Simple(GilButton::Unknown),
601                mod1: Button::Simple(GilButton::Unknown),
602                mod2: Button::Simple(GilButton::Unknown),
603            }),
604            GameInput::MoveForward => Some(LayerEntry {
605                button: Button::Simple(GilButton::Unknown),
606                mod1: Button::Simple(GilButton::Unknown),
607                mod2: Button::Simple(GilButton::Unknown),
608            }),
609            GameInput::MoveBack => Some(LayerEntry {
610                button: Button::Simple(GilButton::Unknown),
611                mod1: Button::Simple(GilButton::Unknown),
612                mod2: Button::Simple(GilButton::Unknown),
613            }),
614            GameInput::MoveLeft => Some(LayerEntry {
615                button: Button::Simple(GilButton::Unknown),
616                mod1: Button::Simple(GilButton::Unknown),
617                mod2: Button::Simple(GilButton::Unknown),
618            }),
619            GameInput::MoveRight => Some(LayerEntry {
620                button: Button::Simple(GilButton::Unknown),
621                mod1: Button::Simple(GilButton::Unknown),
622                mod2: Button::Simple(GilButton::Unknown),
623            }),
624            GameInput::Jump => Some(LayerEntry {
625                button: Button::Simple(GilButton::Unknown),
626                mod1: Button::Simple(GilButton::Unknown),
627                mod2: Button::Simple(GilButton::Unknown),
628            }),
629            GameInput::WallJump => Some(LayerEntry {
630                button: Button::Simple(GilButton::Unknown),
631                mod1: Button::Simple(GilButton::Unknown),
632                mod2: Button::Simple(GilButton::Unknown),
633            }),
634            GameInput::Sit => Some(LayerEntry {
635                button: Button::Simple(GilButton::DPadDown),
636                mod1: Button::Simple(GilButton::RightTrigger),
637                mod2: Button::Simple(GilButton::Unknown),
638            }),
639            GameInput::Crawl => Some(LayerEntry {
640                button: Button::Simple(GilButton::Unknown),
641                mod1: Button::Simple(GilButton::Unknown),
642                mod2: Button::Simple(GilButton::Unknown),
643            }),
644            GameInput::Dance => Some(LayerEntry {
645                button: Button::Simple(GilButton::Unknown),
646                mod1: Button::Simple(GilButton::Unknown),
647                mod2: Button::Simple(GilButton::Unknown),
648            }),
649            GameInput::Greet => Some(LayerEntry {
650                button: Button::Simple(GilButton::Unknown),
651                mod1: Button::Simple(GilButton::Unknown),
652                mod2: Button::Simple(GilButton::Unknown),
653            }),
654            GameInput::Glide => Some(LayerEntry {
655                button: Button::Simple(GilButton::Unknown),
656                mod1: Button::Simple(GilButton::Unknown),
657                mod2: Button::Simple(GilButton::Unknown),
658            }),
659            GameInput::SwimUp => Some(LayerEntry {
660                button: Button::Simple(GilButton::Unknown),
661                mod1: Button::Simple(GilButton::Unknown),
662                mod2: Button::Simple(GilButton::Unknown),
663            }),
664            GameInput::SwimDown => Some(LayerEntry {
665                button: Button::Simple(GilButton::Unknown),
666                mod1: Button::Simple(GilButton::Unknown),
667                mod2: Button::Simple(GilButton::Unknown),
668            }),
669            GameInput::Fly => Some(LayerEntry {
670                button: Button::Simple(GilButton::Unknown),
671                mod1: Button::Simple(GilButton::Unknown),
672                mod2: Button::Simple(GilButton::Unknown),
673            }),
674            GameInput::Sneak => Some(LayerEntry {
675                button: Button::Simple(GilButton::Unknown),
676                mod1: Button::Simple(GilButton::Unknown),
677                mod2: Button::Simple(GilButton::Unknown),
678            }),
679            GameInput::CancelClimb => Some(LayerEntry {
680                button: Button::Simple(GilButton::Unknown),
681                mod1: Button::Simple(GilButton::Unknown),
682                mod2: Button::Simple(GilButton::Unknown),
683            }),
684            GameInput::ToggleLantern => Some(LayerEntry {
685                button: Button::Simple(GilButton::DPadUp),
686                mod1: Button::Simple(GilButton::RightTrigger),
687                mod2: Button::Simple(GilButton::Unknown),
688            }),
689            GameInput::Mount => Some(LayerEntry {
690                button: Button::Simple(GilButton::Unknown),
691                mod1: Button::Simple(GilButton::Unknown),
692                mod2: Button::Simple(GilButton::Unknown),
693            }),
694            GameInput::StayFollow => Some(LayerEntry {
695                button: Button::Simple(GilButton::Unknown),
696                mod1: Button::Simple(GilButton::Unknown),
697                mod2: Button::Simple(GilButton::Unknown),
698            }),
699            GameInput::Chat => Some(LayerEntry {
700                button: Button::Simple(GilButton::Unknown),
701                mod1: Button::Simple(GilButton::Unknown),
702                mod2: Button::Simple(GilButton::Unknown),
703            }),
704            GameInput::Command => Some(LayerEntry {
705                button: Button::Simple(GilButton::Unknown),
706                mod1: Button::Simple(GilButton::Unknown),
707                mod2: Button::Simple(GilButton::Unknown),
708            }),
709            GameInput::Escape => Some(LayerEntry {
710                button: Button::Simple(GilButton::Unknown),
711                mod1: Button::Simple(GilButton::Unknown),
712                mod2: Button::Simple(GilButton::Unknown),
713            }),
714            GameInput::Map => Some(LayerEntry {
715                button: Button::Simple(GilButton::Unknown),
716                mod1: Button::Simple(GilButton::Unknown),
717                mod2: Button::Simple(GilButton::Unknown),
718            }),
719            GameInput::Inventory => Some(LayerEntry {
720                button: Button::Simple(GilButton::Unknown),
721                mod1: Button::Simple(GilButton::Unknown),
722                mod2: Button::Simple(GilButton::Unknown),
723            }),
724            GameInput::Trade => Some(LayerEntry {
725                button: Button::Simple(GilButton::North),
726                mod1: Button::Simple(GilButton::RightTrigger),
727                mod2: Button::Simple(GilButton::Unknown),
728            }),
729            GameInput::Social => Some(LayerEntry {
730                button: Button::Simple(GilButton::Unknown),
731                mod1: Button::Simple(GilButton::Unknown),
732                mod2: Button::Simple(GilButton::Unknown),
733            }),
734            GameInput::Crafting => Some(LayerEntry {
735                button: Button::Simple(GilButton::Unknown),
736                mod1: Button::Simple(GilButton::Unknown),
737                mod2: Button::Simple(GilButton::Unknown),
738            }),
739            GameInput::Diary => Some(LayerEntry {
740                button: Button::Simple(GilButton::Unknown),
741                mod1: Button::Simple(GilButton::Unknown),
742                mod2: Button::Simple(GilButton::Unknown),
743            }),
744            GameInput::Settings => Some(LayerEntry {
745                button: Button::Simple(GilButton::Unknown),
746                mod1: Button::Simple(GilButton::Unknown),
747                mod2: Button::Simple(GilButton::Unknown),
748            }),
749            GameInput::Controls => Some(LayerEntry {
750                button: Button::Simple(GilButton::Unknown),
751                mod1: Button::Simple(GilButton::Unknown),
752                mod2: Button::Simple(GilButton::Unknown),
753            }),
754            GameInput::ToggleInterface => Some(LayerEntry {
755                button: Button::Simple(GilButton::Unknown),
756                mod1: Button::Simple(GilButton::Unknown),
757                mod2: Button::Simple(GilButton::Unknown),
758            }),
759            GameInput::ToggleDebug => Some(LayerEntry {
760                button: Button::Simple(GilButton::Unknown),
761                mod1: Button::Simple(GilButton::Unknown),
762                mod2: Button::Simple(GilButton::Unknown),
763            }),
764            #[cfg(feature = "egui-ui")]
765            GameInput::ToggleEguiDebug => Some(LayerEntry {
766                button: Button::Simple(GilButton::Unknown),
767                mod1: Button::Simple(GilButton::Unknown),
768                mod2: Button::Simple(GilButton::Unknown),
769            }),
770            GameInput::ToggleChat => Some(LayerEntry {
771                button: Button::Simple(GilButton::Unknown),
772                mod1: Button::Simple(GilButton::Unknown),
773                mod2: Button::Simple(GilButton::Unknown),
774            }),
775            GameInput::Fullscreen => Some(LayerEntry {
776                button: Button::Simple(GilButton::Unknown),
777                mod1: Button::Simple(GilButton::Unknown),
778                mod2: Button::Simple(GilButton::Unknown),
779            }),
780            GameInput::Screenshot => Some(LayerEntry {
781                button: Button::Simple(GilButton::Unknown),
782                mod1: Button::Simple(GilButton::Unknown),
783                mod2: Button::Simple(GilButton::Unknown),
784            }),
785            GameInput::ToggleIngameUi => Some(LayerEntry {
786                button: Button::Simple(GilButton::Unknown),
787                mod1: Button::Simple(GilButton::Unknown),
788                mod2: Button::Simple(GilButton::Unknown),
789            }),
790            GameInput::Roll => Some(LayerEntry {
791                button: Button::Simple(GilButton::Unknown),
792                mod1: Button::Simple(GilButton::Unknown),
793                mod2: Button::Simple(GilButton::Unknown),
794            }),
795            GameInput::GiveUp => Some(LayerEntry {
796                button: Button::Simple(GilButton::Unknown),
797                mod1: Button::Simple(GilButton::Unknown),
798                mod2: Button::Simple(GilButton::Unknown),
799            }),
800            GameInput::Respawn => Some(LayerEntry {
801                button: Button::Simple(GilButton::Unknown),
802                mod1: Button::Simple(GilButton::Unknown),
803                mod2: Button::Simple(GilButton::Unknown),
804            }),
805            GameInput::Interact => Some(LayerEntry {
806                button: Button::Simple(GilButton::Unknown),
807                mod1: Button::Simple(GilButton::Unknown),
808                mod2: Button::Simple(GilButton::Unknown),
809            }),
810            GameInput::ToggleWield => Some(LayerEntry {
811                button: Button::Simple(GilButton::Unknown),
812                mod1: Button::Simple(GilButton::Unknown),
813                mod2: Button::Simple(GilButton::Unknown),
814            }),
815            GameInput::SwapLoadout => Some(LayerEntry {
816                button: Button::Simple(GilButton::Unknown),
817                mod1: Button::Simple(GilButton::Unknown),
818                mod2: Button::Simple(GilButton::Unknown),
819            }),
820            GameInput::FreeLook => Some(LayerEntry {
821                button: Button::Simple(GilButton::South),
822                mod1: Button::Simple(GilButton::RightTrigger),
823                mod2: Button::Simple(GilButton::Unknown),
824            }),
825            GameInput::AutoWalk => Some(LayerEntry {
826                button: Button::Simple(GilButton::Unknown),
827                mod1: Button::Simple(GilButton::Unknown),
828                mod2: Button::Simple(GilButton::Unknown),
829            }),
830            GameInput::ZoomIn => Some(LayerEntry {
831                button: Button::Simple(GilButton::Unknown),
832                mod1: Button::Simple(GilButton::Unknown),
833                mod2: Button::Simple(GilButton::Unknown),
834            }),
835            GameInput::ZoomOut => Some(LayerEntry {
836                button: Button::Simple(GilButton::Unknown),
837                mod1: Button::Simple(GilButton::Unknown),
838                mod2: Button::Simple(GilButton::Unknown),
839            }),
840            GameInput::ZoomLock => Some(LayerEntry {
841                button: Button::Simple(GilButton::Unknown),
842                mod1: Button::Simple(GilButton::Unknown),
843                mod2: Button::Simple(GilButton::Unknown),
844            }),
845            GameInput::CameraClamp => Some(LayerEntry {
846                button: Button::Simple(GilButton::Unknown),
847                mod1: Button::Simple(GilButton::Unknown),
848                mod2: Button::Simple(GilButton::Unknown),
849            }),
850            GameInput::CycleCamera => Some(LayerEntry {
851                button: Button::Simple(GilButton::Unknown),
852                mod1: Button::Simple(GilButton::Unknown),
853                mod2: Button::Simple(GilButton::Unknown),
854            }),
855            GameInput::Select => Some(LayerEntry {
856                button: Button::Simple(GilButton::Unknown),
857                mod1: Button::Simple(GilButton::Unknown),
858                mod2: Button::Simple(GilButton::Unknown),
859            }),
860            GameInput::AcceptGroupInvite => Some(LayerEntry {
861                button: Button::Simple(GilButton::DPadRight),
862                mod1: Button::Simple(GilButton::RightTrigger),
863                mod2: Button::Simple(GilButton::Unknown),
864            }),
865            GameInput::DeclineGroupInvite => Some(LayerEntry {
866                button: Button::Simple(GilButton::DPadLeft),
867                mod1: Button::Simple(GilButton::RightTrigger),
868                mod2: Button::Simple(GilButton::Unknown),
869            }),
870            GameInput::MapZoomIn => Some(LayerEntry {
871                button: Button::Simple(GilButton::Unknown),
872                mod1: Button::Simple(GilButton::Unknown),
873                mod2: Button::Simple(GilButton::Unknown),
874            }),
875            GameInput::MapZoomOut => Some(LayerEntry {
876                button: Button::Simple(GilButton::Unknown),
877                mod1: Button::Simple(GilButton::Unknown),
878                mod2: Button::Simple(GilButton::Unknown),
879            }),
880            GameInput::MapSetMarker => Some(LayerEntry {
881                button: Button::Simple(GilButton::Unknown),
882                mod1: Button::Simple(GilButton::Unknown),
883                mod2: Button::Simple(GilButton::Unknown),
884            }),
885            GameInput::SpectateSpeedBoost => Some(LayerEntry {
886                button: Button::Simple(GilButton::Unknown),
887                mod1: Button::Simple(GilButton::Unknown),
888                mod2: Button::Simple(GilButton::Unknown),
889            }),
890            GameInput::SpectateViewpoint => Some(LayerEntry {
891                button: Button::Simple(GilButton::Unknown),
892                mod1: Button::Simple(GilButton::Unknown),
893                mod2: Button::Simple(GilButton::Unknown),
894            }),
895            GameInput::MuteMaster => Some(LayerEntry {
896                button: Button::Simple(GilButton::Unknown),
897                mod1: Button::Simple(GilButton::Unknown),
898                mod2: Button::Simple(GilButton::Unknown),
899            }),
900            GameInput::MuteInactiveMaster => Some(LayerEntry {
901                button: Button::Simple(GilButton::Unknown),
902                mod1: Button::Simple(GilButton::Unknown),
903                mod2: Button::Simple(GilButton::Unknown),
904            }),
905            GameInput::MuteMusic => Some(LayerEntry {
906                button: Button::Simple(GilButton::Unknown),
907                mod1: Button::Simple(GilButton::Unknown),
908                mod2: Button::Simple(GilButton::Unknown),
909            }),
910            GameInput::MuteSfx => Some(LayerEntry {
911                button: Button::Simple(GilButton::Unknown),
912                mod1: Button::Simple(GilButton::Unknown),
913                mod2: Button::Simple(GilButton::Unknown),
914            }),
915            GameInput::MuteAmbience => Some(LayerEntry {
916                button: Button::Simple(GilButton::Unknown),
917                mod1: Button::Simple(GilButton::Unknown),
918                mod2: Button::Simple(GilButton::Unknown),
919            }),
920            GameInput::ToggleWalk => Some(LayerEntry {
921                button: Button::Simple(GilButton::Unknown),
922                mod1: Button::Simple(GilButton::Unknown),
923                mod2: Button::Simple(GilButton::Unknown),
924            }),
925        }
926    }
927
928    pub fn default_menu_button_binding(menu_input: MenuInput) -> Option<Button> {
929        match menu_input {
930            MenuInput::Up => Some(Button::Simple(GilButton::DPadUp)),
931            MenuInput::Down => Some(Button::Simple(GilButton::DPadDown)),
932            MenuInput::Left => Some(Button::Simple(GilButton::DPadLeft)),
933            MenuInput::Right => Some(Button::Simple(GilButton::DPadRight)),
934            MenuInput::ScrollUp => Some(Button::Simple(GilButton::Unknown)),
935            MenuInput::ScrollDown => Some(Button::Simple(GilButton::Unknown)),
936            MenuInput::ScrollLeft => Some(Button::Simple(GilButton::Unknown)),
937            MenuInput::ScrollRight => Some(Button::Simple(GilButton::Unknown)),
938            MenuInput::PageUp => Some(Button::Simple(GilButton::RightTrigger)),
939            MenuInput::PageDown => Some(Button::Simple(GilButton::LeftTrigger)),
940            MenuInput::Apply => Some(Button::Simple(GilButton::South)),
941            MenuInput::Back => Some(Button::Simple(GilButton::East)),
942            MenuInput::Exit => Some(Button::Simple(GilButton::Mode)),
943            MenuInput::LocalFocus => Some(Button::Simple(GilButton::North)),
944            MenuInput::GlobalFocus => Some(Button::Simple(GilButton::Select)),
945            MenuInput::EmulateLeftClick => Some(Button::Simple(GilButton::RightTrigger2)),
946            MenuInput::EmulateRightClick => Some(Button::Simple(GilButton::LeftTrigger2)),
947        }
948    }
949}
950
951impl Default for ControllerSettings {
952    fn default() -> Self {
953        let mut controller_settings = Self {
954            game_button_map: HashMap::new(),
955            inverse_game_button_map: HashMap::new(),
956            menu_button_map: HashMap::new(),
957            inverse_menu_button_map: HashMap::new(),
958            game_analog_button_map: HashMap::new(),
959            inverse_game_analog_button_map: HashMap::new(),
960            menu_analog_button_map: HashMap::new(),
961            inverse_menu_analog_button_map: HashMap::new(),
962            game_axis_map: HashMap::new(),
963            inverse_game_axis_map: HashMap::new(),
964            menu_axis_map: HashMap::new(),
965            inverse_menu_axis_map: HashMap::new(),
966            layer_button_map: HashMap::new(),
967            inverse_layer_button_map: HashMap::new(),
968
969            modifier_buttons: vec![
970                Button::Simple(GilButton::RightTrigger),
971                Button::Simple(GilButton::LeftTrigger),
972            ],
973            pan_sensitivity: 10,
974            pan_invert_y: false,
975            axis_deadzones: HashMap::new(),
976            button_deadzones: HashMap::new(),
977            mouse_emulation_sensitivity: 12,
978            inverted_axes: Vec::new(),
979        };
980        // sets the button bindings for game button inputs
981        for button_input in GameInput::iter() {
982            if let Some(default) = ControllerSettings::default_button_binding(button_input) {
983                controller_settings.insert_game_button_binding(button_input, default)
984            };
985        }
986        // sets the layer bindings for game layer inputs
987        for layer_input in GameInput::iter() {
988            if let Some(default) = ControllerSettings::default_layer_binding(layer_input) {
989                controller_settings.insert_layer_button_binding(layer_input, default);
990            };
991        }
992        // sets the menu button bindings for game menu button inputs
993        for button_input in MenuInput::iter() {
994            if let Some(default) = ControllerSettings::default_menu_button_binding(button_input) {
995                controller_settings.insert_menu_button_binding(button_input, default)
996            };
997        }
998        // sets the axis bindings for game axis inputs
999        for axis_input in AxisGameAction::iter() {
1000            if let Some(default) = ControllerSettings::default_game_axis(axis_input) {
1001                controller_settings.insert_game_axis_binding(axis_input, default)
1002            };
1003        }
1004        // sets the axis bindings for menu axis inputs
1005        for axis_input in AxisMenuAction::iter() {
1006            if let Some(default) = ControllerSettings::default_menu_axis(axis_input) {
1007                controller_settings.insert_menu_axis_binding(axis_input, default)
1008            };
1009        }
1010        controller_settings
1011    }
1012}
1013
1014/// All the menu actions you can bind to an Axis
1015#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize, EnumIter)]
1016pub enum AxisMenuAction {
1017    MoveX,
1018    MoveY,
1019    ScrollX,
1020    ScrollY,
1021}
1022
1023/// All the game actions you can bind to an Axis
1024#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize, EnumIter)]
1025pub enum AxisGameAction {
1026    MovementX,
1027    MovementY,
1028    CameraX,
1029    CameraY,
1030}
1031
1032/// All the menu actions you can bind to an analog button
1033#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
1034pub enum AnalogButtonMenuAction {}
1035
1036/// All the game actions you can bind to an analog button
1037#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
1038pub enum AnalogButtonGameAction {}
1039
1040/// Button::Simple(GilButton::Unknown) is invalid and equal to mapping an action
1041/// to nothing
1042#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
1043pub enum Button {
1044    Simple(GilButton),
1045    EventCode(u32),
1046}
1047
1048impl Default for Button {
1049    fn default() -> Self { Button::Simple(GilButton::Unknown) }
1050}
1051
1052impl Button {
1053    // Returns button description (e.g Left Trigger)
1054    pub fn display_string(&self, localized_strings: &Localization) -> String {
1055        use self::Button::*;
1056        // This exists here to keep the string in scope after the match
1057        let button_string = match self {
1058            Simple(GilButton::South) => localized_strings.get_msg("gamepad-south").to_string(),
1059            Simple(GilButton::East) => localized_strings.get_msg("gamepad-east").to_string(),
1060            Simple(GilButton::North) => localized_strings.get_msg("gamepad-north").to_string(),
1061            Simple(GilButton::West) => localized_strings.get_msg("gamepad-west").to_string(),
1062            Simple(GilButton::C) => localized_strings.get_msg("gamepad-c").to_string(),
1063            Simple(GilButton::Z) => localized_strings.get_msg("gamepad-z").to_string(),
1064            Simple(GilButton::LeftTrigger) => localized_strings
1065                .get_msg("gamepad-left_trigger")
1066                .to_string(),
1067            Simple(GilButton::LeftTrigger2) => localized_strings
1068                .get_msg("gamepad-left_trigger_2")
1069                .to_string(),
1070            Simple(GilButton::RightTrigger) => localized_strings
1071                .get_msg("gamepad-right_trigger")
1072                .to_string(),
1073            Simple(GilButton::RightTrigger2) => localized_strings
1074                .get_msg("gamepad-right_trigger_2")
1075                .to_string(),
1076            Simple(GilButton::Select) => localized_strings.get_msg("gamepad-select").to_string(),
1077            Simple(GilButton::Start) => localized_strings.get_msg("gamepad-start").to_string(),
1078            Simple(GilButton::Mode) => localized_strings.get_msg("gamepad-mode").to_string(),
1079            Simple(GilButton::LeftThumb) => {
1080                localized_strings.get_msg("gamepad-left_thumb").to_string()
1081            },
1082            Simple(GilButton::RightThumb) => {
1083                localized_strings.get_msg("gamepad-right_thumb").to_string()
1084            },
1085            Simple(GilButton::DPadUp) => localized_strings.get_msg("gamepad-dpad_up").to_string(),
1086            Simple(GilButton::DPadDown) => {
1087                localized_strings.get_msg("gamepad-dpad_down").to_string()
1088            },
1089            Simple(GilButton::DPadLeft) => {
1090                localized_strings.get_msg("gamepad-dpad_left").to_string()
1091            },
1092            Simple(GilButton::DPadRight) => {
1093                localized_strings.get_msg("gamepad-dpad_right").to_string()
1094            },
1095            Simple(GilButton::Unknown) => localized_strings.get_msg("gamepad-unknown").to_string(),
1096            EventCode(code) => code.to_string(),
1097        };
1098
1099        button_string.to_owned()
1100    }
1101
1102    // If it exists, returns the shortened version of a button name
1103    // (e.g. Left Trigger -> LT)
1104    pub fn try_shortened(&self) -> Option<String> {
1105        use self::Button::*;
1106        let button_string = match self {
1107            Simple(GilButton::South) => "A",
1108            Simple(GilButton::East) => "B",
1109            Simple(GilButton::North) => "Y",
1110            Simple(GilButton::West) => "X",
1111            Simple(GilButton::LeftTrigger) => "LB",
1112            Simple(GilButton::LeftTrigger2) => "LT",
1113            Simple(GilButton::RightTrigger) => "RB",
1114            Simple(GilButton::RightTrigger2) => "RT",
1115            Simple(GilButton::LeftThumb) => "L3",
1116            Simple(GilButton::RightThumb) => "R3",
1117            _ => return None,
1118        };
1119
1120        Some(button_string.to_owned())
1121    }
1122}
1123
1124// represents a controller button to fire a GameInput on
1125// includes two modifier buttons to determine what layer is active
1126#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
1127#[serde(default)]
1128pub struct LayerEntry {
1129    pub button: Button,
1130    pub mod1: Button,
1131    pub mod2: Button,
1132}
1133
1134impl Default for LayerEntry {
1135    fn default() -> Self {
1136        // binding to unknown = getting skipped from processing
1137        Self {
1138            button: Button::Simple(GilButton::Unknown),
1139            mod1: Button::Simple(GilButton::Unknown),
1140            mod2: Button::Simple(GilButton::Unknown),
1141        }
1142    }
1143}
1144
1145impl LayerEntry {
1146    pub fn display_string(&self, localized_strings: &Localization) -> String {
1147        use self::Button::*;
1148
1149        let mod1: Option<String> = match self.mod1 {
1150            Simple(GilButton::Unknown) => None,
1151            _ => self
1152                .mod1
1153                .try_shortened()
1154                .map_or(Some(self.mod1.display_string(localized_strings)), Some),
1155        };
1156        let mod2: Option<String> = match self.mod2 {
1157            Simple(GilButton::Unknown) => None,
1158            _ => self
1159                .mod2
1160                .try_shortened()
1161                .map_or(Some(self.mod2.display_string(localized_strings)), Some),
1162        };
1163
1164        format!(
1165            "{}{}{} {}",
1166            mod1.map_or("".to_owned(), |m1| format!("{} + ", m1)),
1167            mod2.map_or("".to_owned(), |m2| format!("{} + ", m2)),
1168            self.button.display_string(localized_strings),
1169            self.button
1170                .try_shortened()
1171                .map_or("".to_owned(), |short| format!("({})", short))
1172        )
1173    }
1174}
1175
1176/// AnalogButton::Simple(GilButton::Unknown) is invalid and equal to mapping an
1177/// action to nothing
1178#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
1179pub enum AnalogButton {
1180    Simple(GilButton),
1181    EventCode(u32),
1182}
1183
1184impl Default for AnalogButton {
1185    fn default() -> Self { AnalogButton::Simple(GilButton::Unknown) }
1186}
1187
1188/// Axis::Simple(GilAxis::Unknown) is invalid and equal to mapping an action to
1189/// nothing
1190#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
1191pub enum Axis {
1192    Simple(GilAxis),
1193    EventCode(u32),
1194}
1195
1196impl Default for Axis {
1197    fn default() -> Self { Axis::Simple(GilAxis::Unknown) }
1198}
1199
1200impl From<(GilAxis, GilCode)> for Axis {
1201    fn from((axis, code): (GilAxis, GilCode)) -> Self {
1202        match axis {
1203            GilAxis::Unknown => Self::EventCode(code.into_u32()),
1204            _ => Self::Simple(axis),
1205        }
1206    }
1207}
1208
1209impl From<(GilButton, GilCode)> for Button {
1210    fn from((button, code): (GilButton, GilCode)) -> Self {
1211        match button {
1212            GilButton::Unknown => Self::EventCode(code.into_u32()),
1213            _ => Self::Simple(button),
1214        }
1215    }
1216}
1217
1218impl From<(GilButton, GilCode)> for AnalogButton {
1219    fn from((button, code): (GilButton, GilCode)) -> Self {
1220        match button {
1221            GilButton::Unknown => Self::EventCode(code.into_u32()),
1222            _ => Self::Simple(button),
1223        }
1224    }
1225}