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;
|
MapPreview map;
|
||||||
Session.MapStatus mapStatus;
|
Session.MapStatus mapStatus;
|
||||||
|
MapGenerationArgs lastGeneratedMap;
|
||||||
|
|
||||||
bool chatEnabled;
|
bool chatEnabled;
|
||||||
bool disableTeamChat;
|
bool disableTeamChat;
|
||||||
@@ -249,16 +250,30 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
Game.Settings.Save();
|
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
|
// Check for updated maps, if the user has edited a map we'll preselect it for them
|
||||||
modData.MapCache.UpdateMaps();
|
modData.MapCache.UpdateMaps();
|
||||||
|
|
||||||
Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
|
Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
|
||||||
{
|
{
|
||||||
{ "initialMap", modData.MapCache.PickLastModifiedMap(MapVisibility.Lobby) ?? map.Uid },
|
{ "initialMap", modData.MapCache.PickLastModifiedMap(MapVisibility.Lobby) ?? map.Uid },
|
||||||
|
{ "initialGeneratedMap", lastGeneratedMap },
|
||||||
{ "remoteMapPool", orderManager.ServerMapPool },
|
{ "remoteMapPool", orderManager.ServerMapPool },
|
||||||
{ "initialTab", MapClassification.System },
|
{ "initialTab", MapClassification.System },
|
||||||
{ "onExit", modData.MapCache.UpdateMaps },
|
{ "onExit", modData.MapCache.UpdateMaps },
|
||||||
{ "onSelect", Game.IsHost ? onSelect : null },
|
{ "onSelect", Game.IsHost ? onSelect : null },
|
||||||
|
{ "onSelectGenerated", Game.IsHost ? onSelectGenerated : null },
|
||||||
{ "filter", MapVisibility.Lobby },
|
{ "filter", MapVisibility.Lobby },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -211,10 +211,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
Game.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
|
Game.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
|
||||||
{
|
{
|
||||||
{ "initialMap", null },
|
{ "initialMap", null },
|
||||||
|
{ "initialGeneratedMap", (MapGenerationArgs)null },
|
||||||
{ "remoteMapPool", null },
|
{ "remoteMapPool", null },
|
||||||
{ "initialTab", MapClassification.User },
|
{ "initialTab", MapClassification.User },
|
||||||
{ "onExit", () => SwitchMenu(MenuType.MapEditor) },
|
{ "onExit", () => SwitchMenu(MenuType.MapEditor) },
|
||||||
{ "onSelect", onSelect },
|
{ "onSelect", onSelect },
|
||||||
|
{ "onSelectGenerated", null },
|
||||||
{ "filter", MapVisibility.Lobby | MapVisibility.Shellmap | MapVisibility.MissionSelector },
|
{ "filter", MapVisibility.Lobby | MapVisibility.Shellmap | MapVisibility.MissionSelector },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Primitives;
|
using OpenRA.Primitives;
|
||||||
using OpenRA.Widgets;
|
using OpenRA.Widgets;
|
||||||
|
|
||||||
@@ -91,6 +92,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
[FluentReference]
|
[FluentReference]
|
||||||
const string RemoteMapsTab = "button-mapchooser-remote-maps-tab";
|
const string RemoteMapsTab = "button-mapchooser-remote-maps-tab";
|
||||||
|
|
||||||
|
[FluentReference]
|
||||||
|
const string GeneratedMapsTab = "button-mapchooser-generated-maps-tab";
|
||||||
|
|
||||||
public static string MapSizeLabel(Size size)
|
public static string MapSizeLabel(Size size)
|
||||||
{
|
{
|
||||||
var area = size.Width * size.Height;
|
var area = size.Width * size.Height;
|
||||||
@@ -124,6 +128,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
string selectedUid;
|
string selectedUid;
|
||||||
readonly Action<string> onSelect;
|
readonly Action<string> onSelect;
|
||||||
|
MapGenerationArgs generatedMap;
|
||||||
|
|
||||||
string category;
|
string category;
|
||||||
string mapFilter;
|
string mapFilter;
|
||||||
@@ -131,8 +136,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
Func<MapPreview, long> orderByFunc;
|
Func<MapPreview, long> orderByFunc;
|
||||||
|
|
||||||
[ObjectCreator.UseCtor]
|
[ObjectCreator.UseCtor]
|
||||||
internal MapChooserLogic(Widget widget, ModData modData, string initialMap, HashSet<string> remoteMapPool,
|
internal MapChooserLogic(Widget widget, ModData modData, string initialMap, MapGenerationArgs initialGeneratedMap, HashSet<string> remoteMapPool,
|
||||||
MapClassification initialTab, Action onExit, Action<string> onSelect, MapVisibility filter)
|
MapClassification initialTab, Action onExit, Action<string> onSelect, Action<MapGenerationArgs> onSelectGenerated, MapVisibility filter)
|
||||||
{
|
{
|
||||||
this.widget = widget;
|
this.widget = widget;
|
||||||
this.modData = modData;
|
this.modData = modData;
|
||||||
@@ -145,13 +150,20 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var approving = new Action(() =>
|
var approving = new Action(() =>
|
||||||
{
|
{
|
||||||
Ui.CloseWindow();
|
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 canceling = new Action(() => { Ui.CloseWindow(); onExit(); });
|
||||||
|
|
||||||
var okButton = widget.Get<ButtonWidget>("BUTTON_OK");
|
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;
|
okButton.OnClick = approving;
|
||||||
widget.Get<ButtonWidget>("BUTTON_CANCEL").OnClick = canceling;
|
widget.Get<ButtonWidget>("BUTTON_CANCEL").OnClick = canceling;
|
||||||
|
|
||||||
@@ -162,6 +174,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
SetupOrderByDropdown();
|
SetupOrderByDropdown();
|
||||||
|
|
||||||
|
var filterContainer = widget.GetOrNull("FILTER_ORDER_CONTROLS");
|
||||||
|
if (filterContainer != null)
|
||||||
|
filterContainer.IsVisible = () => currentTab != MapClassification.Generated;
|
||||||
|
|
||||||
var mapFilterInput = widget.GetOrNull<TextFieldWidget>("MAPFILTER_INPUT");
|
var mapFilterInput = widget.GetOrNull<TextFieldWidget>("MAPFILTER_INPUT");
|
||||||
if (mapFilterInput != null)
|
if (mapFilterInput != null)
|
||||||
{
|
{
|
||||||
@@ -196,6 +212,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
scrollpanels[currentTab].ScrollToItem(uid, smooth: true);
|
scrollpanels[currentTab].ScrollToItem(uid, smooth: true);
|
||||||
};
|
};
|
||||||
randomMapButton.IsDisabled = () => visibleMaps == null || visibleMaps.Length == 0;
|
randomMapButton.IsDisabled = () => visibleMaps == null || visibleMaps.Length == 0;
|
||||||
|
randomMapButton.IsVisible = () => currentTab != MapClassification.Generated;
|
||||||
}
|
}
|
||||||
|
|
||||||
var deleteMapButton = widget.Get<ButtonWidget>("DELETE_MAP_BUTTON");
|
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.System, "SYSTEM_MAPS_TAB");
|
||||||
SetupMapPanel(MapClassification.Remote, "REMOTE_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
|
// System and user map tabs are hidden when the server forces a restricted pool
|
||||||
if (remoteMapPool != null)
|
if (remoteMapPool != null)
|
||||||
{
|
{
|
||||||
@@ -260,8 +281,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
tabLabels[MapClassification.System] = SystemMapsTab;
|
tabLabels[MapClassification.System] = SystemMapsTab;
|
||||||
tabLabels[MapClassification.User] = UserMapsTab;
|
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();
|
var uid = map.Select(mp => mp.Uid).First();
|
||||||
selectedUid = Game.ModData.MapCache.ChooseInitialMap(uid, Game.CosmeticRandom);
|
selectedUid = Game.ModData.MapCache.ChooseInitialMap(uid, Game.CosmeticRandom);
|
||||||
@@ -286,7 +314,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
void RefreshMaps(MapClassification tab)
|
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 &&
|
tabMaps[tab] = modData.MapCache.Where(m => m.Status == MapStatus.Available &&
|
||||||
m.Class == tab && (m.Visibility & filter) != 0).ToArray();
|
m.Class == tab && (m.Visibility & filter) != 0).ToArray();
|
||||||
else if (remoteMapPool != null)
|
else if (remoteMapPool != null)
|
||||||
@@ -358,6 +386,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
RefreshMaps(tab);
|
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)
|
void SetupGameModeDropdown(MapClassification tab, DropDownButtonWidget gameModeDropdown)
|
||||||
{
|
{
|
||||||
if (gameModeDropdown != null)
|
if (gameModeDropdown != null)
|
||||||
@@ -443,6 +483,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
void EnumerateMaps(MapClassification tab)
|
void EnumerateMaps(MapClassification tab)
|
||||||
{
|
{
|
||||||
|
if (tab == MapClassification.Generated)
|
||||||
|
return;
|
||||||
|
|
||||||
if (!int.TryParse(mapFilter, out var playerCountFilter))
|
if (!int.TryParse(mapFilter, out var playerCountFilter))
|
||||||
playerCountFilter = -1;
|
playerCountFilter = -1;
|
||||||
|
|
||||||
@@ -532,7 +575,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
modData.MapCache[map].Delete();
|
modData.MapCache[map].Delete();
|
||||||
if (selectedUid == map)
|
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);
|
Game.CosmeticRandom);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -569,7 +612,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
foreach (var map in maps)
|
foreach (var map in maps)
|
||||||
DeleteMap(map);
|
DeleteMap(map);
|
||||||
|
|
||||||
after?.Invoke(Game.ModData.MapCache.ChooseInitialMap(null, Game.CosmeticRandom));
|
after?.Invoke(modData.MapCache.ChooseInitialMap(null, Game.CosmeticRandom));
|
||||||
},
|
},
|
||||||
confirmText: DeleteAllMapsAccept,
|
confirmText: DeleteAllMapsAccept,
|
||||||
onCancel: () => { });
|
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()
|
Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
|
||||||
{
|
{
|
||||||
{ "initialMap", map.Uid },
|
{ "initialMap", map.Uid },
|
||||||
|
{ "initialGeneratedMap", (MapGenerationArgs)null },
|
||||||
{ "remoteMapPool", null },
|
{ "remoteMapPool", null },
|
||||||
{ "initialTab", MapClassification.System },
|
{ "initialTab", MapClassification.System },
|
||||||
{ "onExit", () => modData.MapCache.UpdateMaps() },
|
{ "onExit", () => modData.MapCache.UpdateMaps() },
|
||||||
{ "onSelect", (Action<string>)(uid => map = modData.MapCache[uid]) },
|
{ "onSelect", (Action<string>)(uid => map = modData.MapCache[uid]) },
|
||||||
|
{ "onSelectGenerated", null },
|
||||||
{ "filter", MapVisibility.Lobby },
|
{ "filter", MapVisibility.Lobby },
|
||||||
{ "onStart", () => { } }
|
{ "onStart", () => { } }
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ Container@MAPCHOOSER_PANEL:
|
|||||||
Width: PARENT_WIDTH
|
Width: PARENT_WIDTH
|
||||||
Height: PARENT_HEIGHT
|
Height: PARENT_HEIGHT
|
||||||
ItemSpacing: 1
|
ItemSpacing: 1
|
||||||
|
Container@GENERATE_MAP_TAB:
|
||||||
|
Width: PARENT_WIDTH
|
||||||
|
Height: PARENT_HEIGHT + 30
|
||||||
ScrollItem@MAP_TEMPLATE:
|
ScrollItem@MAP_TEMPLATE:
|
||||||
Width: 210
|
Width: 210
|
||||||
Height: 262
|
Height: 262
|
||||||
@@ -186,3 +189,103 @@ Container@MAPCHOOSER_PANEL:
|
|||||||
Height: 35
|
Height: 35
|
||||||
Text: button-bg-ok
|
Text: button-bg-ok
|
||||||
TooltipContainer@TOOLTIP_CONTAINER:
|
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-delete-all-maps = Delete All Maps
|
||||||
button-bg-ok = Ok
|
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
|
## missionbrowser.yaml
|
||||||
button-missionbrowser-panel-mission-info = Mission Info
|
button-missionbrowser-panel-mission-info = Mission Info
|
||||||
button-missionbrowser-panel-mission-options = Options
|
button-missionbrowser-panel-mission-options = Options
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ Background@MAPCHOOSER_PANEL:
|
|||||||
ScrollPanel@MAP_LIST:
|
ScrollPanel@MAP_LIST:
|
||||||
Width: PARENT_WIDTH
|
Width: PARENT_WIDTH
|
||||||
Height: PARENT_HEIGHT
|
Height: PARENT_HEIGHT
|
||||||
|
Container@GENERATE_MAP_TAB:
|
||||||
|
Width: PARENT_WIDTH
|
||||||
|
Height: PARENT_HEIGHT
|
||||||
ScrollItem@MAP_TEMPLATE:
|
ScrollItem@MAP_TEMPLATE:
|
||||||
Width: 208
|
Width: 208
|
||||||
Height: 266
|
Height: 266
|
||||||
@@ -185,3 +188,105 @@ Background@MAPCHOOSER_PANEL:
|
|||||||
Font: Bold
|
Font: Bold
|
||||||
Key: escape
|
Key: escape
|
||||||
TooltipContainer@TOOLTIP_CONTAINER:
|
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-delete-all-maps = Delete All Maps
|
||||||
button-mapchooser-panel-ok = Ok
|
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
|
## missionbrowser.yaml
|
||||||
button-missionbrowser-panel-start-briefing-video = Watch Briefing
|
button-missionbrowser-panel-start-briefing-video = Watch Briefing
|
||||||
button-missionbrowser-panel-stop-briefing-video = Stop 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-system-maps-tab = Official Maps
|
||||||
button-mapchooser-remote-maps-tab = Server Maps
|
button-mapchooser-remote-maps-tab = Server Maps
|
||||||
button-mapchooser-user-maps-tab = Custom Maps
|
button-mapchooser-user-maps-tab = Custom Maps
|
||||||
|
button-mapchooser-generated-maps-tab = Generate Map
|
||||||
|
|
||||||
## MissionBrowserLogic
|
## MissionBrowserLogic
|
||||||
dialog-no-video =
|
dialog-no-video =
|
||||||
|
|||||||
Reference in New Issue
Block a user