Add a quick save button to the map editor.

This commit is contained in:
Matthias Mailänder
2022-12-25 17:59:56 +01:00
committed by Gustas
parent 3dd1fd6b00
commit 7cdc8c4ec5
10 changed files with 202 additions and 54 deletions

View File

@@ -31,10 +31,12 @@ namespace OpenRA.Mods.Common.Traits
int nextId; int nextId;
public bool Modified; public bool Modified;
public bool SaveFailed;
public void WorldLoaded(World w, WorldRenderer wr) public void WorldLoaded(World w, WorldRenderer wr)
{ {
Add(new OpenMapAction()); Add(new OpenMapAction());
Modified = false;
} }
public void Add(IEditorAction editorAction) public void Add(IEditorAction editorAction)

View File

@@ -81,6 +81,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ "onSave", afterSave }, { "onSave", afterSave },
{ "onExit", () => { Ui.CloseWindow(); onExit(); } }, { "onExit", () => { Ui.CloseWindow(); onExit(); } },
{ "map", map }, { "map", map },
{ "world", world },
{ "playerDefinitions", map.PlayerDefinitions }, { "playerDefinitions", map.PlayerDefinitions },
{ "actorDefinitions", map.ActorDefinitions } { "actorDefinitions", map.ActorDefinitions }
}); });

View File

@@ -14,6 +14,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using OpenRA.FileSystem; using OpenRA.FileSystem;
using OpenRA.Mods.Common.Traits;
using OpenRA.Widgets; using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic namespace OpenRA.Mods.Common.Widgets.Logic
@@ -49,7 +50,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
const string SaveMapFailedPrompt = "dialog-save-map-failed.prompt"; const string SaveMapFailedPrompt = "dialog-save-map-failed.prompt";
[TranslationReference] [TranslationReference]
const string SaveMapFailedAccept = "dialog-save-map-failed.confirm"; const string SaveMapFailedConfirm = "dialog-save-map-failed.confirm";
[TranslationReference] [TranslationReference]
const string Unpacked = "label-unpacked-map"; const string Unpacked = "label-unpacked-map";
@@ -61,7 +62,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
const string OverwriteMapFailedPrompt = "dialog-overwrite-map-failed.prompt"; const string OverwriteMapFailedPrompt = "dialog-overwrite-map-failed.prompt";
[TranslationReference] [TranslationReference]
const string SaveMapFailedConfirm = "dialog-overwrite-map-failed.confirm"; const string OverwriteMapFailedConfirm = "dialog-overwrite-map-failed.confirm";
[TranslationReference] [TranslationReference]
const string OverwriteMapOutsideEditTitle = "dialog-overwrite-map-outside-edit.title"; const string OverwriteMapOutsideEditTitle = "dialog-overwrite-map-outside-edit.title";
@@ -72,9 +73,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
[TranslationReference] [TranslationReference]
const string SaveMapMapOutsideConfirm = "dialog-overwrite-map-outside-edit.confirm"; const string SaveMapMapOutsideConfirm = "dialog-overwrite-map-outside-edit.confirm";
[TranslationReference]
const string SaveCurrentMap = "notification-save-current-map";
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public SaveMapLogic(Widget widget, ModData modData, Action<string> onSave, Action onExit, public SaveMapLogic(Widget widget, ModData modData, Map map, Action<string> onSave, Action onExit,
Map map, List<MiniYamlNode> playerDefinitions, List<MiniYamlNode> actorDefinitions) World world, List<MiniYamlNode> playerDefinitions, List<MiniYamlNode> actorDefinitions)
{ {
var title = widget.Get<TextFieldWidget>("TITLE"); var title = widget.Get<TextFieldWidget>("TITLE");
title.Text = map.Title; title.Text = map.Title;
@@ -202,7 +206,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (playerDefinitions != null) if (playerDefinitions != null)
map.PlayerDefinitions = playerDefinitions; map.PlayerDefinitions = playerDefinitions;
map.RequiresMod = modData.Manifest.Id; Ui.CloseWindow();
onExit();
try try
{ {
@@ -215,22 +220,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic
package = new Folder(combinedPath); package = new Folder(combinedPath);
} }
map.Save(package); SaveMapInner(map, package, world, modData);
Ui.CloseWindow();
onSave(map.Uid);
} }
catch (Exception e) catch (Exception e)
{ {
Log.Write("debug", $"Failed to save map at {combinedPath}"); SaveMapFailed(e, modData, world);
Log.Write("debug", e);
ConfirmationDialogs.ButtonPrompt(modData,
title: SaveMapFailedTitle,
text: SaveMapFailedPrompt,
onConfirm: () => { },
confirmText: SaveMapFailedAccept);
} }
onSave(map.Uid);
}; };
var save = widget.Get<ButtonWidget>("SAVE_BUTTON"); var save = widget.Get<ButtonWidget>("SAVE_BUTTON");
@@ -239,6 +236,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic
save.OnClick = () => save.OnClick = () =>
{ {
var combinedPath = Platform.ResolvePath(Path.Combine(selectedDirectory.Folder.Name, filename.Text + fileTypes[fileType].Extension)); var combinedPath = Platform.ResolvePath(Path.Combine(selectedDirectory.Folder.Name, filename.Text + fileTypes[fileType].Extension));
SaveMap(modData, world, map, combinedPath, saveMap);
};
}
public static void SaveMap(ModData modData, World world, Map map, string combinedPath, Action<string> saveMap)
{
var actionManager = world.WorldActor.TraitOrDefault<EditorActionManager>();
if (map.Package?.Name != combinedPath) if (map.Package?.Name != combinedPath)
{ {
@@ -248,9 +252,21 @@ namespace OpenRA.Mods.Common.Widgets.Logic
ConfirmationDialogs.ButtonPrompt(modData, ConfirmationDialogs.ButtonPrompt(modData,
title: OverwriteMapFailedTitle, title: OverwriteMapFailedTitle,
text: OverwriteMapFailedPrompt, text: OverwriteMapFailedPrompt,
confirmText: SaveMapFailedConfirm, confirmText: OverwriteMapFailedConfirm,
onConfirm: () => saveMap(combinedPath), onConfirm: () =>
onCancel: () => { }); {
saveMap(combinedPath);
if (actionManager != null)
actionManager.SaveFailed = false;
},
onCancel: () =>
{
if (actionManager != null)
actionManager.SaveFailed = false;
});
if (actionManager != null)
actionManager.SaveFailed = true;
return; return;
} }
@@ -265,15 +281,69 @@ namespace OpenRA.Mods.Common.Widgets.Logic
title: OverwriteMapOutsideEditTitle, title: OverwriteMapOutsideEditTitle,
text: OverwriteMapOutsideEditPrompt, text: OverwriteMapOutsideEditPrompt,
confirmText: SaveMapMapOutsideConfirm, confirmText: SaveMapMapOutsideConfirm,
onConfirm: () => saveMap(combinedPath), onConfirm: () =>
onCancel: () => { }); {
saveMap(combinedPath);
if (actionManager != null)
actionManager.SaveFailed = false;
},
onCancel: () =>
{
if (actionManager != null)
actionManager.SaveFailed = false;
});
if (actionManager != null)
actionManager.SaveFailed = true;
return; return;
} }
} }
saveMap(combinedPath); saveMap(combinedPath);
}; }
public static void SaveMapInner(Map map, IReadWritePackage package, World world, ModData modData)
{
map.RequiresMod = modData.Manifest.Id;
try
{
if (package == null)
throw new ArgumentNullException(nameof(package));
map.Save(package);
var actionManager = world.WorldActor.TraitOrDefault<EditorActionManager>();
if (actionManager != null)
actionManager.Modified = false;
TextNotificationsManager.AddTransientLine(modData.Translation.GetString(SaveCurrentMap), world.LocalPlayer);
}
catch (Exception e)
{
SaveMapFailed(e, modData, world);
}
}
static void SaveMapFailed(Exception e, ModData modData, World world)
{
Log.Write("debug", $"Failed to save map.");
Log.Write("debug", e);
var actionManager = world.WorldActor.TraitOrDefault<EditorActionManager>();
if (actionManager != null)
actionManager.SaveFailed = true;
ConfirmationDialogs.ButtonPrompt(modData,
title: SaveMapFailedTitle,
text: SaveMapFailedPrompt,
onConfirm: () =>
{
if (actionManager != null)
actionManager.SaveFailed = false;
},
confirmText: SaveMapFailedConfirm);
} }
} }
} }

View File

@@ -0,0 +1,62 @@
#region Copyright & License Information
/*
* Copyright (c) The OpenRA Developers and Contributors
* 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 OpenRA.FileSystem;
using OpenRA.Mods.Common.Lint;
using OpenRA.Mods.Common.Traits;
using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic.Ingame
{
[ChromeLogicArgsHotkeys("EditorQuickSaveKey")]
public class EditorQuickSaveHotkeyLogic : SingleHotkeyBaseLogic
{
readonly World world;
readonly ModData modData;
[ObjectCreator.UseCtor]
public EditorQuickSaveHotkeyLogic(Widget widget, ModData modData, World world, Dictionary<string, MiniYaml> logicArgs)
: base(widget, modData, "QuickSaveKey", "GLOBAL_KEYHANDLER", logicArgs)
{
this.world = world;
this.modData = modData;
}
protected override bool OnHotkeyActivated(KeyInput keyInput)
{
var actionManager = world.WorldActor.TraitOrDefault<EditorActionManager>();
if (actionManager != null && (!actionManager.Modified || actionManager.SaveFailed))
return false;
var map = world.Map;
Action<string> saveMap = (string combinedPath) =>
{
var editorActorLayer = world.WorldActor.Trait<EditorActorLayer>();
var actorDefinitions = editorActorLayer.Save();
if (actorDefinitions != null)
map.ActorDefinitions = actorDefinitions;
var playerDefinitions = editorActorLayer.Players.ToMiniYaml();
if (playerDefinitions != null)
map.PlayerDefinitions = playerDefinitions;
var package = (IReadWritePackage)map.Package;
SaveMapLogic.SaveMapInner(map, package, world, modData);
};
SaveMapLogic.SaveMap(modData, world, map, map.Package?.Name, saveMap);
return true;
}
}
}

View File

@@ -470,8 +470,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
Ui.OpenWindow("SAVE_MAP_PANEL", new WidgetArgs() Ui.OpenWindow("SAVE_MAP_PANEL", new WidgetArgs()
{ {
{ "onSave", (Action<string>)(_ => { ShowMenu(); actionManager.Modified = false; }) }, { "onSave", (Action<string>)(_ => { ShowMenu(); actionManager.Modified = false; }) },
{ "onExit", ShowMenu }, { "onExit", CloseMenu },
{ "map", world.Map }, { "map", world.Map },
{ "world", world },
{ "playerDefinitions", playerDefinitions }, { "playerDefinitions", playerDefinitions },
{ "actorDefinitions", editorActorLayer.Save() } { "actorDefinitions", editorActorLayer.Save() }
}); });

View File

@@ -20,6 +20,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
var editorRoot = widget.Get("WORLD_ROOT"); var editorRoot = widget.Get("WORLD_ROOT");
Game.LoadWidget(world, "EDITOR_WORLD_ROOT", editorRoot, new WidgetArgs()); Game.LoadWidget(world, "EDITOR_WORLD_ROOT", editorRoot, new WidgetArgs());
Game.LoadWidget(world, "TRANSIENTS_PANEL", editorRoot, new WidgetArgs());
} }
} }
} }

View File

@@ -197,13 +197,14 @@ Container@EDITOR_ROOT:
Logic: LoadMapEditorLogic Logic: LoadMapEditorLogic
Children: Children:
LogicKeyListener@GLOBAL_KEYHANDLER: LogicKeyListener@GLOBAL_KEYHANDLER:
Logic: MusicHotkeyLogic, ScreenshotHotkeyLogic, MuteHotkeyLogic Logic: MusicHotkeyLogic, ScreenshotHotkeyLogic, MuteHotkeyLogic, EditorQuickSaveHotkeyLogic
StopMusicKey: StopMusic StopMusicKey: StopMusic
PauseMusicKey: PauseMusic PauseMusicKey: PauseMusic
PrevMusicKey: PrevMusic PrevMusicKey: PrevMusic
NextMusicKey: NextMusic NextMusicKey: NextMusic
TakeScreenshotKey: TakeScreenshot TakeScreenshotKey: TakeScreenshot
MuteAudioKey: ToggleMute MuteAudioKey: ToggleMute
QuickSaveKey: EditorQuickSave
LogicKeyListener@WORLD_KEYHANDLER: LogicKeyListener@WORLD_KEYHANDLER:
Logic: ResetZoomHotkeyLogic Logic: ResetZoomHotkeyLogic
ResetZoomKey: ResetZoom ResetZoomKey: ResetZoom

View File

@@ -188,13 +188,14 @@ Container@EDITOR_ROOT:
Logic: LoadMapEditorLogic Logic: LoadMapEditorLogic
Children: Children:
LogicKeyListener@GLOBAL_KEYHANDLER: LogicKeyListener@GLOBAL_KEYHANDLER:
Logic: MusicHotkeyLogic, ScreenshotHotkeyLogic, MuteHotkeyLogic Logic: MusicHotkeyLogic, ScreenshotHotkeyLogic, MuteHotkeyLogic, EditorQuickSaveHotkeyLogic
StopMusicKey: StopMusic StopMusicKey: StopMusic
PauseMusicKey: PauseMusic PauseMusicKey: PauseMusic
PrevMusicKey: PrevMusic PrevMusicKey: PrevMusic
NextMusicKey: NextMusic NextMusicKey: NextMusic
TakeScreenshotKey: TakeScreenshot TakeScreenshotKey: TakeScreenshot
MuteAudioKey: ToggleMute MuteAudioKey: ToggleMute
QuickSaveKey: EditorQuickSave
LogicKeyListener@WORLD_KEYHANDLER: LogicKeyListener@WORLD_KEYHANDLER:
Logic: ResetZoomHotkeyLogic Logic: ResetZoomHotkeyLogic
ResetZoomKey: ResetZoom ResetZoomKey: ResetZoom

View File

@@ -20,6 +20,13 @@ EditorCopy: C Ctrl
Platform: Platform:
OSX: C Meta OSX: C Meta
EditorQuickSave: S Ctrl
Description: Save Map
Types: Editor
Contexts: Editor
Platform:
OSX: S Meta
EditorTilesTab: E EditorTilesTab: E
Description: Tiles Tab Description: Tiles Tab
Types: Editor Types: Editor

View File

@@ -129,6 +129,8 @@ dialog-overwrite-map-outside-edit =
By saving you may overwrite progress By saving you may overwrite progress
.confirm = Save .confirm = Save
notification-save-current-map = Saved current map.
## GameInfoLogic ## GameInfoLogic
menu-game-info = menu-game-info =
.objectives = Objectives .objectives = Objectives