Add save/load browser and buttons to the UI.
This commit is contained in:
@@ -636,6 +636,7 @@
|
||||
<Compile Include="Widgets\ExponentialSliderWidget.cs" />
|
||||
<Compile Include="Widgets\Logic\Ingame\GameSaveLoadingLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\MusicHotkeyLogic.cs" />
|
||||
<Compile Include="Widgets\Logic\GameSaveBrowserLogic.cs" />
|
||||
<Compile Include="WorldExtensions.cs" />
|
||||
<Compile Include="UtilityCommands\GetMapHashCommand.cs" />
|
||||
<Compile Include="UtilityCommands\Glob.cs" />
|
||||
|
||||
360
OpenRA.Mods.Common/Widgets/Logic/GameSaveBrowserLogic.cs
Normal file
360
OpenRA.Mods.Common/Widgets/Logic/GameSaveBrowserLogic.cs
Normal file
@@ -0,0 +1,360 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2019 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.IO;
|
||||
using System.Linq;
|
||||
using OpenRA.Network;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
public class GameSaveBrowserLogic : ChromeLogic
|
||||
{
|
||||
readonly Widget panel;
|
||||
readonly ScrollPanelWidget gameList;
|
||||
readonly TextFieldWidget saveTextField;
|
||||
readonly List<string> games = new List<string>();
|
||||
readonly Action onStart;
|
||||
readonly Action onExit;
|
||||
readonly ModData modData;
|
||||
readonly bool isSavePanel;
|
||||
readonly string baseSavePath;
|
||||
|
||||
readonly string defaultSaveFilename;
|
||||
string selectedSave;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
public GameSaveBrowserLogic(Widget widget, ModData modData, Action onExit, Action onStart, bool isSavePanel, World world)
|
||||
{
|
||||
panel = widget;
|
||||
|
||||
this.modData = modData;
|
||||
this.onStart = onStart;
|
||||
this.onExit = onExit;
|
||||
this.isSavePanel = isSavePanel;
|
||||
Game.BeforeGameStart += OnGameStart;
|
||||
|
||||
panel.Get<ButtonWidget>("CANCEL_BUTTON").OnClick = () =>
|
||||
{
|
||||
Ui.CloseWindow();
|
||||
onExit();
|
||||
};
|
||||
|
||||
gameList = panel.Get<ScrollPanelWidget>("GAME_LIST");
|
||||
var gameTemplate = panel.Get<ScrollItemWidget>("GAME_TEMPLATE");
|
||||
var newTemplate = panel.Get<ScrollItemWidget>("NEW_TEMPLATE");
|
||||
|
||||
var mod = modData.Manifest;
|
||||
baseSavePath = Platform.ResolvePath(Platform.SupportDirPrefix, "Saves", mod.Id, mod.Metadata.Version);
|
||||
|
||||
// Avoid filename conflicts when creating new saves
|
||||
if (isSavePanel)
|
||||
{
|
||||
panel.Get("SAVE_TITLE").IsVisible = () => true;
|
||||
|
||||
defaultSaveFilename = world.Map.Title;
|
||||
var filenameAttempt = 0;
|
||||
while (true)
|
||||
{
|
||||
if (!File.Exists(Path.Combine(baseSavePath, defaultSaveFilename + ".orasav")))
|
||||
break;
|
||||
|
||||
defaultSaveFilename = world.Map.Title + " ({0})".F(++filenameAttempt);
|
||||
}
|
||||
|
||||
var saveButton = panel.Get<ButtonWidget>("SAVE_BUTTON");
|
||||
saveButton.OnClick = () => { Save(world); };
|
||||
saveButton.IsVisible = () => true;
|
||||
|
||||
var saveWidgets = panel.Get("SAVE_WIDGETS");
|
||||
saveTextField = saveWidgets.Get<TextFieldWidget>("SAVE_TEXTFIELD");
|
||||
gameList.Bounds.Height -= saveWidgets.Bounds.Height;
|
||||
saveWidgets.IsVisible = () => true;
|
||||
}
|
||||
else
|
||||
{
|
||||
panel.Get("LOAD_TITLE").IsVisible = () => true;
|
||||
var loadButton = panel.Get<ButtonWidget>("LOAD_BUTTON");
|
||||
loadButton.IsVisible = () => true;
|
||||
loadButton.IsDisabled = () => selectedSave == null;
|
||||
loadButton.OnClick = () => { Load(); };
|
||||
}
|
||||
|
||||
if (Directory.Exists(baseSavePath))
|
||||
LoadGames(gameTemplate, newTemplate);
|
||||
|
||||
var renameButton = panel.Get<ButtonWidget>("RENAME_BUTTON");
|
||||
renameButton.IsDisabled = () => selectedSave == null;
|
||||
renameButton.OnClick = () =>
|
||||
{
|
||||
var initialName = Path.GetFileNameWithoutExtension(selectedSave);
|
||||
var invalidChars = Path.GetInvalidFileNameChars();
|
||||
|
||||
ConfirmationDialogs.TextInputPrompt(
|
||||
"Rename Save",
|
||||
"Enter a new file name:",
|
||||
initialName,
|
||||
onAccept: newName => Rename(initialName, newName),
|
||||
onCancel: null,
|
||||
acceptText: "Rename",
|
||||
cancelText: null,
|
||||
inputValidator: newName =>
|
||||
{
|
||||
if (newName == initialName)
|
||||
return false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(newName))
|
||||
return false;
|
||||
|
||||
if (newName.IndexOfAny(invalidChars) >= 0)
|
||||
return false;
|
||||
|
||||
if (File.Exists(Path.Combine(baseSavePath, newName)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
var deleteButton = panel.Get<ButtonWidget>("DELETE_BUTTON");
|
||||
deleteButton.IsDisabled = () => selectedSave == null;
|
||||
deleteButton.OnClick = () =>
|
||||
{
|
||||
ConfirmationDialogs.ButtonPrompt(
|
||||
title: "Delete selected game save?",
|
||||
text: "Delete '{0}'?".F(Path.GetFileNameWithoutExtension(selectedSave)),
|
||||
onConfirm: () =>
|
||||
{
|
||||
Delete(selectedSave);
|
||||
|
||||
if (!games.Any() && !isSavePanel)
|
||||
{
|
||||
Ui.CloseWindow();
|
||||
onExit();
|
||||
}
|
||||
else
|
||||
SelectFirstVisible();
|
||||
},
|
||||
confirmText: "Delete",
|
||||
onCancel: () => { });
|
||||
};
|
||||
|
||||
var deleteAllButton = panel.Get<ButtonWidget>("DELETE_ALL_BUTTON");
|
||||
deleteAllButton.IsDisabled = () => !games.Any();
|
||||
deleteAllButton.OnClick = () =>
|
||||
{
|
||||
ConfirmationDialogs.ButtonPrompt(
|
||||
title: "Delete all game saves?",
|
||||
text: "Delete {0} game saves?".F(games.Count),
|
||||
onConfirm: () =>
|
||||
{
|
||||
foreach (var s in games.ToList())
|
||||
Delete(s);
|
||||
|
||||
Ui.CloseWindow();
|
||||
onExit();
|
||||
},
|
||||
confirmText: "Delete All",
|
||||
onCancel: () => { });
|
||||
};
|
||||
|
||||
SelectFirstVisible();
|
||||
}
|
||||
|
||||
void LoadGames(ScrollItemWidget gameTemplate, ScrollItemWidget newTemplate)
|
||||
{
|
||||
gameList.RemoveChildren();
|
||||
if (isSavePanel)
|
||||
{
|
||||
var item = ScrollItemWidget.Setup(newTemplate,
|
||||
() => selectedSave == null,
|
||||
() => Select(null),
|
||||
() => { });
|
||||
gameList.AddChild(item);
|
||||
}
|
||||
|
||||
var savePaths = Directory.GetFiles(baseSavePath, "*.orasav", SearchOption.AllDirectories)
|
||||
.OrderByDescending(p => File.GetLastWriteTime(p))
|
||||
.ToList();
|
||||
|
||||
foreach (var savePath in savePaths)
|
||||
{
|
||||
games.Add(savePath);
|
||||
|
||||
// Create the item manually so the click handlers can refer to itself
|
||||
// This simplifies the rename handling (only needs to update ItemKey)
|
||||
var item = gameTemplate.Clone() as ScrollItemWidget;
|
||||
item.ItemKey = savePath;
|
||||
item.IsVisible = () => true;
|
||||
item.IsSelected = () => selectedSave == item.ItemKey;
|
||||
item.OnClick = () => Select(item.ItemKey);
|
||||
item.OnDoubleClick = Load;
|
||||
|
||||
var title = Path.GetFileNameWithoutExtension(savePath);
|
||||
item.Get<LabelWidget>("TITLE").GetText = () => title;
|
||||
|
||||
var date = File.GetLastWriteTime(savePath).ToString("yyyy-MM-dd HH:mm:ss");
|
||||
item.Get<LabelWidget>("DATE").GetText = () => date;
|
||||
|
||||
gameList.AddChild(item);
|
||||
}
|
||||
}
|
||||
|
||||
void Rename(string oldName, string newName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var oldPath = Path.Combine(baseSavePath, oldName + ".orasav");
|
||||
var newPath = Path.Combine(baseSavePath, newName + ".orasav");
|
||||
File.Move(oldPath, newPath);
|
||||
|
||||
games[games.IndexOf(oldPath)] = newPath;
|
||||
foreach (var c in gameList.Children)
|
||||
{
|
||||
var item = c as ScrollItemWidget;
|
||||
if (item == null || item.ItemKey != oldPath)
|
||||
continue;
|
||||
|
||||
item.ItemKey = newPath;
|
||||
item.Get<LabelWidget>("TITLE").GetText = () => newName;
|
||||
}
|
||||
|
||||
if (selectedSave == oldPath)
|
||||
selectedSave = newPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
Log.Write("debug", ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
void Delete(string savePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(savePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Game.Debug("Failed to delete save file '{0}'. See the logs for details.", savePath);
|
||||
Log.Write("debug", ex.ToString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (savePath == selectedSave)
|
||||
Select(null);
|
||||
|
||||
var item = gameList.Children
|
||||
.Select(c => c as ScrollItemWidget)
|
||||
.FirstOrDefault(c => c.ItemKey == savePath);
|
||||
|
||||
gameList.RemoveChild(item);
|
||||
games.Remove(savePath);
|
||||
}
|
||||
|
||||
void SelectFirstVisible()
|
||||
{
|
||||
Select(isSavePanel ? null : games.FirstOrDefault());
|
||||
}
|
||||
|
||||
void Select(string savePath)
|
||||
{
|
||||
selectedSave = savePath;
|
||||
if (isSavePanel)
|
||||
saveTextField.Text = savePath == null ? defaultSaveFilename :
|
||||
Path.GetFileNameWithoutExtension(savePath);
|
||||
}
|
||||
|
||||
void Load()
|
||||
{
|
||||
if (selectedSave == null)
|
||||
return;
|
||||
|
||||
// Parse the save to find the map UID
|
||||
var save = new GameSave(selectedSave);
|
||||
var map = modData.MapCache[save.GlobalSettings.Map];
|
||||
if (map.Status != MapStatus.Available)
|
||||
return;
|
||||
|
||||
var orders = new List<Order>()
|
||||
{
|
||||
new Order("LoadGameSave", null, false)
|
||||
{
|
||||
IsImmediate = true,
|
||||
TargetString = Path.GetFileName(selectedSave)
|
||||
},
|
||||
Order.Command("state {0}".F(Session.ClientState.Ready))
|
||||
};
|
||||
|
||||
Game.CreateAndStartLocalServer(map.Uid, orders);
|
||||
}
|
||||
|
||||
void Save(World world)
|
||||
{
|
||||
var filename = saveTextField.Text + ".orasav";
|
||||
var testPath = Platform.ResolvePath(
|
||||
Platform.SupportDirPrefix,
|
||||
"Saves",
|
||||
modData.Manifest.Id,
|
||||
modData.Manifest.Metadata.Version,
|
||||
filename);
|
||||
|
||||
Action inner = () =>
|
||||
{
|
||||
world.RequestGameSave(filename);
|
||||
Ui.CloseWindow();
|
||||
onExit();
|
||||
};
|
||||
|
||||
if (selectedSave != null || File.Exists(testPath))
|
||||
{
|
||||
ConfirmationDialogs.ButtonPrompt(
|
||||
title: "Overwrite save game?",
|
||||
text: "Overwrite {0}?".F(saveTextField.Text),
|
||||
onConfirm: inner,
|
||||
confirmText: "Overwrite",
|
||||
onCancel: () => { });
|
||||
}
|
||||
else
|
||||
inner();
|
||||
}
|
||||
|
||||
void OnGameStart()
|
||||
{
|
||||
Ui.CloseWindow();
|
||||
onStart();
|
||||
}
|
||||
|
||||
bool disposed;
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && !disposed)
|
||||
{
|
||||
disposed = true;
|
||||
Game.BeforeGameStart -= OnGameStart;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
public static bool IsLoadPanelEnabled(Manifest mod)
|
||||
{
|
||||
var baseSavePath = Platform.ResolvePath(Platform.SupportDirPrefix, "Saves", mod.Id, mod.Metadata.Version);
|
||||
if (!Directory.Exists(baseSavePath))
|
||||
return false;
|
||||
|
||||
return Directory.GetFiles(baseSavePath, "*.orasav", SearchOption.AllDirectories).Any();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
{ "ABORT_MISSION", CreateAbortMissionButton },
|
||||
{ "SURRENDER", CreateSurrenderButton },
|
||||
{ "LOAD_GAME", CreateLoadGameButton },
|
||||
{ "SAVE_GAME", CreateSaveGameButton },
|
||||
{ "MUSIC", CreateMusicButton },
|
||||
{ "SETTINGS", CreateSettingsButton },
|
||||
{ "RESUME", CreateResumeButton },
|
||||
@@ -251,6 +253,46 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
};
|
||||
}
|
||||
|
||||
void CreateLoadGameButton()
|
||||
{
|
||||
if (world.Type != WorldType.Regular || !world.LobbyInfo.GlobalSettings.GameSavesEnabled || world.IsReplay)
|
||||
return;
|
||||
|
||||
var button = AddButton("LOAD_GAME", "Load Game");
|
||||
button.IsDisabled = () => leaving || !GameSaveBrowserLogic.IsLoadPanelEnabled(modData.Manifest);
|
||||
button.OnClick = () =>
|
||||
{
|
||||
hideMenu = true;
|
||||
Ui.OpenWindow("GAMESAVE_BROWSER_PANEL", new WidgetArgs
|
||||
{
|
||||
{ "onExit", () => hideMenu = false },
|
||||
{ "onStart", CloseMenu },
|
||||
{ "isSavePanel", false },
|
||||
{ "world", null }
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
void CreateSaveGameButton()
|
||||
{
|
||||
if (world.Type != WorldType.Regular || !world.LobbyInfo.GlobalSettings.GameSavesEnabled || world.IsReplay)
|
||||
return;
|
||||
|
||||
var button = AddButton("SAVE_GAME", "Save Game");
|
||||
button.IsDisabled = () => hasError || leaving || !world.Players.Any(p => p.Playable && p.WinState == WinState.Undefined);
|
||||
button.OnClick = () =>
|
||||
{
|
||||
hideMenu = true;
|
||||
Ui.OpenWindow("GAMESAVE_BROWSER_PANEL", new WidgetArgs
|
||||
{
|
||||
{ "onExit", () => hideMenu = false },
|
||||
{ "onStart", () => { } },
|
||||
{ "isSavePanel", true },
|
||||
{ "world", world }
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
void CreateMusicButton()
|
||||
{
|
||||
var button = AddButton("MUSIC", "Music");
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
protected enum MenuType { Main, Singleplayer, Extras, MapEditor, SystemInfoPrompt, None }
|
||||
|
||||
protected enum MenuPanel { None, Missions, Skirmish, Multiplayer, MapEditor, Replays }
|
||||
protected enum MenuPanel { None, Missions, Skirmish, Multiplayer, MapEditor, Replays, GameSaves }
|
||||
|
||||
protected MenuType menuType = MenuType.Main;
|
||||
readonly Widget rootMenu;
|
||||
@@ -127,6 +127,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
skirmishButton.OnClick = StartSkirmishGame;
|
||||
skirmishButton.Disabled = !hasMaps;
|
||||
|
||||
var loadButton = singleplayerMenu.Get<ButtonWidget>("LOAD_BUTTON");
|
||||
loadButton.IsDisabled = () => !GameSaveBrowserLogic.IsLoadPanelEnabled(modData.Manifest);
|
||||
loadButton.OnClick = OpenGameSaveBrowserPanel;
|
||||
|
||||
singleplayerMenu.Get<ButtonWidget>("BACK_BUTTON").OnClick = () => SwitchMenu(MenuType.Main);
|
||||
|
||||
// Extras menu
|
||||
@@ -500,6 +504,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
});
|
||||
}
|
||||
|
||||
void OpenGameSaveBrowserPanel()
|
||||
{
|
||||
SwitchMenu(MenuType.None);
|
||||
Ui.OpenWindow("GAMESAVE_BROWSER_PANEL", new WidgetArgs
|
||||
{
|
||||
{ "onExit", () => SwitchMenu(MenuType.Singleplayer) },
|
||||
{ "onStart", () => { RemoveShellmapUI(); lastGameState = MenuPanel.GameSaves; } },
|
||||
{ "isSavePanel", false },
|
||||
{ "world", null }
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
@@ -535,6 +551,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
case MenuPanel.MapEditor:
|
||||
SwitchMenu(MenuType.MapEditor);
|
||||
break;
|
||||
|
||||
case MenuPanel.GameSaves:
|
||||
SwitchMenu(MenuType.Singleplayer);
|
||||
break;
|
||||
}
|
||||
|
||||
lastGameState = MenuPanel.None;
|
||||
|
||||
115
mods/cnc/chrome/gamesave-browser.yaml
Normal file
115
mods/cnc/chrome/gamesave-browser.yaml
Normal file
@@ -0,0 +1,115 @@
|
||||
Container@GAMESAVE_BROWSER_PANEL:
|
||||
Logic: GameSaveBrowserLogic
|
||||
X: (WINDOW_RIGHT - WIDTH) / 2
|
||||
Y: (WINDOW_BOTTOM - HEIGHT) / 2
|
||||
Width: 600
|
||||
Height: 400
|
||||
Children:
|
||||
Label@LOAD_TITLE:
|
||||
Width: PARENT_RIGHT
|
||||
Y: 0 - 25
|
||||
Font: BigBold
|
||||
Contrast: true
|
||||
Align: Center
|
||||
Text: Load game
|
||||
Visible: False
|
||||
Label@SAVE_TITLE:
|
||||
Width: PARENT_RIGHT
|
||||
Y: 0 - 25
|
||||
Font: BigBold
|
||||
Contrast: true
|
||||
Align: Center
|
||||
Text: Save game
|
||||
Visible: False
|
||||
Background@bg:
|
||||
Width: PARENT_RIGHT
|
||||
Height: PARENT_BOTTOM
|
||||
Background: panel-black
|
||||
Children:
|
||||
ScrollPanel@GAME_LIST:
|
||||
X: 10
|
||||
Y: 10
|
||||
Width: PARENT_RIGHT - 20
|
||||
Height: PARENT_BOTTOM - 20
|
||||
Children:
|
||||
ScrollItem@NEW_TEMPLATE:
|
||||
Width: PARENT_RIGHT - 27
|
||||
Height: 25
|
||||
X: 2
|
||||
Visible: false
|
||||
Children:
|
||||
Label@TITLE:
|
||||
Width: PARENT_RIGHT
|
||||
Height: PARENT_BOTTOM
|
||||
Align: Center
|
||||
Text: [CREATE NEW FILE]
|
||||
ScrollItem@GAME_TEMPLATE:
|
||||
Width: PARENT_RIGHT - 27
|
||||
Height: 25
|
||||
X: 2
|
||||
Visible: false
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X: 10
|
||||
Width: PARENT_RIGHT - 200 - 10
|
||||
Height: 25
|
||||
Label@DATE:
|
||||
X: PARENT_RIGHT - WIDTH - 10
|
||||
Width: 200
|
||||
Height: 25
|
||||
Align: Right
|
||||
Container@SAVE_WIDGETS:
|
||||
X: 10
|
||||
Y: PARENT_BOTTOM - 35
|
||||
Width: PARENT_RIGHT - 20
|
||||
Height: 35
|
||||
Visible: False
|
||||
Children:
|
||||
TextField@SAVE_TEXTFIELD:
|
||||
Width: PARENT_RIGHT
|
||||
Height: 25
|
||||
Type: Filename
|
||||
Button@CANCEL_BUTTON:
|
||||
Key: escape
|
||||
X: 0
|
||||
Y: PARENT_BOTTOM - 1
|
||||
Width: 100
|
||||
Height: 35
|
||||
Text: Back
|
||||
Button@DELETE_ALL_BUTTON:
|
||||
X: PARENT_RIGHT - 330 - WIDTH
|
||||
Y: PARENT_BOTTOM - 1
|
||||
Width: 100
|
||||
Height: 35
|
||||
Text: Delete All
|
||||
Button@DELETE_BUTTON:
|
||||
X: PARENT_RIGHT - 220 - WIDTH
|
||||
Y: PARENT_BOTTOM - 1
|
||||
Width: 100
|
||||
Height: 35
|
||||
Text: Delete
|
||||
Key: Delete
|
||||
Button@RENAME_BUTTON:
|
||||
X: PARENT_RIGHT - 110 - WIDTH
|
||||
Y: PARENT_BOTTOM - 1
|
||||
Width: 100
|
||||
Height: 35
|
||||
Text: Rename
|
||||
Key: F2
|
||||
Button@LOAD_BUTTON:
|
||||
Key: return
|
||||
X: PARENT_RIGHT - WIDTH
|
||||
Y: PARENT_BOTTOM - 1
|
||||
Width: 100
|
||||
Height: 35
|
||||
Text: Load
|
||||
Visible: False
|
||||
Button@SAVE_BUTTON:
|
||||
Key: return
|
||||
X: PARENT_RIGHT - WIDTH
|
||||
Y: PARENT_BOTTOM - 1
|
||||
Width: 100
|
||||
Height: 35
|
||||
Text: Save
|
||||
Visible: False
|
||||
TooltipContainer@TOOLTIP_CONTAINER:
|
||||
@@ -119,6 +119,12 @@ Container@MENU_BACKGROUND:
|
||||
Width: 140
|
||||
Height: 35
|
||||
Text: Missions
|
||||
Button@LOAD_BUTTON:
|
||||
X: 300
|
||||
Y: 0
|
||||
Width: 140
|
||||
Height: 35
|
||||
Text: Load
|
||||
Button@BACK_BUTTON:
|
||||
Key: escape
|
||||
X: 450
|
||||
|
||||
@@ -107,6 +107,7 @@ ChromeLayout:
|
||||
cnc|chrome/color-picker.yaml
|
||||
cnc|chrome/mapchooser.yaml
|
||||
cnc|chrome/replaybrowser.yaml
|
||||
cnc|chrome/gamesave-browser.yaml
|
||||
cnc|chrome/gamesave-loading.yaml
|
||||
cnc|chrome/ingame.yaml
|
||||
cnc|chrome/ingame-chat.yaml
|
||||
|
||||
116
mods/common/chrome/gamesave-browser.yaml
Normal file
116
mods/common/chrome/gamesave-browser.yaml
Normal file
@@ -0,0 +1,116 @@
|
||||
Background@GAMESAVE_BROWSER_PANEL:
|
||||
Logic: GameSaveBrowserLogic
|
||||
X: (WINDOW_RIGHT - WIDTH) / 2
|
||||
Y: (WINDOW_BOTTOM - HEIGHT) / 2
|
||||
Width: 600
|
||||
Height: 400
|
||||
Children:
|
||||
Label@LOAD_TITLE:
|
||||
Width: PARENT_RIGHT
|
||||
Y: 20
|
||||
Height: 25
|
||||
Font: Bold
|
||||
Align: Center
|
||||
Text: Load game
|
||||
Visible: False
|
||||
Label@SAVE_TITLE:
|
||||
Width: PARENT_RIGHT
|
||||
Y: 20
|
||||
Height: 25
|
||||
Font: Bold
|
||||
Align: Center
|
||||
Text: Save game
|
||||
Visible: False
|
||||
ScrollPanel@GAME_LIST:
|
||||
X: 20
|
||||
Y: 50
|
||||
Width: PARENT_RIGHT - 40
|
||||
Height: PARENT_BOTTOM - 102
|
||||
Children:
|
||||
ScrollItem@NEW_TEMPLATE:
|
||||
Width: PARENT_RIGHT - 27
|
||||
Height: 25
|
||||
X: 2
|
||||
Visible: false
|
||||
Children:
|
||||
Label@TITLE:
|
||||
Width: PARENT_RIGHT
|
||||
Height: PARENT_BOTTOM
|
||||
Align: Center
|
||||
Text: [CREATE NEW FILE]
|
||||
ScrollItem@GAME_TEMPLATE:
|
||||
Width: PARENT_RIGHT - 27
|
||||
Height: 25
|
||||
X: 2
|
||||
Visible: false
|
||||
Children:
|
||||
Label@TITLE:
|
||||
X: 10
|
||||
Width: PARENT_RIGHT - 200 - 10
|
||||
Height: 25
|
||||
Label@DATE:
|
||||
X: PARENT_RIGHT - WIDTH - 10
|
||||
Width: 200
|
||||
Height: 25
|
||||
Align: Right
|
||||
Container@SAVE_WIDGETS:
|
||||
X: 20
|
||||
Y: PARENT_BOTTOM - 77
|
||||
Width: PARENT_RIGHT - 40
|
||||
Height: 32
|
||||
Visible: False
|
||||
Children:
|
||||
TextField@SAVE_TEXTFIELD:
|
||||
Width: PARENT_RIGHT
|
||||
Height: 25
|
||||
Type: Filename
|
||||
Button@CANCEL_BUTTON:
|
||||
Key: escape
|
||||
X: 20
|
||||
Y: PARENT_BOTTOM - 45
|
||||
Width: 100
|
||||
Height: 25
|
||||
Text: Back
|
||||
Font: Bold
|
||||
Button@DELETE_ALL_BUTTON:
|
||||
X: PARENT_RIGHT - 350 - WIDTH
|
||||
Y: PARENT_BOTTOM - 45
|
||||
Width: 100
|
||||
Height: 25
|
||||
Text: Delete All
|
||||
Font: Bold
|
||||
Button@DELETE_BUTTON:
|
||||
X: PARENT_RIGHT - 240 - WIDTH
|
||||
Y: PARENT_BOTTOM - 45
|
||||
Width: 100
|
||||
Height: 25
|
||||
Text: Delete
|
||||
Font: Bold
|
||||
Key: Delete
|
||||
Button@RENAME_BUTTON:
|
||||
X: PARENT_RIGHT - 130 - WIDTH
|
||||
Y: PARENT_BOTTOM - 45
|
||||
Width: 100
|
||||
Height: 25
|
||||
Text: Rename
|
||||
Font: Bold
|
||||
Key: F2
|
||||
Button@LOAD_BUTTON:
|
||||
Key: return
|
||||
X: PARENT_RIGHT - WIDTH - 20
|
||||
Y: PARENT_BOTTOM - 45
|
||||
Width: 100
|
||||
Height: 25
|
||||
Text: Load
|
||||
Font: Bold
|
||||
Visible: False
|
||||
Button@SAVE_BUTTON:
|
||||
Key: return
|
||||
X: PARENT_RIGHT - WIDTH - 20
|
||||
Y: PARENT_BOTTOM - 45
|
||||
Width: 100
|
||||
Height: 25
|
||||
Text: Save
|
||||
Font: Bold
|
||||
Visible: False
|
||||
TooltipContainer@TOOLTIP_CONTAINER:
|
||||
@@ -114,6 +114,13 @@ Container@MAINMENU:
|
||||
Height: 30
|
||||
Text: Missions
|
||||
Font: Bold
|
||||
Button@LOAD_BUTTON:
|
||||
X: PARENT_RIGHT / 2 - WIDTH / 2
|
||||
Y: 140
|
||||
Width: 140
|
||||
Height: 30
|
||||
Text: Load
|
||||
Font: Bold
|
||||
Button@BACK_BUTTON:
|
||||
X: PARENT_RIGHT / 2 - WIDTH / 2
|
||||
Key: escape
|
||||
|
||||
@@ -101,6 +101,13 @@ Container@MAINMENU:
|
||||
Height: 30
|
||||
Text: Missions
|
||||
Font: Bold
|
||||
Button@LOAD_BUTTON:
|
||||
X: PARENT_RIGHT / 2 - WIDTH / 2
|
||||
Y: 140
|
||||
Width: 140
|
||||
Height: 30
|
||||
Text: Load
|
||||
Font: Bold
|
||||
Button@BACK_BUTTON:
|
||||
X: PARENT_RIGHT / 2 - WIDTH / 2
|
||||
Key: escape
|
||||
|
||||
@@ -107,6 +107,7 @@ ChromeLayout:
|
||||
common|chrome/confirmation-dialogs.yaml
|
||||
common|chrome/editor.yaml
|
||||
common|chrome/replaybrowser.yaml
|
||||
common|chrome/gamesave-browser.yaml
|
||||
common|chrome/gamesave-loading.yaml
|
||||
|
||||
Weapons:
|
||||
|
||||
@@ -114,6 +114,7 @@ ChromeLayout:
|
||||
common|chrome/multiplayer-directconnect.yaml
|
||||
common|chrome/connection.yaml
|
||||
common|chrome/replaybrowser.yaml
|
||||
common|chrome/gamesave-browser.yaml
|
||||
ra|chrome/gamesave-loading.yaml
|
||||
common|chrome/dropdowns.yaml
|
||||
common|chrome/musicplayer.yaml
|
||||
|
||||
@@ -163,6 +163,7 @@ ChromeLayout:
|
||||
common|chrome/multiplayer-directconnect.yaml
|
||||
common|chrome/connection.yaml
|
||||
common|chrome/replaybrowser.yaml
|
||||
common|chrome/gamesave-browser.yaml
|
||||
common|chrome/gamesave-loading.yaml
|
||||
ts|chrome/dropdowns.yaml
|
||||
common|chrome/musicplayer.yaml
|
||||
|
||||
Reference in New Issue
Block a user