diff --git a/OpenRA.Mods.Common/Widgets/Logic/IntroductionPromptLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/IntroductionPromptLogic.cs index 849dd07318..f811127828 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/IntroductionPromptLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/IntroductionPromptLogic.cs @@ -73,7 +73,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic mouseControlDescModern.IsVisible = () => !gs.UseClassicMouseStyle; var mouseControlDropdown = widget.Get("MOUSE_CONTROL_DROPDOWN"); - mouseControlDropdown.OnMouseDown = _ => SettingsLogic.ShowMouseControlDropdown(mouseControlDropdown, gs); + mouseControlDropdown.OnMouseDown = _ => InputSettingsLogic.ShowMouseControlDropdown(mouseControlDropdown, gs); mouseControlDropdown.GetText = () => gs.UseClassicMouseStyle ? "Classic" : "Modern"; foreach (var container in new[] { mouseControlDescClassic, mouseControlDescModern }) @@ -99,7 +99,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic edgescrollDesc.IsVisible = () => gs.ViewportEdgeScroll; } - SettingsLogic.BindCheckboxPref(widget, "EDGESCROLL_CHECKBOX", gs, "ViewportEdgeScroll"); + SettingsUtils.BindCheckboxPref(widget, "EDGESCROLL_CHECKBOX", gs, "ViewportEdgeScroll"); var colorDropdown = widget.Get("PLAYERCOLOR"); colorDropdown.IsDisabled = () => worldRenderer.World.Type != WorldType.Shellmap; @@ -108,13 +108,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic var viewportSizes = modData.Manifest.Get(); var battlefieldCameraDropDown = widget.Get("BATTLEFIELD_CAMERA_DROPDOWN"); - var battlefieldCameraLabel = new CachedTransform(vs => SettingsLogic.ViewportSizeNames[vs]); - battlefieldCameraDropDown.OnMouseDown = _ => SettingsLogic.ShowBattlefieldCameraDropdown(battlefieldCameraDropDown, viewportSizes, ds); + var battlefieldCameraLabel = new CachedTransform(vs => DisplaySettingsLogic.ViewportSizeNames[vs]); + battlefieldCameraDropDown.OnMouseDown = _ => DisplaySettingsLogic.ShowBattlefieldCameraDropdown(battlefieldCameraDropDown, viewportSizes, ds); battlefieldCameraDropDown.GetText = () => battlefieldCameraLabel.Update(ds.ViewportDistance); var uiScaleDropdown = widget.Get("UI_SCALE_DROPDOWN"); var uiScaleLabel = new CachedTransform(s => "{0}%".F((int)(100 * s))); - uiScaleDropdown.OnMouseDown = _ => SettingsLogic.ShowUIScaleDropdown(uiScaleDropdown, ds); + uiScaleDropdown.OnMouseDown = _ => DisplaySettingsLogic.ShowUIScaleDropdown(uiScaleDropdown, ds); uiScaleDropdown.GetText = () => uiScaleLabel.Update(ds.UIScale); var minResolution = viewportSizes.MinEffectiveResolution; @@ -125,7 +125,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic uiScaleDropdown.IsDisabled = () => disableUIScale; - SettingsLogic.BindCheckboxPref(widget, "CURSORDOUBLE_CHECKBOX", ds, "CursorDouble"); + SettingsUtils.BindCheckboxPref(widget, "CURSORDOUBLE_CHECKBOX", ds, "CursorDouble"); widget.Get("CONTINUE_BUTTON").OnClick = () => { diff --git a/OpenRA.Mods.Common/Widgets/Logic/Settings/AdvancedSettingsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Settings/AdvancedSettingsLogic.cs new file mode 100644 index 0000000000..6a723e1d6d --- /dev/null +++ b/OpenRA.Mods.Common/Widgets/Logic/Settings/AdvancedSettingsLogic.cs @@ -0,0 +1,85 @@ +#region Copyright & License Information +/* + * Copyright 2007-2021 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using OpenRA.Widgets; + +namespace OpenRA.Mods.Common.Widgets.Logic +{ + public class AdvancedSettingsLogic : ChromeLogic + { + static readonly bool OriginalServerDiscoverNatDevices; + + static AdvancedSettingsLogic() + { + var original = Game.Settings; + OriginalServerDiscoverNatDevices = original.Server.DiscoverNatDevices; + } + + [ObjectCreator.UseCtor] + public AdvancedSettingsLogic(Action>, Func> registerPanel, string panelID, string label) + { + registerPanel(panelID, label, InitPanel, ResetPanel); + } + + Func InitPanel(Widget panel) + { + var ds = Game.Settings.Debug; + var ss = Game.Settings.Server; + var gs = Game.Settings.Game; + + // 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("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"); + + panel.Get("DEBUG_OPTIONS").IsVisible = () => ds.DisplayDeveloperSettings; + panel.Get("DEBUG_HIDDEN_LABEL").IsVisible = () => !ds.DisplayDeveloperSettings; + + return () => ss.DiscoverNatDevices != OriginalServerDiscoverNatDevices; + } + + Action ResetPanel(Widget panel) + { + var ds = Game.Settings.Debug; + var ss = Game.Settings.Server; + var dds = new DebugSettings(); + var dss = new ServerSettings(); + + return () => + { + ss.DiscoverNatDevices = dss.DiscoverNatDevices; + ds.PerfText = dds.PerfText; + ds.PerfGraph = dds.PerfGraph; + ds.SyncCheckUnsyncedCode = dds.SyncCheckUnsyncedCode; + ds.SyncCheckBotModuleCode = dds.SyncCheckBotModuleCode; + ds.BotDebug = dds.BotDebug; + ds.LuaDebug = dds.LuaDebug; + ds.SendSystemInformation = dds.SendSystemInformation; + ds.CheckVersion = dds.CheckVersion; + ds.EnableDebugCommandsInReplays = dds.EnableDebugCommandsInReplays; + }; + } + } +} diff --git a/OpenRA.Mods.Common/Widgets/Logic/Settings/AudioSettingsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Settings/AudioSettingsLogic.cs new file mode 100644 index 0000000000..ebb1fa4f53 --- /dev/null +++ b/OpenRA.Mods.Common/Widgets/Logic/Settings/AudioSettingsLogic.cs @@ -0,0 +1,166 @@ +#region Copyright & License Information +/* + * Copyright 2007-2021 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using System.Linq; +using OpenRA.Graphics; +using OpenRA.Mods.Common.Traits; +using OpenRA.Widgets; + +namespace OpenRA.Mods.Common.Widgets.Logic +{ + public class AudioSettingsLogic : ChromeLogic + { + static readonly string OriginalSoundDevice; + + readonly WorldRenderer worldRenderer; + + SoundDevice soundDevice; + + static AudioSettingsLogic() + { + var original = Game.Settings; + OriginalSoundDevice = original.Sound.Device; + } + + [ObjectCreator.UseCtor] + public AudioSettingsLogic(Action>, Func> registerPanel, string panelID, string label, WorldRenderer worldRenderer) + { + this.worldRenderer = worldRenderer; + + registerPanel(panelID, label, InitPanel, ResetPanel); + } + + Func InitPanel(Widget panel) + { + var musicPlaylist = worldRenderer.World.WorldActor.Trait(); + var ss = Game.Settings.Sound; + + 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("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("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"); + if (noDeviceLabel != null) + noDeviceLabel.Visible = Game.Sound.DummyEngine; + + var controlsContainer = panel.GetOrNull("AUDIO_CONTROLS"); + if (controlsContainer != null) + controlsContainer.Visible = !Game.Sound.DummyEngine; + + var soundVolumeSlider = panel.Get("SOUND_VOLUME"); + soundVolumeSlider.OnChange += x => Game.Sound.SoundVolume = x; + + var musicVolumeSlider = panel.Get("MUSIC_VOLUME"); + musicVolumeSlider.OnChange += x => Game.Sound.MusicVolume = x; + + var videoVolumeSlider = panel.Get("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("AUDIO_DEVICE"); + audioDeviceDropdown.OnMouseDown = _ => ShowAudioDeviceDropdown(audioDeviceDropdown, devices); + + var deviceFont = Game.Renderer.Fonts[audioDeviceDropdown.Font]; + var deviceLabel = new CachedTransform( + s => WidgetUtils.TruncateText(s.Label, audioDeviceDropdown.UsableWidth, deviceFont)); + audioDeviceDropdown.GetText = () => deviceLabel.Update(soundDevice); + + return () => + { + ss.Device = soundDevice.Device; + + return ss.Device != OriginalSoundDevice; + }; + } + + Action ResetPanel(Widget panel) + { + var ss = Game.Settings.Sound; + var dss = new SoundSettings(); + return () => + { + ss.SoundVolume = dss.SoundVolume; + ss.MusicVolume = dss.MusicVolume; + ss.VideoVolume = dss.VideoVolume; + ss.CashTicks = dss.CashTicks; + ss.Mute = dss.Mute; + ss.MuteBackgroundMusic = dss.MuteBackgroundMusic; + ss.Device = dss.Device; + + panel.Get("SOUND_VOLUME").Value = ss.SoundVolume; + Game.Sound.SoundVolume = ss.SoundVolume; + panel.Get("MUSIC_VOLUME").Value = ss.MusicVolume; + Game.Sound.MusicVolume = ss.MusicVolume; + panel.Get("VIDEO_VOLUME").Value = ss.VideoVolume; + Game.Sound.VideoVolume = ss.VideoVolume; + Game.Sound.UnmuteAudio(); + soundDevice = Game.Sound.AvailableDevices().First(); + }; + } + + void ShowAudioDeviceDropdown(DropDownButtonWidget dropdown, SoundDevice[] devices) + { + var i = 0; + var options = devices.ToDictionary(d => (i++).ToString(), d => d); + + Func setupItem = (o, itemTemplate) => + { + var item = ScrollItemWidget.Setup(itemTemplate, + () => soundDevice == options[o], + () => soundDevice = options[o]); + + var deviceLabel = item.Get("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); + } + } +} diff --git a/OpenRA.Mods.Common/Widgets/Logic/Settings/DisplaySettingsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Settings/DisplaySettingsLogic.cs new file mode 100644 index 0000000000..82593c9bbd --- /dev/null +++ b/OpenRA.Mods.Common/Widgets/Logic/Settings/DisplaySettingsLogic.cs @@ -0,0 +1,437 @@ +#region Copyright & License Information +/* + * Copyright 2007-2021 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using OpenRA.Graphics; +using OpenRA.Primitives; +using OpenRA.Support; +using OpenRA.Widgets; + +namespace OpenRA.Mods.Common.Widgets.Logic +{ + public class DisplaySettingsLogic : ChromeLogic + { + static readonly int OriginalVideoDisplay; + static readonly WindowMode OriginalGraphicsMode; + static readonly int2 OriginalGraphicsWindowedSize; + static readonly int2 OriginalGraphicsFullscreenSize; + static readonly GLProfile OriginalGLProfile; + + readonly ModData modData; + readonly WorldRenderer worldRenderer; + readonly WorldViewportSizes viewportSizes; + + static DisplaySettingsLogic() + { + var original = Game.Settings; + OriginalGraphicsMode = original.Graphics.Mode; + OriginalVideoDisplay = original.Graphics.VideoDisplay; + OriginalGraphicsWindowedSize = original.Graphics.WindowedSize; + OriginalGraphicsFullscreenSize = original.Graphics.FullscreenSize; + OriginalGLProfile = original.Graphics.GLProfile; + } + + [ObjectCreator.UseCtor] + public DisplaySettingsLogic(Action>, Func> registerPanel, string panelID, string label, ModData modData, WorldRenderer worldRenderer) + { + this.worldRenderer = worldRenderer; + this.modData = modData; + viewportSizes = modData.Manifest.Get(); + + registerPanel(panelID, label, InitPanel, ResetPanel); + } + + public static readonly Dictionary ViewportSizeNames = new Dictionary() + { + { WorldViewport.Close, "Close" }, + { WorldViewport.Medium, "Medium" }, + { WorldViewport.Far, "Far" }, + { WorldViewport.Native, "Furthest" } + }; + + Func InitPanel(Widget panel) + { + var ds = Game.Settings.Graphics; + var gs = Game.Settings.Game; + + 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("PAUSE_SHELLMAP_CHECKBOX") != null) + SettingsUtils.BindCheckboxPref(panel, "PAUSE_SHELLMAP_CHECKBOX", gs, "PauseShellmap"); + + var windowModeDropdown = panel.Get("MODE_DROPDOWN"); + windowModeDropdown.OnMouseDown = _ => ShowWindowModeDropdown(windowModeDropdown, ds); + windowModeDropdown.GetText = () => ds.Mode == WindowMode.Windowed ? + "Windowed" : ds.Mode == WindowMode.Fullscreen ? "Fullscreen (Legacy)" : "Fullscreen"; + + var displaySelectionDropDown = panel.Get("DISPLAY_SELECTION_DROPDOWN"); + displaySelectionDropDown.OnMouseDown = _ => ShowDisplaySelectionDropdown(displaySelectionDropDown, ds); + var displaySelectionLabel = new CachedTransform(i => "Display {0}".F(i + 1)); + displaySelectionDropDown.GetText = () => displaySelectionLabel.Update(ds.VideoDisplay); + displaySelectionDropDown.IsDisabled = () => Game.Renderer.DisplayCount < 2; + + var glProfileLabel = new CachedTransform(p => p.ToString()); + var glProfileDropdown = panel.Get("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("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("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("BATTLEFIELD_CAMERA_DROPDOWN"); + var battlefieldCameraLabel = new CachedTransform(vs => ViewportSizeNames[vs]); + battlefieldCameraDropDown.OnMouseDown = _ => ShowBattlefieldCameraDropdown(battlefieldCameraDropDown, viewportSizes, ds); + battlefieldCameraDropDown.GetText = () => battlefieldCameraLabel.Update(ds.ViewportDistance); + + // Update vsync immediately + var vsyncCheckbox = panel.Get("VSYNC_CHECKBOX"); + var vsyncOnClick = vsyncCheckbox.OnClick; + vsyncCheckbox.OnClick = () => + { + vsyncOnClick(); + Game.Renderer.SetVSyncEnabled(ds.VSync); + }; + + var uiScaleDropdown = panel.Get("UI_SCALE_DROPDOWN"); + var uiScaleLabel = new CachedTransform(s => "{0}%".F((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").IsVisible = () => ds.Mode != WindowMode.Windowed; + panel.Get("WINDOW_RESOLUTION").IsVisible = () => ds.Mode == WindowMode.Windowed; + var windowWidth = panel.Get("WINDOW_WIDTH"); + var origWidthText = windowWidth.Text = ds.WindowedSize.X.ToString(); + + var windowHeight = panel.Get("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("FRAME_LIMIT_CHECKBOX"); + var frameLimitOrigLabel = frameLimitCheckbox.Text; + var frameLimitLabel = new CachedTransform(fps => frameLimitOrigLabel + " ({0} FPS)".F(fps)); + frameLimitCheckbox.GetText = () => frameLimitLabel.Update(ds.MaxFramerate); + + // Player profile + var ps = Game.Settings.Player; + + var escPressed = false; + var nameTextfield = panel.Get("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 colorPreview = panel.Get("COLOR_MANAGER"); + colorPreview.Color = ps.Color; + + var colorDropdown = panel.Get("PLAYERCOLOR"); + colorDropdown.IsDisabled = () => worldRenderer.World.Type != WorldType.Shellmap; + colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorPreview, worldRenderer.World); + colorDropdown.Get("COLORBLOCK").GetColor = () => ps.Color; + + 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; + }; + } + + Action ResetPanel(Widget panel) + { + var ds = Game.Settings.Graphics; + var ps = Game.Settings.Player; + var dds = new GraphicSettings(); + var dps = new PlayerSettings(); + return () => + { + ds.CapFramerate = dds.CapFramerate; + ds.MaxFramerate = dds.MaxFramerate; + ds.GLProfile = dds.GLProfile; + ds.Mode = dds.Mode; + ds.VideoDisplay = dds.VideoDisplay; + ds.WindowedSize = dds.WindowedSize; + ds.CursorDouble = dds.CursorDouble; + ds.ViewportDistance = dds.ViewportDistance; + + if (ds.UIScale != dds.UIScale) + { + var oldScale = ds.UIScale; + ds.UIScale = dds.UIScale; + Game.Renderer.SetUIScale(dds.UIScale); + RecalculateWidgetLayout(Ui.Root); + Viewport.LastMousePos = (Viewport.LastMousePos.ToFloat2() * oldScale / ds.UIScale).ToInt2(); + } + + ps.Color = dps.Color; + ps.Name = dps.Name; + }; + } + + static void ShowWindowModeDropdown(DropDownButtonWidget dropdown, GraphicSettings s) + { + var options = new Dictionary() + { + { "Fullscreen", WindowMode.PseudoFullscreen }, + { "Fullscreen (Legacy)", WindowMode.Fullscreen }, + { "Windowed", WindowMode.Windowed }, + }; + + Func setupItem = (o, itemTemplate) => + { + var item = ScrollItemWidget.Setup(itemTemplate, + () => s.Mode == options[o], + () => s.Mode = options[o]); + + item.Get("LABEL").GetText = () => o; + return item; + }; + + dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); + } + + static void ShowStatusBarsDropdown(DropDownButtonWidget dropdown, GameSettings s) + { + var options = new Dictionary() + { + { "Standard", StatusBarsType.Standard }, + { "Show On Damage", StatusBarsType.DamageShow }, + { "Always Show", StatusBarsType.AlwaysShow }, + }; + + Func setupItem = (o, itemTemplate) => + { + var item = ScrollItemWidget.Setup(itemTemplate, + () => s.StatusBars == options[o], + () => s.StatusBars = options[o]); + + item.Get("LABEL").GetText = () => o; + return item; + }; + + dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); + } + + static void ShowDisplaySelectionDropdown(DropDownButtonWidget dropdown, GraphicSettings s) + { + Func setupItem = (o, itemTemplate) => + { + var item = ScrollItemWidget.Setup(itemTemplate, + () => s.VideoDisplay == o, + () => s.VideoDisplay = o); + + var label = "Display {0}".F(o + 1); + item.Get("LABEL").GetText = () => label; + return item; + }; + + dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, Enumerable.Range(0, Game.Renderer.DisplayCount), setupItem); + } + + static void ShowGLProfileDropdown(DropDownButtonWidget dropdown, GraphicSettings s) + { + Func setupItem = (o, itemTemplate) => + { + var item = ScrollItemWidget.Setup(itemTemplate, + () => s.GLProfile == o, + () => s.GLProfile = o); + + var label = o.ToString(); + item.Get("LABEL").GetText = () => label; + return item; + }; + + var profiles = new[] { GLProfile.Automatic }.Concat(Game.Renderer.SupportedGLProfiles); + dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, profiles, setupItem); + } + + static void ShowTargetLinesDropdown(DropDownButtonWidget dropdown, GameSettings s) + { + var options = new Dictionary() + { + { "Automatic", TargetLinesType.Automatic }, + { "Manual", TargetLinesType.Manual }, + { "Disabled", TargetLinesType.Disabled }, + }; + + Func setupItem = (o, itemTemplate) => + { + var item = ScrollItemWidget.Setup(itemTemplate, + () => s.TargetLines == options[o], + () => s.TargetLines = options[o]); + + item.Get("LABEL").GetText = () => o; + return item; + }; + + dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); + } + + public static void ShowBattlefieldCameraDropdown(DropDownButtonWidget dropdown, WorldViewportSizes viewportSizes, GraphicSettings gs) + { + Func setupItem = (o, itemTemplate) => + { + var item = ScrollItemWidget.Setup(itemTemplate, + () => gs.ViewportDistance == o, + () => gs.ViewportDistance = o); + + var label = ViewportSizeNames[o]; + item.Get("LABEL").GetText = () => label; + return item; + }; + + var windowHeight = Game.Renderer.NativeResolution.Height; + + var validSizes = new List() { WorldViewport.Close }; + if (viewportSizes.GetSizeRange(WorldViewport.Medium).X < windowHeight) + validSizes.Add(WorldViewport.Medium); + + var farRange = viewportSizes.GetSizeRange(WorldViewport.Far); + if (farRange.X < windowHeight) + validSizes.Add(WorldViewport.Far); + + if (viewportSizes.AllowNativeZoom && farRange.Y < windowHeight) + validSizes.Add(WorldViewport.Native); + + dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, validSizes, setupItem); + } + + static void RecalculateWidgetLayout(Widget w, bool insideScrollPanel = false) + { + // HACK: Recalculate the widget bounds to fit within the new effective window bounds + // This is fragile, and only works when called when Settings is opened via the main menu. + + // HACK: Skip children badges container on the main menu + // This has a fixed size, with calculated size and children positions that break if we adjust them here + if (w.Id == "BADGES_CONTAINER") + return; + + var parentBounds = w.Parent == null + ? new Rectangle(0, 0, Game.Renderer.Resolution.Width, Game.Renderer.Resolution.Height) + : w.Parent.Bounds; + + var substitutions = new Dictionary(); + substitutions.Add("WINDOW_RIGHT", Game.Renderer.Resolution.Width); + substitutions.Add("WINDOW_BOTTOM", Game.Renderer.Resolution.Height); + substitutions.Add("PARENT_RIGHT", parentBounds.Width); + substitutions.Add("PARENT_LEFT", parentBounds.Left); + substitutions.Add("PARENT_TOP", parentBounds.Top); + substitutions.Add("PARENT_BOTTOM", parentBounds.Height); + + var width = Evaluator.Evaluate(w.Width, substitutions); + var height = Evaluator.Evaluate(w.Height, substitutions); + + substitutions.Add("WIDTH", width); + substitutions.Add("HEIGHT", height); + + if (insideScrollPanel) + w.Bounds = new Rectangle(w.Bounds.X, w.Bounds.Y, width, w.Bounds.Height); + else + w.Bounds = new Rectangle( + Evaluator.Evaluate(w.X, substitutions), + Evaluator.Evaluate(w.Y, substitutions), + width, + height); + + foreach (var c in w.Children) + RecalculateWidgetLayout(c, insideScrollPanel || w is ScrollPanelWidget); + } + + public static void ShowUIScaleDropdown(DropDownButtonWidget dropdown, GraphicSettings gs) + { + Func setupItem = (o, itemTemplate) => + { + var item = ScrollItemWidget.Setup(itemTemplate, + () => gs.UIScale == o, + () => + { + Game.RunAfterTick(() => + { + var oldScale = gs.UIScale; + gs.UIScale = o; + + Game.Renderer.SetUIScale(o); + RecalculateWidgetLayout(Ui.Root); + Viewport.LastMousePos = (Viewport.LastMousePos.ToFloat2() * oldScale / gs.UIScale).ToInt2(); + }); + }); + + var label = "{0}%".F((int)(100 * o)); + item.Get("LABEL").GetText = () => label; + return item; + }; + + var viewportSizes = Game.ModData.Manifest.Get(); + var maxScales = new float2(Game.Renderer.NativeResolution) / new float2(viewportSizes.MinEffectiveResolution); + var maxScale = Math.Min(maxScales.X, maxScales.Y); + + var validScales = new[] { 1f, 1.25f, 1.5f, 1.75f, 2f }.Where(x => x <= maxScale); + dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, validScales, setupItem); + } + } +} diff --git a/OpenRA.Mods.Common/Widgets/Logic/Settings/HotkeysSettingsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Settings/HotkeysSettingsLogic.cs new file mode 100644 index 0000000000..d484bac24f --- /dev/null +++ b/OpenRA.Mods.Common/Widgets/Logic/Settings/HotkeysSettingsLogic.cs @@ -0,0 +1,244 @@ +#region Copyright & License Information +/* + * Copyright 2007-2021 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using OpenRA.Primitives; +using OpenRA.Widgets; + +namespace OpenRA.Mods.Common.Widgets.Logic +{ + public class HotkeysSettingsLogic : ChromeLogic + { + readonly ModData modData; + readonly Dictionary logicArgs; + + ScrollPanelWidget hotkeyList; + ButtonWidget selectedHotkeyButton; + HotkeyEntryWidget hotkeyEntryWidget; + HotkeyDefinition duplicateHotkeyDefinition, selectedHotkeyDefinition; + int validHotkeyEntryWidth; + int invalidHotkeyEntryWidth; + bool isHotkeyValid; + bool isHotkeyDefault; + + static HotkeysSettingsLogic() { } + + [ObjectCreator.UseCtor] + public HotkeysSettingsLogic(Action>, Func> registerPanel, string panelID, string label, ModData modData, Dictionary logicArgs) + { + this.modData = modData; + this.logicArgs = logicArgs; + + registerPanel(panelID, label, InitPanel, ResetPanel); + } + + void BindHotkeyPref(HotkeyDefinition hd, Widget template) + { + var key = template.Clone() as Widget; + key.Id = hd.Name; + key.IsVisible = () => true; + + key.Get("FUNCTION").GetText = () => hd.Description + ":"; + + var remapButton = key.Get("HOTKEY"); + WidgetUtils.TruncateButtonToTooltip(remapButton, modData.Hotkeys[hd.Name].GetValue().DisplayString()); + + remapButton.IsHighlighted = () => selectedHotkeyDefinition == hd; + + var hotkeyValidColor = ChromeMetrics.Get("HotkeyColor"); + var hotkeyInvalidColor = ChromeMetrics.Get("HotkeyColorInvalid"); + + remapButton.GetColor = () => + { + return hd.HasDuplicates ? hotkeyInvalidColor : hotkeyValidColor; + }; + + if (selectedHotkeyDefinition == hd) + { + selectedHotkeyButton = remapButton; + hotkeyEntryWidget.Key = modData.Hotkeys[hd.Name].GetValue(); + ValidateHotkey(); + } + + remapButton.OnClick = () => + { + selectedHotkeyDefinition = hd; + selectedHotkeyButton = remapButton; + hotkeyEntryWidget.Key = modData.Hotkeys[hd.Name].GetValue(); + ValidateHotkey(); + hotkeyEntryWidget.TakeKeyboardFocus(); + }; + + hotkeyList.AddChild(key); + } + + Func InitPanel(Widget panel) + { + hotkeyList = panel.Get("HOTKEY_LIST"); + hotkeyList.Layout = new GridLayout(hotkeyList); + var hotkeyHeader = hotkeyList.Get("HEADER"); + var templates = hotkeyList.Get("TEMPLATES"); + hotkeyList.RemoveChildren(); + + Func returnTrue = () => true; + Action doNothing = () => { }; + + if (logicArgs.TryGetValue("HotkeyGroups", out var hotkeyGroups)) + { + InitHotkeyRemapDialog(panel); + + foreach (var hg in hotkeyGroups.Nodes) + { + var templateNode = hg.Value.Nodes.FirstOrDefault(n => n.Key == "Template"); + var typesNode = hg.Value.Nodes.FirstOrDefault(n => n.Key == "Types"); + if (templateNode == null || typesNode == null) + continue; + + var header = ScrollItemWidget.Setup(hotkeyHeader, returnTrue, doNothing); + header.Get("LABEL").GetText = () => hg.Key; + hotkeyList.AddChild(header); + + var types = FieldLoader.GetValue("Types", typesNode.Value.Value); + var added = new HashSet(); + var template = templates.Get(templateNode.Value.Value); + + foreach (var t in types) + { + foreach (var hd in modData.Hotkeys.Definitions.Where(k => k.Types.Contains(t))) + { + if (added.Add(hd)) + { + if (selectedHotkeyDefinition == null) + selectedHotkeyDefinition = hd; + + BindHotkeyPref(hd, template); + } + } + } + } + } + + return () => + { + hotkeyEntryWidget.Key = modData.Hotkeys[selectedHotkeyDefinition.Name].GetValue(); + hotkeyEntryWidget.ForceYieldKeyboardFocus(); + + return false; + }; + } + + Action ResetPanel(Widget panel) + { + return () => + { + foreach (var hd in modData.Hotkeys.Definitions) + { + modData.Hotkeys.Set(hd.Name, hd.Default); + WidgetUtils.TruncateButtonToTooltip(panel.Get(hd.Name).Get("HOTKEY"), hd.Default.DisplayString()); + } + }; + } + + void InitHotkeyRemapDialog(Widget panel) + { + var label = new CachedTransform(hd => hd.Description + ":"); + panel.Get("HOTKEY_LABEL").GetText = () => label.Update(selectedHotkeyDefinition); + + var duplicateNotice = panel.Get("DUPLICATE_NOTICE"); + duplicateNotice.TextColor = ChromeMetrics.Get("NoticeErrorColor"); + duplicateNotice.IsVisible = () => !isHotkeyValid; + var duplicateNoticeText = new CachedTransform(hd => hd != null ? duplicateNotice.Text.F(hd.Description) : duplicateNotice.Text); + duplicateNotice.GetText = () => duplicateNoticeText.Update(duplicateHotkeyDefinition); + + var defaultNotice = panel.Get("DEFAULT_NOTICE"); + defaultNotice.TextColor = ChromeMetrics.Get("NoticeInfoColor"); + defaultNotice.IsVisible = () => isHotkeyValid && isHotkeyDefault; + + var originalNotice = panel.Get("ORIGINAL_NOTICE"); + originalNotice.TextColor = ChromeMetrics.Get("NoticeInfoColor"); + originalNotice.IsVisible = () => isHotkeyValid && !isHotkeyDefault; + var originalNoticeText = new CachedTransform(hd => originalNotice.Text.F(hd.Default.DisplayString())); + originalNotice.GetText = () => originalNoticeText.Update(selectedHotkeyDefinition); + + var resetButton = panel.Get("RESET_HOTKEY_BUTTON"); + resetButton.IsDisabled = () => isHotkeyDefault; + resetButton.OnClick = ResetHotkey; + + var clearButton = panel.Get("CLEAR_HOTKEY_BUTTON"); + clearButton.IsDisabled = () => !hotkeyEntryWidget.Key.IsValid(); + clearButton.OnClick = ClearHotkey; + + var overrideButton = panel.Get("OVERRIDE_HOTKEY_BUTTON"); + overrideButton.IsDisabled = () => isHotkeyValid; + overrideButton.IsVisible = () => !isHotkeyValid; + overrideButton.OnClick = OverrideHotkey; + + hotkeyEntryWidget = panel.Get("HOTKEY_ENTRY"); + hotkeyEntryWidget.IsValid = () => isHotkeyValid; + hotkeyEntryWidget.OnLoseFocus = ValidateHotkey; + hotkeyEntryWidget.OnEscKey = () => + { + hotkeyEntryWidget.Key = modData.Hotkeys[selectedHotkeyDefinition.Name].GetValue(); + }; + + validHotkeyEntryWidth = hotkeyEntryWidget.Bounds.Width; + invalidHotkeyEntryWidth = validHotkeyEntryWidth - (clearButton.Bounds.X - overrideButton.Bounds.X); + } + + void ValidateHotkey() + { + duplicateHotkeyDefinition = modData.Hotkeys.GetFirstDuplicate(selectedHotkeyDefinition.Name, hotkeyEntryWidget.Key, selectedHotkeyDefinition); + isHotkeyValid = duplicateHotkeyDefinition == null; + isHotkeyDefault = hotkeyEntryWidget.Key == selectedHotkeyDefinition.Default || (!hotkeyEntryWidget.Key.IsValid() && !selectedHotkeyDefinition.Default.IsValid()); + + if (isHotkeyValid) + { + hotkeyEntryWidget.Bounds.Width = validHotkeyEntryWidth; + SaveHotkey(); + } + else + { + hotkeyEntryWidget.Bounds.Width = invalidHotkeyEntryWidth; + hotkeyEntryWidget.TakeKeyboardFocus(); + } + } + + void SaveHotkey() + { + WidgetUtils.TruncateButtonToTooltip(selectedHotkeyButton, hotkeyEntryWidget.Key.DisplayString()); + modData.Hotkeys.Set(selectedHotkeyDefinition.Name, hotkeyEntryWidget.Key); + Game.Settings.Save(); + } + + void ResetHotkey() + { + hotkeyEntryWidget.Key = selectedHotkeyDefinition.Default; + hotkeyEntryWidget.YieldKeyboardFocus(); + } + + void ClearHotkey() + { + hotkeyEntryWidget.Key = Hotkey.Invalid; + hotkeyEntryWidget.YieldKeyboardFocus(); + } + + void OverrideHotkey() + { + var duplicateHotkeyButton = hotkeyList.Get(duplicateHotkeyDefinition.Name).Get("HOTKEY"); + WidgetUtils.TruncateButtonToTooltip(duplicateHotkeyButton, Hotkey.Invalid.DisplayString()); + modData.Hotkeys.Set(duplicateHotkeyDefinition.Name, Hotkey.Invalid); + Game.Settings.Save(); + hotkeyEntryWidget.YieldKeyboardFocus(); + } + } +} diff --git a/OpenRA.Mods.Common/Widgets/Logic/Settings/InputSettingsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Settings/InputSettingsLogic.cs new file mode 100644 index 0000000000..8f224eb6c6 --- /dev/null +++ b/OpenRA.Mods.Common/Widgets/Logic/Settings/InputSettingsLogic.cs @@ -0,0 +1,194 @@ +#region Copyright & License Information +/* + * Copyright 2007-2021 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using OpenRA.Widgets; + +namespace OpenRA.Mods.Common.Widgets.Logic +{ + public class InputSettingsLogic : ChromeLogic + { + static InputSettingsLogic() { } + + [ObjectCreator.UseCtor] + public InputSettingsLogic(Action>, Func> registerPanel, string panelID, string label) + { + registerPanel(panelID, label, InitPanel, ResetPanel); + } + + Func 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("MOUSE_CONTROL_DROPDOWN"); + mouseControlDropdown.OnMouseDown = _ => ShowMouseControlDropdown(mouseControlDropdown, gs); + mouseControlDropdown.GetText = () => gs.UseClassicMouseStyle ? "Classic" : "Modern"; + + var mouseScrollDropdown = panel.Get("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("DESC_ZOOM_MODIFIER"); + zoomDescModifier.IsVisible = () => gs.ZoomModifier != Modifiers.None; + + var zoomDescModifierTemplate = zoomDescModifier.Text; + var zoomDescModifierLabel = new CachedTransform( + mod => zoomDescModifierTemplate.Replace("MODIFIER", mod.ToString())); + zoomDescModifier.GetText = () => zoomDescModifierLabel.Update(gs.ZoomModifier); + + var edgescrollDesc = container.Get("DESC_EDGESCROLL"); + edgescrollDesc.IsVisible = () => gs.ViewportEdgeScroll; + } + + // Apply mouse focus preferences immediately + var lockMouseCheckbox = panel.Get("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("ZOOM_MODIFIER"); + zoomModifierDropdown.OnMouseDown = _ => ShowZoomModifierDropdown(zoomModifierDropdown, gs); + zoomModifierDropdown.GetText = () => gs.ZoomModifier.ToString(); + + return () => false; + } + + Action ResetPanel(Widget panel) + { + var gs = Game.Settings.Game; + var dgs = new GameSettings(); + + return () => + { + gs.UseClassicMouseStyle = dgs.UseClassicMouseStyle; + gs.MouseScroll = dgs.MouseScroll; + gs.UseAlternateScrollButton = dgs.UseAlternateScrollButton; + gs.LockMouseWindow = dgs.LockMouseWindow; + gs.ViewportEdgeScroll = dgs.ViewportEdgeScroll; + gs.ViewportEdgeScrollStep = dgs.ViewportEdgeScrollStep; + gs.ZoomSpeed = dgs.ZoomSpeed; + gs.UIScrollSpeed = dgs.UIScrollSpeed; + gs.ZoomModifier = dgs.ZoomModifier; + + panel.Get("SCROLLSPEED_SLIDER").Value = gs.ViewportEdgeScrollStep; + panel.Get("UI_SCROLLSPEED_SLIDER").Value = gs.UIScrollSpeed; + + MakeMouseFocusSettingsLive(); + }; + } + + public static void ShowMouseControlDropdown(DropDownButtonWidget dropdown, GameSettings s) + { + var options = new Dictionary() + { + { "Classic", true }, + { "Modern", false }, + }; + + Func setupItem = (o, itemTemplate) => + { + var item = ScrollItemWidget.Setup(itemTemplate, + () => s.UseClassicMouseStyle == options[o], + () => s.UseClassicMouseStyle = options[o]); + item.Get("LABEL").GetText = () => o; + return item; + }; + + dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); + } + + static void ShowMouseScrollDropdown(DropDownButtonWidget dropdown, GameSettings s) + { + var options = new Dictionary() + { + { "Disabled", MouseScrollType.Disabled }, + { "Standard", MouseScrollType.Standard }, + { "Inverted", MouseScrollType.Inverted }, + { "Joystick", MouseScrollType.Joystick }, + }; + + Func setupItem = (o, itemTemplate) => + { + var item = ScrollItemWidget.Setup(itemTemplate, + () => s.MouseScroll == options[o], + () => s.MouseScroll = options[o]); + item.Get("LABEL").GetText = () => o; + return item; + }; + + dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); + } + + static void ShowZoomModifierDropdown(DropDownButtonWidget dropdown, GameSettings s) + { + var options = new Dictionary() + { + { "Alt", Modifiers.Alt }, + { "Ctrl", Modifiers.Ctrl }, + { "Meta", Modifiers.Meta }, + { "Shift", Modifiers.Shift }, + { "None", Modifiers.None } + }; + + Func setupItem = (o, itemTemplate) => + { + var item = ScrollItemWidget.Setup(itemTemplate, + () => s.ZoomModifier == options[o], + () => s.ZoomModifier = options[o]); + item.Get("LABEL").GetText = () => o; + return item; + }; + + dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); + } + + void MakeMouseFocusSettingsLive() + { + var gameSettings = Game.Settings.Game; + + if (gameSettings.LockMouseWindow) + Game.Renderer.GrabWindowMouseFocus(); + else + Game.Renderer.ReleaseWindowMouseFocus(); + } + } +} diff --git a/OpenRA.Mods.Common/Widgets/Logic/Settings/SettingsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Settings/SettingsLogic.cs new file mode 100644 index 0000000000..2e00cd0f87 --- /dev/null +++ b/OpenRA.Mods.Common/Widgets/Logic/Settings/SettingsLogic.cs @@ -0,0 +1,155 @@ +#region Copyright & License Information +/* + * Copyright 2007-2021 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Linq; +using OpenRA.Graphics; +using OpenRA.Widgets; + +namespace OpenRA.Mods.Common.Widgets.Logic +{ + public class SettingsLogic : ChromeLogic + { + readonly Dictionary> leavePanelActions = new Dictionary>(); + readonly Dictionary resetPanelActions = new Dictionary(); + + readonly Widget panelContainer, tabContainer; + readonly ButtonWidget tabTemplate; + readonly int2 buttonStride; + readonly List buttons = new List(); + readonly Dictionary panels = new Dictionary(); + string activePanel; + + bool needsRestart = false; + + static SettingsLogic() { } + + [ObjectCreator.UseCtor] + public SettingsLogic(Widget widget, Action onExit, WorldRenderer worldRenderer, Dictionary logicArgs) + { + panelContainer = widget.Get("PANEL_CONTAINER"); + var panelTemplate = panelContainer.Get("PANEL_TEMPLATE"); + panelContainer.RemoveChild(panelTemplate); + + tabContainer = widget.Get("TAB_CONTAINER"); + tabTemplate = tabContainer.Get("BUTTON_TEMPLATE"); + tabContainer.RemoveChild(tabTemplate); + + if (logicArgs.TryGetValue("ButtonStride", out var buttonStrideNode)) + buttonStride = FieldLoader.GetValue("ButtonStride", buttonStrideNode.Value); + + if (logicArgs.TryGetValue("Panels", out var settingsPanels)) + { + panels = settingsPanels.ToDictionary(kv => kv.Value); + + foreach (var panel in panels) + { + var container = panelTemplate.Clone() as ContainerWidget; + container.Id = panel.Key; + panelContainer.AddChild(container); + + Game.LoadWidget(worldRenderer.World, panel.Key, container, new WidgetArgs() + { + { "registerPanel", (Action>, Func>)RegisterSettingsPanel }, + { "panelID", panel.Key }, + { "label", panel.Value } + }); + } + } + + widget.Get("BACK_BUTTON").OnClick = () => + { + needsRestart |= leavePanelActions[activePanel](); + var current = Game.Settings; + current.Save(); + + Action closeAndExit = () => { Ui.CloseWindow(); onExit(); }; + if (needsRestart) + { + Action restart = () => + { + var external = Game.ExternalMods[ExternalMod.MakeKey(Game.ModData.Manifest)]; + Game.SwitchToExternalMod(external, null, closeAndExit); + }; + + ConfirmationDialogs.ButtonPrompt( + title: "Restart Now?", + text: "Some changes will not be applied until\nthe game is restarted. Restart now?", + onConfirm: restart, + onCancel: closeAndExit, + confirmText: "Restart Now", + cancelText: "Restart Later"); + } + else + closeAndExit(); + }; + + widget.Get("RESET_BUTTON").OnClick = () => + { + Action reset = () => + { + resetPanelActions[activePanel](); + Game.Settings.Save(); + }; + + ConfirmationDialogs.ButtonPrompt( + title: "Reset \"{0}\"".F(panels[activePanel]), + text: "Are you sure you want to reset\nall settings in this panel?", + onConfirm: reset, + onCancel: () => { }, + confirmText: "Reset", + cancelText: "Cancel"); + }; + } + + public void RegisterSettingsPanel(string panelID, string label, Func> init, Func reset) + { + var panel = panelContainer.Get(panelID); + + if (activePanel == null) + activePanel = panelID; + + panel.IsVisible = () => activePanel == panelID; + + leavePanelActions.Add(panelID, init(panel)); + resetPanelActions.Add(panelID, reset(panel)); + + AddSettingsTab(panelID, label); + } + + ButtonWidget AddSettingsTab(string id, string label) + { + var tab = tabTemplate.Clone() as ButtonWidget; + var lastButton = buttons.LastOrDefault(); + if (lastButton != null) + { + tab.Bounds.X = lastButton.Bounds.X + buttonStride.X; + tab.Bounds.Y = lastButton.Bounds.Y + buttonStride.Y; + } + + tab.Id = id; + tab.GetText = () => label; + tab.IsHighlighted = () => activePanel == id; + tab.OnClick = () => + { + needsRestart |= leavePanelActions[activePanel](); + Game.Settings.Save(); + activePanel = id; + }; + + tabContainer.AddChild(tab); + buttons.Add(tab); + + return tab; + } + } +} diff --git a/OpenRA.Mods.Common/Widgets/Logic/Settings/SettingsUtils.cs b/OpenRA.Mods.Common/Widgets/Logic/Settings/SettingsUtils.cs new file mode 100644 index 0000000000..51b57a6d0a --- /dev/null +++ b/OpenRA.Mods.Common/Widgets/Logic/Settings/SettingsUtils.cs @@ -0,0 +1,52 @@ +#region Copyright & License Information +/* + * Copyright 2007-2021 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System; +using OpenRA.Widgets; + +namespace OpenRA.Mods.Common.Widgets.Logic +{ + public static class SettingsUtils + { + public static void BindCheckboxPref(Widget parent, string id, object group, string pref) + { + var field = group.GetType().GetField(pref); + if (field == null) + throw new InvalidOperationException("{0} does not contain a preference type {1}".F(group.GetType().Name, pref)); + + var cb = parent.Get(id); + cb.IsChecked = () => (bool)field.GetValue(group); + cb.OnClick = () => field.SetValue(group, cb.IsChecked() ^ true); + } + + public static void BindSliderPref(Widget parent, string id, object group, string pref) + { + var field = group.GetType().GetField(pref); + if (field == null) + throw new InvalidOperationException("{0} does not contain a preference type {1}".F(group.GetType().Name, pref)); + + var ss = parent.Get(id); + ss.Value = (float)field.GetValue(group); + ss.OnChange += x => field.SetValue(group, x); + } + + public static void BindIntSliderPref(Widget parent, string id, object group, string pref) + { + var field = group.GetType().GetField(pref); + if (field == null) + throw new InvalidOperationException("{0} does not contain a preference type {1}".F(group.GetType().Name, pref)); + + var ss = parent.Get(id); + ss.Value = (float)(int)field.GetValue(group); + ss.OnChange += x => field.SetValue(group, (int)x); + } + } +} diff --git a/OpenRA.Mods.Common/Widgets/Logic/SettingsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/SettingsLogic.cs deleted file mode 100644 index 2ff1a93e9d..0000000000 --- a/OpenRA.Mods.Common/Widgets/Logic/SettingsLogic.cs +++ /dev/null @@ -1,1105 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. For more - * information, see COPYING. - */ -#endregion - -using System; -using System.Collections.Generic; -using System.Linq; -using OpenRA.Graphics; -using OpenRA.Mods.Common.Traits; -using OpenRA.Primitives; -using OpenRA.Support; -using OpenRA.Widgets; - -namespace OpenRA.Mods.Common.Widgets.Logic -{ - public class SettingsLogic : ChromeLogic - { - enum PanelType { Display, Audio, Input, Hotkeys, Advanced } - - static readonly int OriginalVideoDisplay; - static readonly string OriginalSoundDevice; - static readonly WindowMode OriginalGraphicsMode; - static readonly int2 OriginalGraphicsWindowedSize; - static readonly int2 OriginalGraphicsFullscreenSize; - static readonly GLProfile OriginalGLProfile; - static readonly bool OriginalServerDiscoverNatDevices; - - readonly Dictionary leavePanelActions = new Dictionary(); - readonly Dictionary resetPanelActions = new Dictionary(); - readonly Widget panelContainer, tabContainer; - - readonly ModData modData; - readonly WorldRenderer worldRenderer; - readonly WorldViewportSizes viewportSizes; - readonly Dictionary logicArgs; - - SoundDevice soundDevice; - PanelType settingsPanel = PanelType.Display; - - ScrollPanelWidget hotkeyList; - ButtonWidget selectedHotkeyButton; - HotkeyEntryWidget hotkeyEntryWidget; - HotkeyDefinition duplicateHotkeyDefinition, selectedHotkeyDefinition; - int validHotkeyEntryWidth; - int invalidHotkeyEntryWidth; - bool isHotkeyValid; - bool isHotkeyDefault; - - static SettingsLogic() - { - var original = Game.Settings; - OriginalSoundDevice = original.Sound.Device; - OriginalGraphicsMode = original.Graphics.Mode; - OriginalVideoDisplay = original.Graphics.VideoDisplay; - OriginalGraphicsWindowedSize = original.Graphics.WindowedSize; - OriginalGraphicsFullscreenSize = original.Graphics.FullscreenSize; - OriginalGLProfile = original.Graphics.GLProfile; - OriginalServerDiscoverNatDevices = original.Server.DiscoverNatDevices; - } - - [ObjectCreator.UseCtor] - public SettingsLogic(Widget widget, Action onExit, ModData modData, WorldRenderer worldRenderer, Dictionary logicArgs) - { - this.worldRenderer = worldRenderer; - this.modData = modData; - this.logicArgs = logicArgs; - viewportSizes = modData.Manifest.Get(); - - panelContainer = widget.Get("SETTINGS_PANEL"); - tabContainer = widget.Get("TAB_CONTAINER"); - - var panelNames = new Dictionary() - { - { PanelType.Display, "Display" }, - { PanelType.Audio, "Audio" }, - { PanelType.Input, "Input" }, - { PanelType.Hotkeys, "Hotkeys" }, - { PanelType.Advanced, "Advanced" }, - }; - - RegisterSettingsPanel(PanelType.Display, InitDisplayPanel, ResetDisplayPanel, "DISPLAY_PANEL", "DISPLAY_TAB"); - RegisterSettingsPanel(PanelType.Audio, InitAudioPanel, ResetAudioPanel, "AUDIO_PANEL", "AUDIO_TAB"); - RegisterSettingsPanel(PanelType.Input, InitInputPanel, ResetInputPanel, "INPUT_PANEL", "INPUT_TAB"); - RegisterSettingsPanel(PanelType.Hotkeys, InitHotkeysPanel, ResetHotkeysPanel, "HOTKEYS_PANEL", "HOTKEYS_TAB"); - RegisterSettingsPanel(PanelType.Advanced, InitAdvancedPanel, ResetAdvancedPanel, "ADVANCED_PANEL", "ADVANCED_TAB"); - - panelContainer.Get("BACK_BUTTON").OnClick = () => - { - leavePanelActions[settingsPanel](); - var current = Game.Settings; - current.Save(); - - Action closeAndExit = () => { Ui.CloseWindow(); onExit(); }; - if (current.Sound.Device != OriginalSoundDevice || - current.Graphics.Mode != OriginalGraphicsMode || - current.Graphics.VideoDisplay != OriginalVideoDisplay || - current.Graphics.WindowedSize != OriginalGraphicsWindowedSize || - current.Graphics.FullscreenSize != OriginalGraphicsFullscreenSize || - current.Graphics.GLProfile != OriginalGLProfile || - current.Server.DiscoverNatDevices != OriginalServerDiscoverNatDevices) - { - Action restart = () => - { - var external = Game.ExternalMods[ExternalMod.MakeKey(Game.ModData.Manifest)]; - Game.SwitchToExternalMod(external, null, closeAndExit); - }; - - ConfirmationDialogs.ButtonPrompt( - title: "Restart Now?", - text: "Some changes will not be applied until\nthe game is restarted. Restart now?", - onConfirm: restart, - onCancel: closeAndExit, - confirmText: "Restart Now", - cancelText: "Restart Later"); - } - else - closeAndExit(); - }; - - panelContainer.Get("RESET_BUTTON").OnClick = () => - { - Action reset = () => - { - resetPanelActions[settingsPanel](); - Game.Settings.Save(); - }; - - ConfirmationDialogs.ButtonPrompt( - title: "Reset \"{0}\"".F(panelNames[settingsPanel]), - text: "Are you sure you want to reset\nall settings in this panel?", - onConfirm: reset, - onCancel: () => { }, - confirmText: "Reset", - cancelText: "Cancel"); - }; - } - - public static void BindCheckboxPref(Widget parent, string id, object group, string pref) - { - var field = group.GetType().GetField(pref); - if (field == null) - throw new InvalidOperationException("{0} does not contain a preference type {1}".F(group.GetType().Name, pref)); - - var cb = parent.Get(id); - cb.IsChecked = () => (bool)field.GetValue(group); - cb.OnClick = () => field.SetValue(group, cb.IsChecked() ^ true); - } - - static void BindSliderPref(Widget parent, string id, object group, string pref) - { - var field = group.GetType().GetField(pref); - if (field == null) - throw new InvalidOperationException("{0} does not contain a preference type {1}".F(group.GetType().Name, pref)); - - var ss = parent.Get(id); - ss.Value = (float)field.GetValue(group); - ss.OnChange += x => field.SetValue(group, x); - } - - static void BindIntSliderPref(Widget parent, string id, object group, string pref) - { - var field = group.GetType().GetField(pref); - if (field == null) - throw new InvalidOperationException("{0} does not contain a preference type {1}".F(group.GetType().Name, pref)); - - var ss = parent.Get(id); - ss.Value = (float)(int)field.GetValue(group); - ss.OnChange += x => field.SetValue(group, (int)x); - } - - void BindHotkeyPref(HotkeyDefinition hd, Widget template) - { - var key = template.Clone() as Widget; - key.Id = hd.Name; - key.IsVisible = () => true; - - key.Get("FUNCTION").GetText = () => hd.Description + ":"; - - var remapButton = key.Get("HOTKEY"); - WidgetUtils.TruncateButtonToTooltip(remapButton, modData.Hotkeys[hd.Name].GetValue().DisplayString()); - - remapButton.IsHighlighted = () => selectedHotkeyDefinition == hd; - - var hotkeyValidColor = ChromeMetrics.Get("HotkeyColor"); - var hotkeyInvalidColor = ChromeMetrics.Get("HotkeyColorInvalid"); - - remapButton.GetColor = () => - { - return hd.HasDuplicates ? hotkeyInvalidColor : hotkeyValidColor; - }; - - if (selectedHotkeyDefinition == hd) - { - selectedHotkeyButton = remapButton; - hotkeyEntryWidget.Key = modData.Hotkeys[hd.Name].GetValue(); - ValidateHotkey(); - } - - remapButton.OnClick = () => - { - selectedHotkeyDefinition = hd; - selectedHotkeyButton = remapButton; - hotkeyEntryWidget.Key = modData.Hotkeys[hd.Name].GetValue(); - ValidateHotkey(); - hotkeyEntryWidget.TakeKeyboardFocus(); - }; - - hotkeyList.AddChild(key); - } - - void RegisterSettingsPanel(PanelType type, Func init, Func reset, string panelID, string buttonID) - { - var panel = panelContainer.Get(panelID); - var tab = tabContainer.Get(buttonID); - - panel.IsVisible = () => settingsPanel == type; - tab.IsHighlighted = () => settingsPanel == type; - tab.OnClick = () => { leavePanelActions[settingsPanel](); Game.Settings.Save(); settingsPanel = type; }; - - leavePanelActions.Add(type, init(panel)); - resetPanelActions.Add(type, reset(panel)); - } - - public static readonly Dictionary ViewportSizeNames = new Dictionary() - { - { WorldViewport.Close, "Close" }, - { WorldViewport.Medium, "Medium" }, - { WorldViewport.Far, "Far" }, - { WorldViewport.Native, "Furthest" } - }; - - Action InitDisplayPanel(Widget panel) - { - var ds = Game.Settings.Graphics; - var gs = Game.Settings.Game; - - BindCheckboxPref(panel, "CURSORDOUBLE_CHECKBOX", ds, "CursorDouble"); - BindCheckboxPref(panel, "VSYNC_CHECKBOX", ds, "VSync"); - BindCheckboxPref(panel, "FRAME_LIMIT_CHECKBOX", ds, "CapFramerate"); - BindIntSliderPref(panel, "FRAME_LIMIT_SLIDER", ds, "MaxFramerate"); - BindCheckboxPref(panel, "PLAYER_STANCE_COLORS_CHECKBOX", gs, "UsePlayerStanceColors"); - if (panel.GetOrNull("PAUSE_SHELLMAP_CHECKBOX") != null) - BindCheckboxPref(panel, "PAUSE_SHELLMAP_CHECKBOX", gs, "PauseShellmap"); - - var windowModeDropdown = panel.Get("MODE_DROPDOWN"); - windowModeDropdown.OnMouseDown = _ => ShowWindowModeDropdown(windowModeDropdown, ds); - windowModeDropdown.GetText = () => ds.Mode == WindowMode.Windowed ? - "Windowed" : ds.Mode == WindowMode.Fullscreen ? "Fullscreen (Legacy)" : "Fullscreen"; - - var displaySelectionDropDown = panel.Get("DISPLAY_SELECTION_DROPDOWN"); - displaySelectionDropDown.OnMouseDown = _ => ShowDisplaySelectionDropdown(displaySelectionDropDown, ds); - var displaySelectionLabel = new CachedTransform(i => "Display {0}".F(i + 1)); - displaySelectionDropDown.GetText = () => displaySelectionLabel.Update(ds.VideoDisplay); - displaySelectionDropDown.IsDisabled = () => Game.Renderer.DisplayCount < 2; - - var glProfileLabel = new CachedTransform(p => p.ToString()); - var glProfileDropdown = panel.Get("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("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("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("BATTLEFIELD_CAMERA_DROPDOWN"); - var battlefieldCameraLabel = new CachedTransform(vs => ViewportSizeNames[vs]); - battlefieldCameraDropDown.OnMouseDown = _ => ShowBattlefieldCameraDropdown(battlefieldCameraDropDown, viewportSizes, ds); - battlefieldCameraDropDown.GetText = () => battlefieldCameraLabel.Update(ds.ViewportDistance); - - // Update vsync immediately - var vsyncCheckbox = panel.Get("VSYNC_CHECKBOX"); - var vsyncOnClick = vsyncCheckbox.OnClick; - vsyncCheckbox.OnClick = () => - { - vsyncOnClick(); - Game.Renderer.SetVSyncEnabled(ds.VSync); - }; - - var uiScaleDropdown = panel.Get("UI_SCALE_DROPDOWN"); - var uiScaleLabel = new CachedTransform(s => "{0}%".F((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").IsVisible = () => ds.Mode != WindowMode.Windowed; - panel.Get("WINDOW_RESOLUTION").IsVisible = () => ds.Mode == WindowMode.Windowed; - var windowWidth = panel.Get("WINDOW_WIDTH"); - var origWidthText = windowWidth.Text = ds.WindowedSize.X.ToString(); - - var windowHeight = panel.Get("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("FRAME_LIMIT_CHECKBOX"); - var frameLimitOrigLabel = frameLimitCheckbox.Text; - var frameLimitLabel = new CachedTransform(fps => frameLimitOrigLabel + " ({0} FPS)".F(fps)); - frameLimitCheckbox.GetText = () => frameLimitLabel.Update(ds.MaxFramerate); - - // Player profile - var ps = Game.Settings.Player; - - var escPressed = false; - var nameTextfield = panel.Get("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 colorPreview = panel.Get("COLOR_MANAGER"); - colorPreview.Color = ps.Color; - - var colorDropdown = panel.Get("PLAYERCOLOR"); - colorDropdown.IsDisabled = () => worldRenderer.World.Type != WorldType.Shellmap; - colorDropdown.OnMouseDown = _ => ColorPickerLogic.ShowColorDropDown(colorDropdown, colorPreview, worldRenderer.World); - colorDropdown.Get("COLORBLOCK").GetColor = () => ps.Color; - - return () => - { - Exts.TryParseIntegerInvariant(windowWidth.Text, out var x); - Exts.TryParseIntegerInvariant(windowHeight.Text, out var y); - ds.WindowedSize = new int2(x, y); - nameTextfield.YieldKeyboardFocus(); - }; - } - - Action ResetDisplayPanel(Widget panel) - { - var ds = Game.Settings.Graphics; - var ps = Game.Settings.Player; - var dds = new GraphicSettings(); - var dps = new PlayerSettings(); - return () => - { - ds.CapFramerate = dds.CapFramerate; - ds.MaxFramerate = dds.MaxFramerate; - ds.GLProfile = dds.GLProfile; - ds.Mode = dds.Mode; - ds.VideoDisplay = dds.VideoDisplay; - ds.WindowedSize = dds.WindowedSize; - ds.CursorDouble = dds.CursorDouble; - ds.ViewportDistance = dds.ViewportDistance; - - if (ds.UIScale != dds.UIScale) - { - var oldScale = ds.UIScale; - ds.UIScale = dds.UIScale; - Game.Renderer.SetUIScale(dds.UIScale); - RecalculateWidgetLayout(Ui.Root); - Viewport.LastMousePos = (Viewport.LastMousePos.ToFloat2() * oldScale / ds.UIScale).ToInt2(); - } - - ps.Color = dps.Color; - ps.Name = dps.Name; - }; - } - - Action InitAudioPanel(Widget panel) - { - var musicPlaylist = worldRenderer.World.WorldActor.Trait(); - var ss = Game.Settings.Sound; - - BindCheckboxPref(panel, "CASH_TICKS", ss, "CashTicks"); - BindCheckboxPref(panel, "MUTE_SOUND", ss, "Mute"); - BindCheckboxPref(panel, "MUTE_BACKGROUND_MUSIC", ss, "MuteBackgroundMusic"); - - BindSliderPref(panel, "SOUND_VOLUME", ss, "SoundVolume"); - BindSliderPref(panel, "MUSIC_VOLUME", ss, "MusicVolume"); - BindSliderPref(panel, "VIDEO_VOLUME", ss, "VideoVolume"); - - var muteCheckbox = panel.Get("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("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"); - if (noDeviceLabel != null) - noDeviceLabel.Visible = Game.Sound.DummyEngine; - - var controlsContainer = panel.GetOrNull("AUDIO_CONTROLS"); - if (controlsContainer != null) - controlsContainer.Visible = !Game.Sound.DummyEngine; - - var soundVolumeSlider = panel.Get("SOUND_VOLUME"); - soundVolumeSlider.OnChange += x => Game.Sound.SoundVolume = x; - - var musicVolumeSlider = panel.Get("MUSIC_VOLUME"); - musicVolumeSlider.OnChange += x => Game.Sound.MusicVolume = x; - - var videoVolumeSlider = panel.Get("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("AUDIO_DEVICE"); - audioDeviceDropdown.OnMouseDown = _ => ShowAudioDeviceDropdown(audioDeviceDropdown, devices); - - var deviceFont = Game.Renderer.Fonts[audioDeviceDropdown.Font]; - var deviceLabel = new CachedTransform( - s => WidgetUtils.TruncateText(s.Label, audioDeviceDropdown.UsableWidth, deviceFont)); - audioDeviceDropdown.GetText = () => deviceLabel.Update(soundDevice); - - return () => - { - ss.Device = soundDevice.Device; - }; - } - - Action ResetAudioPanel(Widget panel) - { - var ss = Game.Settings.Sound; - var dss = new SoundSettings(); - return () => - { - ss.SoundVolume = dss.SoundVolume; - ss.MusicVolume = dss.MusicVolume; - ss.VideoVolume = dss.VideoVolume; - ss.CashTicks = dss.CashTicks; - ss.Mute = dss.Mute; - ss.MuteBackgroundMusic = dss.MuteBackgroundMusic; - ss.Device = dss.Device; - - panel.Get("SOUND_VOLUME").Value = ss.SoundVolume; - Game.Sound.SoundVolume = ss.SoundVolume; - panel.Get("MUSIC_VOLUME").Value = ss.MusicVolume; - Game.Sound.MusicVolume = ss.MusicVolume; - panel.Get("VIDEO_VOLUME").Value = ss.VideoVolume; - Game.Sound.VideoVolume = ss.VideoVolume; - Game.Sound.UnmuteAudio(); - soundDevice = Game.Sound.AvailableDevices().First(); - }; - } - - Action InitInputPanel(Widget panel) - { - var gs = Game.Settings.Game; - - BindCheckboxPref(panel, "ALTERNATE_SCROLL_CHECKBOX", gs, "UseAlternateScrollButton"); - BindCheckboxPref(panel, "EDGESCROLL_CHECKBOX", gs, "ViewportEdgeScroll"); - BindCheckboxPref(panel, "LOCKMOUSE_CHECKBOX", gs, "LockMouseWindow"); - BindSliderPref(panel, "ZOOMSPEED_SLIDER", gs, "ZoomSpeed"); - BindSliderPref(panel, "SCROLLSPEED_SLIDER", gs, "ViewportEdgeScrollStep"); - BindSliderPref(panel, "UI_SCROLLSPEED_SLIDER", gs, "UIScrollSpeed"); - - var mouseControlDropdown = panel.Get("MOUSE_CONTROL_DROPDOWN"); - mouseControlDropdown.OnMouseDown = _ => ShowMouseControlDropdown(mouseControlDropdown, gs); - mouseControlDropdown.GetText = () => gs.UseClassicMouseStyle ? "Classic" : "Modern"; - - var mouseScrollDropdown = panel.Get("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("DESC_ZOOM_MODIFIER"); - zoomDescModifier.IsVisible = () => gs.ZoomModifier != Modifiers.None; - - var zoomDescModifierTemplate = zoomDescModifier.Text; - var zoomDescModifierLabel = new CachedTransform( - mod => zoomDescModifierTemplate.Replace("MODIFIER", mod.ToString())); - zoomDescModifier.GetText = () => zoomDescModifierLabel.Update(gs.ZoomModifier); - - var edgescrollDesc = container.Get("DESC_EDGESCROLL"); - edgescrollDesc.IsVisible = () => gs.ViewportEdgeScroll; - } - - // Apply mouse focus preferences immediately - var lockMouseCheckbox = panel.Get("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("ZOOM_MODIFIER"); - zoomModifierDropdown.OnMouseDown = _ => ShowZoomModifierDropdown(zoomModifierDropdown, gs); - zoomModifierDropdown.GetText = () => gs.ZoomModifier.ToString(); - - return () => { }; - } - - Action InitHotkeysPanel(Widget panel) - { - var hotkeyDialogRoot = panel.Get("HOTKEY_DIALOG_ROOT"); - hotkeyList = panel.Get("HOTKEY_LIST"); - hotkeyList.Layout = new GridLayout(hotkeyList); - var hotkeyHeader = hotkeyList.Get("HEADER"); - var templates = hotkeyList.Get("TEMPLATES"); - hotkeyList.RemoveChildren(); - - Func returnTrue = () => true; - Action doNothing = () => { }; - - if (logicArgs.TryGetValue("HotkeyGroups", out var hotkeyGroups)) - { - InitHotkeyRemapDialog(panel); - - foreach (var hg in hotkeyGroups.Nodes) - { - var templateNode = hg.Value.Nodes.FirstOrDefault(n => n.Key == "Template"); - var typesNode = hg.Value.Nodes.FirstOrDefault(n => n.Key == "Types"); - if (templateNode == null || typesNode == null) - continue; - - var header = ScrollItemWidget.Setup(hotkeyHeader, returnTrue, doNothing); - header.Get("LABEL").GetText = () => hg.Key; - hotkeyList.AddChild(header); - - var types = FieldLoader.GetValue("Types", typesNode.Value.Value); - var added = new HashSet(); - var template = templates.Get(templateNode.Value.Value); - - foreach (var t in types) - { - foreach (var hd in modData.Hotkeys.Definitions.Where(k => k.Types.Contains(t))) - { - if (added.Add(hd)) - { - if (selectedHotkeyDefinition == null) - selectedHotkeyDefinition = hd; - - BindHotkeyPref(hd, template); - } - } - } - } - } - - return () => - { - hotkeyEntryWidget.Key = modData.Hotkeys[selectedHotkeyDefinition.Name].GetValue(); - hotkeyEntryWidget.ForceYieldKeyboardFocus(); - }; - } - - Action ResetInputPanel(Widget panel) - { - var gs = Game.Settings.Game; - var dgs = new GameSettings(); - - return () => - { - gs.UseClassicMouseStyle = dgs.UseClassicMouseStyle; - gs.MouseScroll = dgs.MouseScroll; - gs.UseAlternateScrollButton = dgs.UseAlternateScrollButton; - gs.LockMouseWindow = dgs.LockMouseWindow; - gs.ViewportEdgeScroll = dgs.ViewportEdgeScroll; - gs.ViewportEdgeScrollStep = dgs.ViewportEdgeScrollStep; - gs.ZoomSpeed = dgs.ZoomSpeed; - gs.UIScrollSpeed = dgs.UIScrollSpeed; - gs.ZoomModifier = dgs.ZoomModifier; - - panel.Get("SCROLLSPEED_SLIDER").Value = gs.ViewportEdgeScrollStep; - panel.Get("UI_SCROLLSPEED_SLIDER").Value = gs.UIScrollSpeed; - - MakeMouseFocusSettingsLive(); - }; - } - - Action ResetHotkeysPanel(Widget panel) - { - return () => - { - foreach (var hd in modData.Hotkeys.Definitions) - { - modData.Hotkeys.Set(hd.Name, hd.Default); - WidgetUtils.TruncateButtonToTooltip(panel.Get(hd.Name).Get("HOTKEY"), hd.Default.DisplayString()); - } - }; - } - - Action InitAdvancedPanel(Widget panel) - { - var ds = Game.Settings.Debug; - var ss = Game.Settings.Server; - var gs = Game.Settings.Game; - - // Advanced - BindCheckboxPref(panel, "NAT_DISCOVERY", ss, "DiscoverNatDevices"); - BindCheckboxPref(panel, "PERFTEXT_CHECKBOX", ds, "PerfText"); - BindCheckboxPref(panel, "PERFGRAPH_CHECKBOX", ds, "PerfGraph"); - BindCheckboxPref(panel, "FETCH_NEWS_CHECKBOX", gs, "FetchNews"); - BindCheckboxPref(panel, "SENDSYSINFO_CHECKBOX", ds, "SendSystemInformation"); - BindCheckboxPref(panel, "CHECK_VERSION_CHECKBOX", ds, "CheckVersion"); - - var ssi = panel.Get("SENDSYSINFO_CHECKBOX"); - ssi.IsDisabled = () => !gs.FetchNews; - - // Developer - BindCheckboxPref(panel, "BOTDEBUG_CHECKBOX", ds, "BotDebug"); - BindCheckboxPref(panel, "LUADEBUG_CHECKBOX", ds, "LuaDebug"); - BindCheckboxPref(panel, "REPLAY_COMMANDS_CHECKBOX", ds, "EnableDebugCommandsInReplays"); - BindCheckboxPref(panel, "CHECKUNSYNCED_CHECKBOX", ds, "SyncCheckUnsyncedCode"); - BindCheckboxPref(panel, "CHECKBOTSYNC_CHECKBOX", ds, "SyncCheckBotModuleCode"); - - panel.Get("DEBUG_OPTIONS").IsVisible = () => ds.DisplayDeveloperSettings; - panel.Get("DEBUG_HIDDEN_LABEL").IsVisible = () => !ds.DisplayDeveloperSettings; - - return () => { }; - } - - Action ResetAdvancedPanel(Widget panel) - { - var ds = Game.Settings.Debug; - var ss = Game.Settings.Server; - var dds = new DebugSettings(); - var dss = new ServerSettings(); - - return () => - { - ss.DiscoverNatDevices = dss.DiscoverNatDevices; - ds.PerfText = dds.PerfText; - ds.PerfGraph = dds.PerfGraph; - ds.SyncCheckUnsyncedCode = dds.SyncCheckUnsyncedCode; - ds.SyncCheckBotModuleCode = dds.SyncCheckBotModuleCode; - ds.BotDebug = dds.BotDebug; - ds.LuaDebug = dds.LuaDebug; - ds.SendSystemInformation = dds.SendSystemInformation; - ds.CheckVersion = dds.CheckVersion; - ds.EnableDebugCommandsInReplays = dds.EnableDebugCommandsInReplays; - }; - } - - public static void ShowMouseControlDropdown(DropDownButtonWidget dropdown, GameSettings s) - { - var options = new Dictionary() - { - { "Classic", true }, - { "Modern", false }, - }; - - Func setupItem = (o, itemTemplate) => - { - var item = ScrollItemWidget.Setup(itemTemplate, - () => s.UseClassicMouseStyle == options[o], - () => s.UseClassicMouseStyle = options[o]); - item.Get("LABEL").GetText = () => o; - return item; - }; - - dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); - } - - static void ShowMouseScrollDropdown(DropDownButtonWidget dropdown, GameSettings s) - { - var options = new Dictionary() - { - { "Disabled", MouseScrollType.Disabled }, - { "Standard", MouseScrollType.Standard }, - { "Inverted", MouseScrollType.Inverted }, - { "Joystick", MouseScrollType.Joystick }, - }; - - Func setupItem = (o, itemTemplate) => - { - var item = ScrollItemWidget.Setup(itemTemplate, - () => s.MouseScroll == options[o], - () => s.MouseScroll = options[o]); - item.Get("LABEL").GetText = () => o; - return item; - }; - - dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); - } - - static void ShowZoomModifierDropdown(DropDownButtonWidget dropdown, GameSettings s) - { - var options = new Dictionary() - { - { "Alt", Modifiers.Alt }, - { "Ctrl", Modifiers.Ctrl }, - { "Meta", Modifiers.Meta }, - { "Shift", Modifiers.Shift }, - { "None", Modifiers.None } - }; - - Func setupItem = (o, itemTemplate) => - { - var item = ScrollItemWidget.Setup(itemTemplate, - () => s.ZoomModifier == options[o], - () => s.ZoomModifier = options[o]); - item.Get("LABEL").GetText = () => o; - return item; - }; - - dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); - } - - void ShowAudioDeviceDropdown(DropDownButtonWidget dropdown, SoundDevice[] devices) - { - var i = 0; - var options = devices.ToDictionary(d => (i++).ToString(), d => d); - - Func setupItem = (o, itemTemplate) => - { - var item = ScrollItemWidget.Setup(itemTemplate, - () => soundDevice == options[o], - () => soundDevice = options[o]); - - var deviceLabel = item.Get("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); - } - - static void ShowWindowModeDropdown(DropDownButtonWidget dropdown, GraphicSettings s) - { - var options = new Dictionary() - { - { "Fullscreen", WindowMode.PseudoFullscreen }, - { "Fullscreen (Legacy)", WindowMode.Fullscreen }, - { "Windowed", WindowMode.Windowed }, - }; - - Func setupItem = (o, itemTemplate) => - { - var item = ScrollItemWidget.Setup(itemTemplate, - () => s.Mode == options[o], - () => s.Mode = options[o]); - - item.Get("LABEL").GetText = () => o; - return item; - }; - - dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); - } - - static void ShowStatusBarsDropdown(DropDownButtonWidget dropdown, GameSettings s) - { - var options = new Dictionary() - { - { "Standard", StatusBarsType.Standard }, - { "Show On Damage", StatusBarsType.DamageShow }, - { "Always Show", StatusBarsType.AlwaysShow }, - }; - - Func setupItem = (o, itemTemplate) => - { - var item = ScrollItemWidget.Setup(itemTemplate, - () => s.StatusBars == options[o], - () => s.StatusBars = options[o]); - - item.Get("LABEL").GetText = () => o; - return item; - }; - - dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); - } - - static void ShowDisplaySelectionDropdown(DropDownButtonWidget dropdown, GraphicSettings s) - { - Func setupItem = (o, itemTemplate) => - { - var item = ScrollItemWidget.Setup(itemTemplate, - () => s.VideoDisplay == o, - () => s.VideoDisplay = o); - - var label = "Display {0}".F(o + 1); - item.Get("LABEL").GetText = () => label; - return item; - }; - - dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, Enumerable.Range(0, Game.Renderer.DisplayCount), setupItem); - } - - static void ShowGLProfileDropdown(DropDownButtonWidget dropdown, GraphicSettings s) - { - Func setupItem = (o, itemTemplate) => - { - var item = ScrollItemWidget.Setup(itemTemplate, - () => s.GLProfile == o, - () => s.GLProfile = o); - - var label = o.ToString(); - item.Get("LABEL").GetText = () => label; - return item; - }; - - var profiles = new[] { GLProfile.Automatic }.Concat(Game.Renderer.SupportedGLProfiles); - dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, profiles, setupItem); - } - - static void ShowTargetLinesDropdown(DropDownButtonWidget dropdown, GameSettings s) - { - var options = new Dictionary() - { - { "Automatic", TargetLinesType.Automatic }, - { "Manual", TargetLinesType.Manual }, - { "Disabled", TargetLinesType.Disabled }, - }; - - Func setupItem = (o, itemTemplate) => - { - var item = ScrollItemWidget.Setup(itemTemplate, - () => s.TargetLines == options[o], - () => s.TargetLines = options[o]); - - item.Get("LABEL").GetText = () => o; - return item; - }; - - dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); - } - - public static void ShowBattlefieldCameraDropdown(DropDownButtonWidget dropdown, WorldViewportSizes viewportSizes, GraphicSettings gs) - { - Func setupItem = (o, itemTemplate) => - { - var item = ScrollItemWidget.Setup(itemTemplate, - () => gs.ViewportDistance == o, - () => gs.ViewportDistance = o); - - var label = ViewportSizeNames[o]; - item.Get("LABEL").GetText = () => label; - return item; - }; - - var windowHeight = Game.Renderer.NativeResolution.Height; - - var validSizes = new List() { WorldViewport.Close }; - if (viewportSizes.GetSizeRange(WorldViewport.Medium).X < windowHeight) - validSizes.Add(WorldViewport.Medium); - - var farRange = viewportSizes.GetSizeRange(WorldViewport.Far); - if (farRange.X < windowHeight) - validSizes.Add(WorldViewport.Far); - - if (viewportSizes.AllowNativeZoom && farRange.Y < windowHeight) - validSizes.Add(WorldViewport.Native); - - dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, validSizes, setupItem); - } - - static void RecalculateWidgetLayout(Widget w, bool insideScrollPanel = false) - { - // HACK: Recalculate the widget bounds to fit within the new effective window bounds - // This is fragile, and only works when called when Settings is opened via the main menu. - - // HACK: Skip children badges container on the main menu - // This has a fixed size, with calculated size and children positions that break if we adjust them here - if (w.Id == "BADGES_CONTAINER") - return; - - var parentBounds = w.Parent == null - ? new Rectangle(0, 0, Game.Renderer.Resolution.Width, Game.Renderer.Resolution.Height) - : w.Parent.Bounds; - - var substitutions = new Dictionary(); - substitutions.Add("WINDOW_RIGHT", Game.Renderer.Resolution.Width); - substitutions.Add("WINDOW_BOTTOM", Game.Renderer.Resolution.Height); - substitutions.Add("PARENT_RIGHT", parentBounds.Width); - substitutions.Add("PARENT_LEFT", parentBounds.Left); - substitutions.Add("PARENT_TOP", parentBounds.Top); - substitutions.Add("PARENT_BOTTOM", parentBounds.Height); - - var width = Evaluator.Evaluate(w.Width, substitutions); - var height = Evaluator.Evaluate(w.Height, substitutions); - - substitutions.Add("WIDTH", width); - substitutions.Add("HEIGHT", height); - - if (insideScrollPanel) - w.Bounds = new Rectangle(w.Bounds.X, w.Bounds.Y, width, w.Bounds.Height); - else - w.Bounds = new Rectangle(Evaluator.Evaluate(w.X, substitutions), - Evaluator.Evaluate(w.Y, substitutions), - width, - height); - - foreach (var c in w.Children) - RecalculateWidgetLayout(c, insideScrollPanel || w is ScrollPanelWidget); - } - - public static void ShowUIScaleDropdown(DropDownButtonWidget dropdown, GraphicSettings gs) - { - Func setupItem = (o, itemTemplate) => - { - var item = ScrollItemWidget.Setup(itemTemplate, - () => gs.UIScale == o, - () => - { - Game.RunAfterTick(() => - { - var oldScale = gs.UIScale; - gs.UIScale = o; - - Game.Renderer.SetUIScale(o); - RecalculateWidgetLayout(Ui.Root); - Viewport.LastMousePos = (Viewport.LastMousePos.ToFloat2() * oldScale / gs.UIScale).ToInt2(); - }); - }); - - var label = "{0}%".F((int)(100 * o)); - item.Get("LABEL").GetText = () => label; - return item; - }; - - var viewportSizes = Game.ModData.Manifest.Get(); - var maxScales = new float2(Game.Renderer.NativeResolution) / new float2(viewportSizes.MinEffectiveResolution); - var maxScale = Math.Min(maxScales.X, maxScales.Y); - - var validScales = new[] { 1f, 1.25f, 1.5f, 1.75f, 2f }.Where(x => x <= maxScale); - dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, validScales, setupItem); - } - - void MakeMouseFocusSettingsLive() - { - var gameSettings = Game.Settings.Game; - - if (gameSettings.LockMouseWindow) - Game.Renderer.GrabWindowMouseFocus(); - else - Game.Renderer.ReleaseWindowMouseFocus(); - } - - void InitHotkeyRemapDialog(Widget panel) - { - var label = new CachedTransform(hd => hd.Description + ":"); - panel.Get("HOTKEY_LABEL").GetText = () => label.Update(selectedHotkeyDefinition); - - var duplicateNotice = panel.Get("DUPLICATE_NOTICE"); - duplicateNotice.TextColor = ChromeMetrics.Get("NoticeErrorColor"); - duplicateNotice.IsVisible = () => !isHotkeyValid; - var duplicateNoticeText = new CachedTransform(hd => hd != null ? duplicateNotice.Text.F(hd.Description) : duplicateNotice.Text); - duplicateNotice.GetText = () => duplicateNoticeText.Update(duplicateHotkeyDefinition); - - var defaultNotice = panel.Get("DEFAULT_NOTICE"); - defaultNotice.TextColor = ChromeMetrics.Get("NoticeInfoColor"); - defaultNotice.IsVisible = () => isHotkeyValid && isHotkeyDefault; - - var originalNotice = panel.Get("ORIGINAL_NOTICE"); - originalNotice.TextColor = ChromeMetrics.Get("NoticeInfoColor"); - originalNotice.IsVisible = () => isHotkeyValid && !isHotkeyDefault; - var originalNoticeText = new CachedTransform(hd => originalNotice.Text.F(hd.Default.DisplayString())); - originalNotice.GetText = () => originalNoticeText.Update(selectedHotkeyDefinition); - - var resetButton = panel.Get("RESET_HOTKEY_BUTTON"); - resetButton.IsDisabled = () => isHotkeyDefault; - resetButton.OnClick = ResetHotkey; - - var clearButton = panel.Get("CLEAR_HOTKEY_BUTTON"); - clearButton.IsDisabled = () => !hotkeyEntryWidget.Key.IsValid(); - clearButton.OnClick = ClearHotkey; - - var overrideButton = panel.Get("OVERRIDE_HOTKEY_BUTTON"); - overrideButton.IsDisabled = () => isHotkeyValid; - overrideButton.IsVisible = () => !isHotkeyValid; - overrideButton.OnClick = OverrideHotkey; - - hotkeyEntryWidget = panel.Get("HOTKEY_ENTRY"); - hotkeyEntryWidget.IsValid = () => isHotkeyValid; - hotkeyEntryWidget.OnLoseFocus = ValidateHotkey; - hotkeyEntryWidget.OnEscKey = () => - { - hotkeyEntryWidget.Key = modData.Hotkeys[selectedHotkeyDefinition.Name].GetValue(); - }; - - validHotkeyEntryWidth = hotkeyEntryWidget.Bounds.Width; - invalidHotkeyEntryWidth = validHotkeyEntryWidth - (clearButton.Bounds.X - overrideButton.Bounds.X); - } - - void ValidateHotkey() - { - duplicateHotkeyDefinition = modData.Hotkeys.GetFirstDuplicate(selectedHotkeyDefinition.Name, hotkeyEntryWidget.Key, selectedHotkeyDefinition); - isHotkeyValid = duplicateHotkeyDefinition == null; - isHotkeyDefault = hotkeyEntryWidget.Key == selectedHotkeyDefinition.Default || (!hotkeyEntryWidget.Key.IsValid() && !selectedHotkeyDefinition.Default.IsValid()); - - if (isHotkeyValid) - { - hotkeyEntryWidget.Bounds.Width = validHotkeyEntryWidth; - SaveHotkey(); - } - else - { - hotkeyEntryWidget.Bounds.Width = invalidHotkeyEntryWidth; - hotkeyEntryWidget.TakeKeyboardFocus(); - } - } - - void SaveHotkey() - { - WidgetUtils.TruncateButtonToTooltip(selectedHotkeyButton, hotkeyEntryWidget.Key.DisplayString()); - modData.Hotkeys.Set(selectedHotkeyDefinition.Name, hotkeyEntryWidget.Key); - Game.Settings.Save(); - } - - void ResetHotkey() - { - hotkeyEntryWidget.Key = selectedHotkeyDefinition.Default; - hotkeyEntryWidget.YieldKeyboardFocus(); - } - - void ClearHotkey() - { - hotkeyEntryWidget.Key = Hotkey.Invalid; - hotkeyEntryWidget.YieldKeyboardFocus(); - } - - void OverrideHotkey() - { - var duplicateHotkeyButton = hotkeyList.Get(duplicateHotkeyDefinition.Name).Get("HOTKEY"); - WidgetUtils.TruncateButtonToTooltip(duplicateHotkeyButton, Hotkey.Invalid.DisplayString()); - modData.Hotkeys.Set(duplicateHotkeyDefinition.Name, Hotkey.Invalid); - Game.Settings.Save(); - hotkeyEntryWidget.YieldKeyboardFocus(); - } - } -} diff --git a/mods/cnc/chrome/settings-advanced.yaml b/mods/cnc/chrome/settings-advanced.yaml new file mode 100644 index 0000000000..ba13f0a3b3 --- /dev/null +++ b/mods/cnc/chrome/settings-advanced.yaml @@ -0,0 +1,123 @@ +Container@ADVANCED_PANEL: + Logic: AdvancedSettingsLogic + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Children: + Label@ADVANCED_TITLE: + Y: 21 + Width: PARENT_RIGHT + Font: Bold + Text: Advanced + Align: Center + Checkbox@NAT_DISCOVERY: + X: 15 + Y: 43 + Width: 200 + Height: 20 + Font: Regular + Text: Enable Network Discovery (UPnP) + Checkbox@PERFTEXT_CHECKBOX: + X: 15 + Y: 73 + Width: 300 + Height: 20 + Font: Regular + Text: Show Performance Text + Checkbox@PERFGRAPH_CHECKBOX: + X: 15 + Y: 103 + Width: 300 + Height: 20 + Font: Regular + Text: Show Performance Graph + Checkbox@FETCH_NEWS_CHECKBOX: + X: 310 + Y: 43 + Width: 300 + Height: 20 + Font: Regular + Text: Fetch Community News + Checkbox@CHECK_VERSION_CHECKBOX: + X: 310 + Y: 73 + Width: 300 + Height: 20 + Font: Regular + Text: Check for Updates + Checkbox@SENDSYSINFO_CHECKBOX: + X: 310 + Y: 103 + Width: 300 + Height: 20 + Font: Regular + Text: Send System Information + Label@SENDSYSINFO_DESC: + X: 310 + Y: 118 + Width: 255 + Height: 30 + Font: Tiny + WordWrap: True + Text: Your Operating System, OpenGL and .NET runtime versions, and language settings will be sent along with an anonymous ID to help prioritize future development. + Label@DEBUG_TITLE: + Y: 190 + Width: PARENT_RIGHT + Font: Bold + Text: Developer + Align: Center + Container@DEBUG_HIDDEN_LABEL: + Y: 245 + Width: PARENT_RIGHT + Children: + Label@A: + Width: PARENT_RIGHT + Height: 20 + Font: Regular + Text: Additional developer-specific options can be enabled via the + Align: Center + Label@B: + Y: 20 + Width: PARENT_RIGHT + Height: 20 + Font: Regular + Text: Debug.DisplayDeveloperSettings setting or launch flag + Align: Center + Container@DEBUG_OPTIONS: + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Children: + Checkbox@BOTDEBUG_CHECKBOX: + X: 15 + Y: 213 + Width: 300 + Height: 20 + Font: Regular + Text: Show Bot Debug Messages + Checkbox@CHECKUNSYNCED_CHECKBOX: + X: 15 + Y: 243 + Width: 300 + Height: 20 + Font: Regular + Text: Check Sync around Unsynced Code + Checkbox@CHECKBOTSYNC_CHECKBOX: + X: 15 + Y: 273 + Width: 300 + Height: 20 + Font: Regular + Text: Check Sync around BotModule Code + Checkbox@LUADEBUG_CHECKBOX: + X: 310 + Y: 213 + Width: 300 + Height: 20 + Font: Regular + Text: Show Map Debug Messages + Checkbox@REPLAY_COMMANDS_CHECKBOX: + X: 310 + Y: 243 + Width: 300 + Height: 20 + Font: Regular + Text: Enable Debug Commands in Replays diff --git a/mods/cnc/chrome/settings-audio.yaml b/mods/cnc/chrome/settings-audio.yaml new file mode 100644 index 0000000000..694e80e108 --- /dev/null +++ b/mods/cnc/chrome/settings-audio.yaml @@ -0,0 +1,99 @@ +Container@AUDIO_PANEL: + Logic: AudioSettingsLogic + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Children: + Label@AUDIO_TITLE: + Y: 21 + Width: PARENT_RIGHT + Font: Bold + Text: Audio + Align: Center + Label@NO_AUDIO_DEVICE: + Y: 50 + Width: PARENT_RIGHT + Align: Center + Text: Audio controls require an active sound device + Container@AUDIO_CONTROLS: + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Children: + Checkbox@CASH_TICKS: + X: 15 + Y: 43 + Width: 200 + Height: 20 + Font: Regular + Text: Cash Ticks + Checkbox@MUTE_SOUND: + X: 15 + Y: 73 + Width: 200 + Height: 20 + Font: Regular + Text: Mute Sound + Checkbox@MUTE_BACKGROUND_MUSIC: + X: 15 + Y: 103 + Width: 200 + Height: 20 + Font: Regular + Text: Mute Background Music + Label@SOUND_LABEL: + X: PARENT_RIGHT - WIDTH - 270 + Y: 40 + Width: 95 + Height: 25 + Align: Right + Text: Sound Volume: + ExponentialSlider@SOUND_VOLUME: + X: PARENT_RIGHT - WIDTH - 15 + Y: 45 + Width: 250 + Height: 20 + Ticks: 7 + Label@MUSIC_LABEL: + X: PARENT_RIGHT - WIDTH - 270 + Y: 70 + Width: 95 + Height: 25 + Align: Right + Text: Music Volume: + ExponentialSlider@MUSIC_VOLUME: + X: PARENT_RIGHT - WIDTH - 15 + Y: 75 + Width: 250 + Height: 20 + Ticks: 7 + Label@VIDEO_LABEL: + X: PARENT_RIGHT - WIDTH - 270 + Y: 100 + Width: 95 + Height: 25 + Align: Right + Text: Video Volume: + ExponentialSlider@VIDEO_VOLUME: + X: PARENT_RIGHT - WIDTH - 15 + Y: 105 + Width: 250 + Height: 20 + Ticks: 7 + Label@AUDIO_DEVICE_LABEL: + X: 190 - WIDTH - 5 + Y: 240 + Width: 75 + Height: 25 + Align: Right + Text: Audio Device: + DropDownButton@AUDIO_DEVICE: + X: 190 + Y: 240 + Width: 300 + Height: 25 + Label@AUDIO_DEVICE_DESC: + Y: 261 + Width: PARENT_RIGHT + Height: 25 + Font: Tiny + Align: Center + Text: Device changes will be applied after the game is restarted diff --git a/mods/cnc/chrome/settings-display.yaml b/mods/cnc/chrome/settings-display.yaml new file mode 100644 index 0000000000..6adc9e5db3 --- /dev/null +++ b/mods/cnc/chrome/settings-display.yaml @@ -0,0 +1,217 @@ +Container@DISPLAY_PANEL: + Logic: DisplaySettingsLogic + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Children: + Label@VIDEO_TITLE: + Y: 21 + Width: PARENT_RIGHT + Font: Bold + Text: Display + Align: Center + Label@PLAYER: + Text: Player Name: + X: 15 + Y: 40 + Width: 120 + Height: 25 + Align: Right + TextField@PLAYERNAME: + Text: Name + X: 140 + Y: 40 + Width: 160 + Height: 25 + MaxLength: 16 + Label@COLOR: + X: 265 + Y: 40 + Width: 145 + Height: 25 + Text: Preferred Color: + Align: Right + ColorPreviewManager@COLOR_MANAGER: + DropDownButton@PLAYERCOLOR: + X: 415 + Y: 40 + Width: 75 + Height: 25 + IgnoreChildMouseOver: true + PanelAlign: Right + Children: + ColorBlock@COLORBLOCK: + X: 5 + Y: 6 + Width: PARENT_RIGHT - 35 + Height: PARENT_BOTTOM - 12 + Label@BATTLEFIELD_CAMERA: + X: 15 + Y: 70 + Width: 120 + Height: 25 + Text: Battlefield Camera: + Align: Right + DropDownButton@BATTLEFIELD_CAMERA_DROPDOWN: + X: 140 + Y: 70 + Width: 160 + Height: 25 + Font: Regular + Label@TARGET_LINES: + X: 265 + Y: 70 + Width: 145 + Height: 25 + Text: Target Lines: + Align: Right + DropDownButton@TARGET_LINES_DROPDOWN: + X: 415 + Y: 70 + Width: 160 + Height: 25 + Font: Regular + Label@UI_SCALE: + X: 15 + Y: 100 + Width: 120 + Height: 25 + Text: UI Scale: + Align: Right + DropDownButton@UI_SCALE_DROPDOWN: + X: 140 + Y: 100 + Width: 160 + Height: 25 + Font: Regular + Label@STATUS_BARS: + X: 265 + Y: 100 + Width: 145 + Height: 25 + Text: Status Bars: + Align: Right + DropDownButton@STATUS_BAR_DROPDOWN: + X: 415 + Y: 100 + Width: 160 + Height: 25 + Font: Regular + Checkbox@CURSORDOUBLE_CHECKBOX: + X: 15 + Y: 133 + Width: 200 + Height: 20 + Font: Regular + Text: Increase Cursor Size + Checkbox@PLAYER_STANCE_COLORS_CHECKBOX: + X: 310 + Y: 133 + Width: 200 + Height: 20 + Font: Regular + Text: Player Stance Colors + Label@VIDEO_TITLE: + Y: 190 + Width: PARENT_RIGHT + Font: Bold + Text: Video + Align: Center + Label@VIDEO_MODE: + X: 15 + Y: 210 + Width: 120 + Height: 25 + Align: Right + Text: Video Mode: + DropDownButton@MODE_DROPDOWN: + X: 140 + Y: 210 + Width: 160 + Height: 25 + Font: Regular + Text: Windowed + Container@WINDOW_RESOLUTION: + Y: 240 + Children: + Label@WINDOW_SIZE: + X: 15 + Height: 25 + Width: 120 + Align: Right + Text: Window Size: + TextField@WINDOW_WIDTH: + X: 140 + Width: 55 + Height: 25 + MaxLength: 5 + Type: Integer + Label@X: + Text: x + Font: Bold + X: 195 + Height: 25 + Width: 15 + Align: Center + TextField@WINDOW_HEIGHT: + X: 210 + Width: 55 + Height: 25 + MaxLength: 5 + Type: Integer + Container@DISPLAY_SELECTION: + Y: 240 + Children: + Label@DISPLAY_SELECTION_LABEL: + X: 15 + Height: 25 + Width: 120 + Align: Right + Text: Select Display: + DropDownButton@DISPLAY_SELECTION_DROPDOWN: + X: 140 + Width: 160 + Height: 25 + Font: Regular + Checkbox@VSYNC_CHECKBOX: + X: 310 + Y: 210 + Width: 200 + Height: 20 + Font: Regular + Text: Enable VSync + Checkbox@FRAME_LIMIT_CHECKBOX: + X: 310 + Y: 243 + Width: 200 + Height: 20 + Font: Regular + Text: Enable Frame Limiter + Slider@FRAME_LIMIT_SLIDER: + X: 340 + Y: 265 + Width: 200 + Height: 20 + Ticks: 20 + MinimumValue: 50 + MaximumValue: 240 + Label@GL_PROFILE: + X: 15 + Y: 270 + Width: 120 + Height: 25 + Align: Right + Text: OpenGL Profile: + DropDownButton@GL_PROFILE_DROPDOWN: + X: 140 + Y: 270 + Width: 160 + Height: 25 + Font: Regular + Label@RESTART_REQUIRED_DESC: + X: 300 + Y: PARENT_BOTTOM + 10 + Width: PARENT_RIGHT - 300 + Height: 15 + Font: TinyBold + Text: Display and OpenGL changes require restart + Align: Center diff --git a/mods/cnc/chrome/settings-hotkeys.yaml b/mods/cnc/chrome/settings-hotkeys.yaml new file mode 100644 index 0000000000..c2760e3994 --- /dev/null +++ b/mods/cnc/chrome/settings-hotkeys.yaml @@ -0,0 +1,169 @@ +Container@HOTKEYS_PANEL: + Logic: HotkeysSettingsLogic + HotkeyGroups: + Game Commands: + Template: TWO_COLUMN + Types: OrderGenerator, World, Menu + Viewport Commands: + Template: TWO_COLUMN + Types: Viewport + Observer / Replay Commands: + Template: TWO_COLUMN + Types: Observer, Replay + Unit Commands: + Template: THREE_COLUMN + Types: Unit + Unit Stance Commands: + Template: TWO_COLUMN + Types: Stance + Production Commands: + Template: THREE_COLUMN + Types: Production, ProductionSlot + Support Power Commands: + Template: THREE_COLUMN + Types: SupportPower + Music Commands: + Template: TWO_COLUMN + Types: Music + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Children: + Label@HOTKEY_TITLE: + Y: 21 + Width: PARENT_RIGHT + Font: Bold + Text: Hotkeys + Align: Center + ScrollPanel@HOTKEY_LIST: + X: 15 + Y: 40 + Width: PARENT_RIGHT - 30 + TopBottomSpacing: 4 + ItemSpacing: 4 + Height: 191 + Children: + ScrollItem@HEADER: + Width: 528 + Height: 13 + Visible: false + Children: + Label@LABEL: + Font: TinyBold + Width: PARENT_RIGHT + Height: 13 + Align: Center + Container@TEMPLATES: + Children: + Container@TWO_COLUMN: + Width: 262 + Height: 25 + Visible: false + Children: + Label@FUNCTION: + Y: 0 + Width: PARENT_RIGHT - 85 + Height: 25 + Align: Right + Button@HOTKEY: + X: PARENT_RIGHT - WIDTH + Width: 80 + Height: 25 + Align: Left + TooltipContainer: SETTINGS_TOOLTIP_CONTAINER + Container@THREE_COLUMN: + Width: 173 + Height: 25 + Visible: false + Children: + Label@FUNCTION: + Y: 0 - 1 + Width: PARENT_RIGHT - 84 + Height: 25 + Align: Right + Button@HOTKEY: + X: PARENT_RIGHT - WIDTH + 1 + Width: 80 + Height: 25 + Align: Left + TooltipContainer: SETTINGS_TOOLTIP_CONTAINER + Background@HOTKEY_DIALOG_ROOT: + X: 15 + Y: 230 + Width: PARENT_RIGHT - 30 + Height: 65 + Background: panel-gray + Children: + Label@HOTKEY_LABEL: + X: 15 + Y: 19 + Width: 220 - 15 - 10 + Height: 25 + Font: Bold + Align: Right + HotkeyEntry@HOTKEY_ENTRY: + X: 220 + Y: 20 + Width: 254 + Height: 25 + Container@NOTICES: + X: 220 + Y: 42 + Width: 254 + Height: 25 + Children: + Label@DEFAULT_NOTICE: + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Font: Tiny + Align: Left + Text: This is the default + Label@ORIGINAL_NOTICE: + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Font: Tiny + Align: Left + Text: The default is "{0}" + Label@DUPLICATE_NOTICE: + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Font: Tiny + Align: Left + Text: This is already used for "{0}" + Button@OVERRIDE_HOTKEY_BUTTON: + X: PARENT_RIGHT - 50 - 15 - WIDTH - 20 + Y: 20 + Width: 70 + Height: 25 + Text: Override + Button@CLEAR_HOTKEY_BUTTON: + X: PARENT_RIGHT - 25 - 15 - WIDTH - 10 + Y: 20 + Width: 25 + Height: 25 + TooltipText: Unbind the hotkey + TooltipContainer: SETTINGS_TOOLTIP_CONTAINER + TooltipTemplate: SIMPLE_TOOLTIP + Children: + Image: + ImageCollection: lobby-bits + ImageName: kick + X: 7 + Y: 8 + IgnoreMouseOver: True + Button@RESET_HOTKEY_BUTTON: + X: PARENT_RIGHT - WIDTH - 15 + Y: 20 + Width: 25 + Height: 25 + TooltipText: Reset to default + TooltipContainer: SETTINGS_TOOLTIP_CONTAINER + TooltipTemplate: SIMPLE_TOOLTIP + Children: + Image@IMAGE_RELOAD: + X: 5 + Y: 5 + Width: 16 + Height: 16 + ImageCollection: reload-icon + ImageName: enabled + IgnoreMouseOver: True diff --git a/mods/cnc/chrome/settings-input.yaml b/mods/cnc/chrome/settings-input.yaml new file mode 100644 index 0000000000..cc428950df --- /dev/null +++ b/mods/cnc/chrome/settings-input.yaml @@ -0,0 +1,219 @@ +Container@INPUT_PANEL: + Logic: InputSettingsLogic + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Children: + Label@INPUT_TITLE: + Y: 21 + Width: PARENT_RIGHT + Font: Bold + Text: Input + Align: Center + Label@MOUSE_CONTROL_LABEL: + X: 15 + Y: 40 + Width: 110 + Height: 25 + Font: Regular + Text: Control Scheme: + Align: Right + DropDownButton@MOUSE_CONTROL_DROPDOWN: + X: 130 + Y: 40 + Width: 150 + Height: 25 + Font: Regular + Container@MOUSE_CONTROL_DESC_CLASSIC: + X: 25 + Y: 70 + Width: 300 + Children: + LabelWithHighlight@DESC_SELECTION: + Height: 16 + Font: Small + Text: - Select units using the {Left} mouse button + LabelWithHighlight@DESC_COMMANDS: + Y: 17 + Height: 16 + Font: Small + Text: - Command units using the {Left} mouse button + LabelWithHighlight@DESC_BUILDIGS: + Y: 34 + Height: 16 + Font: Small + Text: - Place structures using the {Left} mouse button + LabelWithHighlight@DESC_SUPPORT: + Y: 51 + Height: 16 + Font: Small + Text: - Target support powers using the {Left} mouse button + LabelWithHighlight@DESC_ZOOM: + Y: 68 + Height: 16 + Font: Small + Text: - Zoom the battlefield using the {Scroll Wheel} + LabelWithHighlight@DESC_ZOOM_MODIFIER: + Y: 68 + Height: 16 + Font: Small + Text: - Zoom the battlefield using {MODIFIER + Scroll Wheel} + LabelWithHighlight@DESC_SCROLL_RIGHT: + Y: 85 + Height: 16 + Font: Small + Text: - Pan the battlefield using the {Right} mouse button + LabelWithHighlight@DESC_SCROLL_MIDDLE: + Y: 85 + Height: 16 + Font: Small + Text: - Pan the battlefield using the {Middle} mouse button + Label@DESC_EDGESCROLL: + X: 9 + Y: 102 + Height: 16 + Font: Small + Text: or by moving the cursor to the edge of the screen + Container@MOUSE_CONTROL_DESC_MODERN: + X: 25 + Y: 70 + Width: 300 + Children: + LabelWithHighlight@DESC_SELECTION: + Height: 16 + Font: Small + Text: - Select units using the {Left} mouse button + LabelWithHighlight@DESC_COMMANDS: + Y: 17 + Height: 16 + Font: Small + Text: - Command units using the {Right} mouse button + LabelWithHighlight@DESC_BUILDIGS: + Y: 34 + Height: 16 + Font: Small + Text: - Place structures using the {Left} mouse button + LabelWithHighlight@DESC_SUPPORT: + Y: 51 + Height: 16 + Font: Small + Text: - Target support powers using the {Left} mouse button + LabelWithHighlight@DESC_ZOOM: + Y: 68 + Height: 16 + Font: Small + Text: - Zoom the battlefield using the {Scroll Wheel} + LabelWithHighlight@DESC_ZOOM_MODIFIER: + Y: 68 + Height: 16 + Font: Small + Text: - Zoom the battlefield using {MODIFIER + Scroll Wheel} + LabelWithHighlight@DESC_SCROLL_RIGHT: + Y: 85 + Height: 16 + Font: Small + Text: - Pan the battlefield using the {Right} mouse button + LabelWithHighlight@DESC_SCROLL_MIDDLE: + Y: 85 + Height: 16 + Font: Small + Text: - Pan the battlefield using the {Middle} mouse button + Label@DESC_EDGESCROLL: + X: 9 + Y: 102 + Height: 16 + Font: Small + Text: or by moving the cursor to the edge of the screen + Label@MOUSE_SCROLL_TYPE_LABEL: + X: 15 + Y: 210 + Width: 110 + Height: 25 + Font: Regular + Text: Pan Behaviour: + Align: Right + DropDownButton@MOUSE_SCROLL_TYPE_DROPDOWN: + X: 130 + Y: 210 + Width: 150 + Height: 25 + Font: Regular + Checkbox@LOCKMOUSE_CHECKBOX: + X: 15 + Y: 243 + Width: 190 + Height: 20 + Font: Regular + Text: Lock Mouse to Window + Label@ZOOM_MODIFIER_LABEL: + X: 350 + Y: 70 + Width: 70 + Height: 25 + Font: Regular + Text: Zoom Modifier: + Align: Right + DropDownButton@ZOOM_MODIFIER: + X: 425 + Y: 70 + Width: 150 + Height: 25 + Font: Regular + Checkbox@EDGESCROLL_CHECKBOX: + X: 360 + Y: 103 + Width: 180 + Height: 20 + Font: Regular + Text: Screen Edge Panning + Checkbox@ALTERNATE_SCROLL_CHECKBOX: + X: 360 + Y: 133 + Width: 180 + Height: 20 + Font: Regular + Text: Alternate Mouse Panning + Label@SCROLL_SPEED_LABEL: + X: 310 + Y: 210 + Width: 100 + Height: 25 + Text: Pan Speed: + Align: Right + Slider@SCROLLSPEED_SLIDER: + X: 415 + Y: 215 + Width: 160 + Height: 20 + Ticks: 5 + MinimumValue: 10 + MaximumValue: 50 + Label@ZOOM_SPEED_LABEL: + X: 310 + Y: 240 + Width: 100 + Height: 25 + Text: Zoom Speed: + Align: Right + ExponentialSlider@ZOOMSPEED_SLIDER: + X: 415 + Y: 245 + Width: 160 + Height: 20 + Ticks: 5 + MinimumValue: 0.01 + MaximumValue: 0.4 + Label@UI_SCROLL_SPEED_LABEL: + X: 310 + Y: 270 + Width: 100 + Height: 25 + Text: UI Scroll Speed: + Align: Right + Slider@UI_SCROLLSPEED_SLIDER: + X: 415 + Y: 275 + Width: 160 + Height: 20 + Ticks: 5 + MinimumValue: 1 + MaximumValue: 100 diff --git a/mods/cnc/chrome/settings.yaml b/mods/cnc/chrome/settings.yaml index d2bfa4fd87..e235f00233 100644 --- a/mods/cnc/chrome/settings.yaml +++ b/mods/cnc/chrome/settings.yaml @@ -1,30 +1,12 @@ Container@SETTINGS_PANEL: Logic: SettingsLogic - HotkeyGroups: - Game Commands: - Template: TWO_COLUMN - Types: OrderGenerator, World, Menu - Viewport Commands: - Template: TWO_COLUMN - Types: Viewport - Observer / Replay Commands: - Template: TWO_COLUMN - Types: Observer, Replay - Unit Commands: - Template: THREE_COLUMN - Types: Unit - Unit Stance Commands: - Template: TWO_COLUMN - Types: Stance - Production Commands: - Template: THREE_COLUMN - Types: Production, ProductionSlot - Support Power Commands: - Template: THREE_COLUMN - Types: SupportPower - Music Commands: - Template: TWO_COLUMN - Types: Music + ButtonStride: 120, 0 + Panels: + DISPLAY_PANEL: Display + AUDIO_PANEL: Audio + INPUT_PANEL: Input + HOTKEYS_PANEL: Hotkeys + ADVANCED_PANEL: Advanced X: (WINDOW_RIGHT - WIDTH) / 2 Y: (WINDOW_BOTTOM - HEIGHT) / 2 Width: 590 @@ -39,833 +21,18 @@ Container@SETTINGS_PANEL: Text: Settings Container@TAB_CONTAINER: Children: - Button@DISPLAY_TAB: + Button@BUTTON_TEMPLATE: Width: 110 Height: 35 - Text: Display - Button@AUDIO_TAB: - X: WIDTH + 10 - Width: 110 - Height: 35 - Text: Audio - Button@INPUT_TAB: - X: 2 * (WIDTH + 10) - Width: 110 - Height: 35 - Text: Input - Button@HOTKEYS_TAB: - X: 3 * (WIDTH + 10) - Width: 110 - Height: 35 - Text: Hotkeys - Button@ADVANCED_TAB: - X: 4 * (WIDTH + 10) - Width: 110 - Height: 35 - Text: Advanced - Background@bg: + Background@PANEL_CONTAINER: Y: 34 Width: 590 Height: 310 Background: panel-black Children: - Container@DISPLAY_PANEL: + Container@PANEL_TEMPLATE: Width: PARENT_RIGHT Height: PARENT_BOTTOM - Children: - Label@VIDEO_TITLE: - Y: 21 - Width: PARENT_RIGHT - Font: Bold - Text: Display - Align: Center - Label@PLAYER: - Text: Player Name: - X: 15 - Y: 40 - Width: 120 - Height: 25 - Align: Right - TextField@PLAYERNAME: - Text: Name - X: 140 - Y: 40 - Width: 160 - Height: 25 - MaxLength: 16 - Label@COLOR: - X: 265 - Y: 40 - Width: 145 - Height: 25 - Text: Preferred Color: - Align: Right - ColorPreviewManager@COLOR_MANAGER: - DropDownButton@PLAYERCOLOR: - X: 415 - Y: 40 - Width: 75 - Height: 25 - IgnoreChildMouseOver: true - PanelAlign: Right - Children: - ColorBlock@COLORBLOCK: - X: 5 - Y: 6 - Width: PARENT_RIGHT - 35 - Height: PARENT_BOTTOM - 12 - Label@BATTLEFIELD_CAMERA: - X: 15 - Y: 70 - Width: 120 - Height: 25 - Text: Battlefield Camera: - Align: Right - DropDownButton@BATTLEFIELD_CAMERA_DROPDOWN: - X: 140 - Y: 70 - Width: 160 - Height: 25 - Font: Regular - Label@TARGET_LINES: - X: 265 - Y: 70 - Width: 145 - Height: 25 - Text: Target Lines: - Align: Right - DropDownButton@TARGET_LINES_DROPDOWN: - X: 415 - Y: 70 - Width: 160 - Height: 25 - Font: Regular - Label@UI_SCALE: - X: 15 - Y: 100 - Width: 120 - Height: 25 - Text: UI Scale: - Align: Right - DropDownButton@UI_SCALE_DROPDOWN: - X: 140 - Y: 100 - Width: 160 - Height: 25 - Font: Regular - Label@STATUS_BARS: - X: 265 - Y: 100 - Width: 145 - Height: 25 - Text: Status Bars: - Align: Right - DropDownButton@STATUS_BAR_DROPDOWN: - X: 415 - Y: 100 - Width: 160 - Height: 25 - Font: Regular - Checkbox@CURSORDOUBLE_CHECKBOX: - X: 15 - Y: 133 - Width: 200 - Height: 20 - Font: Regular - Text: Increase Cursor Size - Checkbox@PLAYER_STANCE_COLORS_CHECKBOX: - X: 310 - Y: 133 - Width: 200 - Height: 20 - Font: Regular - Text: Player Stance Colors - Label@VIDEO_TITLE: - Y: 190 - Width: PARENT_RIGHT - Font: Bold - Text: Video - Align: Center - Label@VIDEO_MODE: - X: 15 - Y: 210 - Width: 120 - Height: 25 - Align: Right - Text: Video Mode: - DropDownButton@MODE_DROPDOWN: - X: 140 - Y: 210 - Width: 160 - Height: 25 - Font: Regular - Text: Windowed - Container@WINDOW_RESOLUTION: - Y: 240 - Children: - Label@WINDOW_SIZE: - X: 15 - Height: 25 - Width: 120 - Align: Right - Text: Window Size: - TextField@WINDOW_WIDTH: - X: 140 - Width: 55 - Height: 25 - MaxLength: 5 - Type: Integer - Label@X: - Text: x - Font: Bold - X: 195 - Height: 25 - Width: 15 - Align: Center - TextField@WINDOW_HEIGHT: - X: 210 - Width: 55 - Height: 25 - MaxLength: 5 - Type: Integer - Container@DISPLAY_SELECTION: - Y: 240 - Children: - Label@DISPLAY_SELECTION_LABEL: - X: 15 - Height: 25 - Width: 120 - Align: Right - Text: Select Display: - DropDownButton@DISPLAY_SELECTION_DROPDOWN: - X: 140 - Width: 160 - Height: 25 - Font: Regular - Checkbox@VSYNC_CHECKBOX: - X: 310 - Y: 210 - Width: 200 - Height: 20 - Font: Regular - Text: Enable VSync - Checkbox@FRAME_LIMIT_CHECKBOX: - X: 310 - Y: 243 - Width: 200 - Height: 20 - Font: Regular - Text: Enable Frame Limiter - Slider@FRAME_LIMIT_SLIDER: - X: 340 - Y: 265 - Width: 200 - Height: 20 - Ticks: 20 - MinimumValue: 50 - MaximumValue: 240 - Label@GL_PROFILE: - X: 15 - Y: 270 - Width: 120 - Height: 25 - Align: Right - Text: OpenGL Profile: - DropDownButton@GL_PROFILE_DROPDOWN: - X: 140 - Y: 270 - Width: 160 - Height: 25 - Font: Regular - Label@RESTART_REQUIRED_DESC: - X: 300 - Y: PARENT_BOTTOM + 10 - Width: PARENT_RIGHT - 300 - Height: 15 - Font: TinyBold - Text: Display and OpenGL changes require restart - Align: Center - Container@AUDIO_PANEL: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Children: - Label@AUDIO_TITLE: - Y: 21 - Width: PARENT_RIGHT - Font: Bold - Text: Audio - Align: Center - Label@NO_AUDIO_DEVICE: - Y: 50 - Width: PARENT_RIGHT - Align: Center - Text: Audio controls require an active sound device - Container@AUDIO_CONTROLS: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Children: - Checkbox@CASH_TICKS: - X: 15 - Y: 43 - Width: 200 - Height: 20 - Font: Regular - Text: Cash Ticks - Checkbox@MUTE_SOUND: - X: 15 - Y: 73 - Width: 200 - Height: 20 - Font: Regular - Text: Mute Sound - Checkbox@MUTE_BACKGROUND_MUSIC: - X: 15 - Y: 103 - Width: 200 - Height: 20 - Font: Regular - Text: Mute Background Music - Label@SOUND_LABEL: - X: PARENT_RIGHT - WIDTH - 270 - Y: 40 - Width: 95 - Height: 25 - Align: Right - Text: Sound Volume: - ExponentialSlider@SOUND_VOLUME: - X: PARENT_RIGHT - WIDTH - 15 - Y: 45 - Width: 250 - Height: 20 - Ticks: 7 - Label@MUSIC_LABEL: - X: PARENT_RIGHT - WIDTH - 270 - Y: 70 - Width: 95 - Height: 25 - Align: Right - Text: Music Volume: - ExponentialSlider@MUSIC_VOLUME: - X: PARENT_RIGHT - WIDTH - 15 - Y: 75 - Width: 250 - Height: 20 - Ticks: 7 - Label@VIDEO_LABEL: - X: PARENT_RIGHT - WIDTH - 270 - Y: 100 - Width: 95 - Height: 25 - Align: Right - Text: Video Volume: - ExponentialSlider@VIDEO_VOLUME: - X: PARENT_RIGHT - WIDTH - 15 - Y: 105 - Width: 250 - Height: 20 - Ticks: 7 - Label@AUDIO_DEVICE_LABEL: - X: 190 - WIDTH - 5 - Y: 240 - Width: 75 - Height: 25 - Align: Right - Text: Audio Device: - DropDownButton@AUDIO_DEVICE: - X: 190 - Y: 240 - Width: 300 - Height: 25 - Label@AUDIO_DEVICE_DESC: - Y: 261 - Width: PARENT_RIGHT - Height: 25 - Font: Tiny - Align: Center - Text: Device changes will be applied after the game is restarted - Container@INPUT_PANEL: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Children: - Label@INPUT_TITLE: - Y: 21 - Width: PARENT_RIGHT - Font: Bold - Text: Input - Align: Center - Label@MOUSE_CONTROL_LABEL: - X: 15 - Y: 40 - Width: 110 - Height: 25 - Font: Regular - Text: Control Scheme: - Align: Right - DropDownButton@MOUSE_CONTROL_DROPDOWN: - X: 130 - Y: 40 - Width: 150 - Height: 25 - Font: Regular - Container@MOUSE_CONTROL_DESC_CLASSIC: - X: 25 - Y: 70 - Width: 300 - Children: - LabelWithHighlight@DESC_SELECTION: - Height: 16 - Font: Small - Text: - Select units using the {Left} mouse button - LabelWithHighlight@DESC_COMMANDS: - Y: 17 - Height: 16 - Font: Small - Text: - Command units using the {Left} mouse button - LabelWithHighlight@DESC_BUILDIGS: - Y: 34 - Height: 16 - Font: Small - Text: - Place structures using the {Left} mouse button - LabelWithHighlight@DESC_SUPPORT: - Y: 51 - Height: 16 - Font: Small - Text: - Target support powers using the {Left} mouse button - LabelWithHighlight@DESC_ZOOM: - Y: 68 - Height: 16 - Font: Small - Text: - Zoom the battlefield using the {Scroll Wheel} - LabelWithHighlight@DESC_ZOOM_MODIFIER: - Y: 68 - Height: 16 - Font: Small - Text: - Zoom the battlefield using {MODIFIER + Scroll Wheel} - LabelWithHighlight@DESC_SCROLL_RIGHT: - Y: 85 - Height: 16 - Font: Small - Text: - Pan the battlefield using the {Right} mouse button - LabelWithHighlight@DESC_SCROLL_MIDDLE: - Y: 85 - Height: 16 - Font: Small - Text: - Pan the battlefield using the {Middle} mouse button - Label@DESC_EDGESCROLL: - X: 9 - Y: 102 - Height: 16 - Font: Small - Text: or by moving the cursor to the edge of the screen - Container@MOUSE_CONTROL_DESC_MODERN: - X: 25 - Y: 70 - Width: 300 - Children: - LabelWithHighlight@DESC_SELECTION: - Height: 16 - Font: Small - Text: - Select units using the {Left} mouse button - LabelWithHighlight@DESC_COMMANDS: - Y: 17 - Height: 16 - Font: Small - Text: - Command units using the {Right} mouse button - LabelWithHighlight@DESC_BUILDIGS: - Y: 34 - Height: 16 - Font: Small - Text: - Place structures using the {Left} mouse button - LabelWithHighlight@DESC_SUPPORT: - Y: 51 - Height: 16 - Font: Small - Text: - Target support powers using the {Left} mouse button - LabelWithHighlight@DESC_ZOOM: - Y: 68 - Height: 16 - Font: Small - Text: - Zoom the battlefield using the {Scroll Wheel} - LabelWithHighlight@DESC_ZOOM_MODIFIER: - Y: 68 - Height: 16 - Font: Small - Text: - Zoom the battlefield using {MODIFIER + Scroll Wheel} - LabelWithHighlight@DESC_SCROLL_RIGHT: - Y: 85 - Height: 16 - Font: Small - Text: - Pan the battlefield using the {Right} mouse button - LabelWithHighlight@DESC_SCROLL_MIDDLE: - Y: 85 - Height: 16 - Font: Small - Text: - Pan the battlefield using the {Middle} mouse button - Label@DESC_EDGESCROLL: - X: 9 - Y: 102 - Height: 16 - Font: Small - Text: or by moving the cursor to the edge of the screen - Label@MOUSE_SCROLL_TYPE_LABEL: - X: 15 - Y: 210 - Width: 110 - Height: 25 - Font: Regular - Text: Pan Behaviour: - Align: Right - DropDownButton@MOUSE_SCROLL_TYPE_DROPDOWN: - X: 130 - Y: 210 - Width: 150 - Height: 25 - Font: Regular - Checkbox@LOCKMOUSE_CHECKBOX: - X: 15 - Y: 243 - Width: 190 - Height: 20 - Font: Regular - Text: Lock Mouse to Window - Label@ZOOM_MODIFIER_LABEL: - X: 350 - Y: 70 - Width: 70 - Height: 25 - Font: Regular - Text: Zoom Modifier: - Align: Right - DropDownButton@ZOOM_MODIFIER: - X: 425 - Y: 70 - Width: 150 - Height: 25 - Font: Regular - Checkbox@EDGESCROLL_CHECKBOX: - X: 360 - Y: 103 - Width: 180 - Height: 20 - Font: Regular - Text: Screen Edge Panning - Checkbox@ALTERNATE_SCROLL_CHECKBOX: - X: 360 - Y: 133 - Width: 180 - Height: 20 - Font: Regular - Text: Alternate Mouse Panning - Label@SCROLL_SPEED_LABEL: - X: 310 - Y: 210 - Width: 100 - Height: 25 - Text: Pan Speed: - Align: Right - Slider@SCROLLSPEED_SLIDER: - X: 415 - Y: 215 - Width: 160 - Height: 20 - Ticks: 5 - MinimumValue: 10 - MaximumValue: 50 - Label@ZOOM_SPEED_LABEL: - X: 310 - Y: 240 - Width: 100 - Height: 25 - Text: Zoom Speed: - Align: Right - ExponentialSlider@ZOOMSPEED_SLIDER: - X: 415 - Y: 245 - Width: 160 - Height: 20 - Ticks: 5 - MinimumValue: 0.01 - MaximumValue: 0.4 - Label@UI_SCROLL_SPEED_LABEL: - X: 310 - Y: 270 - Width: 100 - Height: 25 - Text: UI Scroll Speed: - Align: Right - Slider@UI_SCROLLSPEED_SLIDER: - X: 415 - Y: 275 - Width: 160 - Height: 20 - Ticks: 5 - MinimumValue: 1 - MaximumValue: 100 - Container@HOTKEYS_PANEL: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Children: - Label@HOTKEY_TITLE: - Y: 21 - Width: PARENT_RIGHT - Font: Bold - Text: Hotkeys - Align: Center - ScrollPanel@HOTKEY_LIST: - X: 15 - Y: 40 - Width: PARENT_RIGHT - 30 - TopBottomSpacing: 4 - ItemSpacing: 4 - Height: 191 - Children: - ScrollItem@HEADER: - Width: 528 - Height: 13 - Visible: false - Children: - Label@LABEL: - Font: TinyBold - Width: PARENT_RIGHT - Height: 13 - Align: Center - Container@TEMPLATES: - Children: - Container@TWO_COLUMN: - Width: 262 - Height: 25 - Visible: false - Children: - Label@FUNCTION: - Y: 0 - Width: PARENT_RIGHT - 85 - Height: 25 - Align: Right - Button@HOTKEY: - X: PARENT_RIGHT - WIDTH - Width: 80 - Height: 25 - Align: Left - TooltipContainer: SETTINGS_TOOLTIP_CONTAINER - Container@THREE_COLUMN: - Width: 173 - Height: 25 - Visible: false - Children: - Label@FUNCTION: - Y: 0 - 1 - Width: PARENT_RIGHT - 84 - Height: 25 - Align: Right - Button@HOTKEY: - X: PARENT_RIGHT - WIDTH + 1 - Width: 80 - Height: 25 - Align: Left - TooltipContainer: SETTINGS_TOOLTIP_CONTAINER - Background@HOTKEY_DIALOG_ROOT: - X: 15 - Y: 230 - Width: PARENT_RIGHT - 30 - Height: 65 - Background: panel-gray - Children: - Label@HOTKEY_LABEL: - X: 15 - Y: 19 - Width: 220 - 15 - 10 - Height: 25 - Font: Bold - Align: Right - HotkeyEntry@HOTKEY_ENTRY: - X: 220 - Y: 20 - Width: 254 - Height: 25 - Container@NOTICES: - X: 220 - Y: 42 - Width: 254 - Height: 25 - Children: - Label@DEFAULT_NOTICE: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Font: Tiny - Align: Left - Text: This is the default - Label@ORIGINAL_NOTICE: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Font: Tiny - Align: Left - Text: The default is "{0}" - Label@DUPLICATE_NOTICE: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Font: Tiny - Align: Left - Text: This is already used for "{0}" - Button@OVERRIDE_HOTKEY_BUTTON: - X: PARENT_RIGHT - 50 - 15 - WIDTH - 20 - Y: 20 - Width: 70 - Height: 25 - Text: Override - Button@CLEAR_HOTKEY_BUTTON: - X: PARENT_RIGHT - 25 - 15 - WIDTH - 10 - Y: 20 - Width: 25 - Height: 25 - TooltipText: Unbind the hotkey - TooltipContainer: SETTINGS_TOOLTIP_CONTAINER - TooltipTemplate: SIMPLE_TOOLTIP - Children: - Image: - ImageCollection: lobby-bits - ImageName: kick - X: 7 - Y: 8 - IgnoreMouseOver: True - Button@RESET_HOTKEY_BUTTON: - X: PARENT_RIGHT - WIDTH - 15 - Y: 20 - Width: 25 - Height: 25 - TooltipText: Reset to default - TooltipContainer: SETTINGS_TOOLTIP_CONTAINER - TooltipTemplate: SIMPLE_TOOLTIP - Children: - Image@IMAGE_RELOAD: - X: 5 - Y: 5 - Width: 16 - Height: 16 - ImageCollection: reload-icon - ImageName: enabled - IgnoreMouseOver: True - Container@ADVANCED_PANEL: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Children: - Label@ADVANCED_TITLE: - Y: 21 - Width: PARENT_RIGHT - Font: Bold - Text: Advanced - Align: Center - Checkbox@NAT_DISCOVERY: - X: 15 - Y: 43 - Width: 200 - Height: 20 - Font: Regular - Text: Enable Network Discovery (UPnP) - Checkbox@PERFTEXT_CHECKBOX: - X: 15 - Y: 73 - Width: 300 - Height: 20 - Font: Regular - Text: Show Performance Text - Checkbox@PERFGRAPH_CHECKBOX: - X: 15 - Y: 103 - Width: 300 - Height: 20 - Font: Regular - Text: Show Performance Graph - Checkbox@FETCH_NEWS_CHECKBOX: - X: 310 - Y: 43 - Width: 300 - Height: 20 - Font: Regular - Text: Fetch Community News - Checkbox@CHECK_VERSION_CHECKBOX: - X: 310 - Y: 73 - Width: 300 - Height: 20 - Font: Regular - Text: Check for Updates - Checkbox@SENDSYSINFO_CHECKBOX: - X: 310 - Y: 103 - Width: 300 - Height: 20 - Font: Regular - Text: Send System Information - Label@SENDSYSINFO_DESC: - X: 310 - Y: 118 - Width: 255 - Height: 30 - Font: Tiny - WordWrap: True - Text: Your Operating System, OpenGL and .NET runtime versions, and language settings will be sent along with an anonymous ID to help prioritize future development. - Label@DEBUG_TITLE: - Y: 190 - Width: PARENT_RIGHT - Font: Bold - Text: Developer - Align: Center - Container@DEBUG_HIDDEN_LABEL: - Y: 245 - Width: PARENT_RIGHT - Children: - Label@A: - Width: PARENT_RIGHT - Height: 20 - Font: Regular - Text: Additional developer-specific options can be enabled via the - Align: Center - Label@B: - Y: 20 - Width: PARENT_RIGHT - Height: 20 - Font: Regular - Text: Debug.DisplayDeveloperSettings setting or launch flag - Align: Center - Container@DEBUG_OPTIONS: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Children: - Checkbox@BOTDEBUG_CHECKBOX: - X: 15 - Y: 213 - Width: 300 - Height: 20 - Font: Regular - Text: Show Bot Debug Messages - Checkbox@CHECKUNSYNCED_CHECKBOX: - X: 15 - Y: 243 - Width: 300 - Height: 20 - Font: Regular - Text: Check Sync around Unsynced Code - Checkbox@CHECKBOTSYNC_CHECKBOX: - X: 15 - Y: 273 - Width: 300 - Height: 20 - Font: Regular - Text: Check Sync around BotModule Code - Checkbox@LUADEBUG_CHECKBOX: - X: 310 - Y: 213 - Width: 300 - Height: 20 - Font: Regular - Text: Show Map Debug Messages - Checkbox@REPLAY_COMMANDS_CHECKBOX: - X: 310 - Y: 243 - Width: 300 - Height: 20 - Font: Regular - Text: Enable Debug Commands in Replays Button@BACK_BUTTON: Key: escape Y: 343 diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index a638de99fb..dfdbda06c6 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -124,6 +124,11 @@ ChromeLayout: cnc|chrome/ingame-debuginfo.yaml cnc|chrome/music.yaml cnc|chrome/settings.yaml + cnc|chrome/settings-display.yaml + cnc|chrome/settings-audio.yaml + cnc|chrome/settings-input.yaml + cnc|chrome/settings-hotkeys.yaml + cnc|chrome/settings-advanced.yaml cnc|chrome/credits.yaml cnc|chrome/dialogs.yaml cnc|chrome/tooltips.yaml diff --git a/mods/common/chrome/settings-advanced.yaml b/mods/common/chrome/settings-advanced.yaml new file mode 100644 index 0000000000..b179ec6dfc --- /dev/null +++ b/mods/common/chrome/settings-advanced.yaml @@ -0,0 +1,117 @@ +Container@ADVANCED_PANEL: + Logic: AdvancedSettingsLogic + Width: PARENT_RIGHT - 10 + Height: PARENT_BOTTOM + Children: + Checkbox@NAT_DISCOVERY: + X: 15 + Y: 43 + Width: 200 + Height: 20 + Font: Regular + Text: Enable Network Discovery (UPnP) + Checkbox@PERFTEXT_CHECKBOX: + X: 15 + Y: 73 + Width: 300 + Height: 20 + Font: Regular + Text: Show Performance Text + Checkbox@PERFGRAPH_CHECKBOX: + X: 15 + Y: 103 + Width: 300 + Height: 20 + Font: Regular + Text: Show Performance Graph + Checkbox@FETCH_NEWS_CHECKBOX: + X: 310 + Y: 43 + Width: 300 + Height: 20 + Font: Regular + Text: Fetch Community News + Checkbox@CHECK_VERSION_CHECKBOX: + X: 310 + Y: 73 + Width: 300 + Height: 20 + Font: Regular + Text: Check for Updates + Checkbox@SENDSYSINFO_CHECKBOX: + X: 310 + Y: 103 + Width: 300 + Height: 20 + Font: Regular + Text: Send System Information + Label@SENDSYSINFO_DESC: + X: 310 + Y: 118 + Width: 255 + Height: 30 + Font: Tiny + WordWrap: True + Text: Your Operating System, OpenGL and .NET runtime versions, and language settings will be sent along with an anonymous ID to help prioritize future development. + Label@DEBUG_TITLE: + Y: 190 + Width: PARENT_RIGHT + Font: Bold + Text: Developer + Align: Center + Container@DEBUG_HIDDEN_LABEL: + Y: 245 + Width: PARENT_RIGHT + Children: + Label@A: + Width: PARENT_RIGHT + Height: 20 + Font: Regular + Text: Additional developer-specific options can be enabled via the + Align: Center + Label@B: + Y: 20 + Width: PARENT_RIGHT + Height: 20 + Font: Regular + Text: Debug.DisplayDeveloperSettings setting or launch flag + Align: Center + Container@DEBUG_OPTIONS: + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Children: + Checkbox@BOTDEBUG_CHECKBOX: + X: 15 + Y: 213 + Width: 300 + Height: 20 + Font: Regular + Text: Show Bot Debug Messages + Checkbox@CHECKUNSYNCED_CHECKBOX: + X: 15 + Y: 243 + Width: 300 + Height: 20 + Font: Regular + Text: Check Sync around Unsynced Code + Checkbox@CHECKBOTSYNC_CHECKBOX: + X: 15 + Y: 273 + Width: 300 + Height: 20 + Font: Regular + Text: Check Sync around BotModule Code + Checkbox@LUADEBUG_CHECKBOX: + X: 310 + Y: 213 + Width: 300 + Height: 20 + Font: Regular + Text: Show Map Debug Messages + Checkbox@REPLAY_COMMANDS_CHECKBOX: + X: 310 + Y: 243 + Width: 300 + Height: 20 + Font: Regular + Text: Enable Debug Commands in Replays diff --git a/mods/common/chrome/settings-audio.yaml b/mods/common/chrome/settings-audio.yaml new file mode 100644 index 0000000000..e2b12c25c3 --- /dev/null +++ b/mods/common/chrome/settings-audio.yaml @@ -0,0 +1,93 @@ +Container@AUDIO_PANEL: + Logic: AudioSettingsLogic + Width: PARENT_RIGHT - 10 + Height: PARENT_BOTTOM + Children: + Label@NO_AUDIO_DEVICE: + Y: 50 + Width: PARENT_RIGHT + Align: Center + Text: Audio controls require an active sound device + Container@AUDIO_CONTROLS: + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Children: + Checkbox@CASH_TICKS: + X: 15 + Y: 43 + Width: 200 + Height: 20 + Font: Regular + Text: Cash Ticks + Checkbox@MUTE_SOUND: + X: 15 + Y: 73 + Width: 200 + Height: 20 + Font: Regular + Text: Mute Sound + Checkbox@MUTE_BACKGROUND_MUSIC: + X: 15 + Y: 103 + Width: 200 + Height: 20 + Font: Regular + Text: Mute Background Music + Label@SOUND_LABEL: + X: PARENT_RIGHT - WIDTH - 270 + Y: 40 + Width: 95 + Height: 25 + Align: Right + Text: Sound Volume: + ExponentialSlider@SOUND_VOLUME: + X: PARENT_RIGHT - WIDTH - 15 + Y: 45 + Width: 250 + Height: 20 + Ticks: 7 + Label@MUSIC_LABEL: + X: PARENT_RIGHT - WIDTH - 270 + Y: 70 + Width: 95 + Height: 25 + Align: Right + Text: Music Volume: + ExponentialSlider@MUSIC_VOLUME: + X: PARENT_RIGHT - WIDTH - 15 + Y: 75 + Width: 250 + Height: 20 + Ticks: 7 + Label@VIDEO_LABEL: + X: PARENT_RIGHT - WIDTH - 270 + Y: 100 + Width: 95 + Height: 25 + Align: Right + Text: Video Volume: + ExponentialSlider@VIDEO_VOLUME: + X: PARENT_RIGHT - WIDTH - 15 + Y: 105 + Width: 250 + Height: 20 + Ticks: 7 + Label@AUDIO_DEVICE_LABEL: + X: 190 - WIDTH - 5 + Y: 240 + Width: 75 + Height: 25 + Align: Right + Text: Audio Device: + DropDownButton@AUDIO_DEVICE: + X: 190 + Y: 240 + Width: 300 + Height: 25 + Label@AUDIO_DEVICE_DESC: + Y: 261 + Width: PARENT_RIGHT + Height: 25 + Font: Tiny + Align: Center + Text: Device changes will be applied after the game is restarted diff --git a/mods/common/chrome/settings-display.yaml b/mods/common/chrome/settings-display.yaml new file mode 100644 index 0000000000..7a219c735a --- /dev/null +++ b/mods/common/chrome/settings-display.yaml @@ -0,0 +1,218 @@ +Container@DISPLAY_PANEL: + Logic: DisplaySettingsLogic + Width: PARENT_RIGHT - 10 + Height: PARENT_BOTTOM - 50 + Children: + Label@PLAYER: + Text: Player Name: + X: 15 + Y: 40 + Width: 120 + Height: 25 + Align: Right + TextField@PLAYERNAME: + Text: Name + X: 140 + Y: 40 + Width: 160 + Height: 25 + MaxLength: 16 + Label@COLOR: + X: 265 + Y: 40 + Width: 145 + Height: 25 + Text: Preferred Color: + Align: Right + ColorPreviewManager@COLOR_MANAGER: + DropDownButton@PLAYERCOLOR: + X: 415 + Y: 40 + Width: 75 + Height: 25 + IgnoreChildMouseOver: true + PanelAlign: Right + Children: + ColorBlock@COLORBLOCK: + X: 5 + Y: 6 + Width: PARENT_RIGHT - 35 + Height: PARENT_BOTTOM - 12 + Label@BATTLEFIELD_CAMERA: + X: 15 + Y: 70 + Width: 120 + Height: 25 + Text: Battlefield Camera: + Align: Right + DropDownButton@BATTLEFIELD_CAMERA_DROPDOWN: + X: 140 + Y: 70 + Width: 160 + Height: 25 + Font: Regular + Label@TARGET_LINES: + X: 265 + Y: 70 + Width: 145 + Height: 25 + Text: Target Lines: + Align: Right + DropDownButton@TARGET_LINES_DROPDOWN: + X: 415 + Y: 70 + Width: 160 + Height: 25 + Font: Regular + Label@UI_SCALE: + X: 15 + Y: 100 + Width: 120 + Height: 25 + Text: UI Scale: + Align: Right + DropDownButton@UI_SCALE_DROPDOWN: + X: 140 + Y: 100 + Width: 160 + Height: 25 + Font: Regular + Label@STATUS_BARS: + X: 265 + Y: 100 + Width: 145 + Height: 25 + Text: Status Bars: + Align: Right + DropDownButton@STATUS_BAR_DROPDOWN: + X: 415 + Y: 100 + Width: 160 + Height: 25 + Font: Regular + Checkbox@CURSORDOUBLE_CHECKBOX: + X: 15 + Y: 133 + Width: 200 + Height: 20 + Font: Regular + Text: Increase Cursor Size + Checkbox@PLAYER_STANCE_COLORS_CHECKBOX: + X: 195 + Y: 133 + Width: 200 + Height: 20 + Font: Regular + Text: Player Stance Colors + Checkbox@PAUSE_SHELLMAP_CHECKBOX: + X: 375 + Y: 133 + Width: 200 + Height: 20 + Font: Regular + Text: Pause Menu Background + Label@VIDEO_TITLE: + Y: 190 + Width: PARENT_RIGHT + Font: Bold + Text: Video + Align: Center + Label@VIDEO_MODE: + X: 15 + Y: 210 + Width: 120 + Height: 25 + Align: Right + Text: Video Mode: + DropDownButton@MODE_DROPDOWN: + X: 140 + Y: 210 + Width: 160 + Height: 25 + Font: Regular + Text: Windowed + Checkbox@VSYNC_CHECKBOX: + X: 310 + Y: 213 + Width: 200 + Height: 20 + Font: Regular + Text: Enable VSync + Container@WINDOW_RESOLUTION: + Y: 240 + Children: + Label@WINDOW_SIZE: + X: 15 + Height: 25 + Width: 120 + Align: Right + Text: Window Size: + TextField@WINDOW_WIDTH: + X: 140 + Width: 55 + Height: 25 + MaxLength: 5 + Type: Integer + Label@X: + Text: x + Font: Bold + X: 195 + Height: 25 + Width: 15 + Align: Center + TextField@WINDOW_HEIGHT: + X: 210 + Width: 55 + Height: 25 + MaxLength: 5 + Type: Integer + Container@DISPLAY_SELECTION: + Y: 240 + Children: + Label@DISPLAY_SELECTION_LABEL: + X: 15 + Height: 25 + Width: 120 + Align: Right + Text: Select Display: + DropDownButton@DISPLAY_SELECTION_DROPDOWN: + X: 140 + Width: 160 + Height: 25 + Font: Regular + Text: Standard + Checkbox@FRAME_LIMIT_CHECKBOX: + X: 310 + Y: 243 + Width: 200 + Height: 20 + Font: Regular + Text: Enable Frame Limiter + Slider@FRAME_LIMIT_SLIDER: + X: 340 + Y: 265 + Width: 200 + Height: 20 + Ticks: 20 + MinimumValue: 50 + MaximumValue: 240 + Label@GL_PROFILE: + X: 15 + Y: 270 + Width: 120 + Height: 25 + Align: Right + Text: OpenGL Profile: + DropDownButton@GL_PROFILE_DROPDOWN: + X: 140 + Y: 270 + Width: 160 + Height: 25 + Font: Regular + Label@RESTART_REQUIRED_DESC: + Y: PARENT_BOTTOM - 40 + Width: PARENT_RIGHT + Height: 15 + Font: Tiny + Text: Display and OpenGL changes require restart + Align: Center diff --git a/mods/common/chrome/settings-hotkeys.yaml b/mods/common/chrome/settings-hotkeys.yaml new file mode 100644 index 0000000000..15c8c49367 --- /dev/null +++ b/mods/common/chrome/settings-hotkeys.yaml @@ -0,0 +1,163 @@ +Container@HOTKEYS_PANEL: + Logic: HotkeysSettingsLogic + HotkeyGroups: + Game Commands: + Template: TWO_COLUMN + Types: OrderGenerator, World, Menu + Viewport Commands: + Template: TWO_COLUMN + Types: Viewport + Observer / Replay Commands: + Template: TWO_COLUMN + Types: Observer, Replay + Unit Commands: + Template: THREE_COLUMN + Types: Unit + Unit Stance Commands: + Template: TWO_COLUMN + Types: Stance + Production Commands: + Template: THREE_COLUMN + Types: Production, ProductionSlot + Support Power Commands: + Template: THREE_COLUMN + Types: SupportPower + Music Commands: + Template: TWO_COLUMN + Types: Music + Width: PARENT_RIGHT - 10 + Height: PARENT_BOTTOM + Children: + ScrollPanel@HOTKEY_LIST: + X: 15 + Y: 40 + Width: PARENT_RIGHT - 30 + TopBottomSpacing: 4 + ItemSpacing: 4 + Height: 190 + Children: + ScrollItem@HEADER: + BaseName: scrollheader + Width: 528 + Height: 13 + Visible: false + Children: + Label@LABEL: + Font: TinyBold + Width: PARENT_RIGHT + Height: 10 + Align: Center + ScrollItem@HEADER: + Width: 528 + Height: 13 + Visible: false + Children: + Label@LABEL: + Font: TinyBold + Width: PARENT_RIGHT + Height: 10 + Align: Center + Container@TEMPLATES: + Children: + Container@TWO_COLUMN: + Width: 262 + Height: 25 + Visible: false + Children: + Label@FUNCTION: + Y: 0 - 1 + Width: PARENT_RIGHT - 85 + Height: 25 + Align: Right + Button@HOTKEY: + X: PARENT_RIGHT - WIDTH + Width: 80 + Height: 25 + Align: Left + TooltipContainer: SETTINGS_TOOLTIP_CONTAINER + Container@THREE_COLUMN: + Width: 173 + Height: 25 + Visible: false + Children: + Label@FUNCTION: + Y: 0 - 1 + Width: PARENT_RIGHT - 84 + Height: 25 + Align: Right + Button@HOTKEY: + X: PARENT_RIGHT - WIDTH + 1 + Width: 80 + Height: 25 + Align: Left + TooltipContainer: SETTINGS_TOOLTIP_CONTAINER + Background@HOTKEY_DIALOG_ROOT: + X: 15 + Y: 230 + Width: PARENT_RIGHT - 30 + Height: 65 + Background: dialog3 + Children: + Label@HOTKEY_LABEL: + X: 15 + Y: 19 + Width: 219 - 15 - 10 + Height: 25 + Font: Bold + Align: Right + HotkeyEntry@HOTKEY_ENTRY: + X: 219 + Y: 20 + Width: 170 + Height: 25 + Container@NOTICES: + X: 219 + Y: 42 + Width: 170 + Height: 25 + Children: + Label@DEFAULT_NOTICE: + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Font: Tiny + Align: Left + Text: This is the default + Label@ORIGINAL_NOTICE: + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Font: Tiny + Align: Left + Text: The default is "{0}" + Label@DUPLICATE_NOTICE: + Width: PARENT_RIGHT + Height: PARENT_BOTTOM + Font: Tiny + Align: Left + Text: This is already used for "{0}" + Button@OVERRIDE_HOTKEY_BUTTON: + X: PARENT_RIGHT - 3 * WIDTH - 30 + Y: 20 + Width: 70 + Height: 25 + Text: Override + Font: Bold + Button@CLEAR_HOTKEY_BUTTON: + X: PARENT_RIGHT - 2 * WIDTH - 30 + Y: 20 + Width: 65 + Height: 25 + Text: Clear + Font: Bold + TooltipText: Unbind the hotkey + TooltipContainer: SETTINGS_TOOLTIP_CONTAINER + TooltipTemplate: SIMPLE_TOOLTIP + Button@RESET_HOTKEY_BUTTON: + X: PARENT_RIGHT - WIDTH - 20 + Y: 20 + Width: 65 + Height: 25 + Text: Reset + Font: Bold + TooltipText: Reset to default + TooltipContainer: SETTINGS_TOOLTIP_CONTAINER + TooltipTemplate: SIMPLE_TOOLTIP diff --git a/mods/common/chrome/settings-input.yaml b/mods/common/chrome/settings-input.yaml new file mode 100644 index 0000000000..c93129f2eb --- /dev/null +++ b/mods/common/chrome/settings-input.yaml @@ -0,0 +1,213 @@ +Container@INPUT_PANEL: + Logic: InputSettingsLogic + Width: PARENT_RIGHT - 10 + Height: PARENT_BOTTOM + Children: + Label@MOUSE_CONTROL_LABEL: + X: 15 + Y: 40 + Width: 110 + Height: 25 + Font: Regular + Text: Control Scheme: + Align: Right + DropDownButton@MOUSE_CONTROL_DROPDOWN: + X: 130 + Y: 40 + Width: 150 + Height: 25 + Font: Regular + Container@MOUSE_CONTROL_DESC_CLASSIC: + X: 25 + Y: 70 + Width: 300 + Children: + LabelWithHighlight@DESC_SELECTION: + Height: 16 + Font: Small + Text: - Select units using the {Left} mouse button + LabelWithHighlight@DESC_COMMANDS: + Y: 17 + Height: 16 + Font: Small + Text: - Command units using the {Left} mouse button + LabelWithHighlight@DESC_BUILDIGS: + Y: 34 + Height: 16 + Font: Small + Text: - Place structures using the {Left} mouse button + LabelWithHighlight@DESC_SUPPORT: + Y: 51 + Height: 16 + Font: Small + Text: - Target support powers using the {Left} mouse button + LabelWithHighlight@DESC_ZOOM: + Y: 68 + Height: 16 + Font: Small + Text: - Zoom the battlefield using the {Scroll Wheel} + LabelWithHighlight@DESC_ZOOM_MODIFIER: + Y: 68 + Height: 16 + Font: Small + Text: - Zoom the battlefield using {MODIFIER + Scroll Wheel} + LabelWithHighlight@DESC_SCROLL_RIGHT: + Y: 85 + Height: 16 + Font: Small + Text: - Pan the battlefield using the {Right} mouse button + LabelWithHighlight@DESC_SCROLL_MIDDLE: + Y: 85 + Height: 16 + Font: Small + Text: - Pan the battlefield using the {Middle} mouse button + Label@DESC_EDGESCROLL: + X: 9 + Y: 102 + Height: 16 + Font: Small + Text: or by moving the cursor to the edge of the screen + Container@MOUSE_CONTROL_DESC_MODERN: + X: 25 + Y: 70 + Width: 300 + Children: + LabelWithHighlight@DESC_SELECTION: + Height: 16 + Font: Small + Text: - Select units using the {Left} mouse button + LabelWithHighlight@DESC_COMMANDS: + Y: 17 + Height: 16 + Font: Small + Text: - Command units using the {Right} mouse button + LabelWithHighlight@DESC_BUILDIGS: + Y: 34 + Height: 16 + Font: Small + Text: - Place structures using the {Left} mouse button + LabelWithHighlight@DESC_SUPPORT: + Y: 51 + Height: 16 + Font: Small + Text: - Target support powers using the {Left} mouse button + LabelWithHighlight@DESC_ZOOM: + Y: 68 + Height: 16 + Font: Small + Text: - Zoom the battlefield using the {Scroll Wheel} + LabelWithHighlight@DESC_ZOOM_MODIFIER: + Y: 68 + Height: 16 + Font: Small + Text: - Zoom the battlefield using {MODIFIER + Scroll Wheel} + LabelWithHighlight@DESC_SCROLL_RIGHT: + Y: 85 + Height: 16 + Font: Small + Text: - Pan the battlefield using the {Right} mouse button + LabelWithHighlight@DESC_SCROLL_MIDDLE: + Y: 85 + Height: 16 + Font: Small + Text: - Pan the battlefield using the {Middle} mouse button + Label@DESC_EDGESCROLL: + X: 9 + Y: 102 + Height: 16 + Font: Small + Text: or by moving the cursor to the edge of the screen + Label@MOUSE_SCROLL_TYPE_LABEL: + X: 15 + Y: 210 + Width: 110 + Height: 25 + Font: Regular + Text: Pan Behaviour: + Align: Right + DropDownButton@MOUSE_SCROLL_TYPE_DROPDOWN: + X: 130 + Y: 210 + Width: 150 + Height: 25 + Font: Regular + Checkbox@LOCKMOUSE_CHECKBOX: + X: 15 + Y: 243 + Width: 190 + Height: 20 + Font: Regular + Text: Lock Mouse to Window + Label@ZOOM_MODIFIER_LABEL: + X: 350 + Y: 70 + Width: 70 + Height: 25 + Font: Regular + Text: Zoom Modifier: + Align: Right + DropDownButton@ZOOM_MODIFIER: + X: 425 + Y: 70 + Width: 150 + Height: 25 + Font: Regular + Checkbox@EDGESCROLL_CHECKBOX: + X: 360 + Y: 103 + Width: 180 + Height: 20 + Font: Regular + Text: Screen Edge Panning + Checkbox@ALTERNATE_SCROLL_CHECKBOX: + X: 360 + Y: 133 + Width: 180 + Height: 20 + Font: Regular + Text: Alternate Mouse Panning + Label@SCROLL_SPEED_LABEL: + X: 305 + Y: 210 + Width: 100 + Height: 25 + Text: Pan Speed: + Align: Right + Slider@SCROLLSPEED_SLIDER: + X: 410 + Y: 215 + Width: 165 + Height: 20 + Ticks: 5 + MinimumValue: 10 + MaximumValue: 50 + Label@ZOOM_SPEED_LABEL: + X: 305 + Y: 240 + Width: 100 + Height: 25 + Text: Zoom Speed: + Align: Right + ExponentialSlider@ZOOMSPEED_SLIDER: + X: 410 + Y: 245 + Width: 165 + Height: 20 + Ticks: 5 + MinimumValue: 0.01 + MaximumValue: 0.4 + Label@UI_SCROLL_SPEED_LABEL: + X: 305 + Y: 270 + Width: 100 + Height: 25 + Text: UI Scroll Speed: + Align: Right + Slider@UI_SCROLLSPEED_SLIDER: + X: 410 + Y: 275 + Width: 165 + Height: 20 + Ticks: 5 + MinimumValue: 1 + MaximumValue: 100 diff --git a/mods/common/chrome/settings.yaml b/mods/common/chrome/settings.yaml index 23ee7c823d..9d3c88ad55 100644 --- a/mods/common/chrome/settings.yaml +++ b/mods/common/chrome/settings.yaml @@ -1,30 +1,12 @@ Background@SETTINGS_PANEL: Logic: SettingsLogic - HotkeyGroups: - Game Commands: - Template: TWO_COLUMN - Types: OrderGenerator, World, Menu - Viewport Commands: - Template: TWO_COLUMN - Types: Viewport - Observer / Replay Commands: - Template: TWO_COLUMN - Types: Observer, Replay - Unit Commands: - Template: THREE_COLUMN - Types: Unit - Unit Stance Commands: - Template: TWO_COLUMN - Types: Stance - Production Commands: - Template: THREE_COLUMN - Types: Production, ProductionSlot - Support Power Commands: - Template: THREE_COLUMN - Types: SupportPower - Music Commands: - Template: TWO_COLUMN - Types: Music + ButtonStride: 90, 0 + Panels: + DISPLAY_PANEL: Display + AUDIO_PANEL: Audio + INPUT_PANEL: Input + HOTKEYS_PANEL: Hotkeys + ADVANCED_PANEL: Advanced X: (WINDOW_RIGHT - WIDTH) / 2 Y: (WINDOW_BOTTOM - HEIGHT) / 2 Width: 600 @@ -53,822 +35,22 @@ Background@SETTINGS_PANEL: Text: Back Font: Bold Container@TAB_CONTAINER: + X: 70 Y: 50 Width: PARENT_RIGHT Height: 25 Children: - Button@DISPLAY_TAB: - X: 70 + Button@BUTTON_TEMPLATE: Width: 90 Height: 25 - Text: Display Font: Bold - Button@AUDIO_TAB: - X: 70 + WIDTH - Width: 90 - Height: 25 - Text: Audio - Font: Bold - Button@INPUT_TAB: - X: 70 + 2 * WIDTH - Width: 90 - Height: 25 - Text: Input - Font: Bold - Button@HOTKEYS_TAB: - X: 70 + 3 * WIDTH - Width: 90 - Height: 25 - Text: Hotkeys - Font: Bold - Button@ADVANCED_TAB: - X: 70 + 4 * WIDTH - Width: 90 - Height: 25 - Text: Advanced - Font: Bold - Container@DISPLAY_PANEL: - X: 5 - Y: 50 - Width: PARENT_RIGHT - 10 - Height: PARENT_BOTTOM - 50 - Children: - Label@PLAYER: - Text: Player Name: - X: 15 - Y: 40 - Width: 120 - Height: 25 - Align: Right - TextField@PLAYERNAME: - Text: Name - X: 140 - Y: 40 - Width: 160 - Height: 25 - MaxLength: 16 - Label@COLOR: - X: 265 - Y: 40 - Width: 145 - Height: 25 - Text: Preferred Color: - Align: Right - ColorPreviewManager@COLOR_MANAGER: - DropDownButton@PLAYERCOLOR: - X: 415 - Y: 40 - Width: 75 - Height: 25 - IgnoreChildMouseOver: true - PanelAlign: Right - Children: - ColorBlock@COLORBLOCK: - X: 5 - Y: 6 - Width: PARENT_RIGHT - 35 - Height: PARENT_BOTTOM - 12 - Label@BATTLEFIELD_CAMERA: - X: 15 - Y: 70 - Width: 120 - Height: 25 - Text: Battlefield Camera: - Align: Right - DropDownButton@BATTLEFIELD_CAMERA_DROPDOWN: - X: 140 - Y: 70 - Width: 160 - Height: 25 - Font: Regular - Label@TARGET_LINES: - X: 265 - Y: 70 - Width: 145 - Height: 25 - Text: Target Lines: - Align: Right - DropDownButton@TARGET_LINES_DROPDOWN: - X: 415 - Y: 70 - Width: 160 - Height: 25 - Font: Regular - Label@UI_SCALE: - X: 15 - Y: 100 - Width: 120 - Height: 25 - Text: UI Scale: - Align: Right - DropDownButton@UI_SCALE_DROPDOWN: - X: 140 - Y: 100 - Width: 160 - Height: 25 - Font: Regular - Label@STATUS_BARS: - X: 265 - Y: 100 - Width: 145 - Height: 25 - Text: Status Bars: - Align: Right - DropDownButton@STATUS_BAR_DROPDOWN: - X: 415 - Y: 100 - Width: 160 - Height: 25 - Font: Regular - Checkbox@CURSORDOUBLE_CHECKBOX: - X: 15 - Y: 133 - Width: 200 - Height: 20 - Font: Regular - Text: Increase Cursor Size - Checkbox@PLAYER_STANCE_COLORS_CHECKBOX: - X: 195 - Y: 133 - Width: 200 - Height: 20 - Font: Regular - Text: Player Stance Colors - Checkbox@PAUSE_SHELLMAP_CHECKBOX: - X: 375 - Y: 133 - Width: 200 - Height: 20 - Font: Regular - Text: Pause Menu Background - Label@VIDEO_TITLE: - Y: 190 - Width: PARENT_RIGHT - Font: Bold - Text: Video - Align: Center - Label@VIDEO_MODE: - X: 15 - Y: 210 - Width: 120 - Height: 25 - Align: Right - Text: Video Mode: - DropDownButton@MODE_DROPDOWN: - X: 140 - Y: 210 - Width: 160 - Height: 25 - Font: Regular - Text: Windowed - Checkbox@VSYNC_CHECKBOX: - X: 310 - Y: 213 - Width: 200 - Height: 20 - Font: Regular - Text: Enable VSync - Container@WINDOW_RESOLUTION: - Y: 240 - Children: - Label@WINDOW_SIZE: - X: 15 - Height: 25 - Width: 120 - Align: Right - Text: Window Size: - TextField@WINDOW_WIDTH: - X: 140 - Width: 55 - Height: 25 - MaxLength: 5 - Type: Integer - Label@X: - Text: x - Font: Bold - X: 195 - Height: 25 - Width: 15 - Align: Center - TextField@WINDOW_HEIGHT: - X: 210 - Width: 55 - Height: 25 - MaxLength: 5 - Type: Integer - Container@DISPLAY_SELECTION: - Y: 240 - Children: - Label@DISPLAY_SELECTION_LABEL: - X: 15 - Height: 25 - Width: 120 - Align: Right - Text: Select Display: - DropDownButton@DISPLAY_SELECTION_DROPDOWN: - X: 140 - Width: 160 - Height: 25 - Font: Regular - Text: Standard - Checkbox@FRAME_LIMIT_CHECKBOX: - X: 310 - Y: 243 - Width: 200 - Height: 20 - Font: Regular - Text: Enable Frame Limiter - Slider@FRAME_LIMIT_SLIDER: - X: 340 - Y: 265 - Width: 200 - Height: 20 - Ticks: 20 - MinimumValue: 50 - MaximumValue: 240 - Label@GL_PROFILE: - X: 15 - Y: 270 - Width: 120 - Height: 25 - Align: Right - Text: OpenGL Profile: - DropDownButton@GL_PROFILE_DROPDOWN: - X: 140 - Y: 270 - Width: 160 - Height: 25 - Font: Regular - Label@RESTART_REQUIRED_DESC: - Y: PARENT_BOTTOM - 40 - Width: PARENT_RIGHT - Height: 15 - Font: Tiny - Text: Display and OpenGL changes require restart - Align: Center - Container@AUDIO_PANEL: - X: 5 - Y: 50 - Width: PARENT_RIGHT - 10 + Container@PANEL_CONTAINER: + Width: PARENT_RIGHT Height: PARENT_BOTTOM Children: - Label@NO_AUDIO_DEVICE: + Container@PANEL_TEMPLATE: + X: 5 Y: 50 - Width: PARENT_RIGHT - Align: Center - Text: Audio controls require an active sound device - Container@AUDIO_CONTROLS: Width: PARENT_RIGHT Height: PARENT_BOTTOM - Children: - Checkbox@CASH_TICKS: - X: 15 - Y: 43 - Width: 200 - Height: 20 - Font: Regular - Text: Cash Ticks - Checkbox@MUTE_SOUND: - X: 15 - Y: 73 - Width: 200 - Height: 20 - Font: Regular - Text: Mute Sound - Checkbox@MUTE_BACKGROUND_MUSIC: - X: 15 - Y: 103 - Width: 200 - Height: 20 - Font: Regular - Text: Mute Background Music - Label@SOUND_LABEL: - X: PARENT_RIGHT - WIDTH - 270 - Y: 40 - Width: 95 - Height: 25 - Align: Right - Text: Sound Volume: - ExponentialSlider@SOUND_VOLUME: - X: PARENT_RIGHT - WIDTH - 15 - Y: 45 - Width: 250 - Height: 20 - Ticks: 7 - Label@MUSIC_LABEL: - X: PARENT_RIGHT - WIDTH - 270 - Y: 70 - Width: 95 - Height: 25 - Align: Right - Text: Music Volume: - ExponentialSlider@MUSIC_VOLUME: - X: PARENT_RIGHT - WIDTH - 15 - Y: 75 - Width: 250 - Height: 20 - Ticks: 7 - Label@VIDEO_LABEL: - X: PARENT_RIGHT - WIDTH - 270 - Y: 100 - Width: 95 - Height: 25 - Align: Right - Text: Video Volume: - ExponentialSlider@VIDEO_VOLUME: - X: PARENT_RIGHT - WIDTH - 15 - Y: 105 - Width: 250 - Height: 20 - Ticks: 7 - Label@AUDIO_DEVICE_LABEL: - X: 190 - WIDTH - 5 - Y: 240 - Width: 75 - Height: 25 - Align: Right - Text: Audio Device: - DropDownButton@AUDIO_DEVICE: - X: 190 - Y: 240 - Width: 300 - Height: 25 - Label@AUDIO_DEVICE_DESC: - Y: 261 - Width: PARENT_RIGHT - Height: 25 - Font: Tiny - Align: Center - Text: Device changes will be applied after the game is restarted - Container@INPUT_PANEL: - X: 5 - Y: 50 - Width: PARENT_RIGHT - 10 - Height: PARENT_BOTTOM - Children: - Label@MOUSE_CONTROL_LABEL: - X: 15 - Y: 40 - Width: 110 - Height: 25 - Font: Regular - Text: Control Scheme: - Align: Right - DropDownButton@MOUSE_CONTROL_DROPDOWN: - X: 130 - Y: 40 - Width: 150 - Height: 25 - Font: Regular - Container@MOUSE_CONTROL_DESC_CLASSIC: - X: 25 - Y: 70 - Width: 300 - Children: - LabelWithHighlight@DESC_SELECTION: - Height: 16 - Font: Small - Text: - Select units using the {Left} mouse button - LabelWithHighlight@DESC_COMMANDS: - Y: 17 - Height: 16 - Font: Small - Text: - Command units using the {Left} mouse button - LabelWithHighlight@DESC_BUILDIGS: - Y: 34 - Height: 16 - Font: Small - Text: - Place structures using the {Left} mouse button - LabelWithHighlight@DESC_SUPPORT: - Y: 51 - Height: 16 - Font: Small - Text: - Target support powers using the {Left} mouse button - LabelWithHighlight@DESC_ZOOM: - Y: 68 - Height: 16 - Font: Small - Text: - Zoom the battlefield using the {Scroll Wheel} - LabelWithHighlight@DESC_ZOOM_MODIFIER: - Y: 68 - Height: 16 - Font: Small - Text: - Zoom the battlefield using {MODIFIER + Scroll Wheel} - LabelWithHighlight@DESC_SCROLL_RIGHT: - Y: 85 - Height: 16 - Font: Small - Text: - Pan the battlefield using the {Right} mouse button - LabelWithHighlight@DESC_SCROLL_MIDDLE: - Y: 85 - Height: 16 - Font: Small - Text: - Pan the battlefield using the {Middle} mouse button - Label@DESC_EDGESCROLL: - X: 9 - Y: 102 - Height: 16 - Font: Small - Text: or by moving the cursor to the edge of the screen - Container@MOUSE_CONTROL_DESC_MODERN: - X: 25 - Y: 70 - Width: 300 - Children: - LabelWithHighlight@DESC_SELECTION: - Height: 16 - Font: Small - Text: - Select units using the {Left} mouse button - LabelWithHighlight@DESC_COMMANDS: - Y: 17 - Height: 16 - Font: Small - Text: - Command units using the {Right} mouse button - LabelWithHighlight@DESC_BUILDIGS: - Y: 34 - Height: 16 - Font: Small - Text: - Place structures using the {Left} mouse button - LabelWithHighlight@DESC_SUPPORT: - Y: 51 - Height: 16 - Font: Small - Text: - Target support powers using the {Left} mouse button - LabelWithHighlight@DESC_ZOOM: - Y: 68 - Height: 16 - Font: Small - Text: - Zoom the battlefield using the {Scroll Wheel} - LabelWithHighlight@DESC_ZOOM_MODIFIER: - Y: 68 - Height: 16 - Font: Small - Text: - Zoom the battlefield using {MODIFIER + Scroll Wheel} - LabelWithHighlight@DESC_SCROLL_RIGHT: - Y: 85 - Height: 16 - Font: Small - Text: - Pan the battlefield using the {Right} mouse button - LabelWithHighlight@DESC_SCROLL_MIDDLE: - Y: 85 - Height: 16 - Font: Small - Text: - Pan the battlefield using the {Middle} mouse button - Label@DESC_EDGESCROLL: - X: 9 - Y: 102 - Height: 16 - Font: Small - Text: or by moving the cursor to the edge of the screen - Label@MOUSE_SCROLL_TYPE_LABEL: - X: 15 - Y: 210 - Width: 110 - Height: 25 - Font: Regular - Text: Pan Behaviour: - Align: Right - DropDownButton@MOUSE_SCROLL_TYPE_DROPDOWN: - X: 130 - Y: 210 - Width: 150 - Height: 25 - Font: Regular - Checkbox@LOCKMOUSE_CHECKBOX: - X: 15 - Y: 243 - Width: 190 - Height: 20 - Font: Regular - Text: Lock Mouse to Window - Label@ZOOM_MODIFIER_LABEL: - X: 350 - Y: 70 - Width: 70 - Height: 25 - Font: Regular - Text: Zoom Modifier: - Align: Right - DropDownButton@ZOOM_MODIFIER: - X: 425 - Y: 70 - Width: 150 - Height: 25 - Font: Regular - Checkbox@EDGESCROLL_CHECKBOX: - X: 360 - Y: 103 - Width: 180 - Height: 20 - Font: Regular - Text: Screen Edge Panning - Checkbox@ALTERNATE_SCROLL_CHECKBOX: - X: 360 - Y: 133 - Width: 180 - Height: 20 - Font: Regular - Text: Alternate Mouse Panning - Label@SCROLL_SPEED_LABEL: - X: 305 - Y: 210 - Width: 100 - Height: 25 - Text: Pan Speed: - Align: Right - Slider@SCROLLSPEED_SLIDER: - X: 410 - Y: 215 - Width: 165 - Height: 20 - Ticks: 5 - MinimumValue: 10 - MaximumValue: 50 - Label@ZOOM_SPEED_LABEL: - X: 305 - Y: 240 - Width: 100 - Height: 25 - Text: Zoom Speed: - Align: Right - ExponentialSlider@ZOOMSPEED_SLIDER: - X: 410 - Y: 245 - Width: 165 - Height: 20 - Ticks: 5 - MinimumValue: 0.01 - MaximumValue: 0.4 - Label@UI_SCROLL_SPEED_LABEL: - X: 305 - Y: 270 - Width: 100 - Height: 25 - Text: UI Scroll Speed: - Align: Right - Slider@UI_SCROLLSPEED_SLIDER: - X: 410 - Y: 275 - Width: 165 - Height: 20 - Ticks: 5 - MinimumValue: 1 - MaximumValue: 100 - Container@HOTKEYS_PANEL: - X: 5 - Y: 50 - Width: PARENT_RIGHT - 10 - Height: PARENT_BOTTOM - Children: - ScrollPanel@HOTKEY_LIST: - X: 15 - Y: 40 - Width: PARENT_RIGHT - 30 - TopBottomSpacing: 4 - ItemSpacing: 4 - Height: 190 - Children: - ScrollItem@HEADER: - BaseName: scrollheader - Width: 528 - Height: 13 - Visible: false - Children: - Label@LABEL: - Font: TinyBold - Width: PARENT_RIGHT - Height: 10 - Align: Center - ScrollItem@HEADER: - Width: 528 - Height: 13 - Visible: false - Children: - Label@LABEL: - Font: TinyBold - Width: PARENT_RIGHT - Height: 10 - Align: Center - Container@TEMPLATES: - Children: - Container@TWO_COLUMN: - Width: 262 - Height: 25 - Visible: false - Children: - Label@FUNCTION: - Y: 0 - 1 - Width: PARENT_RIGHT - 85 - Height: 25 - Align: Right - Button@HOTKEY: - X: PARENT_RIGHT - WIDTH - Width: 80 - Height: 25 - Align: Left - TooltipContainer: SETTINGS_TOOLTIP_CONTAINER - Container@THREE_COLUMN: - Width: 173 - Height: 25 - Visible: false - Children: - Label@FUNCTION: - Y: 0 - 1 - Width: PARENT_RIGHT - 84 - Height: 25 - Align: Right - Button@HOTKEY: - X: PARENT_RIGHT - WIDTH + 1 - Width: 80 - Height: 25 - Align: Left - TooltipContainer: SETTINGS_TOOLTIP_CONTAINER - Background@HOTKEY_DIALOG_ROOT: - X: 15 - Y: 230 - Width: PARENT_RIGHT - 30 - Height: 65 - Background: dialog3 - Children: - Label@HOTKEY_LABEL: - X: 15 - Y: 19 - Width: 219 - 15 - 10 - Height: 25 - Font: Bold - Align: Right - HotkeyEntry@HOTKEY_ENTRY: - X: 219 - Y: 20 - Width: 170 - Height: 25 - Container@NOTICES: - X: 219 - Y: 42 - Width: 170 - Height: 25 - Children: - Label@DEFAULT_NOTICE: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Font: Tiny - Align: Left - Text: This is the default - Label@ORIGINAL_NOTICE: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Font: Tiny - Align: Left - Text: The default is "{0}" - Label@DUPLICATE_NOTICE: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Font: Tiny - Align: Left - Text: This is already used for "{0}" - Button@OVERRIDE_HOTKEY_BUTTON: - X: PARENT_RIGHT - 3 * WIDTH - 30 - Y: 20 - Width: 70 - Height: 25 - Text: Override - Font: Bold - Button@CLEAR_HOTKEY_BUTTON: - X: PARENT_RIGHT - 2 * WIDTH - 30 - Y: 20 - Width: 65 - Height: 25 - Text: Clear - Font: Bold - TooltipText: Unbind the hotkey - TooltipContainer: SETTINGS_TOOLTIP_CONTAINER - TooltipTemplate: SIMPLE_TOOLTIP - Button@RESET_HOTKEY_BUTTON: - X: PARENT_RIGHT - WIDTH - 20 - Y: 20 - Width: 65 - Height: 25 - Text: Reset - Font: Bold - TooltipText: Reset to default - TooltipContainer: SETTINGS_TOOLTIP_CONTAINER - TooltipTemplate: SIMPLE_TOOLTIP - Container@ADVANCED_PANEL: - X: 5 - Y: 50 - Width: PARENT_RIGHT - 10 - Height: PARENT_BOTTOM - Children: - Checkbox@NAT_DISCOVERY: - X: 15 - Y: 43 - Width: 200 - Height: 20 - Font: Regular - Text: Enable Network Discovery (UPnP) - Checkbox@PERFTEXT_CHECKBOX: - X: 15 - Y: 73 - Width: 300 - Height: 20 - Font: Regular - Text: Show Performance Text - Checkbox@PERFGRAPH_CHECKBOX: - X: 15 - Y: 103 - Width: 300 - Height: 20 - Font: Regular - Text: Show Performance Graph - Checkbox@FETCH_NEWS_CHECKBOX: - X: 310 - Y: 43 - Width: 300 - Height: 20 - Font: Regular - Text: Fetch Community News - Checkbox@CHECK_VERSION_CHECKBOX: - X: 310 - Y: 73 - Width: 300 - Height: 20 - Font: Regular - Text: Check for Updates - Checkbox@SENDSYSINFO_CHECKBOX: - X: 310 - Y: 103 - Width: 300 - Height: 20 - Font: Regular - Text: Send System Information - Label@SENDSYSINFO_DESC: - X: 310 - Y: 118 - Width: 255 - Height: 30 - Font: Tiny - WordWrap: True - Text: Your Operating System, OpenGL and .NET runtime versions, and language settings will be sent along with an anonymous ID to help prioritize future development. - Label@DEBUG_TITLE: - Y: 190 - Width: PARENT_RIGHT - Font: Bold - Text: Developer - Align: Center - Container@DEBUG_HIDDEN_LABEL: - Y: 245 - Width: PARENT_RIGHT - Children: - Label@A: - Width: PARENT_RIGHT - Height: 20 - Font: Regular - Text: Additional developer-specific options can be enabled via the - Align: Center - Label@B: - Y: 20 - Width: PARENT_RIGHT - Height: 20 - Font: Regular - Text: Debug.DisplayDeveloperSettings setting or launch flag - Align: Center - Container@DEBUG_OPTIONS: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Children: - Checkbox@BOTDEBUG_CHECKBOX: - X: 15 - Y: 213 - Width: 300 - Height: 20 - Font: Regular - Text: Show Bot Debug Messages - Checkbox@CHECKUNSYNCED_CHECKBOX: - X: 15 - Y: 243 - Width: 300 - Height: 20 - Font: Regular - Text: Check Sync around Unsynced Code - Checkbox@CHECKBOTSYNC_CHECKBOX: - X: 15 - Y: 273 - Width: 300 - Height: 20 - Font: Regular - Text: Check Sync around BotModule Code - Checkbox@LUADEBUG_CHECKBOX: - X: 310 - Y: 213 - Width: 300 - Height: 20 - Font: Regular - Text: Show Map Debug Messages - Checkbox@REPLAY_COMMANDS_CHECKBOX: - X: 310 - Y: 243 - Width: 300 - Height: 20 - Font: Regular - Text: Enable Debug Commands in Replays TooltipContainer@SETTINGS_TOOLTIP_CONTAINER: diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index f1d0ab462d..c1951591d4 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -84,6 +84,11 @@ ChromeLayout: d2k|chrome/mainmenu.yaml common|chrome/mainmenu-prompts.yaml common|chrome/settings.yaml + common|chrome/settings-display.yaml + common|chrome/settings-audio.yaml + common|chrome/settings-input.yaml + common|chrome/settings-hotkeys.yaml + common|chrome/settings-advanced.yaml common|chrome/credits.yaml common|chrome/lobby.yaml common|chrome/lobby-mappreview.yaml diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 45ad7ee267..17191ebde5 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -100,6 +100,11 @@ ChromeLayout: common|chrome/mainmenu.yaml common|chrome/mainmenu-prompts.yaml common|chrome/settings.yaml + common|chrome/settings-display.yaml + common|chrome/settings-audio.yaml + common|chrome/settings-input.yaml + common|chrome/settings-hotkeys.yaml + common|chrome/settings-advanced.yaml common|chrome/credits.yaml common|chrome/lobby.yaml common|chrome/lobby-mappreview.yaml diff --git a/mods/ts/mod.yaml b/mods/ts/mod.yaml index a56fd201da..7f4af595bc 100644 --- a/mods/ts/mod.yaml +++ b/mods/ts/mod.yaml @@ -147,6 +147,11 @@ ChromeLayout: common|chrome/mainmenu-prompts.yaml ts|chrome/mainmenu-prerelease-notification.yaml common|chrome/settings.yaml + common|chrome/settings-display.yaml + common|chrome/settings-audio.yaml + common|chrome/settings-input.yaml + common|chrome/settings-hotkeys.yaml + common|chrome/settings-advanced.yaml common|chrome/credits.yaml common|chrome/lobby.yaml common|chrome/lobby-mappreview.yaml