Introduce MapCache and MapPreview for improved UI map previews.

This commit is contained in:
Paul Chote
2014-03-14 13:30:03 +13:00
parent 63068d5a7c
commit c30b18a9d6
20 changed files with 407 additions and 290 deletions

View File

@@ -38,8 +38,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
ScrollPanelWidget players;
Dictionary<string, string> countryNames;
string mapUid;
Map map;
MapPreview preview = MapCache.UnknownMap;
ColorPreviewManagerWidget colorPreview;
@@ -124,31 +123,21 @@ namespace OpenRA.Mods.RA.Widgets.Logic
colorPreview.Color = Game.Settings.Player.Color;
var mapPreview = lobby.Get<MapPreviewWidget>("MAP_PREVIEW");
mapPreview.IsVisible = () => map != null;
mapPreview.Map = () => map;
mapPreview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, mapPreview, map, mi);
mapPreview.SpawnClients = () => LobbyUtils.GetSpawnClients(orderManager, map);
mapPreview.Preview = () => preview;
mapPreview.OnMouseDown = mi => LobbyUtils.SelectSpawnPoint(orderManager, mapPreview, preview, mi);
mapPreview.SpawnClients = () => LobbyUtils.GetSpawnClients(orderManager, preview);
var mapTitle = lobby.GetOrNull<LabelWidget>("MAP_TITLE");
if (mapTitle != null)
{
mapTitle.IsVisible = () => map != null;
mapTitle.GetText = () => map.Title;
}
mapTitle.GetText = () => preview.Title;
var mapType = lobby.GetOrNull<LabelWidget>("MAP_TYPE");
if (mapType != null)
{
mapType.IsVisible = () => map != null;
mapType.GetText = () => map.Type;
}
mapType.GetText = () => preview.Type;
var mapAuthor = lobby.GetOrNull<LabelWidget>("MAP_AUTHOR");
if (mapAuthor != null)
{
mapAuthor.IsVisible = () => map != null;
mapAuthor.GetText = () => "Created by {0}".F(map.Author);
}
mapAuthor.GetText = () => "Created by {0}".F(preview.Author);
countryNames = Rules.Info["world"].Traits.WithInterface<CountryInfo>()
.Where(c => c.Selectable)
@@ -174,7 +163,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
{
{ "initialMap", map.Uid },
{ "initialMap", preview.Uid },
{ "onExit", () => { } },
{ "onSelect", onSelect }
});
@@ -308,7 +297,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (allowCheats != null)
{
allowCheats.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllowCheats;
allowCheats.IsDisabled = () => map.Options.Cheats.HasValue || configurationDisabled();
allowCheats.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.Cheats.HasValue || configurationDisabled();
allowCheats.OnClick = () => orderManager.IssueOrder(Order.Command(
"allowcheats {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllowCheats)));
}
@@ -317,7 +306,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (crates != null)
{
crates.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Crates;
crates.IsDisabled = () => map.Options.Crates.HasValue || configurationDisabled();
crates.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.Crates.HasValue || configurationDisabled();
crates.OnClick = () => orderManager.IssueOrder(Order.Command(
"crates {0}".F(!orderManager.LobbyInfo.GlobalSettings.Crates)));
}
@@ -326,7 +315,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (allybuildradius != null)
{
allybuildradius.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius;
allybuildradius.IsDisabled = () => map.Options.AllyBuildRadius.HasValue || configurationDisabled();
allybuildradius.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.AllyBuildRadius.HasValue || configurationDisabled();
allybuildradius.OnClick = () => orderManager.IssueOrder(Order.Command(
"allybuildradius {0}".F(!orderManager.LobbyInfo.GlobalSettings.AllyBuildRadius)));
}
@@ -335,7 +324,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (fragileAlliance != null)
{
fragileAlliance.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.FragileAlliances;
fragileAlliance.IsDisabled = () => map.Options.FragileAlliances.HasValue || configurationDisabled();
fragileAlliance.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.FragileAlliances.HasValue || configurationDisabled();
fragileAlliance.OnClick = () => orderManager.IssueOrder(Order.Command(
"fragilealliance {0}".F(!orderManager.LobbyInfo.GlobalSettings.FragileAlliances)));
}
@@ -343,12 +332,12 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var difficulty = optionsBin.GetOrNull<DropDownButtonWidget>("DIFFICULTY_DROPDOWNBUTTON");
if (difficulty != null)
{
difficulty.IsVisible = () => map.Options.Difficulties.Any();
difficulty.IsDisabled = configurationDisabled;
difficulty.IsVisible = () => preview.Status == MapStatus.Available && preview.Map.Options.Difficulties.Any();
difficulty.IsDisabled = () => preview.Status != MapStatus.Available || configurationDisabled();
difficulty.GetText = () => orderManager.LobbyInfo.GlobalSettings.Difficulty;
difficulty.OnMouseDown = _ =>
{
var options = map.Options.Difficulties.Select(d => new DropDownOption
var options = preview.Map.Options.Difficulties.Select(d => new DropDownOption
{
Title = d,
IsSelected = () => orderManager.LobbyInfo.GlobalSettings.Difficulty == d,
@@ -380,8 +369,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var classes = Rules.Info["world"].Traits.WithInterface<MPStartUnitsInfo>()
.Select(a => a.Class).Distinct();
startingUnits.IsDisabled = () => !map.Options.ConfigurableStartingUnits || configurationDisabled();
startingUnits.GetText = () => !map.Options.ConfigurableStartingUnits ? "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass);
startingUnits.IsDisabled = () => preview.Status != MapStatus.Available || !preview.Map.Options.ConfigurableStartingUnits || configurationDisabled();
startingUnits.GetText = () => preview.Status != MapStatus.Available || !preview.Map.Options.ConfigurableStartingUnits ? "Not Available" : className(orderManager.LobbyInfo.GlobalSettings.StartingUnitsClass);
startingUnits.OnMouseDown = _ =>
{
var options = classes.Select(c => new DropDownOption
@@ -407,8 +396,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var startingCash = optionsBin.GetOrNull<DropDownButtonWidget>("STARTINGCASH_DROPDOWNBUTTON");
if (startingCash != null)
{
startingCash.IsDisabled = () => map.Options.StartingCash.HasValue || configurationDisabled();
startingCash.GetText = () => map.Options.StartingCash.HasValue ? "Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash);
startingCash.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.StartingCash.HasValue || configurationDisabled();
startingCash.GetText = () => preview.Status != MapStatus.Available || preview.Map.Options.StartingCash.HasValue ? "Not Available" : "${0}".F(orderManager.LobbyInfo.GlobalSettings.StartingCash);
startingCash.OnMouseDown = _ =>
{
var options = Rules.Info["player"].Traits.Get<PlayerResourcesInfo>().SelectableCash.Select(c => new DropDownOption
@@ -433,7 +422,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (enableShroud != null)
{
enableShroud.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Shroud;
enableShroud.IsDisabled = () => map.Options.Shroud.HasValue || configurationDisabled();
enableShroud.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.Shroud.HasValue || configurationDisabled();
enableShroud.OnClick = () => orderManager.IssueOrder(Order.Command(
"shroud {0}".F(!orderManager.LobbyInfo.GlobalSettings.Shroud)));
}
@@ -442,7 +431,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (enableFog != null)
{
enableFog.IsChecked = () => orderManager.LobbyInfo.GlobalSettings.Fog;
enableFog.IsDisabled = () => map.Options.Fog.HasValue || configurationDisabled();
enableFog.IsDisabled = () => preview.Status != MapStatus.Available || preview.Map.Options.Fog.HasValue || configurationDisabled();
enableFog.OnClick = () => orderManager.IssueOrder(Order.Command(
"fog {0}".F(!orderManager.LobbyInfo.GlobalSettings.Fog)));
}
@@ -529,24 +518,25 @@ namespace OpenRA.Mods.RA.Widgets.Logic
void UpdateCurrentMap()
{
if (mapUid == orderManager.LobbyInfo.GlobalSettings.Map)
var uid = orderManager.LobbyInfo.GlobalSettings.Map;
if (preview.Uid == uid)
return;
mapUid = orderManager.LobbyInfo.GlobalSettings.Map;
if (!Game.modData.AvailableMaps.ContainsKey(mapUid))
preview = Game.modData.MapCache[uid];
if (preview.Status != MapStatus.Available)
{
if (Game.Settings.Game.AllowDownloading)
{
Game.DownloadMap(mapUid);
Game.DownloadMap(uid);
Game.Debug("A new map has been downloaded...");
}
else
throw new InvalidOperationException("Server's new map doesn't exist on your system and Downloading turned off");
map = new Map(Game.modData.AvailableMaps[mapUid].Path);
}
// Restore default starting cash if the last map set it to something invalid
var pri = Rules.Info["player"].Traits.Get<PlayerResourcesInfo>();
if (!map.Options.StartingCash.HasValue && !pri.SelectableCash.Contains(orderManager.LobbyInfo.GlobalSettings.StartingCash))
if (!preview.Map.Options.StartingCash.HasValue && !pri.SelectableCash.Contains(orderManager.LobbyInfo.GlobalSettings.StartingCash))
orderManager.IssueOrder(Order.Command("startingcash {0}".F(pri.DefaultCash)));
}
@@ -596,7 +586,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
LobbyUtils.SetupEditableColorWidget(template, slot, client, orderManager, colorPreview);
LobbyUtils.SetupEditableFactionWidget(template, slot, client, orderManager, countryNames);
LobbyUtils.SetupEditableTeamWidget(template, slot, client, orderManager, map.GetSpawnPoints().Length);
LobbyUtils.SetupEditableTeamWidget(template, slot, client, orderManager, preview.SpawnPoints.Count);
LobbyUtils.SetupEditableReadyWidget(template, slot, client, orderManager);
}
else

View File

@@ -130,26 +130,23 @@ namespace OpenRA.Mods.RA.Widgets.Logic
color.AttachPanel(colorChooser, onExit);
}
public static Dictionary<CPos, Session.Client> GetSpawnClients(OrderManager orderManager, Map map)
public static Dictionary<CPos, Session.Client> GetSpawnClients(OrderManager orderManager, MapPreview preview)
{
var spawns = map.GetSpawnPoints();
var spawns = preview.SpawnPoints;
return orderManager.LobbyInfo.Clients
.Where(c => c.SpawnPoint != 0)
.ToDictionary(
c => spawns[c.SpawnPoint - 1],
c => c);
.ToDictionary(c => spawns[c.SpawnPoint - 1], c => c);
}
public static void SelectSpawnPoint(OrderManager orderManager, MapPreviewWidget mapPreview, Map map, MouseInput mi)
public static void SelectSpawnPoint(OrderManager orderManager, MapPreviewWidget mapPreview, MapPreview preview, MouseInput mi)
{
if (map == null)
return;
if (mi.Button != MouseButton.Left)
return;
if (!orderManager.LocalClient.IsObserver && orderManager.LocalClient.State == Session.ClientState.Ready)
return;
var selectedSpawn = map.GetSpawnPoints()
var selectedSpawn = preview.SpawnPoints
.Select((sp, i) => Pair.New(mapPreview.ConvertToPreview(sp), i))
.Where(a => (a.First - mi.Location).LengthSquared < 64)
.Select(a => a.Second + 1)

View File

@@ -30,7 +30,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
[ObjectCreator.UseCtor]
internal MapChooserLogic(Widget widget, string initialMap, Action onExit, Action<Map> onSelect)
{
map = Game.modData.AvailableMaps[WidgetUtils.ChooseInitialMap(initialMap)];
map = Game.modData.MapCache[WidgetUtils.ChooseInitialMap(initialMap)].Map;
widget.Get<ButtonWidget>("BUTTON_OK").OnClick = () => { Ui.CloseWindow(); onSelect(map); };
widget.Get<ButtonWidget>("BUTTON_CANCEL").OnClick = () => { Ui.CloseWindow(); onExit(); };
@@ -44,9 +44,9 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var gameModeDropdown = widget.GetOrNull<DropDownButtonWidget>("GAMEMODE_FILTER");
if (gameModeDropdown != null)
{
var selectableMaps = Game.modData.AvailableMaps.Where(m => m.Value.Selectable).ToList();
var selectableMaps = Game.modData.MapCache.Where(m => m.Status == MapStatus.Available && m.Map.Selectable);
var gameModes = selectableMaps
.GroupBy(m => m.Value.Type)
.GroupBy(m => m.Type)
.Select(g => Pair.New(g.Key, g.Count())).ToList();
// 'all game types' extra item
@@ -87,8 +87,9 @@ namespace OpenRA.Mods.RA.Widgets.Logic
void EnumerateMaps(Action<Map> onSelect)
{
var maps = Game.modData.AvailableMaps
.Where(kv => kv.Value.Selectable)
var maps = Game.modData.MapCache
.Where(m => m.Status == MapStatus.Available && m.Map.Selectable)
.ToDictionary(m => m.Uid, m => m.Map)
.Where(kv => kv.Value.Type == gameMode || gameMode == null)
.OrderBy(kv => kv.Value.PlayerCount)
.ThenBy(kv => kv.Value.Title);
@@ -102,10 +103,11 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var titleLabel = item.Get<LabelWidget>("TITLE");
titleLabel.GetText = () => m.Title;
var preview = Game.modData.MapCache[m.Uid];
var previewWidget = item.Get<MapPreviewWidget>("PREVIEW");
previewWidget.IgnoreMouseOver = true;
previewWidget.IgnoreMouseInput = true;
previewWidget.Map = () => m;
previewWidget.Preview = () => preview;
previewWidget.IsVisible = () => previewWidget.RenderBounds.IntersectsWith(scrollpanel.RenderBounds);
var previewLoadingWidget = item.GetOrNull<BackgroundWidget>("PREVIEW_PLACEHOLDER");

View File

@@ -51,7 +51,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
}
Replay currentReplay;
Map currentMap;
MapPreview currentMap = MapCache.UnknownMap;
void SelectReplay(string filename)
{
@@ -61,11 +61,11 @@ namespace OpenRA.Mods.RA.Widgets.Logic
try
{
currentReplay = new Replay(filename);
currentMap = currentReplay.Map();
currentMap = Game.modData.MapCache[currentReplay.LobbyInfo.GlobalSettings.Map];
panel.Get<LabelWidget>("DURATION").GetText =
() => WidgetUtils.FormatTime(currentReplay.Duration);
panel.Get<MapPreviewWidget>("MAP_PREVIEW").Map = () => currentMap;
panel.Get<MapPreviewWidget>("MAP_PREVIEW").Preview = () => currentMap;
panel.Get<LabelWidget>("MAP_TITLE").GetText =
() => currentMap != null ? currentMap.Title : "(Unknown Map)";
@@ -77,7 +77,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
{
Log.Write("debug", "Exception while parsing replay: {0}", e);
currentReplay = null;
currentMap = null;
currentMap = MapCache.UnknownMap;
}
}

View File

@@ -155,10 +155,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic
if (game == null || game.Players == 0)
return "";
var map = Game.modData.FindMapByUid(game.Map);
var maxPlayers = map == null ? "?" : (object)map.PlayerCount;
return "{0} / {1}".F(game.Players, maxPlayers);
var map = Game.modData.MapCache[game.Map];
return "{0} / {1}".F(game.Players, map.PlayerCount == 0 ? "?" : map.PlayerCount.ToString());
}
string GetStateLabel(GameServer game)
@@ -176,11 +174,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic
return "Unknown server state";
}
Map GetMapPreview(GameServer game)
{
return (game == null) ? null : Game.modData.FindMapByUid(game.Map);
}
public static string GenerateModLabel(GameServer s)
{
Mod mod;
@@ -241,20 +234,16 @@ namespace OpenRA.Mods.RA.Widgets.Logic
var item = ScrollItemWidget.Setup(serverTemplate, () => currentServer == game, () => currentServer = game, () => Join(game));
var map = Game.modData.MapCache[game.Map];
var preview = item.Get<MapPreviewWidget>("MAP_PREVIEW");
preview.Map = () => GetMapPreview(game);
preview.IsVisible = () => GetMapPreview(game) != null;
preview.Preview = () => map;
var title = item.Get<LabelWidget>("TITLE");
title.GetText = () => game.Name;
// TODO: Use game.MapTitle once the server supports it
var maptitle = item.Get<LabelWidget>("MAP");
maptitle.GetText = () =>
{
var map = Game.modData.FindMapByUid(game.Map);
return map == null ? "Unknown Map" : map.Title;
};
maptitle.GetText = () => map.Title;
// TODO: Use game.MaxPlayers once the server supports it
var players = item.Get<LabelWidget>("PLAYERS");

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
Widget panel;
Action onCreate;
Action onExit;
Map map;
MapPreview preview = MapCache.UnknownMap;
bool advertiseOnline;
bool allowPortForward;
@@ -32,12 +32,11 @@ namespace OpenRA.Mods.RA.Widgets.Logic
this.onExit = onExit;
var settings = Game.Settings;
preview = Game.modData.MapCache[WidgetUtils.ChooseInitialMap(Game.Settings.Server.Map)];
panel.Get<ButtonWidget>("BACK_BUTTON").OnClick = () => { Ui.CloseWindow(); onExit(); };
panel.Get<ButtonWidget>("CREATE_BUTTON").OnClick = CreateAndJoin;
map = Game.modData.AvailableMaps[ WidgetUtils.ChooseInitialMap(Game.Settings.Server.Map) ];
var mapButton = panel.GetOrNull<ButtonWidget>("MAP_BUTTON");
if (mapButton != null)
{
@@ -45,14 +44,14 @@ namespace OpenRA.Mods.RA.Widgets.Logic
{
Ui.OpenWindow("MAPCHOOSER_PANEL", new WidgetArgs()
{
{ "initialMap", map.Uid },
{ "initialMap", preview.Uid },
{ "onExit", () => {} },
{ "onSelect", (Action<Map>)(m => map = m) }
{ "onSelect", (Action<Map>)(m => preview = Game.modData.MapCache[m.Uid]) }
});
};
panel.Get<MapPreviewWidget>("MAP_PREVIEW").Map = () => map;
panel.Get<LabelWidget>("MAP_NAME").GetText = () => map.Title;
panel.Get<MapPreviewWidget>("MAP_PREVIEW").Preview = () => preview;
panel.Get<LabelWidget>("MAP_NAME").GetText = () => preview.Title;
}
panel.Get<TextFieldWidget>("SERVER_NAME").Text = settings.Server.Name ?? "";
@@ -97,7 +96,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic
Game.Settings.Server.ExternalPort = externalPort;
Game.Settings.Server.AdvertiseOnline = advertiseOnline;
Game.Settings.Server.AllowPortForward = allowPortForward;
Game.Settings.Server.Map = map.Uid;
Game.Settings.Server.Map = preview.Uid;
Game.Settings.Server.Password = password;
Game.Settings.Save();