Reduce jank in the mission chooser.

This commit is contained in:
Paul Chote
2016-02-05 22:46:12 +00:00
parent 7b00da04ca
commit 8b5592e1dd

View File

@@ -14,6 +14,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Widgets; using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic namespace OpenRA.Mods.Common.Widgets.Logic
@@ -38,6 +39,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
readonly ScrollPanelWidget missionList; readonly ScrollPanelWidget missionList;
readonly ScrollItemWidget headerTemplate; readonly ScrollItemWidget headerTemplate;
readonly ScrollItemWidget template; readonly ScrollItemWidget template;
readonly Cache<MapPreview, Map> mapCache = new Cache<MapPreview, Map>(p => new Map(p.Path));
MapPreview selectedMapPreview; MapPreview selectedMapPreview;
Map selectedMap; Map selectedMap;
@@ -90,7 +92,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
stopInfoVideoButton.IsVisible = () => playingVideo == PlayingVideo.Info; stopInfoVideoButton.IsVisible = () => playingVideo == PlayingVideo.Info;
stopInfoVideoButton.OnClick = () => StopVideo(videoPlayer); stopInfoVideoButton.OnClick = () => StopVideo(videoPlayer);
var allMaps = new List<Map>(); var allPreviews = new List<MapPreview>();
missionList.RemoveChildren(); missionList.RemoveChildren();
// Add a group for each campaign // Add a group for each campaign
@@ -103,29 +105,34 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
var missionMapPaths = kv.Value.Nodes.Select(n => Path.GetFullPath(n.Key)).ToList(); var missionMapPaths = kv.Value.Nodes.Select(n => Path.GetFullPath(n.Key)).ToList();
var maps = modData.MapCache var previews = modData.MapCache
.Where(p => p.Status == MapStatus.Available && missionMapPaths.Contains(Path.GetFullPath(p.Path))) .Where(p => p.Status == MapStatus.Available && missionMapPaths.Contains(Path.GetFullPath(p.Path)))
.Select(p => new Map(p.Path)) .OrderBy(p => missionMapPaths.IndexOf(Path.GetFullPath(p.Path)));
.OrderBy(m => missionMapPaths.IndexOf(Path.GetFullPath(m.Path)));
CreateMissionGroup(kv.Key, maps); CreateMissionGroup(kv.Key, previews);
allMaps.AddRange(maps); allPreviews.AddRange(previews);
} }
} }
// Add an additional group for loose missions // Add an additional group for loose missions
var looseMissions = modData.MapCache var loosePreviews = modData.MapCache
.Where(p => p.Status == MapStatus.Available && p.Visibility.HasFlag(MapVisibility.MissionSelector) && !allMaps.Any(m => m.Uid == p.Uid)) .Where(p => p.Status == MapStatus.Available && p.Visibility.HasFlag(MapVisibility.MissionSelector) && !allPreviews.Any(a => a.Uid == p.Uid));
.Select(p => new Map(p.Path));
if (looseMissions.Any()) if (loosePreviews.Any())
{ {
CreateMissionGroup("Missions", looseMissions); CreateMissionGroup("Missions", loosePreviews);
allMaps.AddRange(looseMissions); allPreviews.AddRange(loosePreviews);
} }
if (allMaps.Any()) if (allPreviews.Any())
SelectMap(allMaps.First()); SelectMap(allPreviews.First());
// Preload map and preview data to reduce jank
new Thread(() =>
{
foreach (var p in allPreviews)
modData.MapCache[mapCache[p].Uid].GetMinimap();
}).Start();
var startButton = widget.Get<ButtonWidget>("STARTGAME_BUTTON"); var startButton = widget.Get<ButtonWidget>("STARTGAME_BUTTON");
startButton.OnClick = StartMissionClicked; startButton.OnClick = StartMissionClicked;
@@ -140,39 +147,39 @@ namespace OpenRA.Mods.Common.Widgets.Logic
}; };
} }
void CreateMissionGroup(string title, IEnumerable<Map> maps) void CreateMissionGroup(string title, IEnumerable<MapPreview> previews)
{ {
var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { }); var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { });
header.Get<LabelWidget>("LABEL").GetText = () => title; header.Get<LabelWidget>("LABEL").GetText = () => title;
missionList.AddChild(header); missionList.AddChild(header);
foreach (var m in maps) foreach (var p in previews)
{ {
var map = m; var preview = p;
var item = ScrollItemWidget.Setup(template, var item = ScrollItemWidget.Setup(template,
() => selectedMapPreview != null && selectedMapPreview.Uid == map.Uid, () => selectedMapPreview != null && selectedMapPreview.Uid == preview.Uid,
() => SelectMap(map), () => SelectMap(preview),
StartMissionClicked); StartMissionClicked);
item.Get<LabelWidget>("TITLE").GetText = () => map.Title; item.Get<LabelWidget>("TITLE").GetText = () => preview.Title;
missionList.AddChild(item); missionList.AddChild(item);
} }
} }
void SelectMap(Map map) void SelectMap(MapPreview preview)
{ {
selectedMap = map; selectedMap = mapCache[preview];
selectedMapPreview = Game.ModData.MapCache[map.Uid]; selectedMapPreview = preview;
// Cache the rules on a background thread to avoid jank // Cache the rules on a background thread to avoid jank
new Thread(() => selectedMap.PreloadRules()).Start(); new Thread(() => selectedMap.PreloadRules()).Start();
var briefingVideo = map.Videos.Briefing; var briefingVideo = selectedMap.Videos.Briefing;
var briefingVideoVisible = briefingVideo != null; var briefingVideoVisible = briefingVideo != null;
var briefingVideoDisabled = !(briefingVideoVisible && Game.ModData.ModFiles.Exists(briefingVideo)); var briefingVideoDisabled = !(briefingVideoVisible && Game.ModData.ModFiles.Exists(briefingVideo));
var infoVideo = map.Videos.BackgroundInfo; var infoVideo = selectedMap.Videos.BackgroundInfo;
var infoVideoVisible = infoVideo != null; var infoVideoVisible = infoVideo != null;
var infoVideoDisabled = !(infoVideoVisible && Game.ModData.ModFiles.Exists(infoVideo)); var infoVideoDisabled = !(infoVideoVisible && Game.ModData.ModFiles.Exists(infoVideo));
@@ -184,7 +191,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
startInfoVideoButton.IsDisabled = () => infoVideoDisabled || playingVideo != PlayingVideo.None; startInfoVideoButton.IsDisabled = () => infoVideoDisabled || playingVideo != PlayingVideo.None;
startInfoVideoButton.OnClick = () => PlayVideo(videoPlayer, infoVideo, PlayingVideo.Info, () => StopVideo(videoPlayer)); startInfoVideoButton.OnClick = () => PlayVideo(videoPlayer, infoVideo, PlayingVideo.Info, () => StopVideo(videoPlayer));
var text = map.Description != null ? map.Description.Replace("\\n", "\n") : ""; var text = selectedMap.Description != null ? selectedMap.Description.Replace("\\n", "\n") : "";
text = WidgetUtils.WrapText(text, description.Bounds.Width, descriptionFont); text = WidgetUtils.WrapText(text, description.Bounds.Width, descriptionFont);
description.Text = text; description.Text = text;
description.Bounds.Height = descriptionFont.Measure(text).Y; description.Bounds.Height = descriptionFont.Measure(text).Y;
@@ -193,13 +200,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (difficultyButton != null) if (difficultyButton != null)
{ {
difficultyButton.IsDisabled = () => !map.Options.Difficulties.Any(); difficultyButton.IsDisabled = () => !selectedMap.Options.Difficulties.Any();
difficulty = map.Options.Difficulties.FirstOrDefault(); difficulty = selectedMap.Options.Difficulties.FirstOrDefault();
difficultyButton.GetText = () => difficulty ?? "Normal"; difficultyButton.GetText = () => difficulty ?? "Normal";
difficultyButton.OnMouseDown = _ => difficultyButton.OnMouseDown = _ =>
{ {
var options = map.Options.Difficulties.Select(d => new DropDownOption var options = selectedMap.Options.Difficulties.Select(d => new DropDownOption
{ {
Title = d, Title = d,
IsSelected = () => difficulty == d, IsSelected = () => difficulty == d,