veloren_voxygen/hud/settings_window/
mod.rs

1mod accessibility;
2mod chat;
3mod controls;
4mod gameplay;
5mod interface;
6mod language;
7mod networking;
8mod sound;
9mod video;
10
11use crate::{
12    GlobalState,
13    hud::{Show, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN, img_ids::Imgs},
14    session::settings_change::SettingsChange,
15    ui::fonts::Fonts,
16};
17use conrod_core::{
18    Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, color,
19    widget::{self, Button, Image, Rectangle, Text},
20    widget_ids,
21};
22use i18n::Localization;
23
24use strum::{EnumIter, IntoEnumIterator};
25
26widget_ids! {
27    struct Ids {
28        frame,
29        settings_bg,
30        tabs_align,
31        icon,
32        settings_close,
33        settings_title,
34        settings_content_align,
35
36        tabs[],
37        interface,
38        gameplay,
39        controls,
40        video,
41        sound,
42        language,
43        chat,
44        networking,
45        accessibility,
46    }
47}
48
49const RESET_BUTTONS_HEIGHT: f64 = 34.0;
50const RESET_BUTTONS_WIDTH: f64 = 155.0;
51
52#[derive(Debug, EnumIter, PartialEq, Eq)]
53pub enum SettingsTab {
54    Interface,
55    Chat,
56    Video,
57    Sound,
58    Gameplay,
59    Controls,
60    Lang,
61    Networking,
62    Accessibility,
63}
64impl SettingsTab {
65    fn name_key(&self) -> &str {
66        match self {
67            SettingsTab::Interface => "common-interface",
68            SettingsTab::Chat => "common-chat",
69            SettingsTab::Gameplay => "common-gameplay",
70            SettingsTab::Controls => "common-controls",
71            SettingsTab::Video => "common-video",
72            SettingsTab::Sound => "common-sound",
73            SettingsTab::Lang => "common-languages",
74            SettingsTab::Networking => "common-networking",
75            SettingsTab::Accessibility => "common-accessibility",
76        }
77    }
78
79    fn title_key(&self) -> &str {
80        match self {
81            SettingsTab::Interface => "common-interface_settings",
82            SettingsTab::Chat => "common-chat_settings",
83            SettingsTab::Gameplay => "common-gameplay_settings",
84            SettingsTab::Controls => "common-controls_settings",
85            SettingsTab::Video => "common-video_settings",
86            SettingsTab::Sound => "common-sound_settings",
87            SettingsTab::Lang => "common-language_settings",
88            SettingsTab::Networking => "common-networking_settings",
89            SettingsTab::Accessibility => "common-accessibility_settings",
90        }
91    }
92}
93
94#[derive(WidgetCommon)]
95pub struct SettingsWindow<'a> {
96    global_state: &'a GlobalState,
97    show: &'a Show,
98    imgs: &'a Imgs,
99    fonts: &'a Fonts,
100    localized_strings: &'a Localization,
101    server_view_distance_limit: Option<u32>,
102    fps: f32,
103    #[conrod(common_builder)]
104    common: widget::CommonBuilder,
105}
106
107impl<'a> SettingsWindow<'a> {
108    pub fn new(
109        global_state: &'a GlobalState,
110        show: &'a Show,
111        imgs: &'a Imgs,
112        fonts: &'a Fonts,
113        localized_strings: &'a Localization,
114        server_view_distance_limit: Option<u32>,
115        fps: f32,
116    ) -> Self {
117        Self {
118            global_state,
119            show,
120            imgs,
121            fonts,
122            localized_strings,
123            server_view_distance_limit,
124            fps,
125            common: widget::CommonBuilder::default(),
126        }
127    }
128}
129
130pub struct State {
131    ids: Ids,
132}
133
134pub enum Event {
135    ChangeTab(SettingsTab),
136    Close,
137    SettingsChange(SettingsChange),
138    ChangeChatSettingsTab(Option<usize>),
139}
140
141#[derive(Clone)]
142pub enum ScaleChange {
143    ToAbsolute,
144    ToRelative,
145    Adjust(f64),
146}
147
148impl Widget for SettingsWindow<'_> {
149    type Event = Vec<Event>;
150    type State = State;
151    type Style = ();
152
153    fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
154        State {
155            ids: Ids::new(id_gen),
156        }
157    }
158
159    fn style(&self) -> Self::Style {}
160
161    fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
162        common_base::prof_span!("SettingsWindow::update");
163        let widget::UpdateArgs { state, ui, .. } = args;
164
165        let mut events = Vec::new();
166        let tab_font_scale = 18;
167
168        // Frame
169        Image::new(self.imgs.settings_bg)
170            .w_h(1052.0, 886.0)
171            .mid_top_with_margin_on(ui.window, 5.0)
172            .color(Some(UI_MAIN))
173            .set(state.ids.settings_bg, ui);
174
175        Image::new(self.imgs.settings_frame)
176            .w_h(1052.0, 886.0)
177            .middle_of(state.ids.settings_bg)
178            .color(Some(UI_HIGHLIGHT_0))
179            .set(state.ids.frame, ui);
180
181        // Content Alignment
182        Rectangle::fill_with([814.0, 834.0], color::TRANSPARENT)
183            .top_right_with_margins_on(state.ids.frame, 46.0, 2.0)
184            .set(state.ids.settings_content_align, ui);
185
186        // Tabs Content Alignment
187        Rectangle::fill_with([232.0, 814.0], color::TRANSPARENT)
188            .top_left_with_margins_on(state.ids.frame, 44.0, 2.0)
189            .scroll_kids()
190            .scroll_kids_vertically()
191            .set(state.ids.tabs_align, ui);
192
193        // Icon
194        Image::new(self.imgs.settings)
195            .w_h(29.0 * 1.5, 25.0 * 1.5)
196            .top_left_with_margins_on(state.ids.frame, 2.0, 1.0)
197            .set(state.ids.icon, ui);
198        // Title
199        Text::new(
200            &self
201                .localized_strings
202                .get_msg(self.show.settings_tab.title_key()),
203        )
204        .mid_top_with_margin_on(state.ids.frame, 3.0)
205        .font_id(self.fonts.cyri.conrod_id)
206        .font_size(self.fonts.cyri.scale(29))
207        .color(TEXT_COLOR)
208        .set(state.ids.settings_title, ui);
209
210        // X-Button
211        if Button::image(self.imgs.close_button)
212            .w_h(24.0, 25.0)
213            .hover_image(self.imgs.close_btn_hover)
214            .press_image(self.imgs.close_btn_press)
215            .top_right_with_margins_on(state.ids.frame, 0.0, 0.0)
216            .set(state.ids.settings_close, ui)
217            .was_clicked()
218        {
219            events.push(Event::Close);
220        }
221
222        // Tabs
223        if state.ids.tabs.len() < SettingsTab::iter().len() {
224            state.update(|s| {
225                s.ids
226                    .tabs
227                    .resize(SettingsTab::iter().len(), &mut ui.widget_id_generator())
228            });
229        }
230        for (i, settings_tab) in SettingsTab::iter().enumerate() {
231            let tab_name = self.localized_strings.get_msg(settings_tab.name_key());
232            let mut button = Button::image(if self.show.settings_tab == settings_tab {
233                self.imgs.selection
234            } else {
235                self.imgs.nothing
236            })
237            .w_h(230.0, 48.0)
238            .hover_image(self.imgs.selection_hover)
239            .press_image(self.imgs.selection_press)
240            .image_color(color::rgba(1.0, 0.82, 0.27, 1.0))
241            .label(&tab_name)
242            .label_font_size(self.fonts.cyri.scale(tab_font_scale))
243            .label_font_id(self.fonts.cyri.conrod_id)
244            .label_color(TEXT_COLOR);
245
246            button = if i == 0 {
247                button.mid_top_with_margin_on(state.ids.tabs_align, 28.0)
248            } else {
249                button.down_from(state.ids.tabs[i - 1], 0.0)
250            };
251
252            if button.set(state.ids.tabs[i], ui).was_clicked() {
253                events.push(Event::ChangeTab(settings_tab));
254            }
255        }
256
257        // Content Area
258        let global_state = self.global_state;
259        let imgs = self.imgs;
260        let fonts = self.fonts;
261        let localized_strings = self.localized_strings;
262        match self.show.settings_tab {
263            SettingsTab::Interface => {
264                for change in
265                    interface::Interface::new(global_state, imgs, fonts, localized_strings)
266                        .top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
267                        .wh_of(state.ids.settings_content_align)
268                        .set(state.ids.interface, ui)
269                {
270                    events.push(Event::SettingsChange(change.into()));
271                }
272            },
273            SettingsTab::Chat => {
274                for event in
275                    chat::Chat::new(global_state, self.show, imgs, fonts, localized_strings)
276                        .top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
277                        .wh_of(state.ids.settings_content_align)
278                        .set(state.ids.chat, ui)
279                {
280                    match event {
281                        chat::Event::ChatChange(change) => {
282                            events.push(Event::SettingsChange(change.into()));
283                        },
284                        chat::Event::ChangeChatSettingsTab(index) => {
285                            events.push(Event::ChangeChatSettingsTab(index));
286                        },
287                    }
288                }
289            },
290            SettingsTab::Gameplay => {
291                for change in gameplay::Gameplay::new(global_state, imgs, fonts, localized_strings)
292                    .top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
293                    .wh_of(state.ids.settings_content_align)
294                    .set(state.ids.gameplay, ui)
295                {
296                    events.push(Event::SettingsChange(change.into()));
297                }
298            },
299            SettingsTab::Controls => {
300                for change in controls::Controls::new(global_state, imgs, fonts, localized_strings)
301                    .top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
302                    .wh_of(state.ids.settings_content_align)
303                    .set(state.ids.controls, ui)
304                {
305                    events.push(Event::SettingsChange(change.into()));
306                }
307            },
308            SettingsTab::Video => {
309                for change in video::Video::new(
310                    global_state,
311                    imgs,
312                    fonts,
313                    localized_strings,
314                    self.server_view_distance_limit,
315                    self.fps,
316                )
317                .top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
318                .wh_of(state.ids.settings_content_align)
319                .set(state.ids.video, ui)
320                {
321                    events.push(Event::SettingsChange(change.into()));
322                }
323            },
324            SettingsTab::Sound => {
325                for change in sound::Sound::new(global_state, imgs, fonts, localized_strings)
326                    .top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
327                    .wh_of(state.ids.settings_content_align)
328                    .set(state.ids.sound, ui)
329                {
330                    events.push(Event::SettingsChange(change.into()));
331                }
332            },
333            SettingsTab::Lang => {
334                for change in language::Language::new(global_state, imgs, fonts, localized_strings)
335                    .top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
336                    .wh_of(state.ids.settings_content_align)
337                    .set(state.ids.language, ui)
338                {
339                    events.push(Event::SettingsChange(change.into()));
340                }
341            },
342            SettingsTab::Networking => {
343                for change in networking::Networking::new(
344                    global_state,
345                    imgs,
346                    fonts,
347                    localized_strings,
348                    self.server_view_distance_limit,
349                )
350                .top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
351                .wh_of(state.ids.settings_content_align)
352                .set(state.ids.networking, ui)
353                {
354                    events.push(Event::SettingsChange(change.into()));
355                }
356            },
357            SettingsTab::Accessibility => {
358                for change in
359                    accessibility::Accessibility::new(global_state, imgs, fonts, localized_strings)
360                        .top_left_with_margins_on(state.ids.settings_content_align, 0.0, 0.0)
361                        .wh_of(state.ids.settings_content_align)
362                        .set(state.ids.accessibility, ui)
363                {
364                    events.push(Event::SettingsChange(change.into()));
365                }
366            },
367        }
368
369        events
370    }
371}