diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs index 73144f0c94..ee662f5cb9 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs @@ -20,24 +20,20 @@ namespace OpenRA.Mods.Common.Widgets.Logic public class SaveMapLogic { [ObjectCreator.UseCtor] - public SaveMapLogic(Widget widget, Action onExit, World world) + public SaveMapLogic(Widget widget, Action onExit, Map map, EditorActorLayer editorActorLayer) { - var newMap = world.Map; + var title = widget.Get("TITLE"); + title.Text = map.Title; - var title = widget.GetOrNull("TITLE"); - if (title != null) - title.Text = newMap.Title; + var author = widget.Get("AUTHOR"); + author.Text = map.Author; - var description = widget.GetOrNull("DESCRIPTION"); - if (description != null) - description.Text = newMap.Description; + // TODO: This should use a multi-line textfield once they exist + var description = widget.Get("DESCRIPTION"); + description.Text = map.Description; - var author = widget.GetOrNull("AUTHOR"); - if (author != null) - author.Text = newMap.Author; - - var visibilityDropdown = widget.GetOrNull("CLASS_DROPDOWN"); - if (visibilityDropdown != null) + // TODO: This should use a multi-selection dropdown once they exist + var visibilityDropdown = widget.Get("VISIBILITY_DROPDOWN"); { var mapVisibility = new List(Enum.GetNames(typeof(MapVisibility))); Func setupItem = (option, template) => @@ -48,75 +44,98 @@ namespace OpenRA.Mods.Common.Widgets.Logic item.Get("LABEL").GetText = () => option; return item; }; - visibilityDropdown.Text = Enum.GetName(typeof(MapVisibility), newMap.Visibility); + + visibilityDropdown.Text = Enum.GetName(typeof(MapVisibility), map.Visibility); visibilityDropdown.OnClick = () => visibilityDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, mapVisibility, setupItem); } - var pathDropdown = widget.GetOrNull("PATH_DROPDOWN"); - if (pathDropdown != null) + var directoryDropdown = widget.Get("DIRECTORY_DROPDOWN"); { - var mapFolders = new List(); - foreach (var mapFolder in Game.ModData.Manifest.MapFolders.Keys) + var mapDirectories = Game.ModData.Manifest.MapFolders.Keys.Select(ff => { - var folder = mapFolder; - if (mapFolder.StartsWith("~")) - folder = mapFolder.Substring(1); + var f = Platform.UnresolvePath(ff); + if (f.StartsWith("~")) + f = f.Substring(1); - mapFolders.Add(Platform.ResolvePath(folder)); - } + return f; + }).ToList(); Func setupItem = (option, template) => { var item = ScrollItemWidget.Setup(template, - () => pathDropdown.Text == Platform.UnresolvePath(option), - () => { pathDropdown.Text = Platform.UnresolvePath(option); }); + () => directoryDropdown.Text == option, + () => directoryDropdown.Text = option); item.Get("LABEL").GetText = () => option; return item; }; - var userMapFolder = Game.ModData.Manifest.MapFolders.First(f => f.Value == "User").Key; - if (userMapFolder.StartsWith("~")) - userMapFolder = userMapFolder.Substring(1); - pathDropdown.Text = Platform.UnresolvePath(userMapFolder); - pathDropdown.OnClick = () => - pathDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, mapFolders, setupItem); + var mapDirectory = Platform.UnresolvePath(Path.GetDirectoryName(map.Path)); + var initialDirectory = mapDirectories.FirstOrDefault(f => f == mapDirectory); + + if (initialDirectory == null) + initialDirectory = mapDirectories.First(); + + directoryDropdown.Text = initialDirectory; + directoryDropdown.OnClick = () => + directoryDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, mapDirectories, setupItem); } - var filename = widget.GetOrNull("FILENAME"); - if (filename != null) - filename.Text = Path.GetFileName(world.Map.Path); + var filename = widget.Get("FILENAME"); + filename.Text = Path.GetFileNameWithoutExtension(map.Path); - var close = widget.GetOrNull("CLOSE"); - if (close != null) - close.OnClick = () => { Ui.CloseWindow(); onExit(); }; - - var save = widget.GetOrNull("SAVE"); - if (save != null && !string.IsNullOrEmpty(filename.Text)) + var fileTypes = new Dictionary() { - var editorLayer = world.WorldActor.Trait(); - save.OnClick = () => + { ".oramap", ".oramap" }, + { "(unpacked)", "" } + }; + + var typeDropdown = widget.Get("TYPE_DROPDOWN"); + { + Func setupItem = (option, template) => { - newMap.Title = title.Text; - newMap.Description = description.Text; - newMap.Author = author.Text; - newMap.Visibility = (MapVisibility)Enum.Parse(typeof(MapVisibility), visibilityDropdown.Text); - newMap.ActorDefinitions = editorLayer.Save(); - newMap.PlayerDefinitions = editorLayer.Players.ToMiniYaml(); - newMap.RequiresMod = Game.ModData.Manifest.Mod.Id; - - var combinedPath = Path.Combine(pathDropdown.Text, filename.Text); - var resolvedPath = Platform.ResolvePath(combinedPath); - newMap.Save(resolvedPath); - - // Update the map cache so it can be loaded without restarting the game - Game.ModData.MapCache[newMap.Uid].UpdateFromMap(newMap, MapClassification.User); - - Console.WriteLine("Saved current map at {0}", resolvedPath); - Ui.CloseWindow(); - onExit(); + var item = ScrollItemWidget.Setup(template, + () => typeDropdown.Text == option, + () => typeDropdown.Text = option); + item.Get("LABEL").GetText = () => option; + return item; }; + + typeDropdown.Text = Path.GetExtension(map.Path); + if (string.IsNullOrEmpty(typeDropdown.Text)) + typeDropdown.Text = fileTypes.First(t => t.Value == "").Key; + + typeDropdown.OnClick = () => + typeDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 210, fileTypes.Keys, setupItem); } + + var close = widget.Get("BACK_BUTTON"); + close.OnClick = () => { Ui.CloseWindow(); onExit(); }; + + var save = widget.Get("SAVE_BUTTON"); + save.OnClick = () => + { + if (string.IsNullOrEmpty(filename.Text)) + return; + + map.Title = title.Text; + map.Description = description.Text; + map.Author = author.Text; + map.Visibility = (MapVisibility)Enum.Parse(typeof(MapVisibility), visibilityDropdown.Text); + map.ActorDefinitions = editorActorLayer.Save(); + map.PlayerDefinitions = editorActorLayer.Players.ToMiniYaml(); + map.RequiresMod = Game.ModData.Manifest.Mod.Id; + + var combinedPath = Platform.ResolvePath(Path.Combine(directoryDropdown.Text, filename.Text + fileTypes[typeDropdown.Text])); + map.Save(combinedPath); + + // Update the map cache so it can be loaded without restarting the game + Game.ModData.MapCache[map.Uid].UpdateFromMap(map, MapClassification.User); + + Console.WriteLine("Saved current map at {0}", combinedPath); + Ui.CloseWindow(); + onExit(); + }; } } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs index 88ea5197a0..f06b6be483 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs @@ -101,11 +101,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic saveMapButton.IsVisible = () => world.Type == WorldType.Editor; saveMapButton.OnClick = () => { + hideMenu = true; Ui.OpenWindow("SAVE_MAP_PANEL", new WidgetArgs() - { - { "onExit", () => widget.Visible = true }, - { "world", world }, - }); + { + { "onExit", () => hideMenu = false }, + { "map", world.Map }, + { "editorActorLayer", world.WorldActor.Trait() } + }); }; menu.Get("MUSIC").OnClick = () => diff --git a/mods/cnc/chrome/editor.yaml b/mods/cnc/chrome/editor.yaml index 2307ad7218..cdd1733c4a 100644 --- a/mods/cnc/chrome/editor.yaml +++ b/mods/cnc/chrome/editor.yaml @@ -74,13 +74,14 @@ Container@NEW_MAP_BG: Key: return -Container@SAVE_MAP_PANEL: +Background@SAVE_MAP_PANEL: + Logic: SaveMapLogic X: (WINDOW_RIGHT - WIDTH)/2 Y: (WINDOW_BOTTOM - HEIGHT)/2 - Width: 350 - Height: 330 + Width: 345 + Height: 264 Children: - Label@TITLE: + Label@LABEL_TITLE: Text: Save Map Width: PARENT_RIGHT Y: 0-25 @@ -88,101 +89,107 @@ Container@SAVE_MAP_PANEL: Contrast: true Align: Center Background@SAVE_MAP_BACKGROUND: - Logic: SaveMapLogic Width: PARENT_RIGHT - Height: 295 + Height: 230 Background: panel-black Children: Label@TITLE_LABEL: X: 10 - Y: 39 + Y: 14 Width: 95 Height: 25 Align: Right Text: Title: TextField@TITLE: X: 110 - Y: 40 - Width: 210 - MaxLength: 50 - Height: 25 - Label@DESCRIPTION_LABEL: - X: 10 - Y: 79 - Width: 95 - Height: 25 - Align: Right - Text: Description: - TextField@DESCRIPTION: - X: 110 - Y: 80 - Width: 210 + Y: 15 + Width: 220 MaxLength: 50 Height: 25 Label@AUTHOR_LABEL: X: 10 - Y: 119 + Y: 49 Width: 95 Height: 25 Align: Right Text: Author: TextField@AUTHOR: X: 110 - Y: 120 - Width: 210 + Y: 50 + Width: 220 MaxLength: 50 Height: 25 - Label@CLASS_LABEL: + Label@DESCRIPTION_LABEL: X: 10 - Y: 160 + Y: 84 Width: 95 Height: 25 Align: Right - Text: Class: - DropDownButton@CLASS_DROPDOWN: + Text: Description: + TextField@DESCRIPTION: X: 110 - Y: 160 - Width: 210 + Y: 85 + Width: 220 + MaxLength: 50 Height: 25 - Label@PATH_LABEL: + Label@VISIBILITY_LABEL: X: 10 - Y: 199 - Width: 40 + Y: 119 + Width: 95 Height: 25 Align: Right - Text: Path: - DropDownButton@PATH_DROPDOWN: - X: 60 - Y: 200 - Width: 270 + Text: Visibility: + DropDownButton@VISIBILITY_DROPDOWN: + X: 110 + Y: 120 + Width: 220 Height: 25 + Font: Regular + Label@DIRECTORY_LABEL: + X: 10 + Y: 154 + Width: 95 + Height: 25 + Align: Right + Text: Directory: + DropDownButton@DIRECTORY_DROPDOWN: + X: 110 + Y: 155 + Width: 220 + Height: 25 + Font: Regular Label@FILENAME_LABEL: X: 10 - Y: 239 - Width: 40 + Y: 189 + Width: 95 Height: 25 Align: Right - Text: File: + Text: Filename: TextField@FILENAME: - X: 60 - Y: 240 - Width: 270 + X: 110 + Y: 190 + Width: 105 Height: 25 - Button@CLOSE: - X: 0 - Y: 294 - Width: 140 - Height: 35 - Text: Close - Font: Bold - Key: escape - Button@SAVE: - X: PARENT_RIGHT - WIDTH - Y: 294 - Width: 140 - Height: 35 - Text: Save - Font: Bold + DropDownButton@TYPE_DROPDOWN: + X: 220 + Y: 190 + Width: 110 + Height: 25 + Font: Regular + Button@BACK_BUTTON: + Y: PARENT_BOTTOM - 35 + Width: 140 + Height: 35 + Text: Cancel + Font: Bold + Key: escape + Button@SAVE_BUTTON: + X: PARENT_RIGHT - 140 + Y: PARENT_BOTTOM - 35 + Width: 140 + Height: 35 + Text: Save + Font: Bold Container@EDITOR_ROOT: Logic: LoadMapEditorLogic diff --git a/mods/ra/chrome/editor.yaml b/mods/ra/chrome/editor.yaml index 64d0d21bb2..e1ce379a32 100644 --- a/mods/ra/chrome/editor.yaml +++ b/mods/ra/chrome/editor.yaml @@ -75,7 +75,7 @@ Background@SAVE_MAP_PANEL: X: (WINDOW_RIGHT - WIDTH)/2 Y: (WINDOW_BOTTOM - HEIGHT)/2 Width: 350 - Height: 350 + Height: 335 Children: Label@LABEL_TITLE: X: (PARENT_RIGHT - WIDTH)/2 @@ -95,86 +95,91 @@ Background@SAVE_MAP_PANEL: TextField@TITLE: X: 110 Y: 60 - Width: 210 - MaxLength: 50 - Height: 25 - Label@DESCRIPTION_LABEL: - X: 10 - Y: 99 - Width: 95 - Height: 25 - Align: Right - Text: Description: - TextField@DESCRIPTION: - X: 110 - Y: 100 - Width: 210 + Width: 220 MaxLength: 50 Height: 25 Label@AUTHOR_LABEL: X: 10 - Y: 139 + Y: 94 Width: 95 Height: 25 Align: Right Text: Author: TextField@AUTHOR: X: 110 - Y: 140 - Width: 210 + Y: 95 + Width: 220 MaxLength: 50 Height: 25 - Label@CLASS_LABEL: + Label@DESCRIPTION_LABEL: X: 10 - Y: 180 + Y: 129 Width: 95 Height: 25 Align: Right - Text: Class: - DropDownButton@CLASS_DROPDOWN: + Text: Description: + TextField@DESCRIPTION: X: 110 - Y: 180 - Width: 210 + Y: 130 + Width: 220 + MaxLength: 50 Height: 25 - Label@PATH_LABEL: + Label@VISIBILITY_LABEL: X: 10 - Y: 219 - Width: 40 + Y: 164 + Width: 95 Height: 25 Align: Right - Text: Path: - DropDownButton@PATH_DROPDOWN: - X: 60 - Y: 220 - Width: 270 + Text: Visibility: + DropDownButton@VISIBILITY_DROPDOWN: + X: 110 + Y: 165 + Width: 220 + Height: 25 + Label@DIRECTORY_LABEL: + X: 10 + Y: 199 + Width: 95 + Height: 25 + Align: Right + Text: Directory: + DropDownButton@DIRECTORY_DROPDOWN: + X: 110 + Y: 200 + Width: 220 Height: 25 Label@FILENAME_LABEL: X: 10 - Y: 259 - Width: 40 + Y: 234 + Width: 95 Height: 25 Align: Right - Text: File: + Text: Filename: TextField@FILENAME: - X: 60 - Y: 260 - Width: 270 + X: 110 + Y: 235 + Width: 105 Height: 25 - Button@CLOSE: - X: 30 - Y: 300 - Width: 100 + DropDownButton@TYPE_DROPDOWN: + X: 220 + Y: 235 + Width: 110 Height: 25 - Text: Close - Font: Bold - Key: escape - Button@SAVE: - X: 210 - Y: 300 - Width: 100 + Button@SAVE_BUTTON: + X: 80 + Y: PARENT_BOTTOM - 45 + Width: 120 Height: 25 Text: Save Font: Bold + Button@BACK_BUTTON: + X: 210 + Y: PARENT_BOTTOM - 45 + Width: 120 + Height: 25 + Text: Cancel + Font: Bold + Key: escape Container@EDITOR_ROOT: Logic: LoadMapEditorLogic