#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; using OpenRA.FileFormats; using OpenRA.Primitives; namespace OpenRA.Graphics { public class SequenceProvider { readonly Lazy>>> 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) { Lazy> 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) { Lazy> 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 Sequences(string unitName) { Lazy> 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 class SequenceCache { readonly ModData modData; readonly Lazy spriteLoader; public SpriteLoader SpriteLoader { get { return spriteLoader.Value; } } readonly Dictionary>> sequenceCache = new Dictionary>>(); public Action OnProgress; public SequenceCache(ModData modData, TileSet tileSet) { OnProgress = () => { if (modData.LoadScreen != null) modData.LoadScreen.Display(); }; this.modData = modData; spriteLoader = Exts.Lazy(() => new SpriteLoader(tileSet.Extensions, new SheetBuilder(SheetType.Indexed))); } public IReadOnlyDictionary>> LoadSequences(Map map) { using (new Support.PerfTimer("LoadSequences")) return Load(map.SequenceDefinitions); } IReadOnlyDictionary>> Load(List sequenceNodes) { OnProgress(); var sequenceFiles = modData.Manifest.Sequences; var nodes = sequenceFiles .Select(s => MiniYaml.FromFile(s)) .Aggregate(sequenceNodes, MiniYaml.MergeLiberal); var items = new Dictionary>>(); foreach (var node in nodes) { var key = node.Value.ToLines(node.Key).JoinWith("|"); Lazy> t; if (sequenceCache.TryGetValue(key, out t)) { items.Add(node.Key, t); } else { t = Exts.Lazy(() => (IReadOnlyDictionary)new ReadOnlyDictionary( node.Value.NodesDict.ToDictionary(x => x.Key, x => new Sequence(spriteLoader.Value, node.Key, x.Key, x.Value)))); sequenceCache.Add(key, t); items.Add(node.Key, t); } OnProgress(); } return new ReadOnlyDictionary>>(items); } } }