Skip to content

Commit

Permalink
Reduce jank in the mission chooser.
Browse files Browse the repository at this point in the history
  • Loading branch information
pchote committed Feb 6, 2016
1 parent 7b00da0 commit 8b5592e
Showing 1 changed file with 36 additions and 29 deletions.
65 changes: 36 additions & 29 deletions OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs
Expand Up @@ -14,6 +14,7 @@
using System.Linq;
using System.Threading;
using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Widgets;

namespace OpenRA.Mods.Common.Widgets.Logic
Expand All @@ -38,6 +39,7 @@ enum PlayingVideo { None, Info, Briefing, GameStart }
readonly ScrollPanelWidget missionList;
readonly ScrollItemWidget headerTemplate;
readonly ScrollItemWidget template;
readonly Cache<MapPreview, Map> mapCache = new Cache<MapPreview, Map>(p => new Map(p.Path));

MapPreview selectedMapPreview;
Map selectedMap;
Expand Down Expand Up @@ -90,7 +92,7 @@ public MissionBrowserLogic(Widget widget, World world, Action onStart, Action on
stopInfoVideoButton.IsVisible = () => playingVideo == PlayingVideo.Info;
stopInfoVideoButton.OnClick = () => StopVideo(videoPlayer);

var allMaps = new List<Map>();
var allPreviews = new List<MapPreview>();
missionList.RemoveChildren();

// Add a group for each campaign
Expand All @@ -103,29 +105,34 @@ public MissionBrowserLogic(Widget widget, World world, Action onStart, Action on
{
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)))
.Select(p => new Map(p.Path))
.OrderBy(m => missionMapPaths.IndexOf(Path.GetFullPath(m.Path)));
.OrderBy(p => missionMapPaths.IndexOf(Path.GetFullPath(p.Path)));

CreateMissionGroup(kv.Key, maps);
allMaps.AddRange(maps);
CreateMissionGroup(kv.Key, previews);
allPreviews.AddRange(previews);
}
}

// Add an additional group for loose missions
var looseMissions = modData.MapCache
.Where(p => p.Status == MapStatus.Available && p.Visibility.HasFlag(MapVisibility.MissionSelector) && !allMaps.Any(m => m.Uid == p.Uid))
.Select(p => new Map(p.Path));
var loosePreviews = modData.MapCache
.Where(p => p.Status == MapStatus.Available && p.Visibility.HasFlag(MapVisibility.MissionSelector) && !allPreviews.Any(a => a.Uid == p.Uid));

if (looseMissions.Any())
if (loosePreviews.Any())
{
CreateMissionGroup("Missions", looseMissions);
allMaps.AddRange(looseMissions);
CreateMissionGroup("Missions", loosePreviews);
allPreviews.AddRange(loosePreviews);
}

if (allMaps.Any())
SelectMap(allMaps.First());
if (allPreviews.Any())
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");
startButton.OnClick = StartMissionClicked;
Expand All @@ -140,39 +147,39 @@ public MissionBrowserLogic(Widget widget, World world, Action onStart, Action on
};
}

void CreateMissionGroup(string title, IEnumerable<Map> maps)
void CreateMissionGroup(string title, IEnumerable<MapPreview> previews)
{
var header = ScrollItemWidget.Setup(headerTemplate, () => true, () => { });
header.Get<LabelWidget>("LABEL").GetText = () => title;
missionList.AddChild(header);

foreach (var m in maps)
foreach (var p in previews)
{
var map = m;
var preview = p;

var item = ScrollItemWidget.Setup(template,
() => selectedMapPreview != null && selectedMapPreview.Uid == map.Uid,
() => SelectMap(map),
() => selectedMapPreview != null && selectedMapPreview.Uid == preview.Uid,
() => SelectMap(preview),
StartMissionClicked);

item.Get<LabelWidget>("TITLE").GetText = () => map.Title;
item.Get<LabelWidget>("TITLE").GetText = () => preview.Title;
missionList.AddChild(item);
}
}

void SelectMap(Map map)
void SelectMap(MapPreview preview)
{
selectedMap = map;
selectedMapPreview = Game.ModData.MapCache[map.Uid];
selectedMap = mapCache[preview];
selectedMapPreview = preview;

// Cache the rules on a background thread to avoid jank
new Thread(() => selectedMap.PreloadRules()).Start();

var briefingVideo = map.Videos.Briefing;
var briefingVideo = selectedMap.Videos.Briefing;
var briefingVideoVisible = briefingVideo != null;
var briefingVideoDisabled = !(briefingVideoVisible && Game.ModData.ModFiles.Exists(briefingVideo));

var infoVideo = map.Videos.BackgroundInfo;
var infoVideo = selectedMap.Videos.BackgroundInfo;
var infoVideoVisible = infoVideo != null;
var infoVideoDisabled = !(infoVideoVisible && Game.ModData.ModFiles.Exists(infoVideo));

Expand All @@ -184,7 +191,7 @@ void SelectMap(Map map)
startInfoVideoButton.IsDisabled = () => infoVideoDisabled || playingVideo != PlayingVideo.None;
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);
description.Text = text;
description.Bounds.Height = descriptionFont.Measure(text).Y;
Expand All @@ -193,13 +200,13 @@ void SelectMap(Map map)

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.OnMouseDown = _ =>
{
var options = map.Options.Difficulties.Select(d => new DropDownOption
var options = selectedMap.Options.Difficulties.Select(d => new DropDownOption
{
Title = d,
IsSelected = () => difficulty == d,
Expand Down

0 comments on commit 8b5592e

Please sign in to comment.