#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) { try { return sequences.Value[unitName].Value[sequenceName]; } catch (KeyNotFoundException) { if (sequences.Value.ContainsKey(unitName)) throw new InvalidOperationException("Unit `{0}` does not have a sequence `{1}`".F(unitName, sequenceName)); else throw new InvalidOperationException("Unit `{0}` does not have all sequences defined.".F(unitName)); } } public bool HasSequence(string unitName, string sequenceName) { if (!sequences.Value.ContainsKey(unitName)) throw new InvalidOperationException("Unit `{0}` does not have sequence `{1}` defined.".F(unitName, sequenceName)); return sequences.Value[unitName].Value.ContainsKey(sequenceName); } public IEnumerable Sequences(string unitName) { if (!sequences.Value.ContainsKey(unitName)) throw new InvalidOperationException("Unit `{0}` does not have all sequences defined.".F(unitName)); return sequences.Value[unitName].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 = () => { if (Game.modData != null && Game.modData.LoadScreen != null) Game.modData.LoadScreen.Display(); }; public SequenceCache(ModData modData, TileSet tileSet) { 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); } } }