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