Merge pull request #6758 from RoosterDragon/fix-spriteloader-overcache
Create a separate SpriteFrameLoader for caching sprite frames.
This commit is contained in:
@@ -50,10 +50,10 @@ namespace OpenRA.Editor
|
||||
this.TileSize = Math.Min(tileSize.Width, tileSize.Height);
|
||||
|
||||
templates = new Dictionary<ushort, byte[][]>();
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"))
|
||||
|
||||
@@ -21,12 +21,12 @@ namespace OpenRA.Graphics
|
||||
public class SequenceProvider
|
||||
{
|
||||
readonly Lazy<Sequences> 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> spriteLoader;
|
||||
public SpriteLoader SpriteLoader { get { return spriteLoader.Value; } }
|
||||
readonly Lazy<SpriteCache> spriteCache;
|
||||
public SpriteCache SpriteCache { get { return spriteCache.Value; } }
|
||||
|
||||
readonly Dictionary<string, UnitSequences> sequenceCache = new Dictionary<string, UnitSequences>();
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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<string, Sprite[]> sprites;
|
||||
readonly Cache<string, ISpriteFrame[]> 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<string, Sprite[]>(CacheSprites);
|
||||
frames = new Cache<string, ISpriteFrame[]>(CacheFrames);
|
||||
exts = exts.Append("").ToArray();
|
||||
sprites = new Cache<string, Sprite[]>(filename => SpriteLoader.GetSprites(filename, exts, loaders, sheetBuilder));
|
||||
}
|
||||
|
||||
Sprite[] CacheSprites(string filename)
|
||||
public Sprite[] this[string filename] { get { return sprites[filename]; } }
|
||||
}
|
||||
|
||||
public class FrameCache
|
||||
{
|
||||
return frames[filename].Select(a => SheetBuilder.Add(a))
|
||||
.ToArray();
|
||||
readonly Cache<string, ISpriteFrame[]> frames;
|
||||
|
||||
public FrameCache(ISpriteLoader[] loaders, string[] exts)
|
||||
{
|
||||
frames = new Cache<string, ISpriteFrame[]>(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]; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,11 +37,10 @@ namespace OpenRA.Graphics
|
||||
sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate);
|
||||
templates = new Dictionary<ushort, Sprite[]>();
|
||||
|
||||
// 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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user