1use super::{RESET_BUTTONS_HEIGHT, RESET_BUTTONS_WIDTH};
2
3use crate::{
4 GlobalState,
5 audio::SfxChannelSettings,
6 hud::{MENU_BG, TEXT_COLOR, TEXT_COLOR_GREY, img_ids::Imgs},
7 session::settings_change::Audio::{self as AudioChange, *},
8 ui::{ImageSlider, ToggleButton, fonts::Fonts},
9};
10use conrod_core::{
11 Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, color,
12 position::{Align, Relative},
13 widget::{self, Button, DropDownList, Rectangle, Scrollbar, Text},
14 widget_ids,
15};
16use i18n::Localization;
17
18widget_ids! {
19 struct Ids {
20 window,
21 window_r,
22 window_scrollbar,
23 master_volume_text,
24 master_volume_slider,
25 master_volume_number,
26 master_volume_muted,
27 inactive_master_volume_text,
28 inactive_master_volume_slider,
29 inactive_master_volume_number,
30 inactive_master_volume_muted,
31 music_volume_text,
32 music_volume_slider,
33 music_volume_number,
34 music_volume_muted,
35 sfx_volume_text,
36 sfx_volume_slider,
37 sfx_volume_number,
38 sfx_volume_muted,
39 ambience_volume_text,
40 ambience_volume_slider,
41 ambience_volume_number,
42 ambience_volume_muted,
43 music_spacing_text,
44 music_spacing_slider,
45 music_spacing_number,
46 reset_sound_button,
47 combat_music_toggle_label,
48 combat_music_toggle_button,
49 sfx_channels_label,
50 sfx_channels_list,
51 }
54}
55
56#[derive(WidgetCommon)]
57pub struct Sound<'a> {
58 global_state: &'a GlobalState,
59 imgs: &'a Imgs,
60 fonts: &'a Fonts,
61 localized_strings: &'a Localization,
62 #[conrod(common_builder)]
63 common: widget::CommonBuilder,
64}
65impl<'a> Sound<'a> {
66 pub fn new(
67 global_state: &'a GlobalState,
68 imgs: &'a Imgs,
69 fonts: &'a Fonts,
70 localized_strings: &'a Localization,
71 ) -> Self {
72 Self {
73 global_state,
74 imgs,
75 fonts,
76 localized_strings,
77 common: widget::CommonBuilder::default(),
78 }
79 }
80}
81
82pub struct State {
83 ids: Ids,
84}
85
86impl Widget for Sound<'_> {
87 type Event = Vec<AudioChange>;
88 type State = State;
89 type Style = ();
90
91 fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
92 State {
93 ids: Ids::new(id_gen),
94 }
95 }
96
97 fn style(&self) -> Self::Style {}
98
99 fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
100 common_base::prof_span!("Sound::update");
101 let widget::UpdateArgs { state, ui, .. } = args;
102
103 let mut events = Vec::new();
104
105 Rectangle::fill_with(args.rect.dim(), color::TRANSPARENT)
106 .xy(args.rect.xy())
107 .graphics_for(args.id)
108 .scroll_kids()
109 .scroll_kids_vertically()
110 .set(state.ids.window, ui);
111 Rectangle::fill_with([args.rect.w() / 2.0, args.rect.h()], color::TRANSPARENT)
112 .top_right()
113 .parent(state.ids.window)
114 .set(state.ids.window_r, ui);
115 Scrollbar::y_axis(state.ids.window)
116 .thickness(5.0)
117 .rgba(0.33, 0.33, 0.33, 1.0)
118 .set(state.ids.window_scrollbar, ui);
119
120 let non_master_volume_text_color =
121 match self.global_state.settings.audio.master_volume.muted {
122 true => TEXT_COLOR_GREY,
123 false => TEXT_COLOR,
124 };
125
126 Text::new(&self.localized_strings.get_msg("hud-settings-master_volume"))
128 .top_left_with_margins_on(state.ids.window, 10.0, 10.0)
129 .font_size(self.fonts.cyri.scale(14))
130 .font_id(self.fonts.cyri.conrod_id)
131 .color(TEXT_COLOR)
132 .set(state.ids.master_volume_text, ui);
133 let master_muted = ToggleButton::new(
135 self.global_state.settings.audio.master_volume.muted,
136 self.imgs.button_mute,
137 self.imgs.button_muted,
138 )
139 .w_h(24.0, 25.0)
140 .down_from(state.ids.master_volume_text, 10.0)
141 .hover_images(self.imgs.button_mute_hover, self.imgs.button_muted_hover)
142 .press_images(self.imgs.button_mute_press, self.imgs.button_muted_press)
143 .set(state.ids.master_volume_muted, ui);
144 if master_muted != self.global_state.settings.audio.master_volume.muted {
145 events.push(MuteMasterVolume(master_muted));
146 }
147 if let Some(new_val) = ImageSlider::continuous(
149 self.global_state.settings.audio.master_volume.volume,
150 0.0,
151 1.0,
152 self.imgs.slider_indicator,
153 self.imgs.slider,
154 )
155 .w_h(104.0, 22.0)
156 .right_from(state.ids.master_volume_muted, 8.0)
157 .track_breadth(12.0)
158 .slider_length(10.0)
159 .pad_track((5.0, 5.0))
160 .set(state.ids.master_volume_slider, ui)
161 {
162 events.push(AdjustMasterVolume(new_val));
163 }
164 Text::new(&format!(
166 "{:2.0}%",
167 self.global_state.settings.audio.master_volume.volume * 100.0
168 ))
169 .right_from(state.ids.master_volume_slider, 8.0)
170 .font_size(self.fonts.cyri.scale(14))
171 .font_id(self.fonts.cyri.conrod_id)
172 .color(TEXT_COLOR)
173 .set(state.ids.master_volume_number, ui);
174
175 Text::new(
177 &self
178 .localized_strings
179 .get_msg("hud-settings-inactive_master_volume_perc"),
180 )
181 .down_from(state.ids.master_volume_muted, 10.0)
182 .font_size(self.fonts.cyri.scale(14))
183 .font_id(self.fonts.cyri.conrod_id)
184 .color(TEXT_COLOR)
185 .set(state.ids.inactive_master_volume_text, ui);
186 let inactive_master_muted = ToggleButton::new(
188 self.global_state
189 .settings
190 .audio
191 .inactive_master_volume_perc
192 .muted,
193 self.imgs.button_mute,
194 self.imgs.button_muted,
195 )
196 .w_h(24.0, 25.0)
197 .down_from(state.ids.inactive_master_volume_text, 10.0)
198 .hover_images(self.imgs.button_mute_hover, self.imgs.button_muted_hover)
199 .press_images(self.imgs.button_mute_press, self.imgs.button_muted_press)
200 .set(state.ids.inactive_master_volume_muted, ui);
201 if inactive_master_muted
202 != self
203 .global_state
204 .settings
205 .audio
206 .inactive_master_volume_perc
207 .muted
208 {
209 events.push(MuteInactiveMasterVolume(inactive_master_muted));
210 }
211 if let Some(new_val) = ImageSlider::continuous(
213 self.global_state
214 .settings
215 .audio
216 .inactive_master_volume_perc
217 .volume,
218 0.0,
219 1.0,
220 self.imgs.slider_indicator,
221 self.imgs.slider,
222 )
223 .w_h(104.0, 22.0)
224 .right_from(state.ids.inactive_master_volume_muted, 8.0)
225 .track_breadth(12.0)
226 .slider_length(10.0)
227 .pad_track((5.0, 5.0))
228 .set(state.ids.inactive_master_volume_slider, ui)
229 {
230 events.push(AdjustInactiveMasterVolume(new_val));
231 }
232 Text::new(&format!(
234 "{:2.0}%",
235 self.global_state
236 .settings
237 .audio
238 .inactive_master_volume_perc
239 .volume
240 * 100.0
241 ))
242 .right_from(state.ids.inactive_master_volume_slider, 8.0)
243 .font_size(self.fonts.cyri.scale(14))
244 .font_id(self.fonts.cyri.conrod_id)
245 .color(non_master_volume_text_color)
246 .set(state.ids.inactive_master_volume_number, ui);
247
248 Text::new(&self.localized_strings.get_msg("hud-settings-music_volume"))
250 .down_from(state.ids.inactive_master_volume_muted, 10.0)
251 .font_size(self.fonts.cyri.scale(14))
252 .font_id(self.fonts.cyri.conrod_id)
253 .color(TEXT_COLOR)
254 .set(state.ids.music_volume_text, ui);
255 let music_muted = ToggleButton::new(
257 self.global_state.settings.audio.music_volume.muted,
258 self.imgs.button_mute,
259 self.imgs.button_muted,
260 )
261 .w_h(24.0, 25.0)
262 .down_from(state.ids.music_volume_text, 10.0)
263 .hover_images(self.imgs.button_mute_hover, self.imgs.button_muted_hover)
264 .press_images(self.imgs.button_mute_press, self.imgs.button_muted_press)
265 .set(state.ids.music_volume_muted, ui);
266 if music_muted != self.global_state.settings.audio.music_volume.muted {
267 events.push(MuteMusicVolume(music_muted));
268 }
269 if let Some(new_val) = ImageSlider::continuous(
271 self.global_state.settings.audio.music_volume.volume,
272 0.0,
273 1.0,
274 self.imgs.slider_indicator,
275 self.imgs.slider,
276 )
277 .w_h(104.0, 22.0)
278 .right_from(state.ids.music_volume_muted, 8.0)
279 .track_breadth(12.0)
280 .slider_length(10.0)
281 .pad_track((5.0, 5.0))
282 .set(state.ids.music_volume_slider, ui)
283 {
284 events.push(AdjustMusicVolume(new_val));
285 }
286 Text::new(&format!(
288 "{:2.0}%",
289 self.global_state.settings.audio.music_volume.volume * 100.0
290 ))
291 .right_from(state.ids.music_volume_slider, 8.0)
292 .font_size(self.fonts.cyri.scale(14))
293 .font_id(self.fonts.cyri.conrod_id)
294 .color(non_master_volume_text_color)
295 .set(state.ids.music_volume_number, ui);
296
297 Text::new(
299 &self
300 .localized_strings
301 .get_msg("hud-settings-sound_effect_volume"),
302 )
303 .down_from(state.ids.music_volume_muted, 10.0)
304 .font_size(self.fonts.cyri.scale(14))
305 .font_id(self.fonts.cyri.conrod_id)
306 .color(TEXT_COLOR)
307 .set(state.ids.sfx_volume_text, ui);
308 let sfx_muted = ToggleButton::new(
310 self.global_state.settings.audio.sfx_volume.muted,
311 self.imgs.button_mute,
312 self.imgs.button_muted,
313 )
314 .w_h(24.0, 25.0)
315 .down_from(state.ids.sfx_volume_text, 10.0)
316 .hover_images(self.imgs.button_mute_hover, self.imgs.button_muted_hover)
317 .press_images(self.imgs.button_mute_press, self.imgs.button_muted_press)
318 .set(state.ids.sfx_volume_muted, ui);
319 if sfx_muted != self.global_state.settings.audio.sfx_volume.muted {
320 events.push(MuteSfxVolume(sfx_muted));
321 }
322 if let Some(new_val) = ImageSlider::continuous(
324 self.global_state.settings.audio.sfx_volume.volume,
325 0.0,
326 1.0,
327 self.imgs.slider_indicator,
328 self.imgs.slider,
329 )
330 .w_h(104.0, 22.0)
331 .right_from(state.ids.sfx_volume_muted, 8.0)
332 .track_breadth(12.0)
333 .slider_length(10.0)
334 .pad_track((5.0, 5.0))
335 .set(state.ids.sfx_volume_slider, ui)
336 {
337 events.push(AdjustSfxVolume(new_val));
338 }
339 Text::new(&format!(
341 "{:2.0}%",
342 self.global_state.settings.audio.sfx_volume.volume * 100.0
343 ))
344 .right_from(state.ids.sfx_volume_slider, 8.0)
345 .font_size(self.fonts.cyri.scale(14))
346 .font_id(self.fonts.cyri.conrod_id)
347 .color(non_master_volume_text_color)
348 .set(state.ids.sfx_volume_number, ui);
349
350 Text::new(
352 &self
353 .localized_strings
354 .get_msg("hud-settings-ambience_volume"),
355 )
356 .down_from(state.ids.sfx_volume_muted, 10.0)
357 .font_size(self.fonts.cyri.scale(14))
358 .font_id(self.fonts.cyri.conrod_id)
359 .color(TEXT_COLOR)
360 .set(state.ids.ambience_volume_text, ui);
361 let ambience_muted = ToggleButton::new(
363 self.global_state.settings.audio.ambience_volume.muted,
364 self.imgs.button_mute,
365 self.imgs.button_muted,
366 )
367 .w_h(24.0, 25.0)
368 .down_from(state.ids.ambience_volume_text, 10.0)
369 .hover_images(self.imgs.button_mute_hover, self.imgs.button_muted_hover)
370 .press_images(self.imgs.button_mute_press, self.imgs.button_muted_press)
371 .set(state.ids.ambience_volume_muted, ui);
372 if ambience_muted != self.global_state.settings.audio.ambience_volume.muted {
373 events.push(MuteAmbienceVolume(ambience_muted));
374 }
375 if let Some(new_val) = ImageSlider::continuous(
377 self.global_state.settings.audio.ambience_volume.volume,
378 0.0,
379 1.0,
380 self.imgs.slider_indicator,
381 self.imgs.slider,
382 )
383 .w_h(104.0, 22.0)
384 .right_from(state.ids.ambience_volume_muted, 8.0)
385 .track_breadth(12.0)
386 .slider_length(10.0)
387 .pad_track((5.0, 5.0))
388 .set(state.ids.ambience_volume_slider, ui)
389 {
390 events.push(AdjustAmbienceVolume(new_val));
391 }
392 Text::new(&format!(
394 "{:2.0}%",
395 self.global_state.settings.audio.ambience_volume.volume * 100.0
396 ))
397 .right_from(state.ids.ambience_volume_slider, 8.0)
398 .font_size(self.fonts.cyri.scale(14))
399 .font_id(self.fonts.cyri.conrod_id)
400 .color(non_master_volume_text_color)
401 .set(state.ids.ambience_volume_number, ui);
402
403 Text::new(&self.localized_strings.get_msg("hud-settings-music_spacing"))
405 .down_from(state.ids.ambience_volume_muted, 10.0)
406 .font_size(self.fonts.cyri.scale(14))
407 .font_id(self.fonts.cyri.conrod_id)
408 .color(TEXT_COLOR)
409 .set(state.ids.music_spacing_text, ui);
410 if let Some(new_val) = ImageSlider::continuous(
412 self.global_state.settings.audio.music_spacing,
413 0.0,
414 2.0,
415 self.imgs.slider_indicator,
416 self.imgs.slider,
417 )
418 .w_h(104.0, 22.0)
419 .down_from(state.ids.music_spacing_text, 10.0)
420 .x_align_to(state.ids.ambience_volume_slider, Align::Start)
421 .track_breadth(12.0)
422 .slider_length(10.0)
423 .pad_track((5.0, 5.0))
424 .set(state.ids.music_spacing_slider, ui)
425 {
426 events.push(AdjustMusicSpacing(new_val));
427 }
428 Text::new(&format!(
430 "{:1.2}x",
431 self.global_state.settings.audio.music_spacing
432 ))
433 .right_from(state.ids.music_spacing_slider, 8.0)
434 .font_size(self.fonts.cyri.scale(14))
435 .font_id(self.fonts.cyri.conrod_id)
436 .color(TEXT_COLOR)
437 .set(state.ids.music_spacing_number, ui);
438
439 Text::new(&self.localized_strings.get_msg("hud-settings-sfx_channels"))
442 .down_from(state.ids.music_spacing_number, 10.0)
443 .x_align_to(state.ids.music_spacing_text, Align::Start)
444 .font_size(self.fonts.cyri.scale(14))
445 .font_id(self.fonts.cyri.conrod_id)
446 .color(TEXT_COLOR)
447 .set(state.ids.sfx_channels_label, ui);
448
449 let current: Option<usize> = match self.global_state.settings.audio.num_sfx_channels {
450 16 => Some(0),
451 32 => Some(1),
452 64 => Some(2),
453 _ => None,
454 };
455
456 let num_sfx_setting_list = [
457 SfxChannelSettings::Low.to_string(),
458 SfxChannelSettings::Medium.to_string(),
459 SfxChannelSettings::High.to_string(),
460 ];
461
462 let num_sfx_setting_list_shown = vec![
463 format!(
464 "{} ({})",
465 &SfxChannelSettings::Low.to_string(),
466 &SfxChannelSettings::Low.to_usize().to_string()
467 ),
468 format!(
469 "{} ({})",
470 &SfxChannelSettings::Medium.to_string(),
471 &SfxChannelSettings::Medium.to_usize().to_string()
472 ),
473 format!(
474 "{} ({})",
475 &SfxChannelSettings::High.to_string(),
476 &SfxChannelSettings::High.to_usize().to_string()
477 ),
478 ];
479
480 if let Some(clicked) = DropDownList::new(&num_sfx_setting_list_shown, current)
481 .w_h(150.0, 22.0)
482 .color(MENU_BG)
483 .label_color(TEXT_COLOR)
484 .label_font_id(self.fonts.cyri.conrod_id)
485 .down_from(state.ids.sfx_channels_label, 10.0)
486 .set(state.ids.sfx_channels_list, ui)
487 {
488 let new_val = &num_sfx_setting_list[clicked];
489
490 events.push(SetNumSfxChannels(SfxChannelSettings::from_str_slice(
491 new_val,
492 )));
493 }
494
495 if Button::image(self.imgs.button)
547 .w_h(RESET_BUTTONS_WIDTH, RESET_BUTTONS_HEIGHT)
548 .hover_image(self.imgs.button_hover)
549 .press_image(self.imgs.button_press)
550 .down_from(state.ids.sfx_channels_list, 12.0)
551 .x_align_to(state.ids.ambience_volume_text, Align::Start)
552 .label(&self.localized_strings.get_msg("hud-settings-reset_sound"))
553 .label_font_size(self.fonts.cyri.scale(14))
554 .label_color(TEXT_COLOR)
555 .label_font_id(self.fonts.cyri.conrod_id)
556 .label_y(Relative::Scalar(2.0))
557 .set(state.ids.reset_sound_button, ui)
558 .was_clicked()
559 {
560 events.push(ResetAudioSettings);
561 }
562
563 events
564 }
565}