diff --git a/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs b/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs index 6f5eda33f0..6178e04f40 100644 --- a/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs +++ b/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs @@ -124,7 +124,7 @@ namespace OpenRA.Mods.Common.LoadScreens if (contentInstalled) return true; - Game.InitializeMod(content.ContentInstallerMod, new Arguments()); + Game.InitializeMod(content.ContentInstallerMod, new Arguments(new[] { "Content.Mod=" + modData.Manifest.Id })); return false; } } diff --git a/OpenRA.Mods.Common/LoadScreens/ModChooserLoadScreen.cs b/OpenRA.Mods.Common/LoadScreens/ModContentLoadScreen.cs similarity index 52% rename from OpenRA.Mods.Common/LoadScreens/ModChooserLoadScreen.cs rename to OpenRA.Mods.Common/LoadScreens/ModContentLoadScreen.cs index 69e5fa3e64..a5b190edaf 100644 --- a/OpenRA.Mods.Common/LoadScreens/ModChooserLoadScreen.cs +++ b/OpenRA.Mods.Common/LoadScreens/ModContentLoadScreen.cs @@ -9,14 +9,17 @@ */ #endregion +using System; using System.Collections.Generic; using System.Drawing; +using System.IO; +using System.Linq; using OpenRA.Graphics; using OpenRA.Widgets; namespace OpenRA.Mods.Common.LoadScreens { - public sealed class ModChooserLoadScreen : ILoadScreen + public sealed class ModContentLoadScreen : ILoadScreen { Sprite sprite; Rectangle bounds; @@ -46,10 +49,46 @@ namespace OpenRA.Mods.Common.LoadScreens public void StartGame(Arguments args) { - var widgetArgs = new WidgetArgs(); + var modId = args.GetValue("Content.Mod", null); + Manifest selectedMod; + if (modId == null || !Game.Mods.TryGetValue(modId, out selectedMod)) + throw new InvalidOperationException("Invalid or missing Content.Mod argument."); - Ui.LoadWidget("MODCHOOSER_BACKGROUND", Ui.Root, widgetArgs); - Ui.OpenWindow("MODCHOOSER_DIALOG", widgetArgs); + var content = selectedMod.Get(Game.ModData.ObjectCreator); + + Ui.LoadWidget("MODCHOOSER_BACKGROUND", Ui.Root, new WidgetArgs()); + + if (!IsModInstalled(content)) + { + var widgetArgs = new WidgetArgs + { + { "continueLoading", () => + Game.RunAfterTick(() => Game.InitializeMod(modId, new Arguments())) }, + { "mod", selectedMod }, + { "content", content }, + }; + + Ui.OpenWindow("CONTENT_PROMPT_PANEL", widgetArgs); + } + else + { + var widgetArgs = new WidgetArgs + { + { "mod", selectedMod }, + { "content", content }, + { "onCancel", () => + Game.RunAfterTick(() => Game.InitializeMod(modId, new Arguments())) } + }; + + Ui.OpenWindow("CONTENT_PANEL", widgetArgs); + } + } + + bool IsModInstalled(ModContent content) + { + return content.Packages + .Where(p => p.Value.Required) + .All(p => p.Value.TestFiles.All(f => File.Exists(Platform.ResolvePath(f)))); } public void Dispose() diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 431ab3c817..61f03891a0 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -184,7 +184,7 @@ - + @@ -632,7 +632,6 @@ - diff --git a/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentPromptLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentPromptLogic.cs index f7f35b6ead..ab57f27801 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentPromptLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentPromptLogic.cs @@ -46,7 +46,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { { "mod", mod }, { "content", content }, - { "onCancel", Ui.CloseWindow } + { "onCancel", () => { } } }); }; @@ -71,9 +71,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic }); }; - var backButton = panel.Get("BACK_BUTTON"); - backButton.Bounds.Y += headerHeight; - backButton.OnClick = Ui.CloseWindow; + var quitButton = panel.Get("QUIT_BUTTON"); + quitButton.Bounds.Y += headerHeight; + quitButton.OnClick = Game.Exit; Game.RunAfterTick(Ui.ResetTooltips); } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs index fcca9bc248..f7a6d22308 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs @@ -87,13 +87,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic }); }; - mainMenu.Get("MODS_BUTTON").OnClick = () => + mainMenu.Get("CONTENT_BUTTON").OnClick = () => { // Switching mods changes the world state (by disposing it), // so we can't do this inside the input handler. Game.RunAfterTick(() => { - Game.InitializeMod("modchooser", null); + Game.InitializeMod("modchooser", new Arguments(new[] { "Content.Mod=" + modData.Manifest.Id })); }); }; diff --git a/OpenRA.Mods.Common/Widgets/Logic/ModBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/ModBrowserLogic.cs deleted file mode 100644 index 583e296537..0000000000 --- a/OpenRA.Mods.Common/Widgets/Logic/ModBrowserLogic.cs +++ /dev/null @@ -1,211 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2017 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.Drawing; -using System.IO; -using System.Linq; -using OpenRA.Graphics; -using OpenRA.Primitives; -using OpenRA.Widgets; - -namespace OpenRA.Mods.Common.Widgets.Logic -{ - public class ModBrowserLogic : ChromeLogic - { - readonly Widget modList; - readonly ButtonWidget modTemplate; - readonly Manifest[] allMods; - readonly Dictionary previews = new Dictionary(); - readonly Dictionary logos = new Dictionary(); - readonly Cache content = new Cache(LoadModContent); - - readonly Widget modChooserPanel; - readonly ButtonWidget loadButton; - readonly SheetBuilder sheetBuilder; - Manifest selectedMod; - string selectedAuthor; - string selectedDescription; - int modOffset = 0; - - static ModContent LoadModContent(Manifest mod) - { - return mod.Get(Game.ModData.ObjectCreator); - } - - [ObjectCreator.UseCtor] - public ModBrowserLogic(Widget widget, ModData modData) - { - modChooserPanel = widget; - loadButton = modChooserPanel.Get("LOAD_BUTTON"); - loadButton.OnClick = () => LoadMod(selectedMod); - loadButton.IsDisabled = () => selectedMod.Id == modData.Manifest.Id; - - var contentButton = modChooserPanel.Get("CONFIGURE_BUTTON"); - contentButton.OnClick = () => - { - var widgetArgs = new WidgetArgs - { - { "mod", selectedMod }, - { "content", content[selectedMod] }, - { "onCancel", () => { } } - }; - - Ui.OpenWindow("CONTENT_PANEL", widgetArgs); - }; - - modChooserPanel.Get("QUIT_BUTTON").OnClick = Game.Exit; - - modList = modChooserPanel.Get("MOD_LIST"); - modTemplate = modList.Get("MOD_TEMPLATE"); - - modChooserPanel.Get("MOD_DESC").GetText = () => selectedDescription; - modChooserPanel.Get("MOD_TITLE").GetText = () => selectedMod.Metadata.Title; - modChooserPanel.Get("MOD_AUTHOR").GetText = () => selectedAuthor; - modChooserPanel.Get("MOD_VERSION").GetText = () => selectedMod.Metadata.Version; - - var prevMod = modChooserPanel.Get("PREV_MOD"); - prevMod.OnClick = () => { modOffset -= 1; RebuildModList(); }; - prevMod.IsVisible = () => modOffset > 0; - - var nextMod = modChooserPanel.Get("NEXT_MOD"); - nextMod.OnClick = () => { modOffset += 1; RebuildModList(); }; - nextMod.IsVisible = () => modOffset + 5 < allMods.Length; - - modChooserPanel.Get("MOD_PREVIEW").GetSprite = () => - { - Sprite ret = null; - previews.TryGetValue(selectedMod.Id, out ret); - return ret; - }; - - sheetBuilder = new SheetBuilder(SheetType.BGRA); - allMods = Game.Mods.Values.Where(m => !m.Metadata.Hidden) - .OrderBy(m => m.Metadata.Title) - .ToArray(); - - // Load preview images, and eat any errors - foreach (var mod in allMods) - { - try - { - using (var stream = mod.Package.GetStream("preview.png")) - using (var preview = new Bitmap(stream)) - if (preview.Width == 296 && preview.Height == 196) - previews.Add(mod.Id, sheetBuilder.Add(preview)); - } - catch (Exception) { } - - try - { - using (var stream = mod.Package.GetStream("logo.png")) - using (var logo = new Bitmap(stream)) - if (logo.Width == 96 && logo.Height == 96) - logos.Add(mod.Id, sheetBuilder.Add(logo)); - } - catch (Exception) { } - } - - SelectMod(Game.Mods["ra"]); - - RebuildModList(); - } - - void RebuildModList() - { - modList.RemoveChildren(); - - var width = modTemplate.Bounds.Width; - var height = modTemplate.Bounds.Height; - var innerMargin = modTemplate.Bounds.Left; - var outerMargin = (modList.Bounds.Width - Math.Min(5, allMods.Length) * width - 4 * innerMargin) / 2; - var stride = width + innerMargin; - - for (var i = 0; i < 5; i++) - { - var j = i + modOffset; - if (j >= allMods.Length) - break; - - var mod = allMods[j]; - - var item = modTemplate.Clone() as ButtonWidget; - item.Bounds = new Rectangle(outerMargin + i * stride, 0, width, height); - item.IsHighlighted = () => selectedMod == mod; - item.OnClick = () => SelectMod(mod); - item.OnDoubleClick = () => LoadMod(mod); - item.OnKeyPress = e => - { - if (e.MultiTapCount == 2) - LoadMod(mod); - else - SelectMod(mod); - }; - - item.TooltipText = mod.Metadata.Title; - - if (j < 9) - item.Key = new Hotkey((Keycode)((int)Keycode.NUMBER_1 + j), Modifiers.None); - - Sprite logo = null; - logos.TryGetValue(mod.Id, out logo); - item.Get("MOD_LOGO").GetSprite = () => logo; - item.Get("MOD_NO_LOGO").IsVisible = () => logo == null; - - modList.AddChild(item); - } - } - - void SelectMod(Manifest mod) - { - selectedMod = mod; - selectedAuthor = "By " + (mod.Metadata.Author ?? "unknown author"); - selectedDescription = (mod.Metadata.Description ?? "").Replace("\\n", "\n"); - var selectedIndex = Array.IndexOf(allMods, mod); - if (selectedIndex - modOffset > 4) - modOffset = selectedIndex - 4; - } - - void LoadMod(Manifest mod) - { - var modId = mod.Id; - if (!IsModInstalled(mod)) - { - var widgetArgs = new WidgetArgs - { - { "continueLoading", () => - Game.RunAfterTick(() => Game.InitializeMod(modId, new Arguments())) }, - { "mod", selectedMod }, - { "content", content[selectedMod] }, - }; - - Ui.OpenWindow("CONTENT_PROMPT_PANEL", widgetArgs); - - return; - } - - Game.RunAfterTick(() => - { - Ui.CloseWindow(); - sheetBuilder.Dispose(); - Game.InitializeMod(modId, null); - }); - } - - bool IsModInstalled(Manifest mod) - { - return content[mod].Packages - .Where(p => p.Value.Required) - .All(p => p.Value.TestFiles.All(f => File.Exists(Platform.ResolvePath(f)))); - } - } -} diff --git a/mods/cnc/chrome/mainmenu.yaml b/mods/cnc/chrome/mainmenu.yaml index e4e32ad134..92e9144580 100644 --- a/mods/cnc/chrome/mainmenu.yaml +++ b/mods/cnc/chrome/mainmenu.yaml @@ -78,12 +78,12 @@ Container@MENU_BACKGROUND: Width: 140 Height: 35 Text: Extras - Button@MODS_BUTTON: + Button@CONTENT_BUTTON: X: 600 Y: 0 Width: 140 Height: 35 - Text: Mods + Text: Manage Content Button@QUIT_BUTTON: X: 750 Y: 0 diff --git a/mods/common/chrome/mainmenu.yaml b/mods/common/chrome/mainmenu.yaml index d03c893d16..db6ebe980f 100644 --- a/mods/common/chrome/mainmenu.yaml +++ b/mods/common/chrome/mainmenu.yaml @@ -70,12 +70,12 @@ Container@MAINMENU: Height: 30 Text: Extras Font: Bold - Button@MODS_BUTTON: + Button@CONTENT_BUTTON: X: PARENT_RIGHT/2-WIDTH/2 Y: 220 Width: 140 Height: 30 - Text: Mods + Text: Manage Content Font: Bold Button@QUIT_BUTTON: X: PARENT_RIGHT/2-WIDTH/2 diff --git a/mods/d2k/chrome/mainmenu.yaml b/mods/d2k/chrome/mainmenu.yaml index c5d368ea59..eafb423d12 100644 --- a/mods/d2k/chrome/mainmenu.yaml +++ b/mods/d2k/chrome/mainmenu.yaml @@ -57,12 +57,12 @@ Container@MAINMENU: Height: 30 Text: Extras Font: Bold - Button@MODS_BUTTON: + Button@CONTENT_BUTTON: X: PARENT_RIGHT/2-WIDTH/2 Y: 220 Width: 140 Height: 30 - Text: Mods + Text: Manage Content Font: Bold Button@QUIT_BUTTON: X: PARENT_RIGHT/2-WIDTH/2 diff --git a/mods/modchooser/content.yaml b/mods/modchooser/content.yaml index 0acf4b8f92..caee857ccf 100644 --- a/mods/modchooser/content.yaml +++ b/mods/modchooser/content.yaml @@ -331,12 +331,31 @@ Background@CONTENT_PROMPT_PANEL: Height: 32 Text: Quick Install Font: Bold - Button@BACK_BUTTON: + Button@QUIT_BUTTON: X: PARENT_RIGHT - WIDTH - 30 Y: PARENT_BOTTOM - 52 Background: button-highlighted Width: 110 Height: 32 - Text: Back + Text: Quit Font: Bold Key: escape + +Background@MODCHOOSER_BACKGROUND: + Background: background + Width: WINDOW_RIGHT + Height: WINDOW_BOTTOM + +Background@BUTTON_TOOLTIP: + Logic: ButtonTooltipLogic + Background: panel-thinborder + Height: 25 + Children: + Label@LABEL: + X: 5 + Height: 23 + Font: Bold + Label@HOTKEY: + TextColor: FFFF00 + Height: 23 + Font: Bold diff --git a/mods/modchooser/mod.yaml b/mods/modchooser/mod.yaml index 9f57c94f9d..488606e845 100644 --- a/mods/modchooser/mod.yaml +++ b/mods/modchooser/mod.yaml @@ -1,5 +1,5 @@ Metadata: - Title: Mod Chooser + Title: Mod Content Manager Version: {DEV_VERSION} Author: The OpenRA Developers Hidden: true @@ -19,13 +19,12 @@ Assemblies: common|OpenRA.Mods.Common.dll ChromeLayout: - modchooser|modchooser.yaml modchooser|content.yaml Notifications: modchooser|notifications.yaml -LoadScreen: ModChooserLoadScreen +LoadScreen: ModContentLoadScreen Image: ./mods/modchooser/chrome.png ChromeMetrics: diff --git a/mods/modchooser/modchooser.yaml b/mods/modchooser/modchooser.yaml deleted file mode 100644 index c4ce98d92f..0000000000 --- a/mods/modchooser/modchooser.yaml +++ /dev/null @@ -1,169 +0,0 @@ -Background@MODCHOOSER_BACKGROUND: - Background: background - Width: WINDOW_RIGHT - Height: WINDOW_BOTTOM - -Background@MODCHOOSER_DIALOG: - Logic: ModBrowserLogic - Children: - Container: - X: (WINDOW_RIGHT - WIDTH) / 2 - Y: (WINDOW_BOTTOM - 500) / 2 - Width: 750 - Height: 514 - Children: - Background@DIALOG_BACKGROUND: - Y: 69 - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - 69 - Background: panel-bg - Children: - Label: - X: 53 - Y: 30 - Align: Left - Font: MediumBold - Text: Choose your Battlefield: - Container@MOD_LIST: - X: 53 - Y: 60 - Width: PARENT_RIGHT-106 - Height: 150 - Children: - Button@MOD_TEMPLATE: - X: 16 - Width: 114 - Height: 114 - TooltipContainer: TOOLTIP_CONTAINER - IgnoreChildMouseOver: true - Children: - Container@MOD_NO_LOGO: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Children: - Label@A: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM-20 - Text: Missing or - Align: Center - Label@B: - Y: 20 - Width: PARENT_RIGHT - Height: PARENT_BOTTOM-20 - Text: invalid logo - Align: Center - RGBASprite@MOD_LOGO: - X: 9 - Y: 9 - Button@PREV_MOD: - X: 15 - Y: 85 - Width: 25 - Height: 64 - IgnoreChildMouseOver: true - Children: - Image: - X: 2 - ImageCollection: modchooser - ImageName: leftarrow - Button@NEXT_MOD: - X: PARENT_RIGHT - WIDTH - 20 - Y: 85 - Width: 25 - Height: 64 - IgnoreChildMouseOver: true - Children: - Image: - X: 3 - ImageCollection: modchooser - ImageName: rightarrow - Background@RULE: - X: 30 - Y: PARENT_BOTTOM - 249 - Width: PARENT_RIGHT - 60 - Height: 150 - Background: panel-rule - Label@MOD_TITLE: - X: PARENT_RIGHT - 400 - Y: PARENT_BOTTOM-220 - Align: Left - Font: Bold - Label@MOD_AUTHOR: - X: PARENT_RIGHT - 400 - Y: PARENT_BOTTOM-205 - Align: Left - Font: TinyBold - Label@MOD_VERSION: - X: PARENT_RIGHT - 400 - Y: PARENT_BOTTOM-192 - Align: Left - Font: Tiny - Label@MOD_DESC: - X: PARENT_RIGHT - 400 - Y: PARENT_BOTTOM-175 - Align: Left - VAlign: Top - Font: Tiny - Background@PREVIEW: - X: 30 - Y: PARENT_BOTTOM - 25 - HEIGHT - Width: 300 - Height: 200 - Background: panel-thinborder - Children: - Label: - Width: PARENT_RIGHT - Height: PARENT_BOTTOM - Text: Missing or invalid preview - Align: Center - RGBASprite@MOD_PREVIEW: - X: 2 - Y: 2 - Button@LOAD_BUTTON: - X: PARENT_RIGHT - 300 - WIDTH - Y: PARENT_BOTTOM - 25 - HEIGHT - Width: 100 - Height: 32 - Text: Play - Background: button-highlighted - Key: return - Button@CONFIGURE_BUTTON: - X: PARENT_RIGHT - 145 - WIDTH - Y: PARENT_BOTTOM - 25 - HEIGHT - Width: 140 - Height: 32 - Text: Manage Content - Background: button-highlighted - Button@QUIT_BUTTON: - X: PARENT_RIGHT - 30 - WIDTH - Y: PARENT_BOTTOM - 25 - HEIGHT - Width: 100 - Height: 32 - Text: Quit - Background: button-highlighted - Background@DIALOG_HEADER: - Width: PARENT_RIGHT - Height: 72 - Background: panel-header - Children: - Image: - X: (PARENT_RIGHT - WIDTH) / 2 - Y: 0-28 - Width: 280 - ImageCollection: modchooser - ImageName: logo - TooltipContainer@TOOLTIP_CONTAINER: - -Background@BUTTON_TOOLTIP: - Logic: ButtonTooltipLogic - Background: panel-thinborder - Height: 25 - Children: - Label@LABEL: - X: 5 - Height: 23 - Font: Bold - Label@HOTKEY: - TextColor: FFFF00 - Height: 23 - Font: Bold \ No newline at end of file