diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoLogic.cs index a6a5bfe80a..30cfaba1e3 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoLogic.cs @@ -10,6 +10,7 @@ #endregion using System; +using System.Collections.Generic; using System.Linq; using OpenRA.Mods.Common.Scripting; using OpenRA.Mods.Common.Traits; @@ -21,61 +22,41 @@ namespace OpenRA.Mods.Common.Widgets.Logic class GameInfoLogic : ChromeLogic { - [ObjectCreator.UseCtor] - public GameInfoLogic(Widget widget, World world, IngameInfoPanel activePanel, Action hideMenu) - { - var lp = world.LocalPlayer; - var numTabs = 0; + readonly World world; + readonly Action hideMenu; + readonly IObjectivesPanel iop; + IngameInfoPanel activePanel; + bool hasError; - widget.IsVisible = () => activePanel != IngameInfoPanel.AutoSelect; + [ObjectCreator.UseCtor] + public GameInfoLogic(Widget widget, World world, IngameInfoPanel initialPanel, Action hideMenu) + { + var panels = new Dictionary Setup)>() + { + { IngameInfoPanel.Objectives, ("OBJECTIVES_PANEL", "Objectives", SetupObjectivesPanel) }, + { IngameInfoPanel.Map, ("MAP_PANEL", "Briefing", SetupMapPanel) }, + { IngameInfoPanel.Debug, ("DEBUG_PANEL", "Debug", SetupDebugPanel) }, + { IngameInfoPanel.Chat, ("CHAT_PANEL", "Chat", SetupChatPanel) } + }; + + this.world = world; + this.hideMenu = hideMenu; + activePanel = initialPanel; + + var visiblePanels = new List(); // Objectives/Stats tab var scriptContext = world.WorldActor.TraitOrDefault(); - var hasError = scriptContext != null && scriptContext.FatalErrorOccurred; - var iop = world.WorldActor.TraitsImplementing().FirstOrDefault(); - var hasObjectivesPanel = hasError || (iop != null && iop.PanelName != null); + hasError = scriptContext != null && scriptContext.FatalErrorOccurred; + iop = world.WorldActor.TraitsImplementing().FirstOrDefault(); - if (hasObjectivesPanel) - { - numTabs++; - var objectivesTabButton = widget.Get(string.Concat("BUTTON", numTabs.ToString())); - objectivesTabButton.GetText = () => "Objectives"; - objectivesTabButton.IsVisible = () => numTabs > 1 && !hasError; - objectivesTabButton.OnClick = () => activePanel = IngameInfoPanel.Objectives; - objectivesTabButton.IsHighlighted = () => activePanel == IngameInfoPanel.Objectives; - - var panel = hasError ? "SCRIPT_ERROR_PANEL" : iop.PanelName; - var objectivesPanel = widget.Get("OBJECTIVES_PANEL"); - objectivesPanel.IsVisible = () => activePanel == IngameInfoPanel.Objectives; - - Game.LoadWidget(world, panel, objectivesPanel, new WidgetArgs() - { - { "hideMenu", hideMenu } - }); - - if (activePanel == IngameInfoPanel.AutoSelect) - activePanel = IngameInfoPanel.Objectives; - } + if (hasError || (iop != null && iop.PanelName != null)) + visiblePanels.Add(IngameInfoPanel.Objectives); // Briefing tab var missionData = world.WorldActor.Info.TraitInfoOrDefault(); if (missionData != null && !string.IsNullOrEmpty(missionData.Briefing)) - { - numTabs++; - var mapTabButton = widget.Get(string.Concat("BUTTON", numTabs.ToString())); - mapTabButton.Text = "Briefing"; - mapTabButton.IsVisible = () => numTabs > 1 && !hasError; - mapTabButton.OnClick = () => activePanel = IngameInfoPanel.Map; - mapTabButton.IsHighlighted = () => activePanel == IngameInfoPanel.Map; - - var mapPanel = widget.Get("MAP_PANEL"); - mapPanel.IsVisible = () => activePanel == IngameInfoPanel.Map; - - Game.LoadWidget(world, "MAP_PANEL", mapPanel, new WidgetArgs()); - - if (activePanel == IngameInfoPanel.AutoSelect) - activePanel = IngameInfoPanel.Map; - } + visiblePanels.Add(IngameInfoPanel.Map); // Debug/Cheats tab // Can't use DeveloperMode.Enabled because there is a hardcoded hack to *always* @@ -83,45 +64,36 @@ namespace OpenRA.Mods.Common.Widgets.Logic // if it has been explicitly enabled var def = world.Map.Rules.Actors[SystemActors.Player].TraitInfo().CheckboxEnabled; var developerEnabled = world.LobbyInfo.GlobalSettings.OptionOrDefault("cheats", def); - if (lp != null && developerEnabled) - { - numTabs++; - var debugTabButton = widget.Get(string.Concat("BUTTON", numTabs.ToString())); - debugTabButton.Text = "Debug"; - debugTabButton.IsVisible = () => numTabs > 1 && !hasError; - debugTabButton.IsDisabled = () => world.IsGameOver; - debugTabButton.OnClick = () => activePanel = IngameInfoPanel.Debug; - debugTabButton.IsHighlighted = () => activePanel == IngameInfoPanel.Debug; - - var debugPanelContainer = widget.Get("DEBUG_PANEL"); - debugPanelContainer.IsVisible = () => activePanel == IngameInfoPanel.Debug; - - Game.LoadWidget(world, "DEBUG_PANEL", debugPanelContainer, new WidgetArgs()); - - if (activePanel == IngameInfoPanel.AutoSelect) - activePanel = IngameInfoPanel.Debug; - } + if (world.LocalPlayer != null && developerEnabled) + visiblePanels.Add(IngameInfoPanel.Debug); if (world.LobbyInfo.NonBotClients.Count() > 1) + visiblePanels.Add(IngameInfoPanel.Chat); + + var numTabs = visiblePanels.Count; + var tabContainer = !hasError ? widget.GetOrNull($"TAB_CONTAINER_{numTabs}") : null; + if (tabContainer != null) + tabContainer.IsVisible = () => true; + + for (var i = 0; i < numTabs; i++) { - numTabs++; - var chatPanelContainer = widget.Get("CHAT_PANEL"); - var chatTabButton = widget.Get(string.Concat("BUTTON", numTabs.ToString())); - chatTabButton.Text = "Chat"; - chatTabButton.IsVisible = () => numTabs > 1 && !hasError; - chatTabButton.IsHighlighted = () => activePanel == IngameInfoPanel.Chat; - chatTabButton.OnClick = () => + var type = visiblePanels[i]; + var info = panels[type]; + var tabButton = tabContainer?.Get($"BUTTON{i + 1}"); + + if (tabButton != null) { - activePanel = IngameInfoPanel.Chat; - chatPanelContainer.Get("CHAT_TEXTFIELD").TakeKeyboardFocus(); - }; + tabButton.Text = info.Label; + tabButton.OnClick = () => activePanel = type; + tabButton.IsHighlighted = () => activePanel == type; + } - chatPanelContainer.IsVisible = () => activePanel == IngameInfoPanel.Chat; - - Game.LoadWidget(world, "CHAT_CONTAINER", chatPanelContainer, new WidgetArgs() { { "isMenuChat", true } }); + var panelContainer = widget.Get(info.Panel); + panelContainer.IsVisible = () => activePanel == type; + info.Setup(tabButton, panelContainer); if (activePanel == IngameInfoPanel.AutoSelect) - chatTabButton.OnClick(); + activePanel = type; } // Handle empty space when tabs aren't displayed @@ -148,5 +120,45 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (bgNoTabs != null) bgNoTabs.IsVisible = () => numTabs == 1; } + + void SetupObjectivesPanel(ButtonWidget objectivesTabButton, Widget objectivesPanelContainer) + { + var panel = hasError ? "SCRIPT_ERROR_PANEL" : iop.PanelName; + Game.LoadWidget(world, panel, objectivesPanelContainer, new WidgetArgs() + { + { "hideMenu", hideMenu } + }); + } + + void SetupMapPanel(ButtonWidget mapTabButton, Widget mapPanelContainer) + { + Game.LoadWidget(world, "MAP_PANEL", mapPanelContainer, new WidgetArgs()); + } + + void SetupDebugPanel(ButtonWidget debugTabButton, Widget debugPanelContainer) + { + if (debugTabButton != null) + debugTabButton.IsDisabled = () => world.IsGameOver; + + Game.LoadWidget(world, "DEBUG_PANEL", debugPanelContainer, new WidgetArgs()); + + if (activePanel == IngameInfoPanel.AutoSelect) + activePanel = IngameInfoPanel.Debug; + } + + void SetupChatPanel(ButtonWidget chatTabButton, Widget chatPanelContainer) + { + if (chatTabButton != null) + { + var lastOnClick = chatTabButton.OnClick; + chatTabButton.OnClick = () => + { + lastOnClick(); + chatPanelContainer.Get("CHAT_TEXTFIELD").TakeKeyboardFocus(); + }; + } + + Game.LoadWidget(world, "CHAT_CONTAINER", chatPanelContainer, new WidgetArgs() { { "isMenuChat", true } }); + } } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs index 9522536315..1b81c20cc7 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs @@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic [ObjectCreator.UseCtor] public IngameMenuLogic(Widget widget, ModData modData, World world, Action onExit, WorldRenderer worldRenderer, - IngameInfoPanel activePanel, Dictionary logicArgs) + IngameInfoPanel initialPanel, Dictionary logicArgs) { this.modData = modData; this.world = world; @@ -103,7 +103,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic Action requestHideMenu = h => hideMenu = h; var gameInfoPanel = Game.LoadWidget(world, "GAME_INFO_PANEL", panelRoot, new WidgetArgs() { - { "activePanel", activePanel }, + { "initialPanel", initialPanel }, { "hideMenu", requestHideMenu } }); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/MenuButtonsChromeLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/MenuButtonsChromeLogic.cs index 9f99fec04e..3cbd63a878 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/MenuButtonsChromeLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/MenuButtonsChromeLogic.cs @@ -47,7 +47,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic blinking = false; OpenMenuPanel(options, new WidgetArgs() { - { "activePanel", IngameInfoPanel.AutoSelect } + { "initialPanel", IngameInfoPanel.AutoSelect } }); }; options.IsHighlighted = () => blinking && Game.LocalTick % 50 < 25; @@ -79,7 +79,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic debug.IsDisabled = () => disableSystemButtons; debug.OnClick = () => OpenMenuPanel(debug, new WidgetArgs() { - { "activePanel", IngameInfoPanel.Debug } + { "initialPanel", IngameInfoPanel.Debug } }); } diff --git a/mods/cnc/chrome/ingame-info.yaml b/mods/cnc/chrome/ingame-info.yaml index 88b73a89a1..92b82d43ca 100644 --- a/mods/cnc/chrome/ingame-info.yaml +++ b/mods/cnc/chrome/ingame-info.yaml @@ -20,31 +20,84 @@ Container@GAME_INFO_PANEL: Align: Center Font: BigBold Contrast: true - Container@TAB_CONTAINER: + Container@TAB_CONTAINER_2: + Visible: False + Children: + Button@BUTTON1: + Y: 5 + Width: 140 + Height: 35 + Button@BUTTON2: + X: 150 + Y: 5 + Width: 140 + Height: 35 + Container@TAB_CONTAINER_3: + Visible: False Children: Button@BUTTON1: Y: 5 Width: 140 Height: 35 - Visible: False Button@BUTTON2: X: 150 Y: 5 Width: 140 Height: 35 - Visible: False Button@BUTTON3: X: 300 Y: 5 Width: 140 Height: 35 - Visible: False - Button@BUTTON4: - X: 450 + Container@TAB_CONTAINER_4: + Visible: False + Children: + Button@BUTTON1: Y: 5 - Width: 140 + Width: 121 + Height: 35 + Button@BUTTON2: + X: 131 + Y: 5 + Width: 120 + Height: 35 + Button@BUTTON3: + X: 261 + Y: 5 + Width: 120 + Height: 35 + Button@BUTTON4: + X: 391 + Y: 5 + Width: 121 + Height: 35 + Container@TAB_CONTAINER_5: + Visible: False + Children: + Button@BUTTON1: + Y: 5 + Width: 99 + Height: 35 + Button@BUTTON2: + X: 104 + Y: 5 + Width: 98 + Height: 35 + Button@BUTTON3: + X: 207 + Y: 5 + Width: 98 + Height: 35 + Button@BUTTON4: + X: 310 + Y: 5 + Width: 98 + Height: 35 + Button@BUTTON5: + X: 413 + Y: 5 + Width: 99 Height: 35 - Visible: False Background@BACKGROUND: Y: 39 Width: PARENT_RIGHT diff --git a/mods/common/chrome/ingame-info.yaml b/mods/common/chrome/ingame-info.yaml index 35c7a6d582..27412aaaa0 100644 --- a/mods/common/chrome/ingame-info.yaml +++ b/mods/common/chrome/ingame-info.yaml @@ -25,38 +25,110 @@ Container@GAME_INFO_PANEL: Height: 25 Align: Center Font: Bold - Container@TAB_CONTAINER: + Container@TAB_CONTAINER_2: + X: (PARENT_RIGHT - WIDTH) / 2 + Width: 280 + Height: 25 + Visible: False + Children: + Button@BUTTON1: + Y: 50 + Width: 140 + Height: 25 + Font: Bold + Button@BUTTON2: + X: 140 + Y: 50 + Width: 140 + Height: 25 + Font: Bold + Container@TAB_CONTAINER_3: X: (PARENT_RIGHT - WIDTH) / 2 Width: 360 Height: 25 + Visible: False + Children: + Button@BUTTON1: + Y: 50 + Width: 120 + Height: 25 + Font: Bold + Button@BUTTON2: + X: 120 + Y: 50 + Width: 120 + Height: 25 + Font: Bold + Button@BUTTON3: + X: 240 + Y: 50 + Width: 120 + Height: 25 + Font: Bold + Container@TAB_CONTAINER_4: + X: (PARENT_RIGHT - WIDTH) / 2 + Width: 480 + Height: 25 + Visible: False Children: Button@BUTTON1: Y: 50 Width: 120 Height: 25 Font: Bold - Visible: False Button@BUTTON2: X: 120 Y: 50 Width: 120 Height: 25 Font: Bold - Visible: False Button@BUTTON3: X: 240 Y: 50 Width: 120 Height: 25 Font: Bold - Visible: False Button@BUTTON4: X: 360 Y: 50 Width: 120 Height: 25 Font: Bold - Visible: False + Container@TAB_CONTAINER_5: + X: (PARENT_RIGHT - WIDTH) / 2 + Width: 480 + Height: 25 + Visible: False + Children: + Button@BUTTON1: + Y: 50 + Width: 96 + Height: 25 + Font: Bold + Button@BUTTON2: + X: 96 + Y: 50 + Width: 96 + Height: 25 + Font: Bold + Button@BUTTON3: + X: 192 + Y: 50 + Width: 96 + Height: 25 + Font: Bold + Button@BUTTON4: + X: 288 + Y: 50 + Width: 96 + Height: 25 + Font: Bold + Button@BUTTON5: + X: 384 + Y: 50 + Width: 96 + Height: 25 + Font: Bold Container@STATS_PANEL: Y: 65 Container@MAP_PANEL: