From dee6d036262ea85a3bbe54ff2878a6fc6ce01c9b Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Mon, 1 Oct 2018 10:57:00 +0000 Subject: [PATCH] Allow sprites to store custom metadata. --- OpenRA.Game/Graphics/SpriteLoader.cs | 36 +++++++++++++++---- OpenRA.Mods.Cnc/SpriteLoaders/TmpTSLoader.cs | 4 ++- .../SpriteLoaders/PngSheetLoader.cs | 4 ++- .../SpriteLoaders/ShpD2Loader.cs | 4 ++- .../SpriteLoaders/ShpTDLoader.cs | 4 ++- .../SpriteLoaders/ShpTSLoader.cs | 4 ++- .../SpriteLoaders/TmpRALoader.cs | 4 ++- .../SpriteLoaders/TmpTDLoader.cs | 4 ++- .../ConvertSpriteToPngCommand.cs | 4 ++- OpenRA.Mods.D2k/SpriteLoaders/R8Loader.cs | 4 ++- 10 files changed, 56 insertions(+), 16 deletions(-) diff --git a/OpenRA.Game/Graphics/SpriteLoader.cs b/OpenRA.Game/Graphics/SpriteLoader.cs index 12d6ddd374..db11c58785 100644 --- a/OpenRA.Game/Graphics/SpriteLoader.cs +++ b/OpenRA.Game/Graphics/SpriteLoader.cs @@ -21,7 +21,7 @@ namespace OpenRA.Graphics { public interface ISpriteLoader { - bool TryParseSprite(Stream s, out ISpriteFrame[] frames); + bool TryParseSprite(Stream s, out ISpriteFrame[] frames, out TypeDictionary metadata); } public interface ISpriteFrame @@ -50,6 +50,7 @@ namespace OpenRA.Graphics readonly Dictionary> sprites = new Dictionary>(); readonly Dictionary unloadedFrames = new Dictionary(); + readonly Dictionary metadata = new Dictionary(); public SpriteCache(IReadOnlyFileSystem fileSystem, ISpriteLoader[] loaders, SheetBuilder sheetBuilder) { @@ -80,8 +81,10 @@ namespace OpenRA.Graphics // the loaded cache (initially empty) if (sprite == null) { - unloaded = FrameLoader.GetFrames(fileSystem, filename, loaders); + TypeDictionary fileMetadata = null; + unloaded = FrameLoader.GetFrames(fileSystem, filename, loaders, out fileMetadata); unloadedFrames[filename] = unloaded; + metadata[filename] = fileMetadata; sprite = new Sprite[unloaded.Length]; allSprites.Add(sprite); @@ -111,6 +114,22 @@ namespace OpenRA.Graphics return sprite; } } + + /// + /// Returns a TypeDictionary containing any metadata defined by the frame + /// or null if the frame does not define metadata. + /// + public TypeDictionary FrameMetadata(string filename) + { + TypeDictionary fileMetadata; + if (!metadata.TryGetValue(filename, out fileMetadata)) + { + FrameLoader.GetFrames(fileSystem, filename, loaders, out fileMetadata); + metadata[filename] = fileMetadata; + } + + return fileMetadata; + } } public class FrameCache @@ -119,7 +138,8 @@ namespace OpenRA.Graphics public FrameCache(IReadOnlyFileSystem fileSystem, ISpriteLoader[] loaders) { - frames = new Cache(filename => FrameLoader.GetFrames(fileSystem, filename, loaders)); + TypeDictionary metadata; + frames = new Cache(filename => FrameLoader.GetFrames(fileSystem, filename, loaders, out metadata)); } public ISpriteFrame[] this[string filename] { get { return frames[filename]; } } @@ -127,11 +147,11 @@ namespace OpenRA.Graphics public static class FrameLoader { - public static ISpriteFrame[] GetFrames(IReadOnlyFileSystem fileSystem, string filename, ISpriteLoader[] loaders) + public static ISpriteFrame[] GetFrames(IReadOnlyFileSystem fileSystem, string filename, ISpriteLoader[] loaders, out TypeDictionary metadata) { using (var stream = fileSystem.Open(filename)) { - var spriteFrames = GetFrames(stream, loaders); + var spriteFrames = GetFrames(stream, loaders, out metadata); if (spriteFrames == null) throw new InvalidDataException(filename + " is not a valid sprite file!"); @@ -139,11 +159,13 @@ namespace OpenRA.Graphics } } - public static ISpriteFrame[] GetFrames(Stream stream, ISpriteLoader[] loaders) + public static ISpriteFrame[] GetFrames(Stream stream, ISpriteLoader[] loaders, out TypeDictionary metadata) { ISpriteFrame[] frames; + metadata = null; + foreach (var loader in loaders) - if (loader.TryParseSprite(stream, out frames)) + if (loader.TryParseSprite(stream, out frames, out metadata)) return frames; return null; diff --git a/OpenRA.Mods.Cnc/SpriteLoaders/TmpTSLoader.cs b/OpenRA.Mods.Cnc/SpriteLoaders/TmpTSLoader.cs index 3c9fe35339..259c5f4385 100644 --- a/OpenRA.Mods.Cnc/SpriteLoaders/TmpTSLoader.cs +++ b/OpenRA.Mods.Cnc/SpriteLoaders/TmpTSLoader.cs @@ -12,6 +12,7 @@ using System.Drawing; using System.IO; using OpenRA.Graphics; +using OpenRA.Primitives; namespace OpenRA.Mods.Cnc.SpriteLoaders { @@ -182,8 +183,9 @@ namespace OpenRA.Mods.Cnc.SpriteLoaders return tiles; } - public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames, out TypeDictionary metadata) { + metadata = null; if (!IsTmpTS(s)) { frames = null; diff --git a/OpenRA.Mods.Common/SpriteLoaders/PngSheetLoader.cs b/OpenRA.Mods.Common/SpriteLoaders/PngSheetLoader.cs index 786fa645f3..f13eaa941f 100644 --- a/OpenRA.Mods.Common/SpriteLoaders/PngSheetLoader.cs +++ b/OpenRA.Mods.Common/SpriteLoaders/PngSheetLoader.cs @@ -16,6 +16,7 @@ using System.IO; using System.Linq; using OpenRA.FileFormats; using OpenRA.Graphics; +using OpenRA.Primitives; namespace OpenRA.Mods.Common.SpriteLoaders { @@ -30,8 +31,9 @@ namespace OpenRA.Mods.Common.SpriteLoaders public bool DisableExportPadding { get { return false; } } } - public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames, out TypeDictionary metadata) { + metadata = null; if (!Png.Verify(s)) { frames = null; diff --git a/OpenRA.Mods.Common/SpriteLoaders/ShpD2Loader.cs b/OpenRA.Mods.Common/SpriteLoaders/ShpD2Loader.cs index 2f68943678..514c3c51cb 100644 --- a/OpenRA.Mods.Common/SpriteLoaders/ShpD2Loader.cs +++ b/OpenRA.Mods.Common/SpriteLoaders/ShpD2Loader.cs @@ -14,6 +14,7 @@ using System.Drawing; using System.IO; using OpenRA.Graphics; using OpenRA.Mods.Common.FileFormats; +using OpenRA.Primitives; namespace OpenRA.Mods.Common.SpriteLoaders { @@ -152,8 +153,9 @@ namespace OpenRA.Mods.Common.SpriteLoaders return frames; } - public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames, out TypeDictionary metadata) { + metadata = null; if (!IsShpD2(s)) { frames = null; diff --git a/OpenRA.Mods.Common/SpriteLoaders/ShpTDLoader.cs b/OpenRA.Mods.Common/SpriteLoaders/ShpTDLoader.cs index f243f205ff..bc903d1f4e 100644 --- a/OpenRA.Mods.Common/SpriteLoaders/ShpTDLoader.cs +++ b/OpenRA.Mods.Common/SpriteLoaders/ShpTDLoader.cs @@ -16,6 +16,7 @@ using System.IO; using System.Linq; using OpenRA.Graphics; using OpenRA.Mods.Common.FileFormats; +using OpenRA.Primitives; namespace OpenRA.Mods.Common.SpriteLoaders { @@ -57,8 +58,9 @@ namespace OpenRA.Mods.Common.SpriteLoaders return b == 0x20 || b == 0x40 || b == 0x80; } - public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames, out TypeDictionary metadata) { + metadata = null; if (!IsShpTD(s)) { frames = null; diff --git a/OpenRA.Mods.Common/SpriteLoaders/ShpTSLoader.cs b/OpenRA.Mods.Common/SpriteLoaders/ShpTSLoader.cs index bd362ca65b..e7128e0cd7 100644 --- a/OpenRA.Mods.Common/SpriteLoaders/ShpTSLoader.cs +++ b/OpenRA.Mods.Common/SpriteLoaders/ShpTSLoader.cs @@ -13,6 +13,7 @@ using System.Drawing; using System.IO; using OpenRA.Graphics; using OpenRA.Mods.Common.FileFormats; +using OpenRA.Primitives; namespace OpenRA.Mods.Common.SpriteLoaders { @@ -145,8 +146,9 @@ namespace OpenRA.Mods.Common.SpriteLoaders return frames; } - public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames, out TypeDictionary metadata) { + metadata = null; if (!IsShpTS(s)) { frames = null; diff --git a/OpenRA.Mods.Common/SpriteLoaders/TmpRALoader.cs b/OpenRA.Mods.Common/SpriteLoaders/TmpRALoader.cs index d1e1fe1e73..d63d9a8cf8 100644 --- a/OpenRA.Mods.Common/SpriteLoaders/TmpRALoader.cs +++ b/OpenRA.Mods.Common/SpriteLoaders/TmpRALoader.cs @@ -12,6 +12,7 @@ using System.Drawing; using System.IO; using OpenRA.Graphics; +using OpenRA.Primitives; namespace OpenRA.Mods.Common.SpriteLoaders { @@ -84,8 +85,9 @@ namespace OpenRA.Mods.Common.SpriteLoaders return tiles; } - public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames, out TypeDictionary metadata) { + metadata = null; if (!IsTmpRA(s)) { frames = null; diff --git a/OpenRA.Mods.Common/SpriteLoaders/TmpTDLoader.cs b/OpenRA.Mods.Common/SpriteLoaders/TmpTDLoader.cs index 8d49d70851..c6abfadcc2 100644 --- a/OpenRA.Mods.Common/SpriteLoaders/TmpTDLoader.cs +++ b/OpenRA.Mods.Common/SpriteLoaders/TmpTDLoader.cs @@ -12,6 +12,7 @@ using System.Drawing; using System.IO; using OpenRA.Graphics; +using OpenRA.Primitives; namespace OpenRA.Mods.Common.SpriteLoaders { @@ -81,8 +82,9 @@ namespace OpenRA.Mods.Common.SpriteLoaders return tiles; } - public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames, out TypeDictionary metadata) { + metadata = null; if (!IsTmpTD(s)) { frames = null; diff --git a/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs b/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs index 26c6d6ef1c..6e32afc389 100644 --- a/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs @@ -16,6 +16,7 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; using OpenRA.Graphics; +using OpenRA.Primitives; namespace OpenRA.Mods.Common.UtilityCommands { @@ -47,7 +48,8 @@ namespace OpenRA.Mods.Common.UtilityCommands var palette = new ImmutablePalette(args[2], shadowIndex); - var frames = FrameLoader.GetFrames(File.OpenRead(src), modData.SpriteLoaders); + TypeDictionary metadata; + var frames = FrameLoader.GetFrames(File.OpenRead(src), modData.SpriteLoaders, out metadata); var usePadding = !args.Contains("--nopadding"); var count = 0; diff --git a/OpenRA.Mods.D2k/SpriteLoaders/R8Loader.cs b/OpenRA.Mods.D2k/SpriteLoaders/R8Loader.cs index 54e8710206..9bd8e69c2d 100644 --- a/OpenRA.Mods.D2k/SpriteLoaders/R8Loader.cs +++ b/OpenRA.Mods.D2k/SpriteLoaders/R8Loader.cs @@ -13,6 +13,7 @@ using System.Collections.Generic; using System.Drawing; using System.IO; using OpenRA.Graphics; +using OpenRA.Primitives; namespace OpenRA.Mods.D2k.SpriteLoaders { @@ -82,8 +83,9 @@ namespace OpenRA.Mods.D2k.SpriteLoaders return d == 8; } - public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames, out TypeDictionary metadata) { + metadata = null; if (!IsR8(s)) { frames = null;