From 965a490b70152703f3901f00af088ed75155a4db Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 28 Apr 2025 16:16:55 +0100 Subject: [PATCH] Dynamically populate map chooser tabs. --- .../Widgets/Logic/MapChooserLogic.cs | 93 ++++++++++++------- mods/cnc/chrome/mapchooser.yaml | 17 ++-- mods/cnc/fluent/chrome.ftl | 3 - mods/common/chrome/map-chooser.yaml | 19 ++-- mods/common/fluent/chrome.ftl | 3 - mods/common/fluent/common.ftl | 4 + 6 files changed, 80 insertions(+), 59 deletions(-) diff --git a/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs index 28023d6dbc..a7cf671eec 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs @@ -82,6 +82,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic [FluentReference] const string OrderMapsBySize = "options-order-maps.size"; + [FluentReference] + const string SystemMapsTab = "button-mapchooser-system-maps-tab"; + + [FluentReference] + const string UserMapsTab = "button-mapchooser-user-maps-tab"; + + [FluentReference] + const string RemoteMapsTab = "button-mapchooser-remote-maps-tab"; + readonly string allMaps; readonly Widget widget; @@ -89,6 +98,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly ModData modData; readonly HashSet remoteMapPool; readonly ScrollItemWidget itemTemplate; + readonly MapVisibility filter; MapClassification currentTab; bool disposed; @@ -96,8 +106,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic int remoteUnavailable = 0; readonly Dictionary scrollpanels = []; - readonly Dictionary tabMaps = []; + readonly Dictionary tabLabels = []; + string[] visibleMaps; string selectedUid; @@ -116,6 +127,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic this.modData = modData; this.onSelect = onSelect; this.remoteMapPool = remoteMapPool; + this.filter = filter; allMaps = FluentProvider.GetMessage(AllMaps); @@ -182,8 +194,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic { DeleteOneMap(selectedUid, newUid => { - RefreshMaps(currentTab, filter); + RefreshMaps(currentTab); EnumerateMaps(currentTab); + SetupMapTabs(); if (tabMaps[currentTab].Length == 0) SwitchTab(modData.MapCache[newUid].Class); }); @@ -193,10 +206,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic deleteAllMapsButton.IsVisible = () => currentTab == MapClassification.User; deleteAllMapsButton.OnClick = () => { - DeleteAllMaps(visibleMaps, (string newUid) => + DeleteAllMaps(visibleMaps, newUid => { - RefreshMaps(currentTab, filter); + RefreshMaps(currentTab); EnumerateMaps(currentTab); + SetupMapTabs(); SwitchTab(modData.MapCache[newUid].Class); }); }; @@ -220,29 +234,37 @@ namespace OpenRA.Mods.Common.Widgets.Logic modData.MapCache.QueryRemoteMapDetails(services.MapRepository, remoteMapPool); } - SetupMapTab(MapClassification.User, filter, "USER_MAPS_TAB_BUTTON", "USER_MAPS_TAB"); - SetupMapTab(MapClassification.System, filter, "SYSTEM_MAPS_TAB_BUTTON", "SYSTEM_MAPS_TAB"); - SetupMapTab(MapClassification.Remote, filter, "REMOTE_MAPS_TAB_BUTTON", "REMOTE_MAPS_TAB"); + SetupMapPanel(MapClassification.User, "USER_MAPS_TAB"); + SetupMapPanel(MapClassification.System, "SYSTEM_MAPS_TAB"); + SetupMapPanel(MapClassification.Remote, "REMOTE_MAPS_TAB"); // System and user map tabs are hidden when the server forces a restricted pool if (remoteMapPool != null) { + tabLabels[MapClassification.Remote] = RemoteMapsTab; currentTab = MapClassification.Remote; selectedUid = initialMap; } - else if (initialMap == null && tabMaps.TryGetValue(initialTab, out var map) && map.Length > 0) - { - selectedUid = Game.ModData.MapCache.ChooseInitialMap(map.Select(mp => mp.Uid).First(), - Game.CosmeticRandom); - currentTab = initialTab; - } else { - selectedUid = Game.ModData.MapCache.ChooseInitialMap(initialMap, Game.CosmeticRandom); - currentTab = tabMaps.Keys.FirstOrDefault(k => tabMaps[k].Select(mp => mp.Uid).Contains(selectedUid)); + tabLabels[MapClassification.System] = SystemMapsTab; + tabLabels[MapClassification.User] = UserMapsTab; + + if (initialMap == null && tabMaps.TryGetValue(initialTab, out var map) && map.Length > 0) + { + var uid = map.Select(mp => mp.Uid).First(); + selectedUid = Game.ModData.MapCache.ChooseInitialMap(uid, Game.CosmeticRandom); + currentTab = initialTab; + } + else + { + selectedUid = Game.ModData.MapCache.ChooseInitialMap(initialMap, Game.CosmeticRandom); + currentTab = tabMaps.Keys.FirstOrDefault(k => tabMaps[k].Select(mp => mp.Uid).Contains(selectedUid)); + } } EnumerateMaps(currentTab); + SetupMapTabs(); } void SwitchTab(MapClassification tab) @@ -251,7 +273,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic EnumerateMaps(tab); } - void RefreshMaps(MapClassification tab, MapVisibility filter) + void RefreshMaps(MapClassification tab) { if (tab != MapClassification.Remote) tabMaps[tab] = modData.MapCache.Where(m => m.Status == MapStatus.Available && @@ -283,7 +305,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic return; var missingBefore = remoteSearching + remoteUnavailable; - RefreshMaps(MapClassification.Remote, filter); + RefreshMaps(MapClassification.Remote); var missingAfter = remoteSearching + remoteUnavailable; if (currentTab == MapClassification.Remote && missingBefore != missingAfter) EnumerateMaps(MapClassification.Remote); @@ -294,7 +316,27 @@ namespace OpenRA.Mods.Common.Widgets.Logic tabMaps[tab] = []; } - void SetupMapTab(MapClassification tab, MapVisibility filter, string tabButtonName, string tabContainerName) + void SetupMapTabs() + { + for (var i = 0; i < 3; i++) + widget.Get($"BUTTON{i + 1}").Visible = false; + + var tabCount = 0; + foreach (var kv in tabLabels) + { + var tab = kv.Key; + if (tab == MapClassification.User && tabMaps[tab].Length == 0) + continue; + + var tabButton = widget.Get($"BUTTON{++tabCount}"); + tabButton.IsHighlighted = () => currentTab == tab; + tabButton.OnClick = () => SwitchTab(tab); + tabButton.Visible = true; + tabButton.Text = kv.Value; + } + } + + void SetupMapPanel(MapClassification tab, string tabContainerName) { var tabContainer = widget.Get(tabContainerName); tabContainer.IsVisible = () => currentTab == tab; @@ -302,20 +344,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic tabScrollpanel.Layout = new GridLayout(tabScrollpanel); scrollpanels.Add(tab, tabScrollpanel); - var tabButton = widget.Get(tabButtonName); - tabButton.IsHighlighted = () => currentTab == tab; - - if (remoteMapPool != null) - { - var isRemoteTab = tab == MapClassification.Remote; - tabButton.IsVisible = () => isRemoteTab; - } - else - tabButton.IsVisible = () => tabMaps[tab].Length > 0; - - tabButton.OnClick = () => SwitchTab(tab); - - RefreshMaps(tab, filter); + RefreshMaps(tab); } void SetupGameModeDropdown(MapClassification tab, DropDownButtonWidget gameModeDropdown) diff --git a/mods/cnc/chrome/mapchooser.yaml b/mods/cnc/chrome/mapchooser.yaml index a5514be26c..a2a153c991 100644 --- a/mods/cnc/chrome/mapchooser.yaml +++ b/mods/cnc/chrome/mapchooser.yaml @@ -18,24 +18,21 @@ Container@MAPCHOOSER_PANEL: Height: PARENT_HEIGHT Background: panel-black Children: - Button@SYSTEM_MAPS_TAB_BUTTON: + Button@BUTTON1: X: 15 Y: 15 Height: 31 Width: 135 - Text: button-bg-system-maps-tab - Button@REMOTE_MAPS_TAB_BUTTON: - X: 15 - Y: 15 - Height: 31 - Width: 135 - Text: button-bg-remote-maps-tab - Button@USER_MAPS_TAB_BUTTON: + Button@BUTTON2: X: 155 Y: 15 Height: 31 Width: 135 - Text: button-bg-user-maps-tab + Button@BUTTON3: + X: 295 + Y: 15 + Height: 31 + Width: 135 Container@MAP_TAB_PANES: Width: PARENT_WIDTH - 30 Height: PARENT_HEIGHT - 90 diff --git a/mods/cnc/fluent/chrome.ftl b/mods/cnc/fluent/chrome.ftl index cc8217d081..6266604a7f 100644 --- a/mods/cnc/fluent/chrome.ftl +++ b/mods/cnc/fluent/chrome.ftl @@ -514,9 +514,6 @@ button-settings-title = Settings ## mapchooser.yaml label-mapchooser-panel-title = Select Map -button-bg-system-maps-tab = Official Maps -button-bg-remote-maps-tab = Server Maps -button-bg-user-maps-tab = Custom Maps label-filter-order-controls-desc = Filter: label-filter-order-controls-desc-joiner = in label-filter-order-controls-orderby = Order by: diff --git a/mods/common/chrome/map-chooser.yaml b/mods/common/chrome/map-chooser.yaml index 88d9e98b81..45886e9596 100644 --- a/mods/common/chrome/map-chooser.yaml +++ b/mods/common/chrome/map-chooser.yaml @@ -12,26 +12,23 @@ Background@MAPCHOOSER_PANEL: Height: 20 Text: label-mapchooser-panel-title Font: Bold - Button@SYSTEM_MAPS_TAB_BUTTON: + Button@BUTTON1: X: 20 Y: 48 Height: 31 Width: 140 - Text: button-mapchooser-panel-system-maps-tab Font: Bold - Button@REMOTE_MAPS_TAB_BUTTON: - X: 20 - Y: 48 - Height: 31 - Width: 140 - Text: button-mapchooser-panel-remote-maps-tab - Font: Bold - Button@USER_MAPS_TAB_BUTTON: + Button@BUTTON2: X: 160 Y: 48 Height: 31 Width: 140 - Text: button-mapchooser-panel-user-maps-tab + Font: Bold + Button@BUTTON3: + X: 300 + Y: 48 + Height: 31 + Width: 140 Font: Bold Container@MAP_TAB_PANES: Width: PARENT_WIDTH - 40 diff --git a/mods/common/fluent/chrome.ftl b/mods/common/fluent/chrome.ftl index 1a3a804e3d..e22a54bb3d 100644 --- a/mods/common/fluent/chrome.ftl +++ b/mods/common/fluent/chrome.ftl @@ -333,9 +333,6 @@ button-settings-title = Settings ## map-chooser.yaml label-mapchooser-panel-title = Choose Map -button-mapchooser-panel-system-maps-tab = Official Maps -button-mapchooser-panel-remote-maps-tab = Server Maps -button-mapchooser-panel-user-maps-tab = Custom Maps label-filter-order-controls-desc = Filter: label-filter-order-controls-desc-joiner = in label-filter-order-controls-orderby = Order by: diff --git a/mods/common/fluent/common.ftl b/mods/common/fluent/common.ftl index ca85253494..871a8e6a64 100644 --- a/mods/common/fluent/common.ftl +++ b/mods/common/fluent/common.ftl @@ -545,6 +545,10 @@ options-order-maps = .date = Date .size = Size +button-mapchooser-system-maps-tab = Official Maps +button-mapchooser-remote-maps-tab = Server Maps +button-mapchooser-user-maps-tab = Custom Maps + ## MissionBrowserLogic dialog-no-video = .title = Video not installed