veloren_voxygen/hud/settings_window/
interface.rs

1use super::{RESET_BUTTONS_HEIGHT, RESET_BUTTONS_WIDTH, ScaleChange};
2
3use crate::{
4    GlobalState,
5    hud::{
6        BarNumbers, BuffPosition, CrosshairType, MENU_BG, ShortcutNumbers, TEXT_COLOR,
7        img_ids::Imgs,
8    },
9    session::settings_change::{Interface as InterfaceChange, Interface::*},
10    ui::{ImageSlider, ScaleMode, ToggleButton, fonts::Fonts},
11};
12use conrod_core::{
13    Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, color,
14    position::{Align, Relative},
15    widget::{self, Button, DropDownList, Image, Rectangle, Scrollbar, Text},
16    widget_ids,
17};
18use i18n::Localization;
19
20widget_ids! {
21    struct Ids{
22        window,
23        window_r,
24        window_scrollbar,
25        reset_interface_button,
26        ui_scale_label,
27        ui_scale_slider,
28        ui_scale_value,
29        ui_scale_list,
30        relative_to_win_button,
31        relative_to_win_text,
32        absolute_scale_button,
33        absolute_scale_text,
34        general_txt,
35        load_tips_button,
36        load_tips_button_label,
37        debug_button,
38        debug_button_label,
39        hitboxes_button,
40        hitboxes_button_label,
41        chat_button,
42        chat_button_label,
43        hotkey_hints_button,
44        hotkey_hints_button_label,
45        ch_title,
46        ch_transp_slider,
47        ch_transp_value,
48        ch_transp_text,
49        ch_1_bg,
50        ch_2_bg,
51        ch_3_bg,
52        crosshair_outer_1,
53        crosshair_inner_1,
54        crosshair_outer_2,
55        crosshair_inner_2,
56        crosshair_outer_3,
57        crosshair_inner_3,
58        //
59        hotbar_title,
60        bar_numbers_title,
61        show_bar_numbers_none_button,
62        show_bar_numbers_none_text,
63        show_bar_numbers_values_button,
64        show_bar_numbers_values_text,
65        show_bar_numbers_percentage_button,
66        show_bar_numbers_percentage_text,
67        always_show_bars_button,
68        always_show_bars_label,
69        enable_poise_bar_button,
70        enable_poise_bar_label,
71        use_health_prefixes_text,
72        use_health_prefixes_button,
73        //
74        show_shortcuts_button,
75        show_shortcuts_text,
76        buff_pos_bar_button,
77        buff_pos_bar_text,
78        buff_pos_map_button,
79        buff_pos_map_text,
80        //
81        slots_title,
82        slots_use_prefixes_text,
83        slots_use_prefixes_radio,
84        slots_prefix_switch_point_slider,
85        slots_prefix_switch_point_text,
86        slots_prefix_switch_point_value,
87        //
88        sct_title,
89        sct_show_text,
90        sct_show_radio,
91        sct_round_dmg_text,
92        sct_round_dmg_radio,
93        sct_dmg_accum_duration_slider,
94        sct_dmg_accum_duration_text,
95        sct_dmg_accum_duration_value,
96        sct_show_inc_dmg_text,
97        sct_show_inc_dmg_radio,
98        sct_inc_dmg_accum_duration_slider,
99        sct_inc_dmg_accum_duration_text,
100        sct_inc_dmg_accum_duration_value,
101        //
102        speech_bubble_text,
103        speech_bubble_self_text,
104        speech_bubble_self_button,
105        speech_bubble_dark_mode_text,
106        speech_bubble_dark_mode_button,
107        speech_bubble_icon_text,
108        speech_bubble_icon_button,
109        //
110        experience_numbers_title,
111        accum_experience_text,
112        accum_experience_button,
113    }
114}
115
116#[derive(WidgetCommon)]
117pub struct Interface<'a> {
118    global_state: &'a GlobalState,
119    imgs: &'a Imgs,
120    fonts: &'a Fonts,
121    localized_strings: &'a Localization,
122    #[conrod(common_builder)]
123    common: widget::CommonBuilder,
124}
125impl<'a> Interface<'a> {
126    pub fn new(
127        global_state: &'a GlobalState,
128        imgs: &'a Imgs,
129        fonts: &'a Fonts,
130        localized_strings: &'a Localization,
131    ) -> Self {
132        Self {
133            global_state,
134            imgs,
135            fonts,
136            localized_strings,
137            common: widget::CommonBuilder::default(),
138        }
139    }
140}
141
142pub struct State {
143    ids: Ids,
144}
145
146impl Widget for Interface<'_> {
147    type Event = Vec<InterfaceChange>;
148    type State = State;
149    type Style = ();
150
151    fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
152        State {
153            ids: Ids::new(id_gen),
154        }
155    }
156
157    fn style(&self) -> Self::Style {}
158
159    fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
160        common_base::prof_span!("Interface::update");
161        let widget::UpdateArgs { state, ui, .. } = args;
162
163        let mut events = Vec::new();
164
165        Rectangle::fill_with(args.rect.dim(), color::TRANSPARENT)
166            .xy(args.rect.xy())
167            .graphics_for(args.id)
168            .scroll_kids()
169            .scroll_kids_vertically()
170            .set(state.ids.window, ui);
171        Rectangle::fill_with([args.rect.w() / 2.0, args.rect.h()], color::TRANSPARENT)
172            .top_right()
173            .parent(state.ids.window)
174            .set(state.ids.window_r, ui);
175        Scrollbar::y_axis(state.ids.window)
176            .thickness(5.0)
177            .rgba(0.33, 0.33, 0.33, 1.0)
178            .set(state.ids.window_scrollbar, ui);
179
180        let bar_values = self.global_state.settings.interface.bar_numbers;
181        let crosshair_opacity = self.global_state.settings.interface.crosshair_opacity;
182        let crosshair_type = self.global_state.settings.interface.crosshair_type;
183        let ui_scale = self.global_state.settings.interface.ui_scale;
184
185        Text::new(&self.localized_strings.get_msg("hud-settings-general"))
186            .top_left_with_margins_on(state.ids.window, 5.0, 5.0)
187            .font_size(self.fonts.cyri.scale(18))
188            .font_id(self.fonts.cyri.conrod_id)
189            .color(TEXT_COLOR)
190            .set(state.ids.general_txt, ui);
191
192        // Loading Screen Tips
193        let show_tips = ToggleButton::new(
194            self.global_state.settings.interface.loading_tips,
195            self.imgs.checkbox,
196            self.imgs.checkbox_checked,
197        )
198        .w_h(18.0, 18.0)
199        .down_from(state.ids.general_txt, 20.0)
200        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
201        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
202        .set(state.ids.load_tips_button, ui);
203
204        if self.global_state.settings.interface.loading_tips != show_tips {
205            events.push(ToggleTips(
206                !self.global_state.settings.interface.loading_tips,
207            ));
208        }
209
210        Text::new(&self.localized_strings.get_msg("hud-settings-loading_tips"))
211            .right_from(state.ids.load_tips_button, 10.0)
212            .font_size(self.fonts.cyri.scale(14))
213            .font_id(self.fonts.cyri.conrod_id)
214            .graphics_for(state.ids.load_tips_button)
215            .color(TEXT_COLOR)
216            .set(state.ids.load_tips_button_label, ui);
217
218        // Debug
219        let show_debug = ToggleButton::new(
220            self.global_state.settings.interface.toggle_debug,
221            self.imgs.checkbox,
222            self.imgs.checkbox_checked,
223        )
224        .w_h(18.0, 18.0)
225        .down_from(state.ids.load_tips_button, 8.0)
226        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
227        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
228        .set(state.ids.debug_button, ui);
229
230        if self.global_state.settings.interface.toggle_debug != show_debug {
231            events.push(ToggleDebug(show_debug));
232        }
233
234        Text::new(&self.localized_strings.get_msg("hud-settings-debug_info"))
235            .right_from(state.ids.debug_button, 10.0)
236            .font_size(self.fonts.cyri.scale(14))
237            .font_id(self.fonts.cyri.conrod_id)
238            .graphics_for(state.ids.debug_button)
239            .color(TEXT_COLOR)
240            .set(state.ids.debug_button_label, ui);
241
242        // Hitboxes
243        let show_hitboxes = ToggleButton::new(
244            self.global_state.settings.interface.toggle_hitboxes,
245            self.imgs.checkbox,
246            self.imgs.checkbox_checked,
247        )
248        .w_h(18.0, 18.0)
249        .down_from(state.ids.debug_button, 8.0)
250        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
251        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
252        .set(state.ids.hitboxes_button, ui);
253
254        if self.global_state.settings.interface.toggle_hitboxes != show_hitboxes {
255            events.push(ToggleHitboxes(show_hitboxes));
256        }
257
258        Text::new(&self.localized_strings.get_msg("hud-settings-show_hitboxes"))
259            .right_from(state.ids.hitboxes_button, 10.0)
260            .font_size(self.fonts.cyri.scale(14))
261            .font_id(self.fonts.cyri.conrod_id)
262            .graphics_for(state.ids.hitboxes_button)
263            .color(TEXT_COLOR)
264            .set(state.ids.hitboxes_button_label, ui);
265
266        // Chat
267        let show_chat = ToggleButton::new(
268            self.global_state.settings.interface.toggle_chat,
269            self.imgs.checkbox,
270            self.imgs.checkbox_checked,
271        )
272        .w_h(18.0, 18.0)
273        .down_from(state.ids.hitboxes_button, 8.0)
274        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
275        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
276        .set(state.ids.chat_button, ui);
277
278        if self.global_state.settings.interface.toggle_chat != show_chat {
279            events.push(ToggleChat(show_chat));
280        }
281
282        Text::new(&self.localized_strings.get_msg("hud-settings-show_chat"))
283            .right_from(state.ids.chat_button, 10.0)
284            .font_size(self.fonts.cyri.scale(14))
285            .font_id(self.fonts.cyri.conrod_id)
286            .graphics_for(state.ids.chat_button)
287            .color(TEXT_COLOR)
288            .set(state.ids.chat_button_label, ui);
289
290        // Hotkey hints
291        let show_hotkey_hints = ToggleButton::new(
292            self.global_state.settings.interface.toggle_hotkey_hints,
293            self.imgs.checkbox,
294            self.imgs.checkbox_checked,
295        )
296        .w_h(18.0, 18.0)
297        .down_from(state.ids.chat_button, 8.0)
298        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
299        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
300        .set(state.ids.hotkey_hints_button, ui);
301
302        if self.global_state.settings.interface.toggle_hotkey_hints != show_hotkey_hints {
303            events.push(ToggleHotkeyHints(show_hotkey_hints));
304        }
305
306        Text::new(
307            &self
308                .localized_strings
309                .get_msg("hud-settings-show_hotkey_hints"),
310        )
311        .right_from(state.ids.hotkey_hints_button, 10.0)
312        .font_size(self.fonts.cyri.scale(14))
313        .font_id(self.fonts.cyri.conrod_id)
314        .graphics_for(state.ids.hotkey_hints_button)
315        .color(TEXT_COLOR)
316        .set(state.ids.hotkey_hints_button_label, ui);
317
318        // Ui Scale
319        Text::new(&self.localized_strings.get_msg("hud-settings-ui_scale"))
320            .down_from(state.ids.hotkey_hints_button, 20.0)
321            .font_size(self.fonts.cyri.scale(18))
322            .font_id(self.fonts.cyri.conrod_id)
323            .color(TEXT_COLOR)
324            .set(state.ids.ui_scale_label, ui);
325
326        // Relative Scaling Button
327        let (check_img, check_mo_img, check_press_img, relative_selected) = match ui_scale {
328            ScaleMode::RelativeToWindow(_) => (
329                self.imgs.check_checked,
330                self.imgs.check_checked_mo,
331                self.imgs.check_checked,
332                true,
333            ),
334            ScaleMode::Absolute(_) | ScaleMode::DpiFactor => (
335                self.imgs.check,
336                self.imgs.check_mo,
337                self.imgs.check_press,
338                false,
339            ),
340        };
341        if Button::image(check_img)
342            .w_h(12.0, 12.0)
343            .down_from(state.ids.ui_scale_label, 20.0)
344            .hover_image(check_mo_img)
345            .press_image(check_press_img)
346            .set(state.ids.relative_to_win_button, ui)
347            .was_clicked()
348            && !relative_selected
349        {
350            events.push(UiScale(ScaleChange::ToRelative));
351        }
352
353        Text::new(
354            &self
355                .localized_strings
356                .get_msg("hud-settings-relative_scaling"),
357        )
358        .right_from(state.ids.relative_to_win_button, 10.0)
359        .font_size(self.fonts.cyri.scale(14))
360        .font_id(self.fonts.cyri.conrod_id)
361        .graphics_for(state.ids.relative_to_win_button)
362        .color(TEXT_COLOR)
363        .set(state.ids.relative_to_win_text, ui);
364
365        // Absolute Scaling Button
366        let (check_img, check_mo_img, check_press_img, absolute_selected) = match ui_scale {
367            ScaleMode::Absolute(_) => (
368                self.imgs.check_checked,
369                self.imgs.check_checked_mo,
370                self.imgs.check_checked,
371                true,
372            ),
373            ScaleMode::RelativeToWindow(_) | ScaleMode::DpiFactor => (
374                self.imgs.check,
375                self.imgs.check_mo,
376                self.imgs.check_press,
377                false,
378            ),
379        };
380        if Button::image(check_img)
381            .w_h(12.0, 12.0)
382            .down_from(state.ids.relative_to_win_button, 8.0)
383            .hover_image(check_mo_img)
384            .press_image(check_press_img)
385            .set(state.ids.absolute_scale_button, ui)
386            .was_clicked()
387            && !absolute_selected
388        {
389            events.push(UiScale(ScaleChange::ToAbsolute));
390        }
391
392        Text::new(
393            &self
394                .localized_strings
395                .get_msg("hud-settings-custom_scaling"),
396        )
397        .right_from(state.ids.absolute_scale_button, 10.0)
398        .font_size(self.fonts.cyri.scale(14))
399        .font_id(self.fonts.cyri.conrod_id)
400        .graphics_for(state.ids.absolute_scale_button)
401        .color(TEXT_COLOR)
402        .set(state.ids.absolute_scale_text, ui);
403
404        // Slider -> Inactive when "Relative to window" is selected
405        if let ScaleMode::Absolute(scale) = ui_scale {
406            if let Some(new_val) = ImageSlider::continuous(
407                scale.log(2.0),
408                0.5f64.log(2.0),
409                2.0f64.log(2.0),
410                self.imgs.slider_indicator,
411                self.imgs.slider,
412            )
413            .w_h(208.0, 22.0)
414            .right_from(state.ids.absolute_scale_text, 12.0)
415            .track_breadth(30.0)
416            .slider_length(10.0)
417            .pad_track((5.0, 5.0))
418            .set(state.ids.ui_scale_slider, ui)
419            {
420                events.push(UiScale(ScaleChange::Adjust(2.0f64.powf(new_val))));
421            }
422            let mode_label_list = [0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0];
423            let selected = mode_label_list
424                .iter()
425                .position(|factor| (*factor - scale).abs() < 0.24);
426            // Dropdown menu for custom scaling
427            if let Some(clicked) = DropDownList::new(
428                &mode_label_list
429                    .iter()
430                    .map(|factor| format!("{n:.*}", 2, n = factor))
431                    .collect::<Vec<String>>(),
432                selected,
433            )
434            .w_h(208.0, 22.0)
435            .color(MENU_BG)
436            .label_color(TEXT_COLOR)
437            .label_font_size(self.fonts.cyri.scale(10))
438            .down_from(state.ids.ui_scale_slider, 6.0)
439            .set(state.ids.ui_scale_list, ui)
440            {
441                events.push(UiScale(ScaleChange::Adjust(mode_label_list[clicked])));
442            }
443            // Custom Scaling Text
444            Text::new(&format!("{:.2}", scale))
445                .right_from(state.ids.ui_scale_slider, 10.0)
446                .font_size(self.fonts.cyri.scale(14))
447                .font_id(self.fonts.cyri.conrod_id)
448                .color(TEXT_COLOR)
449                .set(state.ids.ui_scale_value, ui);
450        } else {
451            // Grey and unfunctional slider when Relative is selected
452            ImageSlider::continuous(0.0, 0.0, 1.0, self.imgs.nothing, self.imgs.slider)
453                .w_h(208.0, 22.0)
454                .right_from(state.ids.absolute_scale_text, 10.0)
455                .track_breadth(12.0)
456                .slider_length(10.0)
457                .track_color(Color::Rgba(1.0, 1.0, 1.0, 0.2))
458                .slider_color(Color::Rgba(1.0, 1.0, 1.0, 0.2))
459                .pad_track((5.0, 5.0))
460                .set(state.ids.ui_scale_slider, ui);
461        }
462
463        // Crosshair Options
464        // Crosshair Types
465        // Round
466        if Button::image(if let CrosshairType::Round = crosshair_type {
467            self.imgs.crosshair_bg_pressed
468        } else {
469            self.imgs.crosshair_bg
470        })
471        .w_h(15.0 * 4.0, 15.0 * 4.0)
472        .hover_image(if let CrosshairType::Round = crosshair_type {
473            self.imgs.crosshair_bg_pressed
474        } else {
475            self.imgs.crosshair_bg_hover
476        })
477        .press_image(if let CrosshairType::Round = crosshair_type {
478            self.imgs.crosshair_bg_pressed
479        } else {
480            self.imgs.crosshair_bg_press
481        })
482        .down_from(state.ids.ch_title, 20.0)
483        .set(state.ids.ch_1_bg, ui)
484        .was_clicked()
485        {
486            events.push(CrosshairType(CrosshairType::Round));
487        }
488
489        // Crosshair
490        Image::new(self.imgs.crosshair_outer_round)
491            .w_h(20.0 * 1.5, 20.0 * 1.5)
492            .middle_of(state.ids.ch_1_bg)
493            .color(Some(Color::Rgba(
494                1.0,
495                1.0,
496                1.0,
497                self.global_state.settings.interface.crosshair_opacity,
498            )))
499            .graphics_for(state.ids.ch_1_bg)
500            .set(state.ids.crosshair_outer_1, ui);
501        Image::new(self.imgs.crosshair_inner)
502            .w_h(21.0 * 2.0, 21.0 * 2.0)
503            .middle_of(state.ids.crosshair_outer_1)
504            .color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.6)))
505            .graphics_for(state.ids.ch_1_bg)
506            .set(state.ids.crosshair_inner_1, ui);
507
508        // Rounded Edges
509        if Button::image(if let CrosshairType::RoundEdges = crosshair_type {
510            self.imgs.crosshair_bg_pressed
511        } else {
512            self.imgs.crosshair_bg
513        })
514        .w_h(15.0 * 4.0, 15.0 * 4.0)
515        .hover_image(if let CrosshairType::RoundEdges = crosshair_type {
516            self.imgs.crosshair_bg_pressed
517        } else {
518            self.imgs.crosshair_bg_hover
519        })
520        .press_image(if let CrosshairType::RoundEdges = crosshair_type {
521            self.imgs.crosshair_bg_pressed
522        } else {
523            self.imgs.crosshair_bg_press
524        })
525        .right_from(state.ids.ch_1_bg, 20.0)
526        .set(state.ids.ch_2_bg, ui)
527        .was_clicked()
528        {
529            events.push(CrosshairType(CrosshairType::RoundEdges));
530        }
531
532        // Crosshair
533        Image::new(self.imgs.crosshair_outer_round_edges)
534            .w_h(21.0 * 1.5, 21.0 * 1.5)
535            .middle_of(state.ids.ch_2_bg)
536            .color(Some(Color::Rgba(
537                1.0,
538                1.0,
539                1.0,
540                self.global_state.settings.interface.crosshair_opacity,
541            )))
542            .graphics_for(state.ids.ch_2_bg)
543            .set(state.ids.crosshair_outer_2, ui);
544        Image::new(self.imgs.crosshair_inner)
545            .w_h(21.0 * 2.0, 21.0 * 2.0)
546            .middle_of(state.ids.crosshair_outer_2)
547            .color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.6)))
548            .graphics_for(state.ids.ch_2_bg)
549            .set(state.ids.crosshair_inner_2, ui);
550
551        // Edges
552        if Button::image(if let CrosshairType::Edges = crosshair_type {
553            self.imgs.crosshair_bg_pressed
554        } else {
555            self.imgs.crosshair_bg
556        })
557        .w_h(15.0 * 4.0, 15.0 * 4.0)
558        .hover_image(if let CrosshairType::Edges = crosshair_type {
559            self.imgs.crosshair_bg_pressed
560        } else {
561            self.imgs.crosshair_bg_hover
562        })
563        .press_image(if let CrosshairType::Edges = crosshair_type {
564            self.imgs.crosshair_bg_pressed
565        } else {
566            self.imgs.crosshair_bg_press
567        })
568        .right_from(state.ids.ch_2_bg, 20.0)
569        .set(state.ids.ch_3_bg, ui)
570        .was_clicked()
571        {
572            events.push(CrosshairType(CrosshairType::Edges));
573        }
574
575        // Crosshair
576        Image::new(self.imgs.crosshair_outer_edges)
577            .w_h(21.0 * 1.5, 21.0 * 1.5)
578            .middle_of(state.ids.ch_3_bg)
579            .color(Some(Color::Rgba(
580                1.0,
581                1.0,
582                1.0,
583                self.global_state.settings.interface.crosshair_opacity,
584            )))
585            .graphics_for(state.ids.ch_3_bg)
586            .set(state.ids.crosshair_outer_3, ui);
587        Image::new(self.imgs.crosshair_inner)
588            .w_h(21.0 * 2.0, 21.0 * 2.0)
589            .middle_of(state.ids.crosshair_outer_3)
590            .color(Some(Color::Rgba(1.0, 1.0, 1.0, 0.6)))
591            .graphics_for(state.ids.ch_3_bg)
592            .set(state.ids.crosshair_inner_3, ui);
593        // Crosshair Transparency Text and Slider
594        Text::new(&self.localized_strings.get_msg("hud-settings-crosshair"))
595            .down_from(state.ids.absolute_scale_button, 20.0)
596            .font_size(self.fonts.cyri.scale(18))
597            .font_id(self.fonts.cyri.conrod_id)
598            .color(TEXT_COLOR)
599            .set(state.ids.ch_title, ui);
600        Text::new(&self.localized_strings.get_msg("hud-settings-opacity"))
601            .right_from(state.ids.ch_3_bg, 20.0)
602            .font_size(self.fonts.cyri.scale(14))
603            .font_id(self.fonts.cyri.conrod_id)
604            .color(TEXT_COLOR)
605            .set(state.ids.ch_transp_text, ui);
606
607        if let Some(new_val) = ImageSlider::continuous(
608            crosshair_opacity,
609            0.0,
610            1.0,
611            self.imgs.slider_indicator,
612            self.imgs.slider,
613        )
614        .w_h(104.0, 22.0)
615        .down_from(state.ids.ch_transp_text, 8.0)
616        .track_breadth(12.0)
617        .slider_length(10.0)
618        .pad_track((5.0, 5.0))
619        .set(state.ids.ch_transp_slider, ui)
620        {
621            events.push(CrosshairTransp(new_val));
622        }
623
624        Text::new(&format!("{:.2}", crosshair_opacity,))
625            .right_from(state.ids.ch_transp_slider, 8.0)
626            .font_size(self.fonts.cyri.scale(14))
627            .graphics_for(state.ids.ch_transp_slider)
628            .font_id(self.fonts.cyri.conrod_id)
629            .color(TEXT_COLOR)
630            .set(state.ids.ch_transp_value, ui);
631
632        // Hotbar text
633        Text::new(&self.localized_strings.get_msg("hud-settings-hotbar"))
634            .down_from(state.ids.ch_1_bg, 20.0)
635            .font_size(self.fonts.cyri.scale(18))
636            .font_id(self.fonts.cyri.conrod_id)
637            .color(TEXT_COLOR)
638            .set(state.ids.hotbar_title, ui);
639        // Show Shortcut Numbers
640        if Button::image(
641            match self.global_state.settings.interface.shortcut_numbers {
642                ShortcutNumbers::On => self.imgs.checkbox_checked,
643                ShortcutNumbers::Off => self.imgs.checkbox,
644            },
645        )
646        .w_h(18.0, 18.0)
647        .hover_image(
648            match self.global_state.settings.interface.shortcut_numbers {
649                ShortcutNumbers::On => self.imgs.checkbox_checked_mo,
650                ShortcutNumbers::Off => self.imgs.checkbox_mo,
651            },
652        )
653        .press_image(
654            match self.global_state.settings.interface.shortcut_numbers {
655                ShortcutNumbers::On => self.imgs.checkbox_checked,
656                ShortcutNumbers::Off => self.imgs.checkbox_press,
657            },
658        )
659        .down_from(state.ids.hotbar_title, 8.0)
660        .set(state.ids.show_shortcuts_button, ui)
661        .was_clicked()
662        {
663            match self.global_state.settings.interface.shortcut_numbers {
664                ShortcutNumbers::On => events.push(ToggleShortcutNumbers(ShortcutNumbers::Off)),
665                ShortcutNumbers::Off => events.push(ToggleShortcutNumbers(ShortcutNumbers::On)),
666            }
667        }
668        Text::new(
669            &self
670                .localized_strings
671                .get_msg("hud-settings-toggle_shortcuts"),
672        )
673        .right_from(state.ids.show_shortcuts_button, 10.0)
674        .font_size(self.fonts.cyri.scale(14))
675        .font_id(self.fonts.cyri.conrod_id)
676        .color(TEXT_COLOR)
677        .set(state.ids.show_shortcuts_text, ui);
678        // Buff Position
679        // Buffs above skills
680        if Button::image(match self.global_state.settings.interface.buff_position {
681            BuffPosition::Bar => self.imgs.check_checked,
682            BuffPosition::Map => self.imgs.check,
683        })
684        .w_h(12.0, 12.0)
685        .hover_image(match self.global_state.settings.interface.buff_position {
686            BuffPosition::Bar => self.imgs.check_checked_mo,
687            BuffPosition::Map => self.imgs.check_mo,
688        })
689        .press_image(match self.global_state.settings.interface.buff_position {
690            BuffPosition::Bar => self.imgs.check_checked,
691            BuffPosition::Map => self.imgs.check_press,
692        })
693        .down_from(state.ids.show_shortcuts_button, 8.0)
694        .set(state.ids.buff_pos_bar_button, ui)
695        .was_clicked()
696        {
697            events.push(BuffPosition(BuffPosition::Bar))
698        }
699        Text::new(
700            &self
701                .localized_strings
702                .get_msg("hud-settings-buffs_skillbar"),
703        )
704        .right_from(state.ids.buff_pos_bar_button, 10.0)
705        .font_size(self.fonts.cyri.scale(14))
706        .font_id(self.fonts.cyri.conrod_id)
707        .graphics_for(state.ids.buff_pos_bar_button)
708        .color(TEXT_COLOR)
709        .set(state.ids.buff_pos_bar_text, ui);
710        // Buffs left from minimap
711        if Button::image(match self.global_state.settings.interface.buff_position {
712            BuffPosition::Map => self.imgs.check_checked,
713            BuffPosition::Bar => self.imgs.check,
714        })
715        .w_h(12.0, 12.0)
716        .hover_image(match self.global_state.settings.interface.buff_position {
717            BuffPosition::Map => self.imgs.check_checked_mo,
718            BuffPosition::Bar => self.imgs.check_mo,
719        })
720        .press_image(match self.global_state.settings.interface.buff_position {
721            BuffPosition::Map => self.imgs.check_checked,
722            BuffPosition::Bar => self.imgs.check_press,
723        })
724        .down_from(state.ids.buff_pos_bar_button, 8.0)
725        .set(state.ids.buff_pos_map_button, ui)
726        .was_clicked()
727        {
728            events.push(BuffPosition(BuffPosition::Map))
729        }
730        Text::new(&self.localized_strings.get_msg("hud-settings-buffs_mmap"))
731            .right_from(state.ids.buff_pos_map_button, 10.0)
732            .font_size(self.fonts.cyri.scale(14))
733            .font_id(self.fonts.cyri.conrod_id)
734            .graphics_for(state.ids.buff_pos_map_button)
735            .color(TEXT_COLOR)
736            .set(state.ids.buff_pos_map_text, ui);
737        // Slots text
738        Text::new(&self.localized_strings.get_msg("hud-settings-slots"))
739            .down_from(state.ids.buff_pos_map_button, 20.0)
740            .font_size(self.fonts.cyri.scale(18))
741            .font_id(self.fonts.cyri.conrod_id)
742            .color(TEXT_COLOR)
743            .set(state.ids.slots_title, ui);
744        // Prefix switch checkbox
745        let slots_use_prefixes = ToggleButton::new(
746            self.global_state.settings.interface.slots_use_prefixes,
747            self.imgs.checkbox,
748            self.imgs.checkbox_checked,
749        )
750        .w_h(18.0, 18.0)
751        .down_from(state.ids.slots_title, 20.0)
752        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
753        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
754        .set(state.ids.slots_use_prefixes_radio, ui);
755        if self.global_state.settings.interface.slots_use_prefixes != slots_use_prefixes {
756            events.push(SlotsUsePrefixes(
757                !self.global_state.settings.interface.slots_use_prefixes,
758            ));
759        }
760        Text::new(&self.localized_strings.get_msg("hud-settings-use_prefixes"))
761            .right_from(state.ids.slots_use_prefixes_radio, 10.0)
762            .font_size(self.fonts.cyri.scale(14))
763            .font_id(self.fonts.cyri.conrod_id)
764            .graphics_for(state.ids.slots_use_prefixes_radio)
765            .color(TEXT_COLOR)
766            .set(state.ids.slots_use_prefixes_text, ui);
767        if self.global_state.settings.interface.slots_use_prefixes {
768            let prefix_switch_point = self
769                .global_state
770                .settings
771                .interface
772                .slots_prefix_switch_point;
773
774            Text::new(
775                &self
776                    .localized_strings
777                    .get_msg("hud-settings-prefix_switch_point"),
778            )
779            .down_from(state.ids.slots_use_prefixes_radio, 8.0)
780            .right_from(state.ids.slots_use_prefixes_radio, 10.0)
781            .font_size(self.fonts.cyri.scale(14))
782            .font_id(self.fonts.cyri.conrod_id)
783            .color(TEXT_COLOR)
784            .set(state.ids.slots_prefix_switch_point_text, ui);
785            if let Some(new_val) = ImageSlider::discrete(
786                prefix_switch_point,
787                4,
788                7,
789                self.imgs.slider_indicator,
790                self.imgs.slider,
791            )
792            .w_h(208.0, 22.0)
793            .down_from(state.ids.slots_prefix_switch_point_text, 8.0)
794            .track_breadth(30.0)
795            .slider_length(10.0)
796            .pad_track((5.0, 5.0))
797            .set(state.ids.slots_prefix_switch_point_slider, ui)
798            {
799                events.push(SlotsPrefixSwitchPoint(new_val));
800            }
801            Text::new(&format!("{prefix_switch_point}"))
802                .right_from(state.ids.slots_prefix_switch_point_slider, 10.0)
803                .font_size(self.fonts.cyri.scale(14))
804                .graphics_for(state.ids.slots_prefix_switch_point_slider)
805                .font_id(self.fonts.cyri.conrod_id)
806                .color(TEXT_COLOR)
807                .set(state.ids.slots_prefix_switch_point_value, ui);
808        }
809
810        // Content Right Side
811
812        /*Scrolling Combat text
813
814        O Show Damage Numbers
815            Damage Accumulation Duration:
816            [0s ----I----2s]
817            O Show incoming Damage
818                Incoming Damage Accumulation Duration:
819                [0s ----I----2s]
820            O Round Damage Numbers
821            */
822        // SCT/ Scrolling Combat Text
823        Text::new(
824            &self
825                .localized_strings
826                .get_msg("hud-settings-scrolling_combat_text"),
827        )
828        .top_left_with_margins_on(state.ids.window_r, 5.0, 5.0)
829        .font_size(self.fonts.cyri.scale(18))
830        .font_id(self.fonts.cyri.conrod_id)
831        .color(TEXT_COLOR)
832        .set(state.ids.sct_title, ui);
833        // Generally toggle the SCT
834        let show_sct = ToggleButton::new(
835            self.global_state.settings.interface.sct,
836            self.imgs.checkbox,
837            self.imgs.checkbox_checked,
838        )
839        .w_h(18.0, 18.0)
840        .down_from(state.ids.sct_title, 20.0)
841        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
842        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
843        .set(state.ids.sct_show_radio, ui);
844
845        if self.global_state.settings.interface.sct != show_sct {
846            events.push(Sct(!self.global_state.settings.interface.sct))
847        }
848        Text::new(
849            &self
850                .localized_strings
851                .get_msg("hud-settings-scrolling_combat_text"),
852        )
853        .right_from(state.ids.sct_show_radio, 10.0)
854        .font_size(self.fonts.cyri.scale(14))
855        .font_id(self.fonts.cyri.conrod_id)
856        .graphics_for(state.ids.sct_show_radio)
857        .color(TEXT_COLOR)
858        .set(state.ids.sct_show_text, ui);
859        if self.global_state.settings.interface.sct {
860            let sct_dmg_accum_duration =
861                self.global_state.settings.interface.sct_dmg_accum_duration;
862            let sct_inc_dmg_accum_duration = self
863                .global_state
864                .settings
865                .interface
866                .sct_inc_dmg_accum_duration;
867
868            Text::new(
869                &self
870                    .localized_strings
871                    .get_msg("hud-settings-damage_accumulation_duration"),
872            )
873            .down_from(state.ids.sct_show_radio, 8.0)
874            .right_from(state.ids.sct_show_radio, 10.0)
875            .font_size(self.fonts.cyri.scale(14))
876            .font_id(self.fonts.cyri.conrod_id)
877            .color(TEXT_COLOR)
878            .set(state.ids.sct_dmg_accum_duration_text, ui);
879
880            if let Some(new_val) = ImageSlider::continuous(
881                sct_dmg_accum_duration,
882                0.0,
883                2.0,
884                self.imgs.slider_indicator,
885                self.imgs.slider,
886            )
887            .w_h(104.0, 22.0)
888            .down_from(state.ids.sct_dmg_accum_duration_text, 8.0)
889            .track_breadth(12.0)
890            .slider_length(10.0)
891            .pad_track((5.0, 5.0))
892            .set(state.ids.sct_dmg_accum_duration_slider, ui)
893            {
894                events.push(SctDamageAccumDuration(new_val));
895            }
896
897            Text::new(&format!("{:.2}", sct_dmg_accum_duration,))
898                .right_from(state.ids.sct_dmg_accum_duration_slider, 8.0)
899                .font_size(self.fonts.cyri.scale(14))
900                .graphics_for(state.ids.sct_dmg_accum_duration_slider)
901                .font_id(self.fonts.cyri.conrod_id)
902                .color(TEXT_COLOR)
903                .set(state.ids.sct_dmg_accum_duration_value, ui);
904
905            // Conditionally toggle incoming damage
906            let show_inc_dmg = ToggleButton::new(
907                self.global_state.settings.interface.sct_inc_dmg,
908                self.imgs.checkbox,
909                self.imgs.checkbox_checked,
910            )
911            .w_h(18.0, 18.0)
912            .down_from(state.ids.sct_dmg_accum_duration_slider, 8.0)
913            .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
914            .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
915            .set(state.ids.sct_show_inc_dmg_radio, ui);
916
917            if self.global_state.settings.interface.sct_inc_dmg != show_inc_dmg {
918                events.push(SctIncomingDamage(
919                    !self.global_state.settings.interface.sct_inc_dmg,
920                ))
921            }
922            Text::new(
923                &self
924                    .localized_strings
925                    .get_msg("hud-settings-incoming_damage"),
926            )
927            .right_from(state.ids.sct_show_inc_dmg_radio, 10.0)
928            .font_size(self.fonts.cyri.scale(14))
929            .font_id(self.fonts.cyri.conrod_id)
930            .graphics_for(state.ids.sct_show_inc_dmg_radio)
931            .color(TEXT_COLOR)
932            .set(state.ids.sct_show_inc_dmg_text, ui);
933            if self.global_state.settings.interface.sct_inc_dmg {
934                Text::new(
935                    &self
936                        .localized_strings
937                        .get_msg("hud-settings-incoming_damage_accumulation_duration"),
938                )
939                .down_from(state.ids.sct_show_inc_dmg_radio, 8.0)
940                .right_from(state.ids.sct_show_inc_dmg_radio, 10.0)
941                .font_size(self.fonts.cyri.scale(14))
942                .font_id(self.fonts.cyri.conrod_id)
943                .color(TEXT_COLOR)
944                .set(state.ids.sct_inc_dmg_accum_duration_text, ui);
945
946                if let Some(new_val) = ImageSlider::continuous(
947                    sct_inc_dmg_accum_duration,
948                    0.0,
949                    2.0,
950                    self.imgs.slider_indicator,
951                    self.imgs.slider,
952                )
953                .w_h(104.0, 22.0)
954                .down_from(state.ids.sct_inc_dmg_accum_duration_text, 8.0)
955                .track_breadth(12.0)
956                .slider_length(10.0)
957                .pad_track((5.0, 5.0))
958                .set(state.ids.sct_inc_dmg_accum_duration_slider, ui)
959                {
960                    events.push(SctIncomingDamageAccumDuration(new_val));
961                }
962
963                Text::new(&format!("{:.2}", sct_inc_dmg_accum_duration,))
964                    .right_from(state.ids.sct_inc_dmg_accum_duration_slider, 8.0)
965                    .font_size(self.fonts.cyri.scale(14))
966                    .graphics_for(state.ids.sct_inc_dmg_accum_duration_slider)
967                    .font_id(self.fonts.cyri.conrod_id)
968                    .color(TEXT_COLOR)
969                    .set(state.ids.sct_inc_dmg_accum_duration_value, ui);
970            }
971
972            // Round Damage
973            let show_sct_damage_rounding = ToggleButton::new(
974                self.global_state.settings.interface.sct_damage_rounding,
975                self.imgs.checkbox,
976                self.imgs.checkbox_checked,
977            )
978            .w_h(18.0, 18.0)
979            .down_from(
980                if self.global_state.settings.interface.sct_inc_dmg {
981                    state.ids.sct_inc_dmg_accum_duration_slider
982                } else {
983                    state.ids.sct_show_inc_dmg_radio
984                },
985                8.0,
986            )
987            .x_align_to(state.ids.sct_show_inc_dmg_radio, Align::Start)
988            .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
989            .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
990            .set(state.ids.sct_round_dmg_radio, ui);
991
992            if self.global_state.settings.interface.sct_damage_rounding != show_sct_damage_rounding
993            {
994                events.push(SctRoundDamage(
995                    !self.global_state.settings.interface.sct_damage_rounding,
996                ))
997            }
998            Text::new(&self.localized_strings.get_msg("hud-settings-round_damage"))
999                .right_from(state.ids.sct_round_dmg_radio, 10.0)
1000                .font_size(self.fonts.cyri.scale(14))
1001                .font_id(self.fonts.cyri.conrod_id)
1002                .graphics_for(state.ids.sct_round_dmg_radio)
1003                .color(TEXT_COLOR)
1004                .set(state.ids.sct_round_dmg_text, ui);
1005        }
1006
1007        // Speech bubbles
1008        Text::new(&self.localized_strings.get_msg("hud-settings-speech_bubble"))
1009            .down_from(
1010                if self.global_state.settings.interface.sct {
1011                    state.ids.sct_round_dmg_radio
1012                } else {
1013                    state.ids.sct_show_radio
1014                },
1015                20.0,
1016            )
1017            .x_align(Align::Start)
1018            .x_relative_to(state.ids.sct_show_text, -40.0)
1019            .font_size(self.fonts.cyri.scale(18))
1020            .font_id(self.fonts.cyri.conrod_id)
1021            .color(TEXT_COLOR)
1022            .set(state.ids.speech_bubble_text, ui);
1023
1024        // Show own speech bubbles
1025        let speech_bubble_self = ToggleButton::new(
1026            self.global_state.settings.interface.speech_bubble_self,
1027            self.imgs.checkbox,
1028            self.imgs.checkbox_checked,
1029        )
1030        .down_from(state.ids.speech_bubble_text, 10.0)
1031        .w_h(18.0, 18.0)
1032        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
1033        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
1034        .set(state.ids.speech_bubble_self_button, ui);
1035        if self.global_state.settings.interface.speech_bubble_self != speech_bubble_self {
1036            events.push(SpeechBubbleSelf(speech_bubble_self));
1037        }
1038        Text::new(
1039            &self
1040                .localized_strings
1041                .get_msg("hud-settings-speech_bubble_self"),
1042        )
1043        .right_from(state.ids.speech_bubble_self_button, 10.0)
1044        .font_size(self.fonts.cyri.scale(15))
1045        .font_id(self.fonts.cyri.conrod_id)
1046        .color(TEXT_COLOR)
1047        .set(state.ids.speech_bubble_self_text, ui);
1048
1049        // Speech bubble dark mode
1050        let speech_bubble_dark_mode = ToggleButton::new(
1051            self.global_state.settings.interface.speech_bubble_dark_mode,
1052            self.imgs.checkbox,
1053            self.imgs.checkbox_checked,
1054        )
1055        .down_from(state.ids.speech_bubble_self_button, 10.0)
1056        .w_h(18.0, 18.0)
1057        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
1058        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
1059        .set(state.ids.speech_bubble_dark_mode_button, ui);
1060        if self.global_state.settings.interface.speech_bubble_dark_mode != speech_bubble_dark_mode {
1061            events.push(SpeechBubbleDarkMode(speech_bubble_dark_mode));
1062        }
1063        Text::new(
1064            &self
1065                .localized_strings
1066                .get_msg("hud-settings-speech_bubble_dark_mode"),
1067        )
1068        .right_from(state.ids.speech_bubble_dark_mode_button, 10.0)
1069        .font_size(self.fonts.cyri.scale(15))
1070        .font_id(self.fonts.cyri.conrod_id)
1071        .color(TEXT_COLOR)
1072        .set(state.ids.speech_bubble_dark_mode_text, ui);
1073        // Speech bubble icon
1074        let speech_bubble_icon = ToggleButton::new(
1075            self.global_state.settings.interface.speech_bubble_icon,
1076            self.imgs.checkbox,
1077            self.imgs.checkbox_checked,
1078        )
1079        .down_from(state.ids.speech_bubble_dark_mode_button, 10.0)
1080        .w_h(18.0, 18.0)
1081        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
1082        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
1083        .set(state.ids.speech_bubble_icon_button, ui);
1084        if self.global_state.settings.interface.speech_bubble_icon != speech_bubble_icon {
1085            events.push(SpeechBubbleIcon(speech_bubble_icon));
1086        }
1087        Text::new(
1088            &self
1089                .localized_strings
1090                .get_msg("hud-settings-speech_bubble_icon"),
1091        )
1092        .right_from(state.ids.speech_bubble_icon_button, 10.0)
1093        .font_size(self.fonts.cyri.scale(15))
1094        .font_id(self.fonts.cyri.conrod_id)
1095        .color(TEXT_COLOR)
1096        .set(state.ids.speech_bubble_icon_text, ui);
1097
1098        // Energybars Numbers
1099        // Hotbar text
1100        Text::new(
1101            &self
1102                .localized_strings
1103                .get_msg("hud-settings-energybar_numbers"),
1104        )
1105        .down_from(state.ids.speech_bubble_icon_button, 20.0)
1106        .font_size(self.fonts.cyri.scale(18))
1107        .font_id(self.fonts.cyri.conrod_id)
1108        .color(TEXT_COLOR)
1109        .set(state.ids.bar_numbers_title, ui);
1110
1111        // None
1112        if Button::image(if let BarNumbers::Off = bar_values {
1113            self.imgs.check_checked
1114        } else {
1115            self.imgs.check
1116        })
1117        .w_h(12.0, 12.0)
1118        .hover_image(if let BarNumbers::Off = bar_values {
1119            self.imgs.check_checked_mo
1120        } else {
1121            self.imgs.check_mo
1122        })
1123        .press_image(if let BarNumbers::Off = bar_values {
1124            self.imgs.check_checked
1125        } else {
1126            self.imgs.check_press
1127        })
1128        .down_from(state.ids.bar_numbers_title, 8.0)
1129        .set(state.ids.show_bar_numbers_none_button, ui)
1130        .was_clicked()
1131        {
1132            events.push(ToggleBarNumbers(BarNumbers::Off))
1133        }
1134        Text::new(&self.localized_strings.get_msg("hud-settings-none"))
1135            .right_from(state.ids.show_bar_numbers_none_button, 10.0)
1136            .font_size(self.fonts.cyri.scale(14))
1137            .font_id(self.fonts.cyri.conrod_id)
1138            .graphics_for(state.ids.show_bar_numbers_none_button)
1139            .color(TEXT_COLOR)
1140            .set(state.ids.show_bar_numbers_none_text, ui);
1141
1142        // Values
1143        if Button::image(if let BarNumbers::Values = bar_values {
1144            self.imgs.check_checked
1145        } else {
1146            self.imgs.check
1147        })
1148        .w_h(12.0, 12.0)
1149        .hover_image(if let BarNumbers::Values = bar_values {
1150            self.imgs.check_checked_mo
1151        } else {
1152            self.imgs.check_mo
1153        })
1154        .press_image(if let BarNumbers::Values = bar_values {
1155            self.imgs.check_checked
1156        } else {
1157            self.imgs.check_press
1158        })
1159        .down_from(state.ids.show_bar_numbers_none_button, 8.0)
1160        .set(state.ids.show_bar_numbers_values_button, ui)
1161        .was_clicked()
1162        {
1163            events.push(ToggleBarNumbers(BarNumbers::Values))
1164        }
1165        Text::new(&self.localized_strings.get_msg("hud-settings-values"))
1166            .right_from(state.ids.show_bar_numbers_values_button, 10.0)
1167            .font_size(self.fonts.cyri.scale(14))
1168            .font_id(self.fonts.cyri.conrod_id)
1169            .graphics_for(state.ids.show_bar_numbers_values_button)
1170            .color(TEXT_COLOR)
1171            .set(state.ids.show_bar_numbers_values_text, ui);
1172
1173        // Percentages
1174        if Button::image(if let BarNumbers::Percent = bar_values {
1175            self.imgs.check_checked
1176        } else {
1177            self.imgs.check
1178        })
1179        .w_h(12.0, 12.0)
1180        .hover_image(if let BarNumbers::Percent = bar_values {
1181            self.imgs.check_checked_mo
1182        } else {
1183            self.imgs.check_mo
1184        })
1185        .press_image(if let BarNumbers::Percent = bar_values {
1186            self.imgs.check_checked
1187        } else {
1188            self.imgs.check_press
1189        })
1190        .down_from(state.ids.show_bar_numbers_values_button, 8.0)
1191        .set(state.ids.show_bar_numbers_percentage_button, ui)
1192        .was_clicked()
1193        {
1194            events.push(ToggleBarNumbers(BarNumbers::Percent))
1195        }
1196        Text::new(&self.localized_strings.get_msg("hud-settings-percentages"))
1197            .right_from(state.ids.show_bar_numbers_percentage_button, 10.0)
1198            .font_size(self.fonts.cyri.scale(14))
1199            .font_id(self.fonts.cyri.conrod_id)
1200            .graphics_for(state.ids.show_bar_numbers_percentage_button)
1201            .color(TEXT_COLOR)
1202            .set(state.ids.show_bar_numbers_percentage_text, ui);
1203
1204        // Always show energy bars
1205        let always_show_bars = ToggleButton::new(
1206            self.global_state.settings.interface.always_show_bars,
1207            self.imgs.checkbox,
1208            self.imgs.checkbox_checked,
1209        )
1210        .w_h(18.0, 18.0)
1211        .down_from(state.ids.show_bar_numbers_percentage_button, 20.0)
1212        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
1213        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
1214        .set(state.ids.always_show_bars_button, ui);
1215
1216        if always_show_bars != self.global_state.settings.interface.always_show_bars {
1217            events.push(ToggleAlwaysShowBars(always_show_bars));
1218        }
1219
1220        Text::new(
1221            &self
1222                .localized_strings
1223                .get_msg("hud-settings-always_show_bars"),
1224        )
1225        .right_from(state.ids.always_show_bars_button, 10.0)
1226        .font_size(self.fonts.cyri.scale(14))
1227        .font_id(self.fonts.cyri.conrod_id)
1228        .graphics_for(state.ids.always_show_bars_button)
1229        .color(TEXT_COLOR)
1230        .set(state.ids.always_show_bars_label, ui);
1231
1232        // Enable poise bar
1233        let enable_poise_bar = ToggleButton::new(
1234            self.global_state.settings.interface.enable_poise_bar,
1235            self.imgs.checkbox,
1236            self.imgs.checkbox_checked,
1237        )
1238        .w_h(18.0, 18.0)
1239        .down_from(state.ids.always_show_bars_button, 20.0)
1240        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
1241        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
1242        .set(state.ids.enable_poise_bar_button, ui);
1243
1244        if enable_poise_bar != self.global_state.settings.interface.enable_poise_bar {
1245            events.push(TogglePoiseBar(enable_poise_bar));
1246        }
1247
1248        Text::new(
1249            &self
1250                .localized_strings
1251                .get_msg("hud-settings-enable_poise_bar"),
1252        )
1253        .right_from(state.ids.enable_poise_bar_button, 10.0)
1254        .font_size(self.fonts.cyri.scale(14))
1255        .font_id(self.fonts.cyri.conrod_id)
1256        .graphics_for(state.ids.enable_poise_bar_button)
1257        .color(TEXT_COLOR)
1258        .set(state.ids.enable_poise_bar_label, ui);
1259
1260        // Toggle health SI prefixes
1261        let use_health_prefixes = ToggleButton::new(
1262            self.global_state.settings.interface.use_health_prefixes,
1263            self.imgs.checkbox,
1264            self.imgs.checkbox_checked,
1265        )
1266        .w_h(18.0, 18.0)
1267        .down_from(state.ids.enable_poise_bar_button, 20.0)
1268        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
1269        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
1270        .set(state.ids.use_health_prefixes_button, ui);
1271
1272        if use_health_prefixes != self.global_state.settings.interface.use_health_prefixes {
1273            events.push(ToggleHealthPrefixes(use_health_prefixes));
1274        }
1275
1276        Text::new(
1277            &self
1278                .localized_strings
1279                .get_msg("hud-settings-use_health_prefixes"),
1280        )
1281        .right_from(state.ids.use_health_prefixes_button, 10.0)
1282        .font_size(self.fonts.cyri.scale(14))
1283        .font_id(self.fonts.cyri.conrod_id)
1284        .graphics_for(state.ids.use_health_prefixes_button)
1285        .color(TEXT_COLOR)
1286        .set(state.ids.use_health_prefixes_text, ui);
1287
1288        // Experience Numbers
1289        Text::new(
1290            &self
1291                .localized_strings
1292                .get_msg("hud-settings-experience_numbers"),
1293        )
1294        .down_from(state.ids.use_health_prefixes_button, 20.0)
1295        .font_size(self.fonts.cyri.scale(18))
1296        .font_id(self.fonts.cyri.conrod_id)
1297        .color(TEXT_COLOR)
1298        .set(state.ids.experience_numbers_title, ui);
1299
1300        // Accumulate Experience Gained
1301        let accum_experience = ToggleButton::new(
1302            self.global_state.settings.interface.accum_experience,
1303            self.imgs.checkbox,
1304            self.imgs.checkbox_checked,
1305        )
1306        .w_h(18.0, 18.0)
1307        .down_from(state.ids.experience_numbers_title, 8.0)
1308        .hover_images(self.imgs.checkbox_mo, self.imgs.checkbox_checked_mo)
1309        .press_images(self.imgs.checkbox_press, self.imgs.checkbox_checked)
1310        .set(state.ids.accum_experience_button, ui);
1311
1312        if self.global_state.settings.interface.accum_experience != accum_experience {
1313            events.push(AccumExperience(
1314                !self.global_state.settings.interface.accum_experience,
1315            ));
1316        }
1317
1318        Text::new(
1319            &self
1320                .localized_strings
1321                .get_msg("hud-settings-accumulate_experience"),
1322        )
1323        .right_from(state.ids.accum_experience_button, 10.0)
1324        .font_size(self.fonts.cyri.scale(14))
1325        .font_id(self.fonts.cyri.conrod_id)
1326        .graphics_for(state.ids.accum_experience_button)
1327        .color(TEXT_COLOR)
1328        .set(state.ids.accum_experience_text, ui);
1329
1330        // Reset the interface settings to the default settings
1331        if Button::image(self.imgs.button)
1332            .w_h(RESET_BUTTONS_WIDTH, RESET_BUTTONS_HEIGHT)
1333            .hover_image(self.imgs.button_hover)
1334            .press_image(self.imgs.button_press)
1335            .down_from(
1336                if self.global_state.settings.interface.slots_use_prefixes {
1337                    state.ids.slots_prefix_switch_point_slider
1338                } else {
1339                    state.ids.slots_use_prefixes_radio
1340                },
1341                12.0,
1342            )
1343            .x_align_to(state.ids.slots_use_prefixes_radio, Align::Start)
1344            .label(
1345                &self
1346                    .localized_strings
1347                    .get_msg("hud-settings-reset_interface"),
1348            )
1349            .label_font_size(self.fonts.cyri.scale(14))
1350            .label_color(TEXT_COLOR)
1351            .label_font_id(self.fonts.cyri.conrod_id)
1352            .label_y(Relative::Scalar(2.0))
1353            .set(state.ids.reset_interface_button, ui)
1354            .was_clicked()
1355        {
1356            events.push(ResetInterfaceSettings);
1357        }
1358
1359        events
1360    }
1361}