Reduce jank in the mission chooser.
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user