Files
OpenRA/OpenRA.Game/Graphics/SequenceProvider.cs
RoosterDragon 3c9f589b5e Move try-catch during creation of sequences into the function rather than around the lazy initialization.
This fixes an issue with VS breaking on the exception because it thinks it will go unhandled, even though it will be handled.
2014-06-24 17:21:41 +01:00

144 lines
4.0 KiB
C#

#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* 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. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace OpenRA.Graphics
{
using Sequences = IReadOnlyDictionary<string, Lazy<IReadOnlyDictionary<string, Sequence>>>;
using UnitSequences = Lazy<IReadOnlyDictionary<string, Sequence>>;
public class SequenceProvider
{
readonly Lazy<Sequences> sequences;
public readonly SpriteLoader SpriteLoader;
public SequenceProvider(SequenceCache cache, Map map)
{
this.sequences = Exts.Lazy(() => cache.LoadSequences(map));
this.SpriteLoader = cache.SpriteLoader;
}
public Sequence GetSequence(string unitName, string sequenceName)
{
UnitSequences unitSeq;
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
Sequence seq;
if (!unitSeq.Value.TryGetValue(sequenceName, out seq))
throw new InvalidOperationException("Unit `{0}` does not have a sequence named `{1}`".F(unitName, sequenceName));
return seq;
}
public bool HasSequence(string unitName, string sequenceName)
{
UnitSequences unitSeq;
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
return unitSeq.Value.ContainsKey(sequenceName);
}
public IEnumerable<string> Sequences(string unitName)
{
UnitSequences unitSeq;
if (!sequences.Value.TryGetValue(unitName, out unitSeq))
throw new InvalidOperationException("Unit `{0}` does not have any sequences defined.".F(unitName));
return unitSeq.Value.Keys;
}
public void Preload()
{
foreach (var unitSeq in sequences.Value.Values)
foreach (var seq in unitSeq.Value.Values) { }
}
}
public class SequenceCache
{
readonly ModData modData;
readonly Lazy<SpriteLoader> spriteLoader;
public SpriteLoader SpriteLoader { get { return spriteLoader.Value; } }
readonly Dictionary<string, UnitSequences> sequenceCache = new Dictionary<string, UnitSequences>();
public SequenceCache(ModData modData, TileSet tileSet)
{
this.modData = modData;
spriteLoader = Exts.Lazy(() => new SpriteLoader(tileSet.Extensions, new SheetBuilder(SheetType.Indexed)));
}
public Sequences LoadSequences(Map map)
{
using (new Support.PerfTimer("LoadSequences"))
return Load(map.SequenceDefinitions);
}
Sequences Load(List<MiniYamlNode> sequenceNodes)
{
var sequenceFiles = modData.Manifest.Sequences;
var nodes = sequenceFiles
.Select(s => MiniYaml.FromFile(s))
.Aggregate(sequenceNodes, MiniYaml.MergeLiberal);
var items = new Dictionary<string, UnitSequences>();
foreach (var n in nodes)
{
// Work around the loop closure issue in older versions of C#
var node = n;
var key = node.Value.ToLines(node.Key).JoinWith("|");
UnitSequences t;
if (sequenceCache.TryGetValue(key, out t))
items.Add(node.Key, t);
else
{
t = Exts.Lazy(() => CreateUnitSequences(node));
sequenceCache.Add(key, t);
items.Add(node.Key, t);
}
}
return new ReadOnlyDictionary<string, UnitSequences>(items);
}
IReadOnlyDictionary<string, Sequence> CreateUnitSequences(MiniYamlNode node)
{
var unitSequences = new Dictionary<string, Sequence>();
foreach (var kvp in node.Value.ToDictionary())
{
using (new Support.PerfTimer("new Sequence(\"{0}\")".F(node.Key), 20))
{
try
{
unitSequences.Add(kvp.Key, new Sequence(spriteLoader.Value, node.Key, kvp.Key, kvp.Value));
}
catch (FileNotFoundException ex)
{
Log.Write("debug", ex.Message);
}
}
}
return new ReadOnlyDictionary<string, Sequence>(unitSequences);
}
}
}