Overhaul settings panel layout

- make the panel larger
- place settings widgets in a scroll panel
- arrange settings widgets in two columns
- make tabs in TD vertical
This commit is contained in:
Ivaylo Draganov
2021-09-22 16:59:36 +03:00
committed by reaperrr
parent a36eb585d3
commit 3ecaf76804
24 changed files with 2009 additions and 1565 deletions

View File

@@ -35,6 +35,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var ds = Game.Settings.Debug;
var ss = Game.Settings.Server;
var gs = Game.Settings.Game;
var scrollPanel = panel.Get<ScrollPanelWidget>("SETTINGS_SCROLLPANEL");
// Advanced
SettingsUtils.BindCheckboxPref(panel, "NAT_DISCOVERY", ss, "DiscoverNatDevices");
@@ -55,8 +56,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic
SettingsUtils.BindCheckboxPref(panel, "CHECKBOTSYNC_CHECKBOX", ds, "SyncCheckBotModuleCode");
SettingsUtils.BindCheckboxPref(panel, "PERFLOGGING_CHECKBOX", ds, "EnableSimulationPerfLogging");
panel.Get("DEBUG_OPTIONS").IsVisible = () => ds.DisplayDeveloperSettings;
panel.Get("DEBUG_HIDDEN_LABEL").IsVisible = () => !ds.DisplayDeveloperSettings;
panel.Get("BOTDEBUG_CHECKBOX_CONTAINER").IsVisible = () => ds.DisplayDeveloperSettings;
panel.Get("CHECKUNSYNCED_CHECKBOX_CONTAINER").IsVisible = () => ds.DisplayDeveloperSettings;
panel.Get("CHECKBOTSYNC_CHECKBOX_CONTAINER").IsVisible = () => ds.DisplayDeveloperSettings;
panel.Get("LUADEBUG_CHECKBOX_CONTAINER").IsVisible = () => ds.DisplayDeveloperSettings;
panel.Get("REPLAY_COMMANDS_CHECKBOX_CONTAINER").IsVisible = () => ds.DisplayDeveloperSettings;
panel.Get("PERFLOGGING_CHECKBOX_CONTAINER").IsVisible = () => ds.DisplayDeveloperSettings;
panel.Get("DEBUG_HIDDEN_CONTAINER").IsVisible = () => !ds.DisplayDeveloperSettings;
SettingsUtils.AdjustSettingsScrollPanelLayout(scrollPanel);
return () => ss.DiscoverNatDevices != OriginalServerDiscoverNatDevices;
}

View File

@@ -43,6 +43,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
var musicPlaylist = worldRenderer.World.WorldActor.Trait<MusicPlaylist>();
var ss = Game.Settings.Sound;
var scrollPanel = panel.Get<ScrollPanelWidget>("SETTINGS_SCROLLPANEL");
SettingsUtils.BindCheckboxPref(panel, "CASH_TICKS", ss, "CashTicks");
SettingsUtils.BindCheckboxPref(panel, "MUTE_SOUND", ss, "Mute");
@@ -81,13 +82,16 @@ namespace OpenRA.Mods.Common.Widgets.Logic
};
// Replace controls with a warning label if sound is disabled
var noDeviceLabel = panel.GetOrNull("NO_AUDIO_DEVICE");
var noDeviceLabel = panel.GetOrNull("NO_AUDIO_DEVICE_CONTAINER");
if (noDeviceLabel != null)
noDeviceLabel.Visible = Game.Sound.DummyEngine;
var controlsContainer = panel.GetOrNull("AUDIO_CONTROLS");
if (controlsContainer != null)
controlsContainer.Visible = !Game.Sound.DummyEngine;
panel.Get("CASH_TICKS_CONTAINER").Visible = !Game.Sound.DummyEngine;
panel.Get("MUTE_SOUND_CONTAINER").Visible = !Game.Sound.DummyEngine;
panel.Get("MUTE_BACKGROUND_MUSIC_CONTAINER").Visible = !Game.Sound.DummyEngine;
panel.Get("SOUND_VOLUME_CONTAINER").Visible = !Game.Sound.DummyEngine;
panel.Get("MUSIC_VOLUME_CONTAINER").Visible = !Game.Sound.DummyEngine;
panel.Get("VIDEO_VOLUME_CONTAINER").Visible = !Game.Sound.DummyEngine;
var soundVolumeSlider = panel.Get<SliderWidget>("SOUND_VOLUME");
soundVolumeSlider.OnChange += x => Game.Sound.SoundVolume = x;
@@ -102,13 +106,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic
soundDevice = devices.FirstOrDefault(d => d.Device == ss.Device) ?? devices.First();
var audioDeviceDropdown = panel.Get<DropDownButtonWidget>("AUDIO_DEVICE");
audioDeviceDropdown.OnMouseDown = _ => ShowAudioDeviceDropdown(audioDeviceDropdown, devices);
audioDeviceDropdown.OnMouseDown = _ => ShowAudioDeviceDropdown(audioDeviceDropdown, devices, scrollPanel);
var deviceFont = Game.Renderer.Fonts[audioDeviceDropdown.Font];
var deviceLabel = new CachedTransform<SoundDevice, string>(
s => WidgetUtils.TruncateText(s.Label, audioDeviceDropdown.UsableWidth, deviceFont));
audioDeviceDropdown.GetText = () => deviceLabel.Update(soundDevice);
var restartDesc = panel.Get("RESTART_REQUIRED_DESC");
restartDesc.IsVisible = () => soundDevice.Device != OriginalSoundDevice;
SettingsUtils.AdjustSettingsScrollPanelLayout(scrollPanel);
return () =>
{
ss.Device = soundDevice.Device;
@@ -142,7 +151,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
};
}
void ShowAudioDeviceDropdown(DropDownButtonWidget dropdown, SoundDevice[] devices)
void ShowAudioDeviceDropdown(DropDownButtonWidget dropdown, SoundDevice[] devices, ScrollPanelWidget scrollPanel)
{
var i = 0;
var options = devices.ToDictionary(d => (i++).ToString(), d => d);
@@ -151,7 +160,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
var item = ScrollItemWidget.Setup(itemTemplate,
() => soundDevice == options[o],
() => soundDevice = options[o]);
() =>
{
soundDevice = options[o];
SettingsUtils.AdjustSettingsScrollPanelLayout(scrollPanel);
});
var deviceLabel = item.Get<LabelWidget>("LABEL");
var font = Game.Renderer.Fonts[deviceLabel.Font];

View File

@@ -64,6 +64,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
var ds = Game.Settings.Graphics;
var gs = Game.Settings.Game;
var scrollPanel = panel.Get<ScrollPanelWidget>("SETTINGS_SCROLLPANEL");
SettingsUtils.BindCheckboxPref(panel, "CURSORDOUBLE_CHECKBOX", ds, "CursorDouble");
SettingsUtils.BindCheckboxPref(panel, "VSYNC_CHECKBOX", ds, "VSync");
@@ -74,7 +75,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
SettingsUtils.BindCheckboxPref(panel, "PAUSE_SHELLMAP_CHECKBOX", gs, "PauseShellmap");
var windowModeDropdown = panel.Get<DropDownButtonWidget>("MODE_DROPDOWN");
windowModeDropdown.OnMouseDown = _ => ShowWindowModeDropdown(windowModeDropdown, ds);
windowModeDropdown.OnMouseDown = _ => ShowWindowModeDropdown(windowModeDropdown, ds, scrollPanel);
windowModeDropdown.GetText = () => ds.Mode == WindowMode.Windowed ?
"Windowed" : ds.Mode == WindowMode.Fullscreen ? "Fullscreen (Legacy)" : "Fullscreen";
@@ -130,8 +131,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
uiScaleDropdown.IsDisabled = () => disableUIScale;
panel.Get("DISPLAY_SELECTION").IsVisible = () => ds.Mode != WindowMode.Windowed;
panel.Get("WINDOW_RESOLUTION").IsVisible = () => ds.Mode == WindowMode.Windowed;
panel.Get("DISPLAY_SELECTION_CONTAINER").IsVisible = () => ds.Mode != WindowMode.Windowed;
panel.Get("WINDOW_RESOLUTION_CONTAINER").IsVisible = () => ds.Mode == WindowMode.Windowed;
var windowWidth = panel.Get<TextFieldWidget>("WINDOW_WIDTH");
var origWidthText = windowWidth.Text = ds.WindowedSize.X.ToString();
@@ -148,6 +149,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var frameLimitLabel = new CachedTransform<int, string>(fps => frameLimitOrigLabel + $" ({fps} FPS)");
frameLimitCheckbox.GetText = () => frameLimitLabel.Update(ds.MaxFramerate);
panel.Get<SliderWidget>("FRAME_LIMIT_SLIDER").IsDisabled = () => !frameLimitCheckbox.IsChecked();
// Player profile
var ps = Game.Settings.Player;
@@ -194,6 +197,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
});
colorDropdown.Get<ColorBlockWidget>("COLORBLOCK").GetColor = () => ps.Color;
SettingsUtils.AdjustSettingsScrollPanelLayout(scrollPanel);
return () =>
{
Exts.TryParseIntegerInvariant(windowWidth.Text, out var x);
@@ -244,7 +249,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
};
}
static void ShowWindowModeDropdown(DropDownButtonWidget dropdown, GraphicSettings s)
static void ShowWindowModeDropdown(DropDownButtonWidget dropdown, GraphicSettings s, ScrollPanelWidget scrollPanel)
{
var options = new Dictionary<string, WindowMode>()
{
@@ -257,7 +262,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
var item = ScrollItemWidget.Setup(itemTemplate,
() => s.Mode == options[o],
() => s.Mode = options[o]);
() =>
{
s.Mode = options[o];
SettingsUtils.AdjustSettingsScrollPanelLayout(scrollPanel);
});
item.Get<LabelWidget>("LABEL").GetText = () => o;
return item;
@@ -393,9 +402,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
// 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")
// HACK: Skip children badges container on the main menu and settings tab container
// These have a fixed size, with calculated size and children positions that break if we adjust them here
if (w.Id == "BADGES_CONTAINER" || w.Id == "SETTINGS_TAB_CONTAINER")
return;
var parentBounds = w.Parent == null

View File

@@ -86,31 +86,26 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
hotkeyList = panel.Get<ScrollPanelWidget>("HOTKEY_LIST");
hotkeyList.Layout = new GridLayout(hotkeyList);
var hotkeyHeader = hotkeyList.Get<ScrollItemWidget>("HEADER");
var templates = hotkeyList.Get("TEMPLATES");
var headerTemplate = hotkeyList.Get("HEADER");
var template = hotkeyList.Get("TEMPLATE");
hotkeyList.RemoveChildren();
Func<bool> 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)
if (typesNode == null)
continue;
var header = ScrollItemWidget.Setup(hotkeyHeader, returnTrue, doNothing);
var header = headerTemplate.Clone();
header.Get<LabelWidget>("LABEL").GetText = () => hg.Key;
hotkeyList.AddChild(header);
var types = FieldLoader.GetValue<string[]>("Types", typesNode.Value.Value);
var added = new HashSet<HotkeyDefinition>();
var template = templates.Get(templateNode.Value.Value);
foreach (var t in types)
{

View File

@@ -28,6 +28,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
Func<bool> InitPanel(Widget panel)
{
var gs = Game.Settings.Game;
var scrollPanel = panel.Get<ScrollPanelWidget>("SETTINGS_SCROLLPANEL");
SettingsUtils.BindCheckboxPref(panel, "ALTERNATE_SCROLL_CHECKBOX", gs, "UseAlternateScrollButton");
SettingsUtils.BindCheckboxPref(panel, "EDGESCROLL_CHECKBOX", gs, "ViewportEdgeScroll");
@@ -89,6 +90,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
zoomModifierDropdown.OnMouseDown = _ => ShowZoomModifierDropdown(zoomModifierDropdown, gs);
zoomModifierDropdown.GetText = () => gs.ZoomModifier.ToString();
SettingsUtils.AdjustSettingsScrollPanelLayout(scrollPanel);
return () => false;
}

View File

@@ -40,7 +40,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var panelTemplate = panelContainer.Get<ContainerWidget>("PANEL_TEMPLATE");
panelContainer.RemoveChild(panelTemplate);
tabContainer = widget.Get("TAB_CONTAINER");
tabContainer = widget.Get("SETTINGS_TAB_CONTAINER");
tabTemplate = tabContainer.Get<ButtonWidget>("BUTTON_TEMPLATE");
tabContainer.RemoveChild(tabTemplate);

View File

@@ -48,5 +48,30 @@ namespace OpenRA.Mods.Common.Widgets.Logic
ss.Value = (float)(int)field.GetValue(group);
ss.OnChange += x => field.SetValue(group, (int)x);
}
public static void AdjustSettingsScrollPanelLayout(ScrollPanelWidget scrollPanel)
{
foreach (var row in scrollPanel.Children)
{
if (row.Children.Count == 0)
continue;
var hasVisibleChildren = false;
foreach (var container in row.Children)
{
if (container.IsVisible())
{
hasVisibleChildren = true;
break;
}
}
if (!hasVisibleChildren)
row.Visible = false;
}
scrollPanel.Layout.AdjustChildren();
}
}
}