Add a quick save button to the map editor.
This commit is contained in:
committed by
Gustas
parent
3dd1fd6b00
commit
7cdc8c4ec5
@@ -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)
|
||||||
|
|||||||
@@ -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 }
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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,41 +236,114 @@ 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);
|
||||||
if (map.Package?.Name != combinedPath)
|
|
||||||
{
|
|
||||||
// When creating a new map or when file paths don't match
|
|
||||||
if (modData.MapCache.Any(m => m.Status == MapStatus.Available && m.Package?.Name == combinedPath))
|
|
||||||
{
|
|
||||||
ConfirmationDialogs.ButtonPrompt(modData,
|
|
||||||
title: OverwriteMapFailedTitle,
|
|
||||||
text: OverwriteMapFailedPrompt,
|
|
||||||
confirmText: SaveMapFailedConfirm,
|
|
||||||
onConfirm: () => saveMap(combinedPath),
|
|
||||||
onCancel: () => { });
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// When file paths match
|
|
||||||
var recentUid = modData.MapCache.GetUpdatedMap(map.Uid);
|
|
||||||
if (recentUid != null && map.Uid != recentUid && modData.MapCache[recentUid].Status == MapStatus.Available)
|
|
||||||
{
|
|
||||||
ConfirmationDialogs.ButtonPrompt(modData,
|
|
||||||
title: OverwriteMapOutsideEditTitle,
|
|
||||||
text: OverwriteMapOutsideEditPrompt,
|
|
||||||
confirmText: SaveMapMapOutsideConfirm,
|
|
||||||
onConfirm: () => saveMap(combinedPath),
|
|
||||||
onCancel: () => { });
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
saveMap(combinedPath);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// When creating a new map or when file paths don't match
|
||||||
|
if (modData.MapCache.Any(m => m.Status == MapStatus.Available && m.Package?.Name == combinedPath))
|
||||||
|
{
|
||||||
|
ConfirmationDialogs.ButtonPrompt(modData,
|
||||||
|
title: OverwriteMapFailedTitle,
|
||||||
|
text: OverwriteMapFailedPrompt,
|
||||||
|
confirmText: OverwriteMapFailedConfirm,
|
||||||
|
onConfirm: () =>
|
||||||
|
{
|
||||||
|
saveMap(combinedPath);
|
||||||
|
if (actionManager != null)
|
||||||
|
actionManager.SaveFailed = false;
|
||||||
|
},
|
||||||
|
onCancel: () =>
|
||||||
|
{
|
||||||
|
if (actionManager != null)
|
||||||
|
actionManager.SaveFailed = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (actionManager != null)
|
||||||
|
actionManager.SaveFailed = true;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// When file paths match
|
||||||
|
var recentUid = modData.MapCache.GetUpdatedMap(map.Uid);
|
||||||
|
if (recentUid != null && map.Uid != recentUid && modData.MapCache[recentUid].Status == MapStatus.Available)
|
||||||
|
{
|
||||||
|
ConfirmationDialogs.ButtonPrompt(modData,
|
||||||
|
title: OverwriteMapOutsideEditTitle,
|
||||||
|
text: OverwriteMapOutsideEditPrompt,
|
||||||
|
confirmText: SaveMapMapOutsideConfirm,
|
||||||
|
onConfirm: () =>
|
||||||
|
{
|
||||||
|
saveMap(combinedPath);
|
||||||
|
if (actionManager != null)
|
||||||
|
actionManager.SaveFailed = false;
|
||||||
|
},
|
||||||
|
onCancel: () =>
|
||||||
|
{
|
||||||
|
if (actionManager != null)
|
||||||
|
actionManager.SaveFailed = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (actionManager != null)
|
||||||
|
actionManager.SaveFailed = true;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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() }
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user