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