Example #1
0
        Func <bool> InitPanel(Widget panel)
        {
            var ds          = Game.Settings.Debug;
            var ss          = Game.Settings.Server;
            var gs          = Game.Settings.Game;
            var scrollPanel = panel.Get <ScrollPanelWidget>("SETTINGS_SCROLLPANEL");

            // Advanced
            SettingsUtils.BindCheckboxPref(panel, "NAT_DISCOVERY", ss, "DiscoverNatDevices");
            SettingsUtils.BindCheckboxPref(panel, "PERFTEXT_CHECKBOX", ds, "PerfText");
            SettingsUtils.BindCheckboxPref(panel, "PERFGRAPH_CHECKBOX", ds, "PerfGraph");
            SettingsUtils.BindCheckboxPref(panel, "FETCH_NEWS_CHECKBOX", gs, "FetchNews");
            SettingsUtils.BindCheckboxPref(panel, "SENDSYSINFO_CHECKBOX", ds, "SendSystemInformation");
            SettingsUtils.BindCheckboxPref(panel, "CHECK_VERSION_CHECKBOX", ds, "CheckVersion");

            var ssi = panel.Get <CheckboxWidget>("SENDSYSINFO_CHECKBOX");

            ssi.IsDisabled = () => !gs.FetchNews;

            // Developer
            SettingsUtils.BindCheckboxPref(panel, "BOTDEBUG_CHECKBOX", ds, "BotDebug");
            SettingsUtils.BindCheckboxPref(panel, "LUADEBUG_CHECKBOX", ds, "LuaDebug");
            SettingsUtils.BindCheckboxPref(panel, "REPLAY_COMMANDS_CHECKBOX", ds, "EnableDebugCommandsInReplays");
            SettingsUtils.BindCheckboxPref(panel, "CHECKUNSYNCED_CHECKBOX", ds, "SyncCheckUnsyncedCode");
            SettingsUtils.BindCheckboxPref(panel, "CHECKBOTSYNC_CHECKBOX", ds, "SyncCheckBotModuleCode");
            SettingsUtils.BindCheckboxPref(panel, "PERFLOGGING_CHECKBOX", ds, "EnableSimulationPerfLogging");

            panel.Get("BOTDEBUG_CHECKBOX_CONTAINER").IsVisible        = () => ds.DisplayDeveloperSettings;
            panel.Get("CHECKUNSYNCED_CHECKBOX_CONTAINER").IsVisible   = () => ds.DisplayDeveloperSettings;
            panel.Get("CHECKBOTSYNC_CHECKBOX_CONTAINER").IsVisible    = () => ds.DisplayDeveloperSettings;
            panel.Get("LUADEBUG_CHECKBOX_CONTAINER").IsVisible        = () => ds.DisplayDeveloperSettings;
            panel.Get("REPLAY_COMMANDS_CHECKBOX_CONTAINER").IsVisible = () => ds.DisplayDeveloperSettings;
            panel.Get("PERFLOGGING_CHECKBOX_CONTAINER").IsVisible     = () => ds.DisplayDeveloperSettings;
            panel.Get("DEBUG_HIDDEN_CONTAINER").IsVisible             = () => !ds.DisplayDeveloperSettings;

            SettingsUtils.AdjustSettingsScrollPanelLayout(scrollPanel);

            return(() => ss.DiscoverNatDevices != OriginalServerDiscoverNatDevices);
        }
Example #2
0
        void ShowAudioDeviceDropdown(DropDownButtonWidget dropdown, SoundDevice[] devices, ScrollPanelWidget scrollPanel)
        {
            var i       = 0;
            var options = devices.ToDictionary(d => (i++).ToString(), d => d);

            Func <string, ScrollItemWidget, ScrollItemWidget> setupItem = (o, itemTemplate) =>
            {
                var item = ScrollItemWidget.Setup(itemTemplate,
                                                  () => soundDevice == options[o],
                                                  () =>
                {
                    soundDevice = options[o];
                    SettingsUtils.AdjustSettingsScrollPanelLayout(scrollPanel);
                });

                var deviceLabel = item.Get <LabelWidget>("LABEL");
                var font        = Game.Renderer.Fonts[deviceLabel.Font];
                var label       = WidgetUtils.TruncateText(options[o].Label, deviceLabel.Bounds.Width, font);
                deviceLabel.GetText = () => label;
                return(item);
            };

            dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem);
        }
Example #3
0
        Func <bool> InitPanel(Widget panel)
        {
            var ds          = Game.Settings.Graphics;
            var gs          = Game.Settings.Game;
            var scrollPanel = panel.Get <ScrollPanelWidget>("SETTINGS_SCROLLPANEL");

            SettingsUtils.BindCheckboxPref(panel, "CURSORDOUBLE_CHECKBOX", ds, "CursorDouble");
            SettingsUtils.BindCheckboxPref(panel, "VSYNC_CHECKBOX", ds, "VSync");
            SettingsUtils.BindCheckboxPref(panel, "FRAME_LIMIT_CHECKBOX", ds, "CapFramerate");
            SettingsUtils.BindIntSliderPref(panel, "FRAME_LIMIT_SLIDER", ds, "MaxFramerate");
            SettingsUtils.BindCheckboxPref(panel, "PLAYER_STANCE_COLORS_CHECKBOX", gs, "UsePlayerStanceColors");
            if (panel.GetOrNull <CheckboxWidget>("PAUSE_SHELLMAP_CHECKBOX") != null)
            {
                SettingsUtils.BindCheckboxPref(panel, "PAUSE_SHELLMAP_CHECKBOX", gs, "PauseShellmap");
            }

            var windowModeDropdown = panel.Get <DropDownButtonWidget>("MODE_DROPDOWN");

            windowModeDropdown.OnMouseDown = _ => ShowWindowModeDropdown(windowModeDropdown, ds, scrollPanel);
            windowModeDropdown.GetText     = () => ds.Mode == WindowMode.Windowed ?
                                             "Windowed" : ds.Mode == WindowMode.Fullscreen ? "Fullscreen (Legacy)" : "Fullscreen";

            var displaySelectionDropDown = panel.Get <DropDownButtonWidget>("DISPLAY_SELECTION_DROPDOWN");

            displaySelectionDropDown.OnMouseDown = _ => ShowDisplaySelectionDropdown(displaySelectionDropDown, ds);
            var displaySelectionLabel = new CachedTransform <int, string>(i => $"Display {i + 1}");

            displaySelectionDropDown.GetText    = () => displaySelectionLabel.Update(ds.VideoDisplay);
            displaySelectionDropDown.IsDisabled = () => Game.Renderer.DisplayCount < 2;

            var glProfileLabel    = new CachedTransform <GLProfile, string>(p => p.ToString());
            var glProfileDropdown = panel.Get <DropDownButtonWidget>("GL_PROFILE_DROPDOWN");
            var disableProfile    = Game.Renderer.SupportedGLProfiles.Length < 2 && ds.GLProfile == GLProfile.Automatic;

            glProfileDropdown.OnMouseDown = _ => ShowGLProfileDropdown(glProfileDropdown, ds);
            glProfileDropdown.GetText     = () => glProfileLabel.Update(ds.GLProfile);
            glProfileDropdown.IsDisabled  = () => disableProfile;

            var statusBarsDropDown = panel.Get <DropDownButtonWidget>("STATUS_BAR_DROPDOWN");

            statusBarsDropDown.OnMouseDown = _ => ShowStatusBarsDropdown(statusBarsDropDown, gs);
            statusBarsDropDown.GetText     = () => gs.StatusBars == StatusBarsType.Standard ?
                                             "Standard" : gs.StatusBars == StatusBarsType.DamageShow ? "Show On Damage" : "Always Show";

            var targetLinesDropDown = panel.Get <DropDownButtonWidget>("TARGET_LINES_DROPDOWN");

            targetLinesDropDown.OnMouseDown = _ => ShowTargetLinesDropdown(targetLinesDropDown, gs);
            targetLinesDropDown.GetText     = () => gs.TargetLines == TargetLinesType.Automatic ?
                                              "Automatic" : gs.TargetLines == TargetLinesType.Manual ? "Manual" : "Disabled";

            var battlefieldCameraDropDown = panel.Get <DropDownButtonWidget>("BATTLEFIELD_CAMERA_DROPDOWN");
            var battlefieldCameraLabel    = new CachedTransform <WorldViewport, string>(vs => ViewportSizeNames[vs]);

            battlefieldCameraDropDown.OnMouseDown = _ => ShowBattlefieldCameraDropdown(battlefieldCameraDropDown, viewportSizes, ds);
            battlefieldCameraDropDown.GetText     = () => battlefieldCameraLabel.Update(ds.ViewportDistance);

            BindTextNotificationPoolFilterSettings(panel, gs);

            // Update vsync immediately
            var vsyncCheckbox = panel.Get <CheckboxWidget>("VSYNC_CHECKBOX");
            var vsyncOnClick  = vsyncCheckbox.OnClick;

            vsyncCheckbox.OnClick = () =>
            {
                vsyncOnClick();
                Game.Renderer.SetVSyncEnabled(ds.VSync);
            };

            var uiScaleDropdown = panel.Get <DropDownButtonWidget>("UI_SCALE_DROPDOWN");
            var uiScaleLabel    = new CachedTransform <float, string>(s => $"{(int)(100 * s)}%");

            uiScaleDropdown.OnMouseDown = _ => ShowUIScaleDropdown(uiScaleDropdown, ds);
            uiScaleDropdown.GetText     = () => uiScaleLabel.Update(ds.UIScale);

            var minResolution  = viewportSizes.MinEffectiveResolution;
            var resolution     = Game.Renderer.Resolution;
            var disableUIScale = worldRenderer.World.Type != WorldType.Shellmap ||
                                 resolution.Width * ds.UIScale < 1.25f * minResolution.Width ||
                                 resolution.Height * ds.UIScale < 1.25f * minResolution.Height;

            uiScaleDropdown.IsDisabled = () => disableUIScale;

            panel.Get("DISPLAY_SELECTION_CONTAINER").IsVisible = () => ds.Mode != WindowMode.Windowed;
            panel.Get("WINDOW_RESOLUTION_CONTAINER").IsVisible = () => ds.Mode == WindowMode.Windowed;
            var windowWidth   = panel.Get <TextFieldWidget>("WINDOW_WIDTH");
            var origWidthText = windowWidth.Text = ds.WindowedSize.X.ToString();

            var windowHeight   = panel.Get <TextFieldWidget>("WINDOW_HEIGHT");
            var origHeightText = windowHeight.Text = ds.WindowedSize.Y.ToString();

            windowHeight.Text = ds.WindowedSize.Y.ToString();

            var restartDesc = panel.Get("RESTART_REQUIRED_DESC");

            restartDesc.IsVisible = () => ds.Mode != OriginalGraphicsMode || ds.VideoDisplay != OriginalVideoDisplay || ds.GLProfile != OriginalGLProfile ||
                                    (ds.Mode == WindowMode.Windowed && (origWidthText != windowWidth.Text || origHeightText != windowHeight.Text));

            var frameLimitCheckbox  = panel.Get <CheckboxWidget>("FRAME_LIMIT_CHECKBOX");
            var frameLimitOrigLabel = frameLimitCheckbox.Text;
            var frameLimitLabel     = new CachedTransform <int, string>(fps => frameLimitOrigLabel + $" ({fps} FPS)");

            frameLimitCheckbox.GetText = () => frameLimitLabel.Update(ds.MaxFramerate);

            panel.Get <SliderWidget>("FRAME_LIMIT_SLIDER").IsDisabled = () => !frameLimitCheckbox.IsChecked();

            // Player profile
            var ps = Game.Settings.Player;

            var escPressed    = false;
            var nameTextfield = panel.Get <TextFieldWidget>("PLAYERNAME");

            nameTextfield.IsDisabled  = () => worldRenderer.World.Type != WorldType.Shellmap;
            nameTextfield.Text        = Settings.SanitizedPlayerName(ps.Name);
            nameTextfield.OnLoseFocus = () =>
            {
                if (escPressed)
                {
                    escPressed = false;
                    return;
                }

                nameTextfield.Text = nameTextfield.Text.Trim();
                if (nameTextfield.Text.Length == 0)
                {
                    nameTextfield.Text = Settings.SanitizedPlayerName(ps.Name);
                }
                else
                {
                    nameTextfield.Text = Settings.SanitizedPlayerName(nameTextfield.Text);
                    ps.Name            = nameTextfield.Text;
                }
            };

            nameTextfield.OnEnterKey = _ => { nameTextfield.YieldKeyboardFocus(); return(true); };
            nameTextfield.OnEscKey   = _ =>
            {
                nameTextfield.Text = Settings.SanitizedPlayerName(ps.Name);
                escPressed         = true;
                nameTextfield.YieldKeyboardFocus();
                return(true);
            };

            var colorManager = modData.DefaultRules.Actors[SystemActors.World].TraitInfo <ColorPickerManagerInfo>();

            colorManager.Color = ps.Color;

            var colorDropdown = panel.Get <DropDownButtonWidget>("PLAYERCOLOR");

            colorDropdown.IsDisabled  = () => worldRenderer.World.Type != WorldType.Shellmap;
            colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorManager, worldRenderer, () =>
            {
                Game.Settings.Player.Color = colorManager.Color;
                Game.Settings.Save();
            });
            colorDropdown.Get <ColorBlockWidget>("COLORBLOCK").GetColor = () => ps.Color;

            SettingsUtils.AdjustSettingsScrollPanelLayout(scrollPanel);

            return(() =>
            {
                Exts.TryParseIntegerInvariant(windowWidth.Text, out var x);
                Exts.TryParseIntegerInvariant(windowHeight.Text, out var y);
                ds.WindowedSize = new int2(x, y);
                nameTextfield.YieldKeyboardFocus();

                return ds.Mode != OriginalGraphicsMode ||
                ds.VideoDisplay != OriginalVideoDisplay ||
                ds.WindowedSize != OriginalGraphicsWindowedSize ||
                ds.FullscreenSize != OriginalGraphicsFullscreenSize ||
                ds.GLProfile != OriginalGLProfile;
            });
        }
Example #4
0
        public IntroductionPromptLogic(Widget widget, ModData modData, WorldRenderer worldRenderer, Action onComplete)
        {
            var ps = Game.Settings.Player;
            var ds = Game.Settings.Graphics;
            var gs = Game.Settings.Game;

            var escPressed    = false;
            var nameTextfield = widget.Get <TextFieldWidget>("PLAYERNAME");

            nameTextfield.IsDisabled  = () => worldRenderer.World.Type != WorldType.Shellmap;
            nameTextfield.Text        = Settings.SanitizedPlayerName(ps.Name);
            nameTextfield.OnLoseFocus = () =>
            {
                if (escPressed)
                {
                    escPressed = false;
                    return;
                }

                nameTextfield.Text = nameTextfield.Text.Trim();
                if (nameTextfield.Text.Length == 0)
                {
                    nameTextfield.Text = Settings.SanitizedPlayerName(ps.Name);
                }
                else
                {
                    nameTextfield.Text = Settings.SanitizedPlayerName(nameTextfield.Text);
                    ps.Name            = nameTextfield.Text;
                }
            };

            nameTextfield.OnEnterKey = () => { nameTextfield.YieldKeyboardFocus(); return(true); };
            nameTextfield.OnEscKey   = () =>
            {
                nameTextfield.Text = Settings.SanitizedPlayerName(ps.Name);
                escPressed         = true;
                nameTextfield.YieldKeyboardFocus();
                return(true);
            };

            var colorManager = modData.DefaultRules.Actors[SystemActors.World].TraitInfo <ColorPickerManagerInfo>();

            colorManager.Color = ps.Color;

            var mouseControlDescClassic = widget.Get("MOUSE_CONTROL_DESC_CLASSIC");

            mouseControlDescClassic.IsVisible = () => gs.UseClassicMouseStyle;

            var mouseControlDescModern = widget.Get("MOUSE_CONTROL_DESC_MODERN");

            mouseControlDescModern.IsVisible = () => !gs.UseClassicMouseStyle;

            var mouseControlDropdown = widget.Get <DropDownButtonWidget>("MOUSE_CONTROL_DROPDOWN");

            mouseControlDropdown.OnMouseDown = _ => InputSettingsLogic.ShowMouseControlDropdown(mouseControlDropdown, gs);
            mouseControlDropdown.GetText     = () => gs.UseClassicMouseStyle ? "Classic" : "Modern";

            foreach (var container in new[] { mouseControlDescClassic, mouseControlDescModern })
            {
                var classicScrollRight = container.Get("DESC_SCROLL_RIGHT");
                classicScrollRight.IsVisible = () => gs.UseClassicMouseStyle ^ gs.UseAlternateScrollButton;

                var classicScrollMiddle = container.Get("DESC_SCROLL_MIDDLE");
                classicScrollMiddle.IsVisible = () => !gs.UseClassicMouseStyle ^ gs.UseAlternateScrollButton;

                var zoomDesc = container.Get("DESC_ZOOM");
                zoomDesc.IsVisible = () => gs.ZoomModifier == Modifiers.None;

                var zoomDescModifier = container.Get <LabelWidget>("DESC_ZOOM_MODIFIER");
                zoomDescModifier.IsVisible = () => gs.ZoomModifier != Modifiers.None;

                var zoomDescModifierTemplate = zoomDescModifier.Text;
                var zoomDescModifierLabel    = new CachedTransform <Modifiers, string>(
                    mod => zoomDescModifierTemplate.Replace("MODIFIER", mod.ToString()));
                zoomDescModifier.GetText = () => zoomDescModifierLabel.Update(gs.ZoomModifier);

                var edgescrollDesc = container.Get <LabelWidget>("DESC_EDGESCROLL");
                edgescrollDesc.IsVisible = () => gs.ViewportEdgeScroll;
            }

            SettingsUtils.BindCheckboxPref(widget, "EDGESCROLL_CHECKBOX", gs, "ViewportEdgeScroll");

            var colorDropdown = widget.Get <DropDownButtonWidget>("PLAYERCOLOR");

            colorDropdown.IsDisabled  = () => worldRenderer.World.Type != WorldType.Shellmap;
            colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorManager, worldRenderer);
            colorDropdown.Get <ColorBlockWidget>("COLORBLOCK").GetColor = () => ps.Color;

            var viewportSizes             = modData.Manifest.Get <WorldViewportSizes>();
            var battlefieldCameraDropDown = widget.Get <DropDownButtonWidget>("BATTLEFIELD_CAMERA_DROPDOWN");
            var battlefieldCameraLabel    = new CachedTransform <WorldViewport, string>(vs => DisplaySettingsLogic.ViewportSizeNames[vs]);

            battlefieldCameraDropDown.OnMouseDown = _ => DisplaySettingsLogic.ShowBattlefieldCameraDropdown(battlefieldCameraDropDown, viewportSizes, ds);
            battlefieldCameraDropDown.GetText     = () => battlefieldCameraLabel.Update(ds.ViewportDistance);

            var uiScaleDropdown = widget.Get <DropDownButtonWidget>("UI_SCALE_DROPDOWN");
            var uiScaleLabel    = new CachedTransform <float, string>(s => $"{(int)(100 * s)}%");

            uiScaleDropdown.OnMouseDown = _ => DisplaySettingsLogic.ShowUIScaleDropdown(uiScaleDropdown, ds);
            uiScaleDropdown.GetText     = () => uiScaleLabel.Update(ds.UIScale);

            var minResolution  = viewportSizes.MinEffectiveResolution;
            var resolution     = Game.Renderer.Resolution;
            var disableUIScale = worldRenderer.World.Type != WorldType.Shellmap ||
                                 resolution.Width * ds.UIScale < 1.25f * minResolution.Width ||
                                 resolution.Height * ds.UIScale < 1.25f * minResolution.Height;

            uiScaleDropdown.IsDisabled = () => disableUIScale;

            SettingsUtils.BindCheckboxPref(widget, "CURSORDOUBLE_CHECKBOX", ds, "CursorDouble");

            widget.Get <ButtonWidget>("CONTINUE_BUTTON").OnClick = () =>
            {
                Game.Settings.Game.IntroductionPromptVersion = IntroductionVersion;
                Game.Settings.Save();
                Ui.CloseWindow();
                onComplete();
            };
        }
        Func <bool> InitPanel(Widget panel)
        {
            var gs = Game.Settings.Game;

            SettingsUtils.BindCheckboxPref(panel, "ALTERNATE_SCROLL_CHECKBOX", gs, "UseAlternateScrollButton");
            SettingsUtils.BindCheckboxPref(panel, "EDGESCROLL_CHECKBOX", gs, "ViewportEdgeScroll");
            SettingsUtils.BindCheckboxPref(panel, "LOCKMOUSE_CHECKBOX", gs, "LockMouseWindow");
            SettingsUtils.BindSliderPref(panel, "ZOOMSPEED_SLIDER", gs, "ZoomSpeed");
            SettingsUtils.BindSliderPref(panel, "SCROLLSPEED_SLIDER", gs, "ViewportEdgeScrollStep");
            SettingsUtils.BindSliderPref(panel, "UI_SCROLLSPEED_SLIDER", gs, "UIScrollSpeed");

            var mouseControlDropdown = panel.Get <DropDownButtonWidget>("MOUSE_CONTROL_DROPDOWN");

            mouseControlDropdown.OnMouseDown = _ => ShowMouseControlDropdown(mouseControlDropdown, gs);
            mouseControlDropdown.GetText     = () => gs.UseClassicMouseStyle ? "Classic" : "Modern";

            var mouseScrollDropdown = panel.Get <DropDownButtonWidget>("MOUSE_SCROLL_TYPE_DROPDOWN");

            mouseScrollDropdown.OnMouseDown = _ => ShowMouseScrollDropdown(mouseScrollDropdown, gs);
            mouseScrollDropdown.GetText     = () => gs.MouseScroll.ToString();

            var mouseControlDescClassic = panel.Get("MOUSE_CONTROL_DESC_CLASSIC");

            mouseControlDescClassic.IsVisible = () => gs.UseClassicMouseStyle;

            var mouseControlDescModern = panel.Get("MOUSE_CONTROL_DESC_MODERN");

            mouseControlDescModern.IsVisible = () => !gs.UseClassicMouseStyle;

            foreach (var container in new[] { mouseControlDescClassic, mouseControlDescModern })
            {
                var classicScrollRight = container.Get("DESC_SCROLL_RIGHT");
                classicScrollRight.IsVisible = () => gs.UseClassicMouseStyle ^ gs.UseAlternateScrollButton;

                var classicScrollMiddle = container.Get("DESC_SCROLL_MIDDLE");
                classicScrollMiddle.IsVisible = () => !gs.UseClassicMouseStyle ^ gs.UseAlternateScrollButton;

                var zoomDesc = container.Get("DESC_ZOOM");
                zoomDesc.IsVisible = () => gs.ZoomModifier == Modifiers.None;

                var zoomDescModifier = container.Get <LabelWidget>("DESC_ZOOM_MODIFIER");
                zoomDescModifier.IsVisible = () => gs.ZoomModifier != Modifiers.None;

                var zoomDescModifierTemplate = zoomDescModifier.Text;
                var zoomDescModifierLabel    = new CachedTransform <Modifiers, string>(
                    mod => zoomDescModifierTemplate.Replace("MODIFIER", mod.ToString()));
                zoomDescModifier.GetText = () => zoomDescModifierLabel.Update(gs.ZoomModifier);

                var edgescrollDesc = container.Get <LabelWidget>("DESC_EDGESCROLL");
                edgescrollDesc.IsVisible = () => gs.ViewportEdgeScroll;
            }

            // Apply mouse focus preferences immediately
            var lockMouseCheckbox = panel.Get <CheckboxWidget>("LOCKMOUSE_CHECKBOX");
            var oldOnClick        = lockMouseCheckbox.OnClick;

            lockMouseCheckbox.OnClick = () =>
            {
                // Still perform the old behaviour for clicking the checkbox, before
                // applying the changes live.
                oldOnClick();

                MakeMouseFocusSettingsLive();
            };

            var zoomModifierDropdown = panel.Get <DropDownButtonWidget>("ZOOM_MODIFIER");

            zoomModifierDropdown.OnMouseDown = _ => ShowZoomModifierDropdown(zoomModifierDropdown, gs);
            zoomModifierDropdown.GetText     = () => gs.ZoomModifier.ToString();

            return(() => false);
        }
Example #6
0
        Func <bool> InitPanel(Widget panel)
        {
            var musicPlaylist = worldRenderer.World.WorldActor.Trait <MusicPlaylist>();
            var ss            = Game.Settings.Sound;
            var scrollPanel   = panel.Get <ScrollPanelWidget>("SETTINGS_SCROLLPANEL");

            SettingsUtils.BindCheckboxPref(panel, "CASH_TICKS", ss, "CashTicks");
            SettingsUtils.BindCheckboxPref(panel, "MUTE_SOUND", ss, "Mute");
            SettingsUtils.BindCheckboxPref(panel, "MUTE_BACKGROUND_MUSIC", ss, "MuteBackgroundMusic");

            SettingsUtils.BindSliderPref(panel, "SOUND_VOLUME", ss, "SoundVolume");
            SettingsUtils.BindSliderPref(panel, "MUSIC_VOLUME", ss, "MusicVolume");
            SettingsUtils.BindSliderPref(panel, "VIDEO_VOLUME", ss, "VideoVolume");

            var muteCheckbox          = panel.Get <CheckboxWidget>("MUTE_SOUND");
            var muteCheckboxOnClick   = muteCheckbox.OnClick;
            var muteCheckboxIsChecked = muteCheckbox.IsChecked;

            muteCheckbox.IsChecked  = () => muteCheckboxIsChecked() || Game.Sound.DummyEngine;
            muteCheckbox.IsDisabled = () => Game.Sound.DummyEngine;
            muteCheckbox.OnClick    = () =>
            {
                muteCheckboxOnClick();

                if (ss.Mute)
                {
                    Game.Sound.MuteAudio();
                }
                else
                {
                    Game.Sound.UnmuteAudio();
                }
            };

            var muteBackgroundMusicCheckbox        = panel.Get <CheckboxWidget>("MUTE_BACKGROUND_MUSIC");
            var muteBackgroundMusicCheckboxOnClick = muteBackgroundMusicCheckbox.OnClick;

            muteBackgroundMusicCheckbox.OnClick = () =>
            {
                muteBackgroundMusicCheckboxOnClick();

                if (!musicPlaylist.AllowMuteBackgroundMusic)
                {
                    return;
                }

                if (musicPlaylist.CurrentSongIsBackground)
                {
                    musicPlaylist.Stop();
                }
            };

            // Replace controls with a warning label if sound is disabled
            var noDeviceLabel = panel.GetOrNull("NO_AUDIO_DEVICE_CONTAINER");

            if (noDeviceLabel != null)
            {
                noDeviceLabel.Visible = Game.Sound.DummyEngine;
            }

            panel.Get("CASH_TICKS_CONTAINER").Visible            = !Game.Sound.DummyEngine;
            panel.Get("MUTE_SOUND_CONTAINER").Visible            = !Game.Sound.DummyEngine;
            panel.Get("MUTE_BACKGROUND_MUSIC_CONTAINER").Visible = !Game.Sound.DummyEngine;
            panel.Get("SOUND_VOLUME_CONTAINER").Visible          = !Game.Sound.DummyEngine;
            panel.Get("MUSIC_VOLUME_CONTAINER").Visible          = !Game.Sound.DummyEngine;
            panel.Get("VIDEO_VOLUME_CONTAINER").Visible          = !Game.Sound.DummyEngine;

            var soundVolumeSlider = panel.Get <SliderWidget>("SOUND_VOLUME");

            soundVolumeSlider.OnChange += x => Game.Sound.SoundVolume = x;

            var musicVolumeSlider = panel.Get <SliderWidget>("MUSIC_VOLUME");

            musicVolumeSlider.OnChange += x => Game.Sound.MusicVolume = x;

            var videoVolumeSlider = panel.Get <SliderWidget>("VIDEO_VOLUME");

            videoVolumeSlider.OnChange += x => Game.Sound.VideoVolume = x;

            var devices = Game.Sound.AvailableDevices();

            soundDevice = devices.FirstOrDefault(d => d.Device == ss.Device) ?? devices.First();

            var audioDeviceDropdown = panel.Get <DropDownButtonWidget>("AUDIO_DEVICE");

            audioDeviceDropdown.OnMouseDown = _ => ShowAudioDeviceDropdown(audioDeviceDropdown, devices, scrollPanel);

            var deviceFont  = Game.Renderer.Fonts[audioDeviceDropdown.Font];
            var deviceLabel = new CachedTransform <SoundDevice, string>(
                s => WidgetUtils.TruncateText(s.Label, audioDeviceDropdown.UsableWidth, deviceFont));

            audioDeviceDropdown.GetText = () => deviceLabel.Update(soundDevice);

            var restartDesc = panel.Get("RESTART_REQUIRED_DESC");

            restartDesc.IsVisible = () => soundDevice.Device != OriginalSoundDevice;

            SettingsUtils.AdjustSettingsScrollPanelLayout(scrollPanel);

            return(() =>
            {
                ss.Device = soundDevice.Device;

                return ss.Device != OriginalSoundDevice;
            });
        }