1use super::{RESET_BUTTONS_HEIGHT, RESET_BUTTONS_WIDTH};
2
3use crate::{
4 GlobalState,
5 game_input::GameInput,
6 hud::{ERROR_COLOR, TEXT_BIND_CONFLICT_COLOR, TEXT_COLOR, img_ids::Imgs},
7 session::settings_change::Control::{self as ControlChange, *},
8 ui::{ToggleButton, fonts::Fonts},
9 window::{MenuInput, RemappingMode},
10};
11use conrod_core::{
12 Borderable, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, color,
13 position::Relative,
14 widget::{self, Button, DropDownList, Rectangle, Scrollbar, Text},
15 widget_ids,
16};
17use i18n::Localization;
18use std::sync::LazyLock;
19use strum::IntoEnumIterator;
20
21widget_ids! {
22 struct Ids {
23 window,
24 window_r,
25 window_scrollbar,
26 reset_controls_button,
27 keybind_helper,
28 gamepad_mode_button,
29 gamepad_option_dropdown,
30 controls_alignment_rectangle,
31 controls_texts[],
32 controls_buttons[],
33 gamelayer_mod1_checkbox,
34 gamelayer_mod2_checkbox,
35 gamelayer_mod1_text,
36 gamelayer_mod2_text,
37 }
38}
39
40#[derive(WidgetCommon)]
41pub struct Controls<'a> {
42 global_state: &'a GlobalState,
43 imgs: &'a Imgs,
44 fonts: &'a Fonts,
45 localized_strings: &'a Localization,
46 #[conrod(common_builder)]
47 common: widget::CommonBuilder,
48}
49impl<'a> Controls<'a> {
50 pub fn new(
51 global_state: &'a GlobalState,
52 imgs: &'a Imgs,
53 fonts: &'a Fonts,
54 localized_strings: &'a Localization,
55 ) -> Self {
56 Self {
57 global_state,
58 imgs,
59 fonts,
60 localized_strings,
61 common: widget::CommonBuilder::default(),
62 }
63 }
64}
65
66#[derive(PartialEq, Clone, Copy)]
67pub enum BindingMode {
68 Keyboard,
69 Gamepad,
70}
71#[derive(Clone, Copy)]
72pub enum GamepadBindingOption {
73 GameButtons,
74 GameLayers,
75 MenuButtons,
76}
77#[derive(Clone, Copy)]
78pub enum KeyMouseBindingOption {
79 KeyMouseButtons,
80 MenuButtons,
81}
82
83pub struct State {
84 ids: Ids,
85 pub binding_mode: BindingMode,
86 pub gamepad_binding_option: GamepadBindingOption,
87 pub keymouse_binding_option: KeyMouseBindingOption,
88}
89
90static SORTED_GAMEINPUTS: LazyLock<Vec<GameInput>> = LazyLock::new(|| {
91 let mut bindings_vec: Vec<GameInput> = GameInput::iter().collect();
92 bindings_vec.sort();
93 bindings_vec
94});
95static SORTED_MENUINPUTS: LazyLock<Vec<MenuInput>> = LazyLock::new(|| {
96 let mut bindings_vec: Vec<MenuInput> = MenuInput::iter().collect();
97 bindings_vec.sort();
98 bindings_vec
99});
100
101impl Widget for Controls<'_> {
102 type Event = Vec<ControlChange>;
103 type State = State;
104 type Style = ();
105
106 fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
107 State {
108 ids: Ids::new(id_gen),
109 binding_mode: BindingMode::Keyboard,
110 gamepad_binding_option: GamepadBindingOption::GameButtons,
111 keymouse_binding_option: KeyMouseBindingOption::KeyMouseButtons,
112 }
113 }
114
115 fn style(&self) -> Self::Style {}
116
117 fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
118 common_base::prof_span!("Controls::update");
119 let widget::UpdateArgs { state, ui, .. } = args;
120
121 let mut events = Vec::new();
122
123 Rectangle::fill_with(args.rect.dim(), color::TRANSPARENT)
124 .xy(args.rect.xy())
125 .graphics_for(args.id)
126 .scroll_kids()
127 .scroll_kids_vertically()
128 .set(state.ids.window, ui);
129 Rectangle::fill_with([args.rect.w() / 2.0, args.rect.h()], color::TRANSPARENT)
130 .top_right()
131 .parent(state.ids.window)
132 .set(state.ids.window_r, ui);
133 Scrollbar::y_axis(state.ids.window)
134 .thickness(5.0)
135 .rgba(0.33, 0.33, 0.33, 1.0)
136 .set(state.ids.window_scrollbar, ui);
137
138 let binding_mode = state.binding_mode;
140 let gamepad_binding_option = state.gamepad_binding_option;
141 let keymouse_binding_option = state.keymouse_binding_option;
142
143 let mut resize_ids = |len| {
145 if len > state.ids.controls_texts.len() || len > state.ids.controls_buttons.len() {
146 state.update(|s| {
147 s.ids
148 .controls_texts
149 .resize(len, &mut ui.widget_id_generator());
150 s.ids
151 .controls_buttons
152 .resize(len, &mut ui.widget_id_generator());
153 });
154 }
155 };
156
157 let mut previous_element_id = None;
159
160 if let BindingMode::Gamepad = binding_mode {
161 match gamepad_binding_option {
162 GamepadBindingOption::GameButtons => {
163 let gamepad_controls = &self.global_state.settings.controller;
164
165 resize_ids(SORTED_GAMEINPUTS.len());
166
167 for (game_input, (&text_id, &button_id)) in SORTED_GAMEINPUTS.iter().zip(
169 state
170 .ids
171 .controls_texts
172 .iter()
173 .zip(state.ids.controls_buttons.iter()),
174 ) {
175 let (input_string, input_color) =
176 if let RemappingMode::RemapGamepadButtons(r_input) =
177 self.global_state.window.remapping_mode
178 && r_input == *game_input
179 {
180 (
181 self.localized_strings
182 .get_msg("hud-settings-awaitingkey")
183 .into_owned(),
184 TEXT_COLOR,
185 )
186 } else if let Some(button) =
187 gamepad_controls.get_game_button_binding(*game_input)
188 {
189 (
190 format!(
191 "{} {}",
192 button.display_string(self.localized_strings),
193 button
194 .try_shortened()
195 .map_or("".to_owned(), |short| format!("({})", short))
196 ),
197 if gamepad_controls.game_button_has_conflicting_bindings(button)
198 {
199 TEXT_BIND_CONFLICT_COLOR
200 } else {
201 TEXT_COLOR
202 },
203 )
204 } else {
205 (
206 self.localized_strings
207 .get_msg("hud-settings-unbound")
208 .into_owned(),
209 ERROR_COLOR,
210 )
211 };
212 let loc_key = self
213 .localized_strings
214 .get_msg(game_input.get_localization_key());
215 let text_widget = Text::new(&loc_key)
216 .color(TEXT_COLOR)
217 .font_id(self.fonts.cyri.conrod_id)
218 .font_size(self.fonts.cyri.scale(18));
219 let button_widget = Button::new()
220 .label(&input_string)
221 .label_color(input_color)
222 .label_font_id(self.fonts.cyri.conrod_id)
223 .label_font_size(self.fonts.cyri.scale(15))
224 .w(150.0)
225 .rgba(0.0, 0.0, 0.0, 0.0)
226 .border_rgba(0.0, 0.0, 0.0, 255.0)
227 .label_y(Relative::Scalar(3.0));
228 let text_widget = match previous_element_id {
230 None => {
231 text_widget.top_left_with_margins_on(state.ids.window, 10.0, 5.0)
232 },
233 Some(prev_id) => text_widget.down_from(prev_id, 10.0),
234 };
235 let text_width = text_widget.get_w(ui).unwrap_or(0.0);
236 text_widget.set(text_id, ui);
237 button_widget
238 .right_from(text_id, 350.0 - text_width)
239 .set(button_id, ui);
240
241 for _ in ui.widget_input(button_id).clicks().left() {
242 events.push(ChangeBindingGamepadButton(*game_input));
243 }
244 for _ in ui.widget_input(button_id).clicks().right() {
245 events.push(RemoveBindingGamepadButton(*game_input));
246 }
247 previous_element_id = Some(text_id);
249 }
250 },
251 GamepadBindingOption::GameLayers => {
252 let gamepad_controls = &self.global_state.settings.controller;
253
254 resize_ids(SORTED_GAMEINPUTS.len());
255
256 for (game_input, (&text_id, &button_id)) in SORTED_GAMEINPUTS.iter().zip(
258 state
259 .ids
260 .controls_texts
261 .iter()
262 .zip(state.ids.controls_buttons.iter()),
263 ) {
264 let (input_string, input_color) =
265 if let RemappingMode::RemapGamepadLayers(r_input) =
266 self.global_state.window.remapping_mode
267 && r_input == *game_input
268 {
269 (
270 self.localized_strings
271 .get_msg("hud-settings-awaitingkey")
272 .into_owned(),
273 TEXT_COLOR,
274 )
275 } else if let Some(entry) =
276 gamepad_controls.get_layer_button_binding(*game_input)
277 {
278 (
279 entry.display_string(self.localized_strings),
280 if gamepad_controls.layer_entry_has_conflicting_bindings(entry)
281 {
282 TEXT_BIND_CONFLICT_COLOR
283 } else {
284 TEXT_COLOR
285 },
286 )
287 } else {
288 (
289 self.localized_strings
290 .get_msg("hud-settings-unbound")
291 .into_owned(),
292 ERROR_COLOR,
293 )
294 };
295 let loc_key = self
296 .localized_strings
297 .get_msg(game_input.get_localization_key());
298 let text_widget = Text::new(&loc_key)
299 .color(TEXT_COLOR)
300 .font_id(self.fonts.cyri.conrod_id)
301 .font_size(self.fonts.cyri.scale(18));
302 let button_widget = Button::new()
303 .label(&input_string)
304 .label_color(input_color)
305 .label_font_id(self.fonts.cyri.conrod_id)
306 .label_font_size(self.fonts.cyri.scale(15))
307 .w(150.0)
308 .rgba(0.0, 0.0, 0.0, 0.0)
309 .border_rgba(0.0, 0.0, 0.0, 255.0)
310 .label_y(Relative::Scalar(3.0));
311 let text_widget = match previous_element_id {
313 None => {
314 text_widget.top_left_with_margins_on(state.ids.window, 10.0, 5.0)
315 },
316 Some(prev_id) => text_widget.down_from(prev_id, 10.0),
317 };
318 let text_width = text_widget.get_w(ui).unwrap_or(0.0);
319 text_widget.set(text_id, ui);
320 button_widget
321 .right_from(text_id, 350.0 - text_width)
322 .set(button_id, ui);
323
324 for _ in ui.widget_input(button_id).clicks().left() {
325 events.push(ChangeBindingGamepadLayer(*game_input));
326 }
327 for _ in ui.widget_input(button_id).clicks().right() {
328 events.push(RemoveBindingGamepadLayer(*game_input));
329 }
330 previous_element_id = Some(text_id);
332 }
333 },
334 GamepadBindingOption::MenuButtons => {
335 let gamepad_controls = &self.global_state.settings.controller;
336
337 resize_ids(SORTED_MENUINPUTS.len());
338
339 for (menu_input, (&text_id, &button_id)) in SORTED_MENUINPUTS.iter().zip(
341 state
342 .ids
343 .controls_texts
344 .iter()
345 .zip(state.ids.controls_buttons.iter()),
346 ) {
347 let (input_string, input_color) =
348 if let RemappingMode::RemapGamepadMenu(r_input) =
349 self.global_state.window.remapping_mode
350 && r_input == *menu_input
351 {
352 (
353 self.localized_strings
354 .get_msg("hud-settings-awaitingkey")
355 .into_owned(),
356 TEXT_COLOR,
357 )
358 } else if let Some(button) =
359 gamepad_controls.get_menu_button_binding(*menu_input)
360 {
361 (
362 format!(
363 "{} {}",
364 button.display_string(self.localized_strings),
365 button
366 .try_shortened()
367 .map_or("".to_owned(), |short| format!("({})", short))
368 ),
369 if gamepad_controls.menu_button_has_conflicting_bindings(button)
370 {
371 TEXT_BIND_CONFLICT_COLOR
372 } else {
373 TEXT_COLOR
374 },
375 )
376 } else {
377 (
378 self.localized_strings
379 .get_msg("hud-settings-unbound")
380 .into_owned(),
381 ERROR_COLOR,
382 )
383 };
384 let loc_key = self
385 .localized_strings
386 .get_msg(menu_input.get_localization_key());
387 let text_widget = Text::new(&loc_key)
388 .color(TEXT_COLOR)
389 .font_id(self.fonts.cyri.conrod_id)
390 .font_size(self.fonts.cyri.scale(18));
391 let button_widget = Button::new()
392 .label(&input_string)
393 .label_color(input_color)
394 .label_font_id(self.fonts.cyri.conrod_id)
395 .label_font_size(self.fonts.cyri.scale(15))
396 .w(150.0)
397 .rgba(0.0, 0.0, 0.0, 0.0)
398 .border_rgba(0.0, 0.0, 0.0, 255.0)
399 .label_y(Relative::Scalar(3.0));
400 let text_widget = match previous_element_id {
402 None => {
403 text_widget.top_left_with_margins_on(state.ids.window, 10.0, 5.0)
404 },
405 Some(prev_id) => text_widget.down_from(prev_id, 10.0),
406 };
407 let text_width = text_widget.get_w(ui).unwrap_or(0.0);
408 text_widget.set(text_id, ui);
409 button_widget
410 .right_from(text_id, 350.0 - text_width)
411 .set(button_id, ui);
412
413 for _ in ui.widget_input(button_id).clicks().left() {
414 events.push(ChangeBindingGamepadMenu(*menu_input));
415 }
416 for _ in ui.widget_input(button_id).clicks().right() {
417 events.push(RemoveBindingGamepadMenu(*menu_input));
418 }
419 previous_element_id = Some(text_id);
421 }
422 },
423 }
424 } else {
425 match keymouse_binding_option {
426 KeyMouseBindingOption::MenuButtons => {
427 let controls = &self.global_state.settings.controls;
428
429 resize_ids(SORTED_MENUINPUTS.len());
430
431 for (menu_input, (&text_id, &button_id)) in SORTED_MENUINPUTS.iter().zip(
433 state
434 .ids
435 .controls_texts
436 .iter()
437 .zip(state.ids.controls_buttons.iter()),
438 ) {
439 let (key_string, key_color) =
440 if let RemappingMode::RemapKeyboardMenu(r_input) =
441 self.global_state.window.remapping_mode
442 && r_input == *menu_input
443 {
444 (
445 self.localized_strings
446 .get_msg("hud-settings-awaitingkey")
447 .into_owned(),
448 TEXT_COLOR,
449 )
450 } else if let Some(key) = controls.get_menu_binding(*menu_input) {
451 (
452 format!(
453 "{} {}",
454 key.display_string(),
455 key.try_shortened()
456 .map_or("".to_owned(), |short| format!("({})", short))
457 ),
458 if controls.has_conflicting_menu_bindings(key) {
459 TEXT_BIND_CONFLICT_COLOR
460 } else {
461 TEXT_COLOR
462 },
463 )
464 } else {
465 (
466 self.localized_strings
467 .get_msg("hud-settings-unbound")
468 .into_owned(),
469 ERROR_COLOR,
470 )
471 };
472 let loc_key = self
473 .localized_strings
474 .get_msg(menu_input.get_localization_key());
475 let text_widget = Text::new(&loc_key)
476 .color(TEXT_COLOR)
477 .font_id(self.fonts.cyri.conrod_id)
478 .font_size(self.fonts.cyri.scale(18));
479 let button_widget = Button::new()
480 .label(&key_string)
481 .label_color(key_color)
482 .label_font_id(self.fonts.cyri.conrod_id)
483 .label_font_size(self.fonts.cyri.scale(15))
484 .w(150.0)
485 .rgba(0.0, 0.0, 0.0, 0.0)
486 .border_rgba(0.0, 0.0, 0.0, 255.0)
487 .label_y(Relative::Scalar(3.0));
488 let text_widget = match previous_element_id {
490 None => {
491 text_widget.top_left_with_margins_on(state.ids.window, 10.0, 5.0)
492 },
493 Some(prev_id) => text_widget.down_from(prev_id, 10.0),
494 };
495 let text_width = text_widget.get_w(ui).unwrap_or(0.0);
496 text_widget.set(text_id, ui);
497 button_widget
498 .right_from(text_id, 350.0 - text_width)
499 .set(button_id, ui);
500
501 for _ in ui.widget_input(button_id).clicks().left() {
502 events.push(ChangeBindingKeyboardMenu(*menu_input));
503 }
504 for _ in ui.widget_input(button_id).clicks().right() {
505 events.push(RemoveBindingKeyboardMenu(*menu_input));
506 }
507 previous_element_id = Some(text_id);
509 }
510 },
511 KeyMouseBindingOption::KeyMouseButtons => {
512 let controls = &self.global_state.settings.controls;
513
514 resize_ids(SORTED_GAMEINPUTS.len());
515
516 for (game_input, (&text_id, &button_id)) in SORTED_GAMEINPUTS.iter().zip(
518 state
519 .ids
520 .controls_texts
521 .iter()
522 .zip(state.ids.controls_buttons.iter()),
523 ) {
524 let (key_string, key_color) = if let RemappingMode::RemapKeyboard(r_input) =
525 self.global_state.window.remapping_mode
526 && r_input == *game_input
527 {
528 (
529 self.localized_strings
530 .get_msg("hud-settings-awaitingkey")
531 .into_owned(),
532 TEXT_COLOR,
533 )
534 } else if let Some(key) = controls.get_binding(*game_input) {
535 (
536 format!(
537 "{} {}",
538 key.display_string(),
539 key.try_shortened()
540 .map_or("".to_owned(), |short| format!("({})", short))
541 ),
542 if controls.has_conflicting_bindings(key) {
543 TEXT_BIND_CONFLICT_COLOR
544 } else {
545 TEXT_COLOR
546 },
547 )
548 } else {
549 (
550 self.localized_strings
551 .get_msg("hud-settings-unbound")
552 .into_owned(),
553 ERROR_COLOR,
554 )
555 };
556 let loc_key = self
557 .localized_strings
558 .get_msg(game_input.get_localization_key());
559 let text_widget = Text::new(&loc_key)
560 .color(TEXT_COLOR)
561 .font_id(self.fonts.cyri.conrod_id)
562 .font_size(self.fonts.cyri.scale(18));
563 let button_widget = Button::new()
564 .label(&key_string)
565 .label_color(key_color)
566 .label_font_id(self.fonts.cyri.conrod_id)
567 .label_font_size(self.fonts.cyri.scale(15))
568 .w(150.0)
569 .rgba(0.0, 0.0, 0.0, 0.0)
570 .border_rgba(0.0, 0.0, 0.0, 255.0)
571 .label_y(Relative::Scalar(3.0));
572 let text_widget = match previous_element_id {
574 None => {
575 text_widget.top_left_with_margins_on(state.ids.window, 10.0, 5.0)
576 },
577 Some(prev_id) => text_widget.down_from(prev_id, 10.0),
578 };
579 let text_width = text_widget.get_w(ui).unwrap_or(0.0);
580 text_widget.set(text_id, ui);
581 button_widget
582 .right_from(text_id, 350.0 - text_width)
583 .set(button_id, ui);
584
585 for _ in ui.widget_input(button_id).clicks().left() {
586 events.push(ChangeBindingKeyboard(*game_input));
587 }
588 for _ in ui.widget_input(button_id).clicks().right() {
589 events.push(RemoveBindingKeyboard(*game_input));
590 }
591 previous_element_id = Some(text_id);
593 }
594 },
595 }
596 }
597
598 if let Some(prev_id) = previous_element_id {
600 if Button::image(self.imgs.button)
601 .w_h(RESET_BUTTONS_WIDTH, RESET_BUTTONS_HEIGHT)
602 .hover_image(self.imgs.button_hover)
603 .press_image(self.imgs.button_press)
604 .down_from(prev_id, 20.0)
605 .label(
606 &self
607 .localized_strings
608 .get_msg("hud-settings-reset_keybinds"),
609 )
610 .label_font_size(self.fonts.cyri.scale(14))
611 .label_color(TEXT_COLOR)
612 .label_font_id(self.fonts.cyri.conrod_id)
613 .label_y(Relative::Scalar(2.0))
614 .set(state.ids.reset_controls_button, ui)
615 .was_clicked()
616 {
617 if state.binding_mode != BindingMode::Gamepad {
618 events.push(ResetKeyBindingsKeyboard);
619 } else {
620 events.push(ResetKeyBindingsGamepad);
623 }
624 }
625 previous_element_id = Some(state.ids.reset_controls_button)
626 }
627
628 let offset = ui
629 .widget_graph()
630 .widget(state.ids.window)
631 .and_then(|widget| {
632 widget
633 .maybe_y_scroll_state
634 .as_ref()
635 .map(|scroll| scroll.offset)
636 })
637 .unwrap_or(0.0);
638
639 let keybind_helper_text = self
640 .localized_strings
641 .get_msg("hud-settings-keybind-helper");
642 let keybind_helper = Text::new(&keybind_helper_text)
643 .color(TEXT_COLOR)
644 .font_id(self.fonts.cyri.conrod_id)
645 .font_size(self.fonts.cyri.scale(18));
646 keybind_helper
647 .top_right_with_margins_on(state.ids.window, offset + 5.0, 10.0)
648 .set(state.ids.keybind_helper, ui);
649
650 if let BindingMode::Keyboard = state.binding_mode {
652 let keybindings = &self
653 .localized_strings
654 .get_msg("hud-settings-keyboard-binding");
655 let menu_keybindings = &self.localized_strings.get_msg("hud-settings-menu_buttons");
656
657 let binding_mode_list = [keybindings, menu_keybindings];
658 if let Some(clicked) = DropDownList::new(
659 &binding_mode_list,
660 Some(state.keymouse_binding_option as usize),
661 )
662 .label_color(TEXT_COLOR)
663 .label_font_id(self.fonts.cyri.conrod_id)
664 .label_font_size(self.fonts.cyri.scale(15))
665 .w_h(125.0, 35.0)
666 .rgba(0.0, 0.0, 0.0, 0.0)
667 .border_rgba(0.0, 0.0, 0.0, 255.0)
668 .label_y(Relative::Scalar(1.0))
669 .down_from(state.ids.gamepad_mode_button, 10.0)
670 .set(state.ids.gamepad_option_dropdown, ui)
671 {
672 match clicked {
673 0 => {
674 state.update(|s| {
675 s.keymouse_binding_option = KeyMouseBindingOption::KeyMouseButtons
676 });
677 events.push(ResetBindingMode);
678 },
679 1 => {
680 state.update(|s| {
681 s.keymouse_binding_option = KeyMouseBindingOption::MenuButtons
682 });
683 events.push(ResetBindingMode);
684 },
685 _ => {
686 state.update(|s| {
687 s.keymouse_binding_option = KeyMouseBindingOption::KeyMouseButtons
688 });
689 events.push(ResetBindingMode);
690 },
691 }
692 }
693 }
694
695 if let BindingMode::Gamepad = state.binding_mode {
697 let game_buttons = &self.localized_strings.get_msg("hud-settings-game_buttons");
698 let game_layers = &self.localized_strings.get_msg("hud-settings-game_layers");
699 let menu_buttons = &self.localized_strings.get_msg("hud-settings-menu_buttons");
700
701 let binding_mode_list = [game_buttons, game_layers, menu_buttons];
702 if let Some(clicked) = DropDownList::new(
703 &binding_mode_list,
704 Some(state.gamepad_binding_option as usize),
705 )
706 .label_color(TEXT_COLOR)
707 .label_font_id(self.fonts.cyri.conrod_id)
708 .label_font_size(self.fonts.cyri.scale(15))
709 .w_h(125.0, 35.0)
710 .rgba(0.0, 0.0, 0.0, 0.0)
711 .border_rgba(0.0, 0.0, 0.0, 255.0)
712 .label_y(Relative::Scalar(1.0))
713 .down_from(state.ids.gamepad_mode_button, 10.0)
714 .set(state.ids.gamepad_option_dropdown, ui)
715 {
716 match clicked {
717 0 => {
718 state.update(|s| {
719 s.gamepad_binding_option = GamepadBindingOption::GameButtons
720 });
721 events.push(ResetBindingMode);
722 },
723 1 => {
724 state.update(|s| {
725 s.gamepad_binding_option = GamepadBindingOption::GameLayers
726 });
727 events.push(ResetBindingMode);
728 },
729 2 => {
730 state.update(|s| {
731 s.gamepad_binding_option = GamepadBindingOption::MenuButtons
732 });
733 events.push(ResetBindingMode);
734 },
735 _ => {
736 state.update(|s| {
737 s.gamepad_binding_option = GamepadBindingOption::GameButtons
738 });
739 events.push(ResetBindingMode);
740 },
741 }
742 }
743
744 if let GamepadBindingOption::GameLayers = state.gamepad_binding_option {
746 let mod1_text = "RB";
748 let gamelayer_mod1 = ToggleButton::new(
749 self.global_state.window.gamelayer_mod1,
750 self.imgs.checkbox,
751 self.imgs.checkbox_checked,
752 )
753 .down_from(state.ids.gamepad_option_dropdown, 10.0)
754 .w_h(18.0, 18.0)
755 .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
756 .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
757 .set(state.ids.gamelayer_mod1_checkbox, ui);
758 if self.global_state.window.gamelayer_mod1 != gamelayer_mod1 {
759 events.push(GameLayerMod1(gamelayer_mod1));
760 }
761 Text::new(mod1_text)
762 .right_from(state.ids.gamelayer_mod1_checkbox, 10.0)
763 .font_size(self.fonts.cyri.scale(15))
764 .font_id(self.fonts.cyri.conrod_id)
765 .color(TEXT_COLOR)
766 .set(state.ids.gamelayer_mod1_text, ui);
767
768 let mod2_text = "LB";
770 let gamelayer_mod2 = ToggleButton::new(
771 self.global_state.window.gamelayer_mod2,
772 self.imgs.checkbox,
773 self.imgs.checkbox_checked,
774 )
775 .down_from(state.ids.gamelayer_mod1_checkbox, 10.0)
776 .w_h(18.0, 18.0)
777 .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
778 .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
779 .set(state.ids.gamelayer_mod2_checkbox, ui);
780 if self.global_state.window.gamelayer_mod2 != gamelayer_mod2 {
781 events.push(GameLayerMod2(gamelayer_mod2));
782 }
783 Text::new(mod2_text)
784 .right_from(state.ids.gamelayer_mod2_checkbox, 10.0)
785 .font_size(self.fonts.cyri.scale(15))
786 .font_id(self.fonts.cyri.conrod_id)
787 .color(TEXT_COLOR)
788 .set(state.ids.gamelayer_mod2_text, ui);
789 }
790 }
791
792 let gamepad = &self.localized_strings.get_msg("hud-settings-gamepad");
793 let keyboard = &self.localized_strings.get_msg("hud-settings-keyboard");
794
795 let binding_mode_toggle_widget = Button::new()
796 .label(if let BindingMode::Gamepad = state.binding_mode {
797 gamepad
798 } else {
799 keyboard
800 })
801 .label_color(TEXT_COLOR)
802 .label_font_id(self.fonts.cyri.conrod_id)
803 .label_font_size(self.fonts.cyri.scale(15))
804 .w_h(125.0, 35.0)
805 .rgba(0.0, 0.0, 0.0, 0.0)
806 .border_rgba(0.0, 0.0, 0.0, 255.0)
807 .label_y(Relative::Scalar(1.0));
808 if binding_mode_toggle_widget
809 .down_from(state.ids.keybind_helper, 10.0)
810 .align_right_of(state.ids.keybind_helper)
811 .set(state.ids.gamepad_mode_button, ui)
812 .was_clicked()
813 {
814 if let BindingMode::Keyboard = state.binding_mode {
815 state.update(|s| s.binding_mode = BindingMode::Gamepad);
816 events.push(ResetBindingMode);
817 } else {
818 state.update(|s| s.binding_mode = BindingMode::Keyboard);
819 events.push(ResetBindingMode);
820 }
821 }
822
823 if let Some(prev_id) = previous_element_id {
825 Rectangle::fill_with([1.0, 1.0], color::TRANSPARENT)
826 .down_from(prev_id, 10.0)
827 .set(state.ids.controls_alignment_rectangle, ui);
828 }
829
830 events
831 }
832}