Add plumbing for mod-defined sprite loaders.

This commit is contained in:
Paul Chote
2014-10-05 15:01:45 +13:00
parent ad0da91ecc
commit 9cf8328979
8 changed files with 54 additions and 19 deletions

View File

@@ -45,7 +45,7 @@ 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(new string[0], new SheetBuilder(SheetType.Indexed));
var spriteLoader = new SpriteLoader(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();

View File

@@ -79,7 +79,7 @@ namespace OpenRA.Graphics
{
this.modData = modData;
spriteLoader = Exts.Lazy(() => new SpriteLoader(tileSet.Extensions, new SheetBuilder(SheetType.Indexed)));
spriteLoader = Exts.Lazy(() => new SpriteLoader(modData.SpriteLoaders, tileSet.Extensions, new SheetBuilder(SheetType.Indexed)));
}
public Sequences LoadSequences(Map map)

View File

@@ -8,21 +8,44 @@
*/
#endregion
using System.Drawing;
using System.IO;
using System.Linq;
using OpenRA.FileSystem;
using OpenRA.Primitives;
namespace OpenRA.Graphics
{
public interface ISpriteLoader
{
bool TryParseSprite(Stream s, out ISpriteFrame[] frames);
}
public interface ISpriteFrame
{
Size Size { get; }
Size FrameSize { get; }
float2 Offset { get; }
byte[] Data { get; }
bool DisableExportPadding { get; }
}
public interface ISpriteSource
{
IReadOnlyList<ISpriteFrame> Frames { get; }
}
public class SpriteLoader
{
public readonly SheetBuilder SheetBuilder;
readonly ISpriteLoader[] loaders;
readonly Cache<string, Sprite[]> sprites;
readonly Cache<string, ISpriteFrame[]> frames;
readonly string[] exts;
public SpriteLoader(string[] exts, SheetBuilder sheetBuilder)
public SpriteLoader(ISpriteLoader[] loaders, string[] exts, SheetBuilder sheetBuilder)
{
this.loaders = loaders;
SheetBuilder = sheetBuilder;
// Include extension-less version
@@ -40,8 +63,16 @@ namespace OpenRA.Graphics
ISpriteFrame[] CacheFrames(string filename)
{
using (var stream = GlobalFileSystem.OpenWithExts(filename, exts))
{
ISpriteFrame[] frames;
foreach (var loader in loaders)
if (loader.TryParseSprite(stream, out frames))
return frames;
// Fall back to the hardcoded types (for now).
return SpriteSource.LoadSpriteSource(stream, filename).Frames
.ToArray();
}
}
public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; }

View File

@@ -14,20 +14,6 @@ using OpenRA.FileFormats;
namespace OpenRA.Graphics
{
public interface ISpriteFrame
{
Size Size { get; }
Size FrameSize { get; }
float2 Offset { get; }
byte[] Data { get; }
bool DisableExportPadding { get; }
}
public interface ISpriteSource
{
IReadOnlyList<ISpriteFrame> Frames { get; }
}
// TODO: Most of this should be moved into the format parsers themselves.
public enum SpriteType { Unknown, ShpTD, ShpTS, ShpD2, TmpTD, TmpRA, TmpTS, R8 }
public static class SpriteSource

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Graphics
templates = new Dictionary<ushort, Sprite[]>();
// We manage the SheetBuilder ourselves, to avoid loading all of the tileset images
var spriteLoader = new SpriteLoader(tileset.Extensions, null);
var spriteLoader = new SpriteLoader(Game.modData.SpriteLoaders, tileset.Extensions, null);
foreach (var t in tileset.Templates)
{
var allFrames = spriteLoader.LoadAllFrames(t.Value.Image);

View File

@@ -37,6 +37,8 @@ namespace OpenRA
public readonly Size TileSize = new Size(24, 24);
public readonly TileShape TileShape = TileShape.Rectangle;
public readonly string[] SpriteFormats = { };
[Desc("(x,y,z) offset of the full cell and each sub-cell", "X & Y should be between -512 ... 512 and Z >= 0")]
public readonly WVec[] SubCellOffsets =
{
@@ -128,6 +130,9 @@ namespace OpenRA
compat.Add(c.Trim());
MapCompatibility = compat.ToArray();
if (yaml.ContainsKey("SpriteFormats"))
SpriteFormats = FieldLoader.GetValue<string[]>("SpriteFormats", yaml["SpriteFormats"].Value);
}
static string[] YamlList(Dictionary<string, MiniYaml> yaml, string key)

View File

@@ -24,6 +24,7 @@ namespace OpenRA
public readonly ObjectCreator ObjectCreator;
public readonly WidgetLoader WidgetLoader;
public readonly MapCache MapCache;
public readonly ISpriteLoader[] SpriteLoaders;
public ILoadScreen LoadScreen = null;
public VoxelLoader VoxelLoader;
public readonly RulesetCache RulesetCache;
@@ -45,6 +46,18 @@ namespace OpenRA
RulesetCache.LoadingProgress += HandleLoadingProgress;
MapCache = new MapCache(this);
var loaders = new List<ISpriteLoader>();
foreach (var format in Manifest.SpriteFormats)
{
var loader = ObjectCreator.FindType(format + "Loader");
if (loader == null || !loader.GetInterfaces().Contains(typeof(ISpriteLoader)))
throw new InvalidOperationException("Unable to find a sprite loader for type '{0}'.".F(format));
loaders.Add((ISpriteLoader)ObjectCreator.CreateBasic(loader));
}
SpriteLoaders = loaders.ToArray();
// HACK: Mount only local folders so we have a half-working environment for the asset installer
GlobalFileSystem.UnmountAll();
foreach (var dir in Manifest.Folders)

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
var palette = new ImmutablePalette(args[2], shadowIndex);
var frames = new SpriteLoader(new string[0], null)
var frames = new SpriteLoader(modData.SpriteLoaders, new string[0], null)
.LoadAllFrames(src);
var usePadding = !args.Contains("--nopadding");