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