diff --git a/OpenRA.Editor/TileSetRenderer.cs b/OpenRA.Editor/TileSetRenderer.cs index c39b9b5cf4..cc05aae7ce 100644 --- a/OpenRA.Editor/TileSetRenderer.cs +++ b/OpenRA.Editor/TileSetRenderer.cs @@ -50,10 +50,10 @@ namespace OpenRA.Editor this.TileSize = Math.Min(tileSize.Width, tileSize.Height); templates = new Dictionary(); - var spriteLoader = new SpriteLoader(Game.modData.SpriteLoaders, tileset.Extensions, null); + var frameCache = new FrameCache(Game.modData.SpriteLoaders, tileset.Extensions); foreach (var t in tileset.Templates) { - var allFrames = spriteLoader.LoadAllFrames(t.Value.Image); + var allFrames = frameCache[t.Value.Image]; var frames = t.Value.Frames != null ? t.Value.Frames.Select(f => allFrames[f]).ToArray() : allFrames; templates.Add(t.Value.Id, frames.Select(f => ExtractSquareTile(f)).ToArray()); } diff --git a/OpenRA.Game/Graphics/CursorProvider.cs b/OpenRA.Game/Graphics/CursorProvider.cs index 28701e2fd4..7dd832e4e1 100644 --- a/OpenRA.Game/Graphics/CursorProvider.cs +++ b/OpenRA.Game/Graphics/CursorProvider.cs @@ -45,10 +45,10 @@ namespace OpenRA.Graphics foreach (var p in nodesDict["Palettes"].Nodes) palette.AddPalette(p.Key, new ImmutablePalette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false); - var spriteLoader = new SpriteLoader(modData.SpriteLoaders, new string[0], new SheetBuilder(SheetType.Indexed)); + var spriteCache = new SpriteCache(modData.SpriteLoaders, new string[0], new SheetBuilder(SheetType.Indexed)); foreach (var s in nodesDict["Cursors"].Nodes) - LoadSequencesForCursor(spriteLoader, s.Key, s.Value); - spriteLoader.SheetBuilder.Current.ReleaseBuffer(); + LoadSequencesForCursor(spriteCache, s.Key, s.Value); + spriteCache.SheetBuilder.Current.ReleaseBuffer(); palette.Initialize(); } @@ -59,10 +59,10 @@ namespace OpenRA.Graphics return new PaletteReference(name, palette.GetPaletteIndex(name), pal); } - void LoadSequencesForCursor(SpriteLoader loader, string cursorSrc, MiniYaml cursor) + void LoadSequencesForCursor(SpriteCache cache, string cursorSrc, MiniYaml cursor) { foreach (var sequence in cursor.Nodes) - cursors.Add(sequence.Key, new CursorSequence(loader, cursorSrc, cursor.Value, sequence.Value)); + cursors.Add(sequence.Key, new CursorSequence(cache, cursorSrc, cursor.Value, sequence.Value)); } public bool HasCursorSequence(string cursor) diff --git a/OpenRA.Game/Graphics/CursorSequence.cs b/OpenRA.Game/Graphics/CursorSequence.cs index fb11c2823b..1db1f46b43 100644 --- a/OpenRA.Game/Graphics/CursorSequence.cs +++ b/OpenRA.Game/Graphics/CursorSequence.cs @@ -23,9 +23,9 @@ namespace OpenRA.Graphics Sprite[] sprites; - public CursorSequence(SpriteLoader loader, string cursorSrc, string palette, MiniYaml info) + public CursorSequence(SpriteCache cache, string cursorSrc, string palette, MiniYaml info) { - sprites = loader.LoadAllSprites(cursorSrc); + sprites = cache[cursorSrc]; var d = info.ToDictionary(); start = Exts.ParseIntegerInvariant(d["start"].Value); diff --git a/OpenRA.Game/Graphics/Sequence.cs b/OpenRA.Game/Graphics/Sequence.cs index 936f8d1c6e..bd946a1dbb 100644 --- a/OpenRA.Game/Graphics/Sequence.cs +++ b/OpenRA.Game/Graphics/Sequence.cs @@ -29,7 +29,7 @@ namespace OpenRA.Graphics public readonly int ShadowZOffset; public readonly int[] Frames; - public Sequence(SpriteLoader loader, string unit, string name, MiniYaml info) + public Sequence(SpriteCache cache, string unit, string name, MiniYaml info) { var srcOverride = info.Value; Name = name; @@ -50,7 +50,7 @@ namespace OpenRA.Graphics // Apply offset to each sprite in the sequence // Different sequences may apply different offsets to the same frame - sprites = loader.LoadAllSprites(srcOverride ?? unit).Select( + sprites = cache[srcOverride ?? unit].Select( s => new Sprite(s.sheet, s.bounds, s.offset + offset, s.channel, blendMode)).ToArray(); if (!d.ContainsKey("Length")) diff --git a/OpenRA.Game/Graphics/SequenceProvider.cs b/OpenRA.Game/Graphics/SequenceProvider.cs index bed18baac0..c2a69b679b 100644 --- a/OpenRA.Game/Graphics/SequenceProvider.cs +++ b/OpenRA.Game/Graphics/SequenceProvider.cs @@ -21,12 +21,12 @@ namespace OpenRA.Graphics public class SequenceProvider { readonly Lazy sequences; - public readonly SpriteLoader SpriteLoader; + public readonly SpriteCache SpriteCache; public SequenceProvider(SequenceCache cache, Map map) { this.sequences = Exts.Lazy(() => cache.LoadSequences(map)); - this.SpriteLoader = cache.SpriteLoader; + this.SpriteCache = cache.SpriteCache; } public Sequence GetSequence(string unitName, string sequenceName) @@ -70,8 +70,8 @@ namespace OpenRA.Graphics public class SequenceCache { readonly ModData modData; - readonly Lazy spriteLoader; - public SpriteLoader SpriteLoader { get { return spriteLoader.Value; } } + readonly Lazy spriteCache; + public SpriteCache SpriteCache { get { return spriteCache.Value; } } readonly Dictionary sequenceCache = new Dictionary(); @@ -79,7 +79,7 @@ namespace OpenRA.Graphics { this.modData = modData; - spriteLoader = Exts.Lazy(() => new SpriteLoader(modData.SpriteLoaders, tileSet.Extensions, new SheetBuilder(SheetType.Indexed))); + spriteCache = Exts.Lazy(() => new SpriteCache(modData.SpriteLoaders, tileSet.Extensions, new SheetBuilder(SheetType.Indexed))); } public Sequences LoadSequences(Map map) @@ -128,7 +128,7 @@ namespace OpenRA.Graphics { try { - unitSequences.Add(kvp.Key, new Sequence(spriteLoader.Value, node.Key, kvp.Key, kvp.Value)); + unitSequences.Add(kvp.Key, new Sequence(spriteCache.Value, node.Key, kvp.Key, kvp.Value)); } catch (FileNotFoundException ex) { diff --git a/OpenRA.Game/Graphics/SpriteLoader.cs b/OpenRA.Game/Graphics/SpriteLoader.cs index d542a1ea89..cc0ba8941d 100644 --- a/OpenRA.Game/Graphics/SpriteLoader.cs +++ b/OpenRA.Game/Graphics/SpriteLoader.cs @@ -30,32 +30,42 @@ namespace OpenRA.Graphics bool DisableExportPadding { get; } } - public class SpriteLoader + public class SpriteCache { public readonly SheetBuilder SheetBuilder; - readonly ISpriteLoader[] loaders; readonly Cache sprites; - readonly Cache frames; - readonly string[] exts; - public SpriteLoader(ISpriteLoader[] loaders, string[] exts, SheetBuilder sheetBuilder) + public SpriteCache(ISpriteLoader[] loaders, string[] exts, SheetBuilder sheetBuilder) { - this.loaders = loaders; SheetBuilder = sheetBuilder; - // Include extension-less version - this.exts = exts.Append("").ToArray(); - sprites = new Cache(CacheSprites); - frames = new Cache(CacheFrames); + exts = exts.Append("").ToArray(); + sprites = new Cache(filename => SpriteLoader.GetSprites(filename, exts, loaders, sheetBuilder)); } - Sprite[] CacheSprites(string filename) + public Sprite[] this[string filename] { get { return sprites[filename]; } } + } + + public class FrameCache + { + readonly Cache frames; + + public FrameCache(ISpriteLoader[] loaders, string[] exts) { - return frames[filename].Select(a => SheetBuilder.Add(a)) - .ToArray(); + frames = new Cache(filename => SpriteLoader.GetFrames(filename, exts, loaders)); } - ISpriteFrame[] CacheFrames(string filename) + public ISpriteFrame[] this[string filename] { get { return frames[filename]; } } + } + + public static class SpriteLoader + { + public static Sprite[] GetSprites(string filename, string[] exts, ISpriteLoader[] loaders, SheetBuilder sheetBuilder) + { + return GetFrames(filename, exts, loaders).Select(a => sheetBuilder.Add(a)).ToArray(); + } + + public static ISpriteFrame[] GetFrames(string filename, string[] exts, ISpriteLoader[] loaders) { using (var stream = GlobalFileSystem.OpenWithExts(filename, exts)) { @@ -67,8 +77,5 @@ namespace OpenRA.Graphics throw new InvalidDataException(filename + " is not a valid sprite file"); } } - - public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; } - public ISpriteFrame[] LoadAllFrames(string filename) { return frames[filename]; } } } diff --git a/OpenRA.Game/Graphics/Theater.cs b/OpenRA.Game/Graphics/Theater.cs index 110b27703a..7e3e614c60 100644 --- a/OpenRA.Game/Graphics/Theater.cs +++ b/OpenRA.Game/Graphics/Theater.cs @@ -37,11 +37,10 @@ namespace OpenRA.Graphics sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate); templates = new Dictionary(); - // We manage the SheetBuilder ourselves, to avoid loading all of the tileset images - var spriteLoader = new SpriteLoader(Game.modData.SpriteLoaders, tileset.Extensions, null); + var frameCache = new FrameCache(Game.modData.SpriteLoaders, tileset.Extensions); foreach (var t in tileset.Templates) { - var allFrames = spriteLoader.LoadAllFrames(t.Value.Image); + var allFrames = frameCache[t.Value.Image]; var frames = t.Value.Frames != null ? t.Value.Frames.Select(f => allFrames[f]).ToArray() : allFrames; templates.Add(t.Value.Id, frames.Select(f => sheetBuilder.Add(f)).ToArray()); } diff --git a/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs b/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs index f70338b257..a073e867de 100644 --- a/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs @@ -41,8 +41,7 @@ namespace OpenRA.Mods.Common.UtilityCommands var palette = new ImmutablePalette(args[2], shadowIndex); - var frames = new SpriteLoader(modData.SpriteLoaders, new string[0], null) - .LoadAllFrames(src); + var frames = SpriteLoader.GetFrames(src, new string[0], modData.SpriteLoaders); var usePadding = !args.Contains("--nopadding"); var count = 0; diff --git a/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs index 4faa58bf28..32e6bef8e2 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs @@ -308,7 +308,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic else { currentFilename = filename; - currentSprites = world.Map.SequenceProvider.SpriteLoader.LoadAllSprites(filename); + currentSprites = world.Map.SequenceProvider.SpriteCache[filename]; currentFrame = 0; frameSlider.MaximumValue = (float)currentSprites.Length - 1; frameSlider.Ticks = currentSprites.Length;