Add Generate Map tab to the lobby map chooser.
This commit is contained in:
committed by
Gustas Kažukauskas
parent
979483b63c
commit
6ffd786d5b
156
OpenRA.Mods.Common/Widgets/GeneratedMapPreviewWidget.cs
Normal file
156
OpenRA.Mods.Common/Widgets/GeneratedMapPreviewWidget.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
#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 System.Linq;
|
||||
using OpenRA.FileFormats;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.Common.Widgets
|
||||
{
|
||||
public class GeneratedMapPreviewWidget : Widget
|
||||
{
|
||||
public readonly bool ShowSpawnPoints = true;
|
||||
|
||||
readonly Sprite spawnUnclaimed;
|
||||
readonly SpriteFont spawnFont;
|
||||
readonly Color spawnColor, spawnContrastColor;
|
||||
readonly int2 spawnLabelOffset;
|
||||
|
||||
Sheet mapSheet;
|
||||
Sprite mapSprite;
|
||||
Rectangle mapRect;
|
||||
|
||||
public GeneratedMapPreviewWidget()
|
||||
{
|
||||
spawnUnclaimed = ChromeProvider.GetImage("lobby-bits", "spawn-unclaimed");
|
||||
spawnFont = Game.Renderer.Fonts[ChromeMetrics.Get<string>("SpawnFont")];
|
||||
spawnColor = ChromeMetrics.Get<Color>("SpawnColor");
|
||||
spawnContrastColor = ChromeMetrics.Get<Color>("SpawnContrastColor");
|
||||
spawnLabelOffset = ChromeMetrics.Get<int2>("SpawnLabelOffset");
|
||||
}
|
||||
|
||||
protected GeneratedMapPreviewWidget(GeneratedMapPreviewWidget other)
|
||||
: base(other)
|
||||
{
|
||||
ShowSpawnPoints = other.ShowSpawnPoints;
|
||||
spawnUnclaimed = ChromeProvider.GetImage("lobby-bits", "spawn-unclaimed");
|
||||
spawnFont = Game.Renderer.Fonts[ChromeMetrics.Get<string>("SpawnFont")];
|
||||
spawnColor = ChromeMetrics.Get<Color>("SpawnColor");
|
||||
spawnContrastColor = ChromeMetrics.Get<Color>("SpawnContrastColor");
|
||||
spawnLabelOffset = ChromeMetrics.Get<int2>("SpawnLabelOffset");
|
||||
}
|
||||
|
||||
public override GeneratedMapPreviewWidget Clone() { return new GeneratedMapPreviewWidget(this); }
|
||||
|
||||
(int2 Pos, string Label, int2 LabelOffset)[] spawns = [];
|
||||
|
||||
public void Update(MapPreview map)
|
||||
{
|
||||
Update(map.SpawnPoints, map.Bounds, map.GridType, map.Preview);
|
||||
}
|
||||
|
||||
public void Update(Map map)
|
||||
{
|
||||
var spawnPoints = map.ActorDefinitions
|
||||
.Where(d => d.Value.Value == "mpspawn")
|
||||
.Select(kv => new ActorReference(kv.Value.Value, kv.Value.ToDictionary()).Get<LocationInit>().Value);
|
||||
|
||||
Update(spawnPoints, map.Bounds, map.Grid.Type, new Png(map.Package.GetStream("map.png")));
|
||||
}
|
||||
|
||||
void Update(IEnumerable<CPos> spawnPoints, Rectangle bounds, MapGridType gridType, Png preview)
|
||||
{
|
||||
if (mapSheet == null || mapSheet.Size.Width < preview.Width || mapSheet.Size.Height < preview.Height)
|
||||
{
|
||||
mapSheet?.Dispose();
|
||||
mapSheet = new Sheet(SheetType.BGRA, new Size(preview.Width, preview.Height).NextPowerOf2());
|
||||
}
|
||||
|
||||
var spriteRect = new Rectangle(0, 0, preview.Width, preview.Height);
|
||||
mapSprite = new Sprite(mapSheet, spriteRect, TextureChannel.RGBA);
|
||||
OpenRA.Graphics.Util.FastCopyIntoSprite(mapSprite, preview);
|
||||
mapSheet.CommitBufferedData();
|
||||
|
||||
// Update map rect
|
||||
var previewScale = Math.Min(RenderBounds.Width * 1f / spriteRect.Width, RenderBounds.Height * 1f / spriteRect.Height);
|
||||
var w = (int)(previewScale * spriteRect.Width);
|
||||
var h = (int)(previewScale * spriteRect.Height);
|
||||
var x = RenderBounds.X + (RenderBounds.Width - w) / 2;
|
||||
var y = RenderBounds.Y + (RenderBounds.Height - h) / 2;
|
||||
mapRect = new Rectangle(x, y, w, h);
|
||||
|
||||
if (ShowSpawnPoints)
|
||||
{
|
||||
var s = new List<(int2, string, int2)>();
|
||||
foreach (var p in spawnPoints)
|
||||
{
|
||||
var pos = ConvertToPreview(p, bounds, gridType, previewScale);
|
||||
|
||||
var sprite = spawnUnclaimed;
|
||||
var offset = sprite.Size.XY.ToInt2() / 2;
|
||||
WidgetUtils.DrawSprite(sprite, pos - offset);
|
||||
|
||||
var number = Convert.ToChar('A' + s.Count).ToString();
|
||||
var textOffset = spawnFont.Measure(number) / 2 + spawnLabelOffset;
|
||||
s.Add((pos, number, textOffset));
|
||||
}
|
||||
|
||||
spawns = s.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
mapSprite = null;
|
||||
}
|
||||
|
||||
public int2 ConvertToPreview(CPos cell, Rectangle bounds, MapGridType gridType, float previewScale)
|
||||
{
|
||||
var point = cell.ToMPos(gridType);
|
||||
var cellWidth = gridType == MapGridType.RectangularIsometric ? 2 : 1;
|
||||
var dx = (int)(previewScale * cellWidth * (point.U - bounds.Left));
|
||||
var dy = (int)(previewScale * (point.V - bounds.Top));
|
||||
|
||||
// Odd rows are shifted right by 1px
|
||||
if ((point.V & 1) == 1)
|
||||
dx++;
|
||||
|
||||
return new int2(mapRect.X + dx, mapRect.Y + dy);
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
if (mapSprite == null)
|
||||
return;
|
||||
|
||||
WidgetUtils.DrawSprite(mapSprite, mapRect.Location, mapRect.Size);
|
||||
var offset = spawnUnclaimed.Size.XY.ToInt2() / 2;
|
||||
foreach (var (pos, label, labelOffset) in spawns)
|
||||
{
|
||||
WidgetUtils.DrawSprite(spawnUnclaimed, pos - offset);
|
||||
spawnFont.DrawTextWithContrast(label, pos - labelOffset, spawnColor, spawnContrastColor, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Removed()
|
||||
{
|
||||
base.Removed();
|
||||
mapSheet?.Dispose();
|
||||
mapSheet = null;
|
||||
}
|
||||
|
||||
public bool Loaded => mapSprite != null;
|
||||
}
|
||||
}
|
||||
@@ -98,6 +98,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
MapPreview map;
|
||||
Session.MapStatus mapStatus;
|
||||
MapGenerationArgs lastGeneratedMap;
|
||||
|
||||
bool chatEnabled;
|
||||
bool disableTeamChat;
|
||||
@@ -249,16 +250,30 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
Game.Settings.Save();
|
||||
});
|
||||
|
||||
var onSelectGenerated = new Action<MapGenerationArgs>(args =>
|
||||
{
|
||||
if (args.Uid == map.Uid)
|
||||
return;
|
||||
|
||||
lastGeneratedMap = args;
|
||||
orderManager.IssueOrder(Order.FromTargetString("GenerateMap", args.Serialize(), true));
|
||||
orderManager.IssueOrder(Order.Command("map " + args.Uid));
|
||||
Game.Settings.Server.Map = args.Uid;
|
||||
Game.Settings.Save();
|
||||
});
|
||||
|
||||
// Check for updated maps, if the user has edited a map we'll preselect it for them
|
||||
modData.MapCache.UpdateMaps();
|
||||
|
||||
Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
|
||||
{
|
||||
{ "initialMap", modData.MapCache.PickLastModifiedMap(MapVisibility.Lobby) ?? map.Uid },
|
||||
{ "initialGeneratedMap", lastGeneratedMap },
|
||||
{ "remoteMapPool", orderManager.ServerMapPool },
|
||||
{ "initialTab", MapClassification.System },
|
||||
{ "onExit", modData.MapCache.UpdateMaps },
|
||||
{ "onSelect", Game.IsHost ? onSelect : null },
|
||||
{ "onSelectGenerated", Game.IsHost ? onSelectGenerated : null },
|
||||
{ "filter", MapVisibility.Lobby },
|
||||
});
|
||||
};
|
||||
|
||||
@@ -211,10 +211,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
Game.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
|
||||
{
|
||||
{ "initialMap", null },
|
||||
{ "initialGeneratedMap", (MapGenerationArgs)null },
|
||||
{ "remoteMapPool", null },
|
||||
{ "initialTab", MapClassification.User },
|
||||
{ "onExit", () => SwitchMenu(MenuType.MapEditor) },
|
||||
{ "onSelect", onSelect },
|
||||
{ "onSelectGenerated", null },
|
||||
{ "filter", MapVisibility.Lobby | MapVisibility.Shellmap | MapVisibility.MissionSelector },
|
||||
});
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
@@ -91,6 +92,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
[FluentReference]
|
||||
const string RemoteMapsTab = "button-mapchooser-remote-maps-tab";
|
||||
|
||||
[FluentReference]
|
||||
const string GeneratedMapsTab = "button-mapchooser-generated-maps-tab";
|
||||
|
||||
public static string MapSizeLabel(Size size)
|
||||
{
|
||||
var area = size.Width * size.Height;
|
||||
@@ -124,6 +128,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
string selectedUid;
|
||||
readonly Action<string> onSelect;
|
||||
MapGenerationArgs generatedMap;
|
||||
|
||||
string category;
|
||||
string mapFilter;
|
||||
@@ -131,8 +136,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
Func<MapPreview, long> orderByFunc;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
internal MapChooserLogic(Widget widget, ModData modData, string initialMap, HashSet<string> remoteMapPool,
|
||||
MapClassification initialTab, Action onExit, Action<string> onSelect, MapVisibility filter)
|
||||
internal MapChooserLogic(Widget widget, ModData modData, string initialMap, MapGenerationArgs initialGeneratedMap, HashSet<string> remoteMapPool,
|
||||
MapClassification initialTab, Action onExit, Action<string> onSelect, Action<MapGenerationArgs> onSelectGenerated, MapVisibility filter)
|
||||
{
|
||||
this.widget = widget;
|
||||
this.modData = modData;
|
||||
@@ -145,13 +150,20 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
var approving = new Action(() =>
|
||||
{
|
||||
Ui.CloseWindow();
|
||||
onSelect?.Invoke(selectedUid);
|
||||
if (currentTab == MapClassification.Generated && generatedMap != null)
|
||||
onSelectGenerated?.Invoke(generatedMap);
|
||||
else
|
||||
onSelect?.Invoke(selectedUid);
|
||||
});
|
||||
|
||||
var canceling = new Action(() => { Ui.CloseWindow(); onExit(); });
|
||||
|
||||
var okButton = widget.Get<ButtonWidget>("BUTTON_OK");
|
||||
okButton.Disabled = this.onSelect == null;
|
||||
if (onSelect != null)
|
||||
okButton.IsDisabled = () => currentTab == MapClassification.Generated && generatedMap == null;
|
||||
else
|
||||
okButton.Disabled = true;
|
||||
|
||||
okButton.OnClick = approving;
|
||||
widget.Get<ButtonWidget>("BUTTON_CANCEL").OnClick = canceling;
|
||||
|
||||
@@ -162,6 +174,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
SetupOrderByDropdown();
|
||||
|
||||
var filterContainer = widget.GetOrNull("FILTER_ORDER_CONTROLS");
|
||||
if (filterContainer != null)
|
||||
filterContainer.IsVisible = () => currentTab != MapClassification.Generated;
|
||||
|
||||
var mapFilterInput = widget.GetOrNull<TextFieldWidget>("MAPFILTER_INPUT");
|
||||
if (mapFilterInput != null)
|
||||
{
|
||||
@@ -196,6 +212,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
scrollpanels[currentTab].ScrollToItem(uid, smooth: true);
|
||||
};
|
||||
randomMapButton.IsDisabled = () => visibleMaps == null || visibleMaps.Length == 0;
|
||||
randomMapButton.IsVisible = () => currentTab != MapClassification.Generated;
|
||||
}
|
||||
|
||||
var deleteMapButton = widget.Get<ButtonWidget>("DELETE_MAP_BUTTON");
|
||||
@@ -249,6 +266,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
SetupMapPanel(MapClassification.System, "SYSTEM_MAPS_TAB");
|
||||
SetupMapPanel(MapClassification.Remote, "REMOTE_MAPS_TAB");
|
||||
|
||||
var hasGenerator = modData.DefaultRules.Actors[SystemActors.EditorWorld].HasTraitInfo<IEditorMapGeneratorInfo>();
|
||||
if (onSelectGenerated != null && hasGenerator)
|
||||
SetupGenerateMapPanel(MapClassification.Generated, "GENERATE_MAP_TAB", initialGeneratedMap);
|
||||
|
||||
// System and user map tabs are hidden when the server forces a restricted pool
|
||||
if (remoteMapPool != null)
|
||||
{
|
||||
@@ -260,8 +281,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
tabLabels[MapClassification.System] = SystemMapsTab;
|
||||
tabLabels[MapClassification.User] = UserMapsTab;
|
||||
if (onSelectGenerated != null && hasGenerator)
|
||||
tabLabels[MapClassification.Generated] = GeneratedMapsTab;
|
||||
|
||||
if (initialMap == null && tabMaps.TryGetValue(initialTab, out var map) && map.Length > 0)
|
||||
if (initialMap != null && modData.MapCache[initialMap].Class == MapClassification.Generated && onSelectGenerated != null && hasGenerator)
|
||||
{
|
||||
currentTab = MapClassification.Generated;
|
||||
selectedUid = modData.MapCache.ChooseInitialMap(null, Game.CosmeticRandom);
|
||||
}
|
||||
else if (initialMap == null && tabMaps.TryGetValue(initialTab, out var map) && map.Length > 0)
|
||||
{
|
||||
var uid = map.Select(mp => mp.Uid).First();
|
||||
selectedUid = Game.ModData.MapCache.ChooseInitialMap(uid, Game.CosmeticRandom);
|
||||
@@ -286,7 +314,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
void RefreshMaps(MapClassification tab)
|
||||
{
|
||||
if (tab != MapClassification.Remote)
|
||||
if (tab == MapClassification.System || tab == MapClassification.User)
|
||||
tabMaps[tab] = modData.MapCache.Where(m => m.Status == MapStatus.Available &&
|
||||
m.Class == tab && (m.Visibility & filter) != 0).ToArray();
|
||||
else if (remoteMapPool != null)
|
||||
@@ -358,6 +386,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
RefreshMaps(tab);
|
||||
}
|
||||
|
||||
void SetupGenerateMapPanel(MapClassification tab, string tabContainerName, MapGenerationArgs initialSettings)
|
||||
{
|
||||
var tabContainer = widget.Get<ContainerWidget>(tabContainerName);
|
||||
tabContainer.IsVisible = () => currentTab == tab;
|
||||
Ui.LoadWidget("MAPCHOOSER_GENERATE_PANEL", tabContainer, new WidgetArgs
|
||||
{
|
||||
{ "modData", modData },
|
||||
{ "initialSettings", initialSettings },
|
||||
{ "onGenerate", (Action<MapGenerationArgs>)(data => generatedMap = data) }
|
||||
});
|
||||
}
|
||||
|
||||
void SetupGameModeDropdown(MapClassification tab, DropDownButtonWidget gameModeDropdown)
|
||||
{
|
||||
if (gameModeDropdown != null)
|
||||
@@ -443,6 +483,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
|
||||
void EnumerateMaps(MapClassification tab)
|
||||
{
|
||||
if (tab == MapClassification.Generated)
|
||||
return;
|
||||
|
||||
if (!int.TryParse(mapFilter, out var playerCountFilter))
|
||||
playerCountFilter = -1;
|
||||
|
||||
@@ -532,7 +575,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
modData.MapCache[map].Delete();
|
||||
if (selectedUid == map)
|
||||
selectedUid = Game.ModData.MapCache.ChooseInitialMap(tabMaps[currentTab].Select(mp => mp.Uid).FirstOrDefault(),
|
||||
selectedUid = modData.MapCache.ChooseInitialMap(tabMaps[currentTab].Select(mp => mp.Uid).FirstOrDefault(),
|
||||
Game.CosmeticRandom);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -569,7 +612,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
foreach (var map in maps)
|
||||
DeleteMap(map);
|
||||
|
||||
after?.Invoke(Game.ModData.MapCache.ChooseInitialMap(null, Game.CosmeticRandom));
|
||||
after?.Invoke(modData.MapCache.ChooseInitialMap(null, Game.CosmeticRandom));
|
||||
},
|
||||
confirmText: DeleteAllMapsAccept,
|
||||
onCancel: () => { });
|
||||
|
||||
424
OpenRA.Mods.Common/Widgets/Logic/MapGeneratorLogic.cs
Normal file
424
OpenRA.Mods.Common/Widgets/Logic/MapGeneratorLogic.cs
Normal file
@@ -0,0 +1,424 @@
|
||||
#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 System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Mods.Common.MapGenerator;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
{
|
||||
public class MapGeneratorLogic : ChromeLogic
|
||||
{
|
||||
[FluentReference]
|
||||
const string Tileset = "label-mapchooser-random-map-tileset";
|
||||
|
||||
[FluentReference]
|
||||
const string MapSize = "label-mapchooser-random-map-size";
|
||||
|
||||
[FluentReference]
|
||||
const string RandomMap = "label-mapchooser-random-map-title";
|
||||
|
||||
[FluentReference]
|
||||
const string Generating = "label-mapchooser-random-map-generating";
|
||||
|
||||
[FluentReference]
|
||||
const string GenerationFailed = "label-mapchooser-random-map-error";
|
||||
|
||||
[FluentReference("players")]
|
||||
const string Players = "label-player-count";
|
||||
|
||||
[FluentReference("author")]
|
||||
const string CreatedBy = "label-created-by";
|
||||
|
||||
[FluentReference]
|
||||
const string MapSizeSmall = "label-map-size-small";
|
||||
|
||||
[FluentReference]
|
||||
const string MapSizeMedium = "label-map-size-medium";
|
||||
|
||||
[FluentReference]
|
||||
const string MapSizeLarge = "label-map-size-large";
|
||||
|
||||
[FluentReference]
|
||||
const string MapSizeHuge = "label-map-size-huge";
|
||||
|
||||
public static readonly IReadOnlyDictionary<string, int2> MapSizes = new Dictionary<string, int2>()
|
||||
{
|
||||
{ MapSizeSmall, new int2(48, 60) },
|
||||
{ MapSizeMedium, new int2(60, 90) },
|
||||
{ MapSizeLarge, new int2(90, 120) },
|
||||
{ MapSizeHuge, new int2(120, 160) },
|
||||
};
|
||||
|
||||
readonly ModData modData;
|
||||
readonly IEditorMapGeneratorInfo generator;
|
||||
readonly IMapGeneratorSettings settings;
|
||||
readonly Action<MapGenerationArgs> onGenerate;
|
||||
|
||||
readonly GeneratedMapPreviewWidget preview;
|
||||
readonly ScrollPanelWidget settingsPanel;
|
||||
readonly Widget checkboxSettingTemplate;
|
||||
readonly Widget textSettingTemplate;
|
||||
readonly Widget dropdownSettingTemplate;
|
||||
readonly Widget tilesetSetting;
|
||||
readonly Widget sizeSetting;
|
||||
|
||||
ITerrainInfo selectedTerrain;
|
||||
string selectedSize;
|
||||
Size size;
|
||||
|
||||
volatile bool generating;
|
||||
volatile bool failed;
|
||||
|
||||
[ObjectCreator.UseCtor]
|
||||
internal MapGeneratorLogic(Widget widget, ModData modData, MapGenerationArgs initialSettings, Action<MapGenerationArgs> onGenerate)
|
||||
{
|
||||
this.modData = modData;
|
||||
this.onGenerate = onGenerate;
|
||||
|
||||
generator = modData.DefaultRules.Actors[SystemActors.EditorWorld].TraitInfos<IEditorMapGeneratorInfo>().First();
|
||||
settings = generator.GetSettings();
|
||||
preview = widget.Get<GeneratedMapPreviewWidget>("PREVIEW");
|
||||
|
||||
widget.Get("ERROR").IsVisible = () => failed;
|
||||
|
||||
var title = new CachedTransform<string, string>(id => FluentProvider.GetMessage(id));
|
||||
var previewTitleLabel = widget.Get<LabelWidget>("TITLE");
|
||||
previewTitleLabel.GetText = () => title.Update(generating ? Generating : failed ? GenerationFailed : RandomMap);
|
||||
|
||||
var previewDetailsLabel = widget.GetOrNull<LabelWidget>("DETAILS");
|
||||
if (previewDetailsLabel != null)
|
||||
{
|
||||
// The default "Conquest" label is hardcoded in Map.cs
|
||||
var desc = new CachedTransform<int, string>(p => "Conquest " + FluentProvider.GetMessage(Players, "players", p));
|
||||
var playersOption = settings.Options.FirstOrDefault(o => o.Id == "Players") as MapGeneratorMultiIntegerChoiceOption;
|
||||
previewDetailsLabel.GetText = () => desc.Update(playersOption?.Value ?? 0);
|
||||
previewDetailsLabel.IsVisible = () => !failed;
|
||||
}
|
||||
|
||||
var previewAuthorLabel = widget.GetOrNull<LabelWithTooltipWidget>("AUTHOR");
|
||||
if (previewAuthorLabel != null)
|
||||
{
|
||||
var desc = FluentProvider.GetMessage(CreatedBy, "author", FluentProvider.GetMessage(generator.Name));
|
||||
previewAuthorLabel.GetText = () => desc;
|
||||
previewAuthorLabel.IsVisible = () => !failed;
|
||||
}
|
||||
|
||||
var previewSizeLabel = widget.GetOrNull<LabelWidget>("SIZE");
|
||||
if (previewSizeLabel != null)
|
||||
{
|
||||
var desc = new CachedTransform<Size, string>(MapChooserLogic.MapSizeLabel);
|
||||
previewSizeLabel.IsVisible = () => !failed;
|
||||
previewSizeLabel.GetText = () => desc.Update(size);
|
||||
}
|
||||
|
||||
settingsPanel = widget.Get<ScrollPanelWidget>("SETTINGS_PANEL");
|
||||
checkboxSettingTemplate = settingsPanel.Get<Widget>("CHECKBOX_TEMPLATE");
|
||||
textSettingTemplate = settingsPanel.Get<Widget>("TEXT_TEMPLATE");
|
||||
dropdownSettingTemplate = settingsPanel.Get<Widget>("DROPDOWN_TEMPLATE");
|
||||
settingsPanel.Layout = new GridLayout(settingsPanel);
|
||||
|
||||
// Tileset and map size are handled outside the generator logic so must be created manually
|
||||
var validTerrainInfos = generator.Tilesets.Select(t => modData.DefaultTerrainInfo[t]).ToList();
|
||||
var tilesetLabel = FluentProvider.GetMessage(Tileset);
|
||||
tilesetSetting = dropdownSettingTemplate.Clone();
|
||||
tilesetSetting.Get<LabelWidget>("LABEL").GetText = () => tilesetLabel;
|
||||
|
||||
var label = new CachedTransform<ITerrainInfo, string>(ti => FluentProvider.GetMessage(ti.Name));
|
||||
var tilesetDropdown = tilesetSetting.Get<DropDownButtonWidget>("DROPDOWN");
|
||||
tilesetDropdown.GetText = () => label.Update(selectedTerrain);
|
||||
tilesetDropdown.OnMouseDown = _ =>
|
||||
{
|
||||
ScrollItemWidget SetupItem(ITerrainInfo terrainInfo, ScrollItemWidget template)
|
||||
{
|
||||
bool IsSelected() => terrainInfo == selectedTerrain;
|
||||
void OnClick()
|
||||
{
|
||||
selectedTerrain = terrainInfo;
|
||||
RefreshSettings();
|
||||
GenerateMap();
|
||||
}
|
||||
|
||||
var item = ScrollItemWidget.Setup(template, IsSelected, OnClick);
|
||||
var itemLabel = FluentProvider.GetMessage(terrainInfo.Name);
|
||||
item.Get<LabelWidget>("LABEL").GetText = () => itemLabel;
|
||||
return item;
|
||||
}
|
||||
|
||||
tilesetDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", validTerrainInfos.Count * 30, validTerrainInfos, SetupItem);
|
||||
};
|
||||
|
||||
var sizeLabel = FluentProvider.GetMessage(MapSize);
|
||||
sizeSetting = dropdownSettingTemplate.Clone();
|
||||
sizeSetting.Get<LabelWidget>("LABEL").GetText = () => sizeLabel;
|
||||
|
||||
var sizeDropdown = sizeSetting.Get<DropDownButtonWidget>("DROPDOWN");
|
||||
var sizeDropdownLabel = new CachedTransform<string, string>(s => FluentProvider.GetMessage(s));
|
||||
sizeDropdown.GetText = () => sizeDropdownLabel.Update(selectedSize);
|
||||
sizeDropdown.OnMouseDown = _ =>
|
||||
{
|
||||
ScrollItemWidget SetupItem(string size, ScrollItemWidget template)
|
||||
{
|
||||
bool IsSelected() => size == selectedSize;
|
||||
void OnClick()
|
||||
{
|
||||
selectedSize = size;
|
||||
RandomizeSize();
|
||||
GenerateMap();
|
||||
}
|
||||
|
||||
var item = ScrollItemWidget.Setup(template, IsSelected, OnClick);
|
||||
var label = FluentProvider.GetMessage(size);
|
||||
item.Get<LabelWidget>("LABEL").GetText = () => label;
|
||||
return item;
|
||||
}
|
||||
|
||||
sizeDropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", MapSizes.Count * 30, MapSizes.Keys, SetupItem);
|
||||
};
|
||||
|
||||
var generateButton = widget.Get<ButtonWidget>("BUTTON_GENERATE");
|
||||
generateButton.IsDisabled = () => generating;
|
||||
generateButton.OnClick = () =>
|
||||
{
|
||||
settings.Randomize(Game.CosmeticRandom);
|
||||
RandomizeSize();
|
||||
GenerateMap();
|
||||
};
|
||||
|
||||
selectedSize = MapSizes.Keys.Skip(1).First();
|
||||
if (initialSettings != null)
|
||||
{
|
||||
selectedTerrain = modData.DefaultTerrainInfo[initialSettings.Tileset];
|
||||
size = initialSettings.Size;
|
||||
foreach (var kv in MapSizes)
|
||||
if (kv.Value.X > size.Width && kv.Value.Y <= size.Width)
|
||||
selectedSize = kv.Key;
|
||||
|
||||
settings.Initialize(initialSettings);
|
||||
RefreshSettings();
|
||||
|
||||
var map = modData.MapCache[initialSettings.Uid];
|
||||
if (map.Status == MapStatus.Available)
|
||||
{
|
||||
preview.Update(map);
|
||||
onGenerate(initialSettings);
|
||||
}
|
||||
else
|
||||
GenerateMap();
|
||||
}
|
||||
else
|
||||
{
|
||||
selectedTerrain = validTerrainInfos[0];
|
||||
settings.Randomize(Game.CosmeticRandom);
|
||||
RandomizeSize();
|
||||
RefreshSettings();
|
||||
GenerateMap();
|
||||
}
|
||||
}
|
||||
|
||||
void RandomizeSize()
|
||||
{
|
||||
var sizeRange = MapSizes[selectedSize];
|
||||
var width = Game.CosmeticRandom.Next(sizeRange.X, sizeRange.Y);
|
||||
size = new Size(width + 2, width + 2);
|
||||
}
|
||||
|
||||
void RefreshSettings()
|
||||
{
|
||||
settingsPanel.RemoveChildren();
|
||||
tilesetSetting.Bounds = sizeSetting.Bounds = dropdownSettingTemplate.Bounds;
|
||||
settingsPanel.AddChild(tilesetSetting);
|
||||
settingsPanel.AddChild(sizeSetting);
|
||||
|
||||
var playerCount = settings.PlayerCount;
|
||||
foreach (var o in settings.Options)
|
||||
{
|
||||
if (o.Id == "Seed")
|
||||
continue;
|
||||
|
||||
Widget settingWidget = null;
|
||||
switch (o)
|
||||
{
|
||||
case MapGeneratorBooleanOption bo:
|
||||
{
|
||||
settingWidget = checkboxSettingTemplate.Clone();
|
||||
var checkboxWidget = settingWidget.Get<CheckboxWidget>("CHECKBOX");
|
||||
var label = FluentProvider.GetMessage(bo.Label);
|
||||
checkboxWidget.GetText = () => label;
|
||||
checkboxWidget.IsChecked = () => bo.Value;
|
||||
checkboxWidget.OnClick = () =>
|
||||
{
|
||||
bo.Value ^= true;
|
||||
GenerateMap();
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
case MapGeneratorIntegerOption io:
|
||||
{
|
||||
settingWidget = textSettingTemplate.Clone();
|
||||
var labelWidget = settingWidget.Get<LabelWidget>("LABEL");
|
||||
var label = FluentProvider.GetMessage(io.Label);
|
||||
labelWidget.GetText = () => label;
|
||||
var textFieldWidget = settingWidget.Get<TextFieldWidget>("INPUT");
|
||||
textFieldWidget.Type = TextFieldType.Integer;
|
||||
textFieldWidget.Text = FieldSaver.FormatValue(io.Value);
|
||||
textFieldWidget.OnTextEdited = () =>
|
||||
{
|
||||
var valid = int.TryParse(textFieldWidget.Text, out io.Value);
|
||||
textFieldWidget.IsValid = () => valid;
|
||||
};
|
||||
|
||||
textFieldWidget.OnEscKey = _ => { textFieldWidget.YieldKeyboardFocus(); return true; };
|
||||
textFieldWidget.OnEnterKey = _ => { textFieldWidget.YieldKeyboardFocus(); return true; };
|
||||
textFieldWidget.OnLoseFocus = GenerateMap;
|
||||
break;
|
||||
}
|
||||
|
||||
case MapGeneratorMultiIntegerChoiceOption mio:
|
||||
{
|
||||
settingWidget = dropdownSettingTemplate.Clone();
|
||||
var labelWidget = settingWidget.Get<LabelWidget>("LABEL");
|
||||
var label = FluentProvider.GetMessage(mio.Label);
|
||||
labelWidget.GetText = () => label;
|
||||
|
||||
var labelCache = new CachedTransform<int, string>(v => FieldSaver.FormatValue(v));
|
||||
var dropDownWidget = settingWidget.Get<DropDownButtonWidget>("DROPDOWN");
|
||||
dropDownWidget.GetText = () => labelCache.Update(mio.Value);
|
||||
dropDownWidget.OnMouseDown = _ =>
|
||||
{
|
||||
ScrollItemWidget SetupItem(int choice, ScrollItemWidget template)
|
||||
{
|
||||
bool IsSelected() => choice == mio.Value;
|
||||
void OnClick()
|
||||
{
|
||||
mio.Value = choice;
|
||||
if (o.Id == "Players")
|
||||
RefreshSettings();
|
||||
GenerateMap();
|
||||
}
|
||||
|
||||
var item = ScrollItemWidget.Setup(template, IsSelected, OnClick);
|
||||
var itemLabel = FieldSaver.FormatValue(choice);
|
||||
item.Get<LabelWidget>("LABEL").GetText = () => itemLabel;
|
||||
item.GetTooltipText = null;
|
||||
return item;
|
||||
}
|
||||
|
||||
dropDownWidget.ShowDropDown("LABEL_DROPDOWN_WITH_TOOLTIP_TEMPLATE", mio.Choices.Length * 30, mio.Choices, SetupItem);
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
case MapGeneratorMultiChoiceOption mo:
|
||||
{
|
||||
var validChoices = mo.ValidChoices(selectedTerrain, playerCount);
|
||||
if (!validChoices.Contains(mo.Value))
|
||||
mo.Value = mo.Default?.FirstOrDefault(validChoices.Contains) ?? validChoices.FirstOrDefault();
|
||||
|
||||
if (mo.Label != null && validChoices.Count > 0)
|
||||
{
|
||||
settingWidget = dropdownSettingTemplate.Clone();
|
||||
var labelWidget = settingWidget.Get<LabelWidget>("LABEL");
|
||||
var label = FluentProvider.GetMessage(mo.Label);
|
||||
labelWidget.GetText = () => label;
|
||||
|
||||
var labelCache = new CachedTransform<string, string>(v => FluentProvider.GetMessage(mo.Choices[v].Label + ".label"));
|
||||
var dropDownWidget = settingWidget.Get<DropDownButtonWidget>("DROPDOWN");
|
||||
dropDownWidget.GetText = () => labelCache.Update(mo.Value);
|
||||
dropDownWidget.OnMouseDown = _ =>
|
||||
{
|
||||
ScrollItemWidget SetupItem(string choice, ScrollItemWidget template)
|
||||
{
|
||||
bool IsSelected() => choice == mo.Value;
|
||||
void OnClick()
|
||||
{
|
||||
mo.Value = choice;
|
||||
GenerateMap();
|
||||
}
|
||||
|
||||
var item = ScrollItemWidget.Setup(template, IsSelected, OnClick);
|
||||
|
||||
var itemLabel = FluentProvider.GetMessage(mo.Choices[choice].Label + ".label");
|
||||
item.Get<LabelWidget>("LABEL").GetText = () => itemLabel;
|
||||
if (FluentProvider.TryGetMessage(mo.Choices[choice].Label + ".description", out var desc))
|
||||
item.GetTooltipText = () => desc;
|
||||
else
|
||||
item.GetTooltipText = null;
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
dropDownWidget.ShowDropDown("LABEL_DROPDOWN_WITH_TOOLTIP_TEMPLATE", validChoices.Count * 30, validChoices, SetupItem);
|
||||
};
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"Unhandled MapGeneratorOption type {o.GetType().Name}");
|
||||
}
|
||||
|
||||
if (settingWidget == null)
|
||||
continue;
|
||||
|
||||
settingWidget.IsVisible = () => true;
|
||||
settingsPanel.AddChild(settingWidget);
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateMap()
|
||||
{
|
||||
generating = true;
|
||||
onGenerate(null);
|
||||
failed = false;
|
||||
preview.Clear();
|
||||
Task.Run(() =>
|
||||
{
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
var args = settings.Compile(selectedTerrain, size);
|
||||
var map = generator.Generate(modData, args);
|
||||
|
||||
// Map UID and preview image are generated on save
|
||||
var package = new ZipFileLoader.ReadWriteZipFile();
|
||||
map.Save(package);
|
||||
args.Uid = map.Uid;
|
||||
|
||||
Game.RunAfterTick(() =>
|
||||
{
|
||||
preview.Update(map);
|
||||
onGenerate(args);
|
||||
generating = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore the exception
|
||||
}
|
||||
}
|
||||
|
||||
failed = true;
|
||||
generating = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,10 +98,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
|
||||
{
|
||||
{ "initialMap", map.Uid },
|
||||
{ "initialGeneratedMap", (MapGenerationArgs)null },
|
||||
{ "remoteMapPool", null },
|
||||
{ "initialTab", MapClassification.System },
|
||||
{ "onExit", () => modData.MapCache.UpdateMaps() },
|
||||
{ "onSelect", (Action<string>)(uid => map = modData.MapCache[uid]) },
|
||||
{ "onSelectGenerated", null },
|
||||
{ "filter", MapVisibility.Lobby },
|
||||
{ "onStart", () => { } }
|
||||
});
|
||||
|
||||
@@ -63,6 +63,9 @@ Container@MAPCHOOSER_PANEL:
|
||||
Width: PARENT_WIDTH
|
||||
Height: PARENT_HEIGHT
|
||||
ItemSpacing: 1
|
||||
Container@GENERATE_MAP_TAB:
|
||||
Width: PARENT_WIDTH
|
||||
Height: PARENT_HEIGHT + 30
|
||||
ScrollItem@MAP_TEMPLATE:
|
||||
Width: 210
|
||||
Height: 262
|
||||
@@ -186,3 +189,103 @@ Container@MAPCHOOSER_PANEL:
|
||||
Height: 35
|
||||
Text: button-bg-ok
|
||||
TooltipContainer@TOOLTIP_CONTAINER:
|
||||
|
||||
Container@MAPCHOOSER_GENERATE_PANEL:
|
||||
Logic: MapGeneratorLogic
|
||||
Width: PARENT_WIDTH
|
||||
Height: PARENT_HEIGHT
|
||||
Children:
|
||||
Background@MAP_BG:
|
||||
X: PARENT_WIDTH - WIDTH
|
||||
Width: 370
|
||||
Height: 370
|
||||
Background: panel-gray
|
||||
Children:
|
||||
GeneratedMapPreview@PREVIEW:
|
||||
X: 1
|
||||
Y: 1
|
||||
Width: PARENT_WIDTH - 2
|
||||
Height: PARENT_HEIGHT - 2
|
||||
Label@TITLE:
|
||||
X: PARENT_WIDTH - WIDTH
|
||||
Y: 375
|
||||
Width: 370
|
||||
Height: 24
|
||||
Align: Center
|
||||
Text: label-mapchooser-random-map-title
|
||||
Font: Bold
|
||||
Label@ERROR:
|
||||
X: PARENT_WIDTH - WIDTH
|
||||
Y: 405
|
||||
Width: 370
|
||||
Height: 24
|
||||
Align: Center
|
||||
Text: label-mapchooser-random-map-error-desc
|
||||
Label@DETAILS:
|
||||
X: PARENT_WIDTH - WIDTH
|
||||
Y: 405
|
||||
Width: 370
|
||||
Height: 24
|
||||
Align: Center
|
||||
LabelWithTooltip@AUTHOR:
|
||||
X: PARENT_WIDTH - WIDTH
|
||||
Y: 425
|
||||
Width: 370
|
||||
Height: 24
|
||||
Align: Center
|
||||
Label@SIZE:
|
||||
X: PARENT_WIDTH - WIDTH
|
||||
Y: 445
|
||||
Width: 370
|
||||
Height: 24
|
||||
Align: Center
|
||||
Button@BUTTON_GENERATE:
|
||||
X: PARENT_WIDTH - 135 - WIDTH
|
||||
Y: PARENT_HEIGHT + 14
|
||||
Width: 140
|
||||
Height: 35
|
||||
Text: button-mapchooser-random-map-generate
|
||||
ScrollPanel@SETTINGS_PANEL:
|
||||
TopBottomSpacing: 5
|
||||
Width: 485
|
||||
Height: PARENT_HEIGHT
|
||||
Children:
|
||||
Container@CHECKBOX_TEMPLATE:
|
||||
Width: 230
|
||||
Height: 30
|
||||
Children:
|
||||
Checkbox@CHECKBOX:
|
||||
X: 10
|
||||
Y: 5
|
||||
Width: PARENT_WIDTH - 20
|
||||
Height: 20
|
||||
Container@TEXT_TEMPLATE:
|
||||
Width: 230
|
||||
Height: 50
|
||||
Children:
|
||||
LabelForInput@LABEL:
|
||||
X: 10
|
||||
Width: PARENT_WIDTH - 20
|
||||
Height: 20
|
||||
For: INPUT
|
||||
TextField@INPUT:
|
||||
X: 10
|
||||
Y: 20
|
||||
Width: PARENT_WIDTH - 20
|
||||
Height: 25
|
||||
Container@DROPDOWN_TEMPLATE:
|
||||
Width: 230
|
||||
Height: 50
|
||||
Children:
|
||||
LabelForInput@LABEL:
|
||||
X: 10
|
||||
Width: PARENT_WIDTH - 20
|
||||
Height: 20
|
||||
For: DROPDOWN
|
||||
DropDownButton@DROPDOWN:
|
||||
X: 10
|
||||
Y: 20
|
||||
Width: PARENT_WIDTH - 20
|
||||
Height: 25
|
||||
PanelRoot: GENERATOR_DROPDOWN_PANEL_ROOT # ensure that tooltips for the options are on top of the dropdown panel
|
||||
Container@GENERATOR_DROPDOWN_PANEL_ROOT:
|
||||
|
||||
@@ -534,6 +534,14 @@ button-bg-delete-map = Delete Map
|
||||
button-bg-delete-all-maps = Delete All Maps
|
||||
button-bg-ok = Ok
|
||||
|
||||
label-mapchooser-random-map-title = Random Map
|
||||
label-mapchooser-random-map-generating = Generating...
|
||||
label-mapchooser-random-map-error = Map Generation Failed
|
||||
button-mapchooser-random-map-generate = Generate
|
||||
label-mapchooser-random-map-tileset = Environment:
|
||||
label-mapchooser-random-map-size = Map Size:
|
||||
label-mapchooser-random-map-error-desc = Adjust the settings to try again.
|
||||
|
||||
## missionbrowser.yaml
|
||||
button-missionbrowser-panel-mission-info = Mission Info
|
||||
button-missionbrowser-panel-mission-options = Options
|
||||
|
||||
@@ -57,6 +57,9 @@ Background@MAPCHOOSER_PANEL:
|
||||
ScrollPanel@MAP_LIST:
|
||||
Width: PARENT_WIDTH
|
||||
Height: PARENT_HEIGHT
|
||||
Container@GENERATE_MAP_TAB:
|
||||
Width: PARENT_WIDTH
|
||||
Height: PARENT_HEIGHT
|
||||
ScrollItem@MAP_TEMPLATE:
|
||||
Width: 208
|
||||
Height: 266
|
||||
@@ -185,3 +188,105 @@ Background@MAPCHOOSER_PANEL:
|
||||
Font: Bold
|
||||
Key: escape
|
||||
TooltipContainer@TOOLTIP_CONTAINER:
|
||||
|
||||
|
||||
Container@MAPCHOOSER_GENERATE_PANEL:
|
||||
Logic: MapGeneratorLogic
|
||||
Width: PARENT_WIDTH
|
||||
Height: PARENT_HEIGHT
|
||||
Children:
|
||||
Background@MAP_BG:
|
||||
X: PARENT_WIDTH - WIDTH
|
||||
Width: 370
|
||||
Height: 370
|
||||
Background: dialog3
|
||||
Children:
|
||||
GeneratedMapPreview@PREVIEW:
|
||||
X: 1
|
||||
Y: 1
|
||||
Width: PARENT_WIDTH - 2
|
||||
Height: PARENT_HEIGHT - 2
|
||||
Label@TITLE:
|
||||
X: PARENT_WIDTH - WIDTH
|
||||
Y: 375
|
||||
Width: 370
|
||||
Height: 24
|
||||
Align: Center
|
||||
Text: label-mapchooser-random-map-title
|
||||
Font: Bold
|
||||
Label@ERROR:
|
||||
X: PARENT_WIDTH - WIDTH
|
||||
Y: 405
|
||||
Width: 370
|
||||
Height: 24
|
||||
Align: Center
|
||||
Text: label-mapchooser-random-map-error-desc
|
||||
Label@DETAILS:
|
||||
X: PARENT_WIDTH - WIDTH
|
||||
Y: 405
|
||||
Width: 370
|
||||
Height: 24
|
||||
Align: Center
|
||||
LabelWithTooltip@AUTHOR:
|
||||
X: PARENT_WIDTH - WIDTH
|
||||
Y: 425
|
||||
Width: 370
|
||||
Height: 24
|
||||
Align: Center
|
||||
Label@SIZE:
|
||||
X: PARENT_WIDTH - WIDTH
|
||||
Y: 445
|
||||
Width: 370
|
||||
Height: 24
|
||||
Align: Center
|
||||
Button@BUTTON_GENERATE:
|
||||
X: PARENT_WIDTH - 380
|
||||
Y: PARENT_HEIGHT + 40
|
||||
Width: 120
|
||||
Height: 25
|
||||
Text: button-mapchooser-random-map-generate
|
||||
Font: Bold
|
||||
ScrollPanel@SETTINGS_PANEL:
|
||||
TopBottomSpacing: 5
|
||||
Width: 485
|
||||
Height: PARENT_HEIGHT + 30
|
||||
Children:
|
||||
Container@CHECKBOX_TEMPLATE:
|
||||
Width: 230
|
||||
Height: 30
|
||||
Children:
|
||||
Checkbox@CHECKBOX:
|
||||
X: 10
|
||||
Y: 5
|
||||
Width: PARENT_WIDTH - 20
|
||||
Height: 20
|
||||
Container@TEXT_TEMPLATE:
|
||||
Width: 230
|
||||
Height: 50
|
||||
Children:
|
||||
LabelForInput@LABEL:
|
||||
X: 10
|
||||
Width: PARENT_WIDTH - 20
|
||||
Height: 20
|
||||
For: INPUT
|
||||
TextField@INPUT:
|
||||
X: 10
|
||||
Y: 20
|
||||
Width: PARENT_WIDTH - 20
|
||||
Height: 25
|
||||
Container@DROPDOWN_TEMPLATE:
|
||||
Width: 230
|
||||
Height: 50
|
||||
Children:
|
||||
LabelForInput@LABEL:
|
||||
X: 10
|
||||
Width: PARENT_WIDTH - 20
|
||||
Height: 20
|
||||
For: DROPDOWN
|
||||
DropDownButton@DROPDOWN:
|
||||
X: 10
|
||||
Y: 20
|
||||
Width: PARENT_WIDTH - 20
|
||||
Height: 25
|
||||
PanelRoot: GENERATOR_DROPDOWN_PANEL_ROOT # ensure that tooltips for the options are on top of the dropdown panel
|
||||
Container@GENERATOR_DROPDOWN_PANEL_ROOT:
|
||||
|
||||
@@ -353,6 +353,14 @@ button-mapchooser-panel-delete-map = Delete Map
|
||||
button-mapchooser-panel-delete-all-maps = Delete All Maps
|
||||
button-mapchooser-panel-ok = Ok
|
||||
|
||||
label-mapchooser-random-map-title = Random Map
|
||||
label-mapchooser-random-map-generating = Generating...
|
||||
label-mapchooser-random-map-error = Map Generation Failed
|
||||
button-mapchooser-random-map-generate = Generate
|
||||
label-mapchooser-random-map-tileset = Environment:
|
||||
label-mapchooser-random-map-size = Map Size:
|
||||
label-mapchooser-random-map-error-desc = Adjust the settings to try again.
|
||||
|
||||
## missionbrowser.yaml
|
||||
button-missionbrowser-panel-start-briefing-video = Watch Briefing
|
||||
button-missionbrowser-panel-stop-briefing-video = Stop Briefing
|
||||
|
||||
@@ -514,6 +514,7 @@ options-order-maps =
|
||||
button-mapchooser-system-maps-tab = Official Maps
|
||||
button-mapchooser-remote-maps-tab = Server Maps
|
||||
button-mapchooser-user-maps-tab = Custom Maps
|
||||
button-mapchooser-generated-maps-tab = Generate Map
|
||||
|
||||
## MissionBrowserLogic
|
||||
dialog-no-video =
|
||||
|
||||
Reference in New Issue
Block a user