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);
|
this.TileSize = Math.Min(tileSize.Width, tileSize.Height);
|
||||||
|
|
||||||
templates = new Dictionary<ushort, byte[][]>();
|
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)
|
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;
|
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());
|
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)
|
foreach (var p in nodesDict["Palettes"].Nodes)
|
||||||
palette.AddPalette(p.Key, new ImmutablePalette(GlobalFileSystem.Open(p.Value.Value), shadowIndex), false);
|
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)
|
foreach (var s in nodesDict["Cursors"].Nodes)
|
||||||
LoadSequencesForCursor(spriteLoader, s.Key, s.Value);
|
LoadSequencesForCursor(spriteCache, s.Key, s.Value);
|
||||||
spriteLoader.SheetBuilder.Current.ReleaseBuffer();
|
spriteCache.SheetBuilder.Current.ReleaseBuffer();
|
||||||
|
|
||||||
palette.Initialize();
|
palette.Initialize();
|
||||||
}
|
}
|
||||||
@@ -59,10 +59,10 @@ namespace OpenRA.Graphics
|
|||||||
return new PaletteReference(name, palette.GetPaletteIndex(name), pal);
|
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)
|
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)
|
public bool HasCursorSequence(string cursor)
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
Sprite[] sprites;
|
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();
|
var d = info.ToDictionary();
|
||||||
|
|
||||||
start = Exts.ParseIntegerInvariant(d["start"].Value);
|
start = Exts.ParseIntegerInvariant(d["start"].Value);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace OpenRA.Graphics
|
|||||||
public readonly int ShadowZOffset;
|
public readonly int ShadowZOffset;
|
||||||
public readonly int[] Frames;
|
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;
|
var srcOverride = info.Value;
|
||||||
Name = name;
|
Name = name;
|
||||||
@@ -50,7 +50,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
// Apply offset to each sprite in the sequence
|
// Apply offset to each sprite in the sequence
|
||||||
// Different sequences may apply different offsets to the same frame
|
// 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();
|
s => new Sprite(s.sheet, s.bounds, s.offset + offset, s.channel, blendMode)).ToArray();
|
||||||
|
|
||||||
if (!d.ContainsKey("Length"))
|
if (!d.ContainsKey("Length"))
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ namespace OpenRA.Graphics
|
|||||||
public class SequenceProvider
|
public class SequenceProvider
|
||||||
{
|
{
|
||||||
readonly Lazy<Sequences> sequences;
|
readonly Lazy<Sequences> sequences;
|
||||||
public readonly SpriteLoader SpriteLoader;
|
public readonly SpriteCache SpriteCache;
|
||||||
|
|
||||||
public SequenceProvider(SequenceCache cache, Map map)
|
public SequenceProvider(SequenceCache cache, Map map)
|
||||||
{
|
{
|
||||||
this.sequences = Exts.Lazy(() => cache.LoadSequences(map));
|
this.sequences = Exts.Lazy(() => cache.LoadSequences(map));
|
||||||
this.SpriteLoader = cache.SpriteLoader;
|
this.SpriteCache = cache.SpriteCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Sequence GetSequence(string unitName, string sequenceName)
|
public Sequence GetSequence(string unitName, string sequenceName)
|
||||||
@@ -70,8 +70,8 @@ namespace OpenRA.Graphics
|
|||||||
public class SequenceCache
|
public class SequenceCache
|
||||||
{
|
{
|
||||||
readonly ModData modData;
|
readonly ModData modData;
|
||||||
readonly Lazy<SpriteLoader> spriteLoader;
|
readonly Lazy<SpriteCache> spriteCache;
|
||||||
public SpriteLoader SpriteLoader { get { return spriteLoader.Value; } }
|
public SpriteCache SpriteCache { get { return spriteCache.Value; } }
|
||||||
|
|
||||||
readonly Dictionary<string, UnitSequences> sequenceCache = new Dictionary<string, UnitSequences>();
|
readonly Dictionary<string, UnitSequences> sequenceCache = new Dictionary<string, UnitSequences>();
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
this.modData = modData;
|
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)
|
public Sequences LoadSequences(Map map)
|
||||||
@@ -128,7 +128,7 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
try
|
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)
|
catch (FileNotFoundException ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,32 +30,42 @@ namespace OpenRA.Graphics
|
|||||||
bool DisableExportPadding { get; }
|
bool DisableExportPadding { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SpriteLoader
|
public class SpriteCache
|
||||||
{
|
{
|
||||||
public readonly SheetBuilder SheetBuilder;
|
public readonly SheetBuilder SheetBuilder;
|
||||||
readonly ISpriteLoader[] loaders;
|
|
||||||
readonly Cache<string, Sprite[]> sprites;
|
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;
|
SheetBuilder = sheetBuilder;
|
||||||
|
|
||||||
// Include extension-less version
|
// Include extension-less version
|
||||||
this.exts = exts.Append("").ToArray();
|
exts = exts.Append("").ToArray();
|
||||||
sprites = new Cache<string, Sprite[]>(CacheSprites);
|
sprites = new Cache<string, Sprite[]>(filename => SpriteLoader.GetSprites(filename, exts, loaders, sheetBuilder));
|
||||||
frames = new Cache<string, ISpriteFrame[]>(CacheFrames);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite[] CacheSprites(string filename)
|
public Sprite[] this[string filename] { get { return sprites[filename]; } }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FrameCache
|
||||||
|
{
|
||||||
|
readonly Cache<string, ISpriteFrame[]> frames;
|
||||||
|
|
||||||
|
public FrameCache(ISpriteLoader[] loaders, string[] exts)
|
||||||
{
|
{
|
||||||
return frames[filename].Select(a => SheetBuilder.Add(a))
|
frames = new Cache<string, ISpriteFrame[]>(filename => SpriteLoader.GetFrames(filename, exts, loaders));
|
||||||
.ToArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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))
|
using (var stream = GlobalFileSystem.OpenWithExts(filename, exts))
|
||||||
{
|
{
|
||||||
@@ -67,8 +77,5 @@ namespace OpenRA.Graphics
|
|||||||
throw new InvalidDataException(filename + " is not a valid sprite file");
|
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);
|
sheetBuilder = new SheetBuilder(SheetType.Indexed, allocate);
|
||||||
templates = new Dictionary<ushort, Sprite[]>();
|
templates = new Dictionary<ushort, Sprite[]>();
|
||||||
|
|
||||||
// We manage the SheetBuilder ourselves, to avoid loading all of the tileset images
|
var frameCache = new FrameCache(Game.modData.SpriteLoaders, tileset.Extensions);
|
||||||
var spriteLoader = new SpriteLoader(Game.modData.SpriteLoaders, tileset.Extensions, null);
|
|
||||||
foreach (var t in tileset.Templates)
|
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;
|
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());
|
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 palette = new ImmutablePalette(args[2], shadowIndex);
|
||||||
|
|
||||||
var frames = new SpriteLoader(modData.SpriteLoaders, new string[0], null)
|
var frames = SpriteLoader.GetFrames(src, new string[0], modData.SpriteLoaders);
|
||||||
.LoadAllFrames(src);
|
|
||||||
|
|
||||||
var usePadding = !args.Contains("--nopadding");
|
var usePadding = !args.Contains("--nopadding");
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
currentFilename = filename;
|
currentFilename = filename;
|
||||||
currentSprites = world.Map.SequenceProvider.SpriteLoader.LoadAllSprites(filename);
|
currentSprites = world.Map.SequenceProvider.SpriteCache[filename];
|
||||||
currentFrame = 0;
|
currentFrame = 0;
|
||||||
frameSlider.MaximumValue = (float)currentSprites.Length - 1;
|
frameSlider.MaximumValue = (float)currentSprites.Length - 1;
|
||||||
frameSlider.Ticks = currentSprites.Length;
|
frameSlider.Ticks = currentSprites.Length;
|
||||||
|
|||||||
Reference in New Issue
Block a user