diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 10b4df284b..b538e1454a 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -3722,6 +3722,8 @@ STR_6258 :Clear (transparent) STR_6259 :Disabled STR_6260 :Show blocked tiles STR_6261 :Show wide paths +STR_6262 :Master volume +STR_6263 :{SMALLFONT}{BLACK}Toggle all sound on/off ############# # Scenarios # diff --git a/src/openrct2-ui/audio/AudioMixer.cpp b/src/openrct2-ui/audio/AudioMixer.cpp index a7e80ae25e..564e808eb4 100644 --- a/src/openrct2-ui/audio/AudioMixer.cpp +++ b/src/openrct2-ui/audio/AudioMixer.cpp @@ -380,7 +380,8 @@ namespace OpenRCT2::Audio int32_t ApplyVolume(const IAudioChannel* channel, void* buffer, size_t len) { float volumeAdjust = _volume; - volumeAdjust *= (gConfigSound.master_volume / 100.0f); + volumeAdjust *= gConfigSound.master_sound_enabled ? (gConfigSound.master_volume / 100.0f) : 0; + switch (channel->GetGroup()) { case MIXER_GROUP_SOUND: diff --git a/src/openrct2-ui/windows/Options.cpp b/src/openrct2-ui/windows/Options.cpp index 6cfc9b1f11..44ceba0990 100644 --- a/src/openrct2-ui/windows/Options.cpp +++ b/src/openrct2-ui/windows/Options.cpp @@ -122,12 +122,14 @@ enum WINDOW_OPTIONS_WIDGET_IDX { // Audio WIDX_SOUND = WIDX_PAGE_START, WIDX_SOUND_DROPDOWN, + WIDX_MASTER_SOUND_CHECKBOX, WIDX_SOUND_CHECKBOX, WIDX_MUSIC_CHECKBOX, WIDX_AUDIO_FOCUS_CHECKBOX, WIDX_TITLE_MUSIC_LABEL, WIDX_TITLE_MUSIC, WIDX_TITLE_MUSIC_DROPDOWN, + WIDX_MASTER_VOLUME, WIDX_SOUND_VOLUME, WIDX_MUSIC_VOLUME, @@ -277,14 +279,16 @@ static rct_widget window_options_audio_widgets[] = { MAIN_OPTIONS_WIDGETS, { WWT_DROPDOWN, 1, 10, 299, 53, 64, STR_NONE, STR_NONE }, // Audio device { WWT_BUTTON, 1, 288, 298, 54, 63, STR_DROPDOWN_GLYPH, STR_AUDIO_DEVICE_TIP }, - { WWT_CHECKBOX, 1, 10, 229, 69, 80, STR_SOUND_EFFECTS, STR_SOUND_EFFECTS_TIP }, // Enable / disable sound effects - { WWT_CHECKBOX, 1, 10, 229, 84, 95, STR_RIDE_MUSIC, STR_RIDE_MUSIC_TIP }, // Enable / disable ride music - { WWT_CHECKBOX, 1, 10, 299, 98, 110, STR_AUDIO_FOCUS, STR_AUDIO_FOCUS_TIP }, // Enable / disable audio disabled on focus lost - { WWT_LABEL, 1, 10, 154, 113, 125, STR_OPTIONS_MUSIC_LABEL,STR_NONE }, // Title music label - { WWT_DROPDOWN, 1, 155, 299, 112, 124, STR_NONE, STR_NONE }, // Title music - { WWT_BUTTON, 1, 288, 298, 113, 123, STR_DROPDOWN_GLYPH, STR_TITLE_MUSIC_TIP }, - { WWT_SCROLL, 1, 155, 299, 68, 80, SCROLL_HORIZONTAL, STR_NONE }, // Sound effect volume - { WWT_SCROLL, 1, 155, 299, 83, 95, SCROLL_HORIZONTAL, STR_NONE }, // Music volume + { WWT_CHECKBOX, 1, 10, 229, 69, 80, STR_MASTER_VOLUME, STR_MASTER_VOLUME_TIP }, // Enable / disable master sound + { WWT_CHECKBOX, 1, 10, 229, 84, 95, STR_SOUND_EFFECTS, STR_SOUND_EFFECTS_TIP }, // Enable / disable sound effects + { WWT_CHECKBOX, 1, 10, 229, 99, 110, STR_RIDE_MUSIC, STR_RIDE_MUSIC_TIP }, // Enable / disable ride music + { WWT_CHECKBOX, 1, 10, 299, 113, 125, STR_AUDIO_FOCUS, STR_AUDIO_FOCUS_TIP }, // Enable / disable audio disabled on focus lost + { WWT_LABEL, 1, 10, 154, 128, 140, STR_OPTIONS_MUSIC_LABEL,STR_NONE }, // Title music label + { WWT_DROPDOWN, 1, 155, 299, 127, 139, STR_NONE, STR_NONE }, // Title music + { WWT_BUTTON, 1, 288, 298, 128, 138, STR_DROPDOWN_GLYPH, STR_TITLE_MUSIC_TIP }, + { WWT_SCROLL, 1, 155, 299, 68, 80, SCROLL_HORIZONTAL, STR_NONE }, // Master volume + { WWT_SCROLL, 1, 155, 299, 83, 95, SCROLL_HORIZONTAL, STR_NONE }, // Sound effect volume + { WWT_SCROLL, 1, 155, 299, 98, 110, SCROLL_HORIZONTAL, STR_NONE }, // Music volume { WIDGETS_END }, }; @@ -548,6 +552,7 @@ static uint64_t window_options_page_enabled_widgets[] = { MAIN_OPTIONS_ENABLED_WIDGETS | (1 << WIDX_SOUND) | (1 << WIDX_SOUND_DROPDOWN) | + (1 << WIDX_MASTER_SOUND_CHECKBOX) | (1 << WIDX_SOUND_CHECKBOX) | (1 << WIDX_MUSIC_CHECKBOX) | (1 << WIDX_AUDIO_FOCUS_CHECKBOX) | @@ -766,6 +771,13 @@ static void window_options_mouseup(rct_window* w, rct_widgetindex widgetIndex) config_save_default(); window_invalidate(w); break; + + case WIDX_MASTER_SOUND_CHECKBOX: + gConfigSound.master_sound_enabled = !gConfigSound.master_sound_enabled; + config_save_default(); + window_invalidate(w); + break; + case WIDX_MUSIC_CHECKBOX: gConfigSound.ride_music_enabled = !gConfigSound.ride_music_enabled; if (!gConfigSound.ride_music_enabled) @@ -775,6 +787,7 @@ static void window_options_mouseup(rct_window* w, rct_widgetindex widgetIndex) config_save_default(); window_invalidate(w); break; + case WIDX_AUDIO_FOCUS_CHECKBOX: gConfigSound.audio_focus = !gConfigSound.audio_focus; config_save_default(); @@ -1776,22 +1789,34 @@ static void window_options_invalidate(rct_window* w) window_options_audio_widgets[WIDX_TITLE_MUSIC].text = window_options_title_music_names[gConfigSound.title_music]; widget_set_checkbox_value(w, WIDX_SOUND_CHECKBOX, gConfigSound.sound_enabled); + widget_set_checkbox_value(w, WIDX_MASTER_SOUND_CHECKBOX, gConfigSound.master_sound_enabled); widget_set_checkbox_value(w, WIDX_MUSIC_CHECKBOX, gConfigSound.ride_music_enabled); widget_set_checkbox_value(w, WIDX_AUDIO_FOCUS_CHECKBOX, gConfigSound.audio_focus); // Initialize only on first frame, otherwise the scrollbars wont be able to be modified if (w->frame_no == 0) { - widget = &window_options_audio_widgets[WIDX_SOUND_VOLUME]; - w->scrolls[0].h_left = (int16_t)ceil( - (gConfigSound.sound_volume / 100.0f) * (w->scrolls[0].h_right - ((widget->right - widget->left) - 1))); - widget = &window_options_audio_widgets[WIDX_MUSIC_VOLUME]; - w->scrolls[1].h_left = (int16_t)ceil( - (gConfigSound.ride_music_volume / 100.0f) * (w->scrolls[1].h_right - ((widget->right - widget->left) - 1))); - } + widget = &window_options_audio_widgets[WIDX_MASTER_VOLUME]; + w->scrolls[0].h_left = ceil( + (gConfigSound.master_volume / 100.0f) * + (w->scrolls[0].h_right - ((widget->right - widget->left) - 1)) + ); + widget_scroll_update_thumbs(w, WIDX_MASTER_VOLUME); - widget_scroll_update_thumbs(w, WIDX_SOUND_VOLUME); - widget_scroll_update_thumbs(w, WIDX_MUSIC_VOLUME); + widget = &window_options_audio_widgets[WIDX_SOUND_VOLUME]; + w->scrolls[1].h_left = ceil( + (gConfigSound.sound_volume / 100.0f) * + (w->scrolls[1].h_right - ((widget->right - widget->left) - 1)) + ); + widget_scroll_update_thumbs(w, WIDX_SOUND_VOLUME); + + widget = &window_options_audio_widgets[WIDX_MUSIC_VOLUME]; + w->scrolls[2].h_left = ceil( + (gConfigSound.ride_music_volume / 100.0f) * + (w->scrolls[2].h_right - ((widget->right - widget->left) - 1)) + ); + widget_scroll_update_thumbs(w, WIDX_MUSIC_VOLUME); + } } break; @@ -1883,6 +1908,12 @@ static void window_options_invalidate(rct_window* w) w->widgets[WIDX_PAGE_BACKGROUND].bottom = w->height - 1; } +static uint8_t get_scroll_percentage(rct_widget* widget, rct_scroll* scroll) +{ + uint8_t width = widget->right - widget->left - 1; + return (float)scroll->h_left / (scroll->h_right - width) * 100; +} + static void window_options_update(rct_window* w) { // Tab animation @@ -1891,24 +1922,34 @@ static void window_options_update(rct_window* w) if (w->page == WINDOW_OPTIONS_PAGE_AUDIO) { - rct_widget* widget = &window_options_audio_widgets[WIDX_SOUND_VOLUME]; - uint8_t sound_volume = (uint8_t)( - ((float)w->scrolls[0].h_left / (w->scrolls[0].h_right - ((widget->right - widget->left) - 1))) * 100); - widget = &window_options_audio_widgets[WIDX_MUSIC_VOLUME]; - uint8_t ride_music_volume = (uint8_t)( - ((float)w->scrolls[1].h_left / (w->scrolls[1].h_right - ((widget->right - widget->left) - 1))) * 100); + rct_widget* widget; + + widget = &window_options_audio_widgets[WIDX_MASTER_VOLUME]; + uint8_t master_volume = get_scroll_percentage(widget, &w->scrolls[0]); + if (master_volume != gConfigSound.master_volume) + { + gConfigSound.master_volume = master_volume; + config_save_default(); + widget_invalidate(w, WIDX_MASTER_VOLUME); + } + + widget = &window_options_audio_widgets[WIDX_SOUND_VOLUME]; + uint8_t sound_volume = get_scroll_percentage(widget, &w->scrolls[1]); if (sound_volume != gConfigSound.sound_volume) { gConfigSound.sound_volume = sound_volume; config_save_default(); + widget_invalidate(w, WIDX_SOUND_VOLUME); } + + widget = &window_options_audio_widgets[WIDX_MUSIC_VOLUME]; + uint8_t ride_music_volume = get_scroll_percentage(widget, &w->scrolls[2]); if (ride_music_volume != gConfigSound.ride_music_volume) { gConfigSound.ride_music_volume = ride_music_volume; config_save_default(); + widget_invalidate(w, WIDX_MUSIC_VOLUME); } - widget_invalidate(w, WIDX_SOUND_VOLUME); - widget_invalidate(w, WIDX_MUSIC_VOLUME); } } diff --git a/src/openrct2/config/Config.cpp b/src/openrct2/config/Config.cpp index 044a38cdc2..285c2a51d6 100644 --- a/src/openrct2/config/Config.cpp +++ b/src/openrct2/config/Config.cpp @@ -320,6 +320,8 @@ namespace Config if (reader->ReadSection("sound")) { auto model = &gConfigSound; + model->device = reader->GetCString("audio_device", nullptr); + model->master_sound_enabled = reader->GetBoolean("master_sound", true); model->master_volume = reader->GetInt32("master_volume", 100); model->title_music = reader->GetInt32("title_music", 2); model->sound_enabled = reader->GetBoolean("sound", true); @@ -327,7 +329,6 @@ namespace Config model->ride_music_enabled = reader->GetBoolean("ride_music", true); model->ride_music_volume = reader->GetInt32("ride_music_volume", 100); model->audio_focus = reader->GetBoolean("audio_focus", false); - model->device = reader->GetCString("audio_device", nullptr); } } @@ -335,6 +336,8 @@ namespace Config { auto model = &gConfigSound; writer->WriteSection("sound"); + writer->WriteString("audio_device", model->device); + writer->WriteBoolean("master_sound", model->master_sound_enabled); writer->WriteInt32("master_volume", model->master_volume); writer->WriteInt32("title_music", model->title_music); writer->WriteBoolean("sound", model->sound_enabled); @@ -342,7 +345,6 @@ namespace Config writer->WriteBoolean("ride_music", model->ride_music_enabled); writer->WriteInt32("ride_music_volume", model->ride_music_volume); writer->WriteBoolean("audio_focus", model->audio_focus); - writer->WriteString("audio_device", model->device); } static void ReadNetwork(IIniReader* reader) diff --git a/src/openrct2/config/Config.h b/src/openrct2/config/Config.h index e937267a7a..99fb103da3 100644 --- a/src/openrct2/config/Config.h +++ b/src/openrct2/config/Config.h @@ -108,6 +108,7 @@ struct InterfaceConfiguration struct SoundConfiguration { utf8* device; + bool master_sound_enabled; uint8_t master_volume; uint8_t title_music; bool sound_enabled; diff --git a/src/openrct2/localisation/StringIds.h b/src/openrct2/localisation/StringIds.h index ebdbef518e..3529c3a775 100644 --- a/src/openrct2/localisation/StringIds.h +++ b/src/openrct2/localisation/StringIds.h @@ -3885,6 +3885,9 @@ enum STR_DEBUG_PAINT_SHOW_BLOCKED_TILES = 6260, STR_DEBUG_PAINT_SHOW_WIDE_PATHS = 6261, + STR_MASTER_VOLUME = 6262, + STR_MASTER_VOLUME_TIP = 6263, + // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working STR_COUNT = 32768 };