From 7207841f8b8614cd93e54c6259f9136cf545cd84 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 5 Oct 2014 11:26:34 +1300 Subject: [PATCH 01/15] Use the existing SpriteLoader cache for tilesets. --- OpenRA.Editor/TileSetRenderer.cs | 41 ++++++-------------------- OpenRA.Game/FileFormats/R8Reader.cs | 1 - OpenRA.Game/FileFormats/ShpD2Reader.cs | 1 - OpenRA.Game/FileFormats/ShpReader.cs | 1 - OpenRA.Game/FileFormats/ShpTSReader.cs | 1 - OpenRA.Game/FileFormats/TmpRAReader.cs | 1 - OpenRA.Game/FileFormats/TmpTDReader.cs | 1 - OpenRA.Game/FileFormats/TmpTSReader.cs | 1 - OpenRA.Game/Graphics/SpriteLoader.cs | 14 +++++++-- OpenRA.Game/Graphics/SpriteSource.cs | 1 - OpenRA.Game/Graphics/Theater.cs | 39 ++++++------------------ 11 files changed, 29 insertions(+), 73 deletions(-) diff --git a/OpenRA.Editor/TileSetRenderer.cs b/OpenRA.Editor/TileSetRenderer.cs index c1bcef7c46..ab23986121 100644 --- a/OpenRA.Editor/TileSetRenderer.cs +++ b/OpenRA.Editor/TileSetRenderer.cs @@ -22,7 +22,7 @@ namespace OpenRA.Editor { public readonly int TileSize; public TileSet TileSet; - Dictionary> templates; + Dictionary templates; // Extract a square tile that the editor can render byte[] ExtractSquareTile(ISpriteFrame frame) @@ -44,42 +44,19 @@ namespace OpenRA.Editor return data; } - List LoadTemplate(string filename, string[] exts, Dictionary sourceCache, int[] frames) - { - ISpriteSource source; - if (!sourceCache.ContainsKey(filename)) - { - using (var s = GlobalFileSystem.OpenWithExts(filename, exts)) - source = SpriteSource.LoadSpriteSource(s, filename); - - if (source.CacheWhenLoadingTileset) - sourceCache.Add(filename, source); - } - else - source = sourceCache[filename]; - - if (frames != null) - { - var ret = new List(); - var srcFrames = source.Frames; - foreach (var i in frames) - ret.Add(ExtractSquareTile(srcFrames[i])); - - return ret; - } - - return source.Frames.Select(f => ExtractSquareTile(f)).ToList(); - } - public TileSetRenderer(TileSet tileset, Size tileSize) { this.TileSet = tileset; this.TileSize = Math.Min(tileSize.Width, tileSize.Height); - templates = new Dictionary>(); - var sourceCache = new Dictionary(); - foreach (var t in TileSet.Templates) - templates.Add(t.Key, LoadTemplate(t.Value.Image, tileset.Extensions, sourceCache, t.Value.Frames)); + templates = new Dictionary(); + var spriteLoader = new SpriteLoader(tileset.Extensions, null); + foreach (var t in tileset.Templates) + { + var allFrames = spriteLoader.LoadAllFrames(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()); + } } public Bitmap RenderTemplate(ushort id, IPalette p) diff --git a/OpenRA.Game/FileFormats/R8Reader.cs b/OpenRA.Game/FileFormats/R8Reader.cs index 0db3ff57ff..1448ee25b6 100644 --- a/OpenRA.Game/FileFormats/R8Reader.cs +++ b/OpenRA.Game/FileFormats/R8Reader.cs @@ -62,7 +62,6 @@ namespace OpenRA.FileFormats } public IReadOnlyList Frames { get; private set; } - public bool CacheWhenLoadingTileset { get { return true; } } public readonly int ImageCount; public R8Reader(Stream stream) diff --git a/OpenRA.Game/FileFormats/ShpD2Reader.cs b/OpenRA.Game/FileFormats/ShpD2Reader.cs index dca7a888d6..51231eb618 100644 --- a/OpenRA.Game/FileFormats/ShpD2Reader.cs +++ b/OpenRA.Game/FileFormats/ShpD2Reader.cs @@ -84,7 +84,6 @@ namespace OpenRA.FileFormats } public IReadOnlyList Frames { get; private set; } - public bool CacheWhenLoadingTileset { get { return false; } } public ShpD2Reader(Stream s) { diff --git a/OpenRA.Game/FileFormats/ShpReader.cs b/OpenRA.Game/FileFormats/ShpReader.cs index 0d7004cca5..173deb5ed6 100644 --- a/OpenRA.Game/FileFormats/ShpReader.cs +++ b/OpenRA.Game/FileFormats/ShpReader.cs @@ -60,7 +60,6 @@ namespace OpenRA.FileFormats } public IReadOnlyList Frames { get; private set; } - public bool CacheWhenLoadingTileset { get { return false; } } public readonly Size Size; int recurseDepth = 0; diff --git a/OpenRA.Game/FileFormats/ShpTSReader.cs b/OpenRA.Game/FileFormats/ShpTSReader.cs index 661a2790f4..6b067f0fcb 100644 --- a/OpenRA.Game/FileFormats/ShpTSReader.cs +++ b/OpenRA.Game/FileFormats/ShpTSReader.cs @@ -45,7 +45,6 @@ namespace OpenRA.FileFormats } public IReadOnlyList Frames { get; private set; } - public bool CacheWhenLoadingTileset { get { return false; } } public ShpTSReader(Stream stream) { diff --git a/OpenRA.Game/FileFormats/TmpRAReader.cs b/OpenRA.Game/FileFormats/TmpRAReader.cs index 5b8f4b520e..cfd761e84a 100644 --- a/OpenRA.Game/FileFormats/TmpRAReader.cs +++ b/OpenRA.Game/FileFormats/TmpRAReader.cs @@ -17,7 +17,6 @@ namespace OpenRA.FileFormats public class TmpRAReader : ISpriteSource { public IReadOnlyList Frames { get; private set; } - public bool CacheWhenLoadingTileset { get { return false; } } public TmpRAReader(Stream s) { diff --git a/OpenRA.Game/FileFormats/TmpTDReader.cs b/OpenRA.Game/FileFormats/TmpTDReader.cs index d0521460d2..540d63c6af 100644 --- a/OpenRA.Game/FileFormats/TmpTDReader.cs +++ b/OpenRA.Game/FileFormats/TmpTDReader.cs @@ -36,7 +36,6 @@ namespace OpenRA.FileFormats public class TmpTDReader : ISpriteSource { public IReadOnlyList Frames { get; private set; } - public bool CacheWhenLoadingTileset { get { return false; } } public TmpTDReader(Stream s) { diff --git a/OpenRA.Game/FileFormats/TmpTSReader.cs b/OpenRA.Game/FileFormats/TmpTSReader.cs index d405e2d01d..e6fdb4a7b9 100644 --- a/OpenRA.Game/FileFormats/TmpTSReader.cs +++ b/OpenRA.Game/FileFormats/TmpTSReader.cs @@ -50,7 +50,6 @@ namespace OpenRA.FileFormats public class TmpTSReader : ISpriteSource { public IReadOnlyList Frames { get; private set; } - public bool CacheWhenLoadingTileset { get { return false; } } public TmpTSReader(Stream s) { diff --git a/OpenRA.Game/Graphics/SpriteLoader.cs b/OpenRA.Game/Graphics/SpriteLoader.cs index fe7c8781b5..5414e6c7b5 100644 --- a/OpenRA.Game/Graphics/SpriteLoader.cs +++ b/OpenRA.Game/Graphics/SpriteLoader.cs @@ -18,6 +18,7 @@ namespace OpenRA.Graphics { public readonly SheetBuilder SheetBuilder; readonly Cache sprites; + readonly Cache frames; readonly string[] exts; public SpriteLoader(string[] exts, SheetBuilder sheetBuilder) @@ -26,17 +27,24 @@ namespace OpenRA.Graphics // Include extension-less version this.exts = exts.Append("").ToArray(); - sprites = new Cache(CacheSpriteFrames); + sprites = new Cache(CacheSprites); + frames = new Cache(CacheFrames); } - Sprite[] CacheSpriteFrames(string filename) + Sprite[] CacheSprites(string filename) + { + return frames[filename].Select(a => SheetBuilder.Add(a)) + .ToArray(); + } + + ISpriteFrame[] CacheFrames(string filename) { using (var stream = GlobalFileSystem.OpenWithExts(filename, exts)) return SpriteSource.LoadSpriteSource(stream, filename).Frames - .Select(a => SheetBuilder.Add(a)) .ToArray(); } public Sprite[] LoadAllSprites(string filename) { return sprites[filename]; } + public ISpriteFrame[] LoadAllFrames(string filename) { return frames[filename]; } } } diff --git a/OpenRA.Game/Graphics/SpriteSource.cs b/OpenRA.Game/Graphics/SpriteSource.cs index ae23aa5501..0434fd1bde 100644 --- a/OpenRA.Game/Graphics/SpriteSource.cs +++ b/OpenRA.Game/Graphics/SpriteSource.cs @@ -25,7 +25,6 @@ namespace OpenRA.Graphics public interface ISpriteSource { IReadOnlyList Frames { get; } - bool CacheWhenLoadingTileset { get; } } // TODO: Most of this should be moved into the format parsers themselves. diff --git a/OpenRA.Game/Graphics/Theater.cs b/OpenRA.Game/Graphics/Theater.cs index e3b962160e..a5b87b04be 100644 --- a/OpenRA.Game/Graphics/Theater.cs +++ b/OpenRA.Game/Graphics/Theater.cs @@ -22,33 +22,6 @@ namespace OpenRA.Graphics Dictionary templates; Sprite missingTile; - Sprite[] LoadTemplate(string filename, string[] exts, Dictionary sourceCache, int[] frames) - { - ISpriteSource source; - if (!sourceCache.ContainsKey(filename)) - { - using (var s = GlobalFileSystem.OpenWithExts(filename, exts)) - source = SpriteSource.LoadSpriteSource(s, filename); - - if (source.CacheWhenLoadingTileset) - sourceCache.Add(filename, source); - } - else - source = sourceCache[filename]; - - if (frames != null) - { - var ret = new List(); - var srcFrames = source.Frames.ToArray(); - foreach (var i in frames) - ret.Add(sheetBuilder.Add(srcFrames[i])); - - return ret.ToArray(); - } - - return source.Frames.Select(f => sheetBuilder.Add(f)).ToArray(); - } - public Theater(TileSet tileset) { var allocated = false; @@ -61,11 +34,17 @@ namespace OpenRA.Graphics return new Sheet(new Size(tileset.SheetSize, tileset.SheetSize), true); }; - var sourceCache = new Dictionary(); - templates = new Dictionary(); 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(tileset.Extensions, null); foreach (var t in tileset.Templates) - templates.Add(t.Value.Id, LoadTemplate(t.Value.Image, tileset.Extensions, sourceCache, t.Value.Frames)); + { + var allFrames = spriteLoader.LoadAllFrames(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()); + } // 1x1px transparent tile missingTile = sheetBuilder.Add(new byte[1], new Size(1, 1)); From 2b92ce7edd5fdf788cff9fdd32b6312327436fff Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 5 Oct 2014 14:41:40 +1300 Subject: [PATCH 02/15] Use SpriteLoader for frame exporting. --- OpenRA.Game/FileFormats/R8Reader.cs | 1 + OpenRA.Game/FileFormats/ShpD2Reader.cs | 1 + OpenRA.Game/FileFormats/ShpReader.cs | 1 + OpenRA.Game/FileFormats/ShpTSReader.cs | 1 + OpenRA.Game/FileFormats/TmpTDReader.cs | 1 + OpenRA.Game/FileFormats/TmpTSReader.cs | 1 + OpenRA.Game/Graphics/SpriteSource.cs | 1 + .../UtilityCommands/ConvertSpriteToPngCommand.cs | 16 +++++++--------- 8 files changed, 14 insertions(+), 9 deletions(-) diff --git a/OpenRA.Game/FileFormats/R8Reader.cs b/OpenRA.Game/FileFormats/R8Reader.cs index 1448ee25b6..fdb6c78623 100644 --- a/OpenRA.Game/FileFormats/R8Reader.cs +++ b/OpenRA.Game/FileFormats/R8Reader.cs @@ -23,6 +23,7 @@ namespace OpenRA.FileFormats public Size FrameSize { get; private set; } public float2 Offset { get; private set; } public byte[] Data { get; set; } + public bool DisableExportPadding { get { return true; } } public R8Image(Stream s) { diff --git a/OpenRA.Game/FileFormats/ShpD2Reader.cs b/OpenRA.Game/FileFormats/ShpD2Reader.cs index 51231eb618..eb90db60ad 100644 --- a/OpenRA.Game/FileFormats/ShpD2Reader.cs +++ b/OpenRA.Game/FileFormats/ShpD2Reader.cs @@ -30,6 +30,7 @@ namespace OpenRA.FileFormats public Size FrameSize { get { return Size; } } public float2 Offset { get { return float2.Zero; } } public byte[] Data { get; set; } + public bool DisableExportPadding { get { return false; } } public Frame(Stream s) { diff --git a/OpenRA.Game/FileFormats/ShpReader.cs b/OpenRA.Game/FileFormats/ShpReader.cs index 173deb5ed6..87da8a92ef 100644 --- a/OpenRA.Game/FileFormats/ShpReader.cs +++ b/OpenRA.Game/FileFormats/ShpReader.cs @@ -27,6 +27,7 @@ namespace OpenRA.FileFormats public Size FrameSize { get { return reader.Size; } } public float2 Offset { get { return float2.Zero; } } public byte[] Data { get; set; } + public bool DisableExportPadding { get { return false; } } public uint FileOffset; public Format Format; diff --git a/OpenRA.Game/FileFormats/ShpTSReader.cs b/OpenRA.Game/FileFormats/ShpTSReader.cs index 6b067f0fcb..f45a412323 100644 --- a/OpenRA.Game/FileFormats/ShpTSReader.cs +++ b/OpenRA.Game/FileFormats/ShpTSReader.cs @@ -22,6 +22,7 @@ namespace OpenRA.FileFormats public Size FrameSize { get; private set; } public float2 Offset { get; private set; } public byte[] Data { get; set; } + public bool DisableExportPadding { get { return false; } } public readonly uint FileOffset; public readonly byte Format; diff --git a/OpenRA.Game/FileFormats/TmpTDReader.cs b/OpenRA.Game/FileFormats/TmpTDReader.cs index 540d63c6af..44e8ca0872 100644 --- a/OpenRA.Game/FileFormats/TmpTDReader.cs +++ b/OpenRA.Game/FileFormats/TmpTDReader.cs @@ -20,6 +20,7 @@ namespace OpenRA.FileFormats public Size FrameSize { get; private set; } public float2 Offset { get { return float2.Zero; } } public byte[] Data { get; set; } + public bool DisableExportPadding { get { return false; } } public TmpTile(byte[] data, Size size) { diff --git a/OpenRA.Game/FileFormats/TmpTSReader.cs b/OpenRA.Game/FileFormats/TmpTSReader.cs index e6fdb4a7b9..6ad7f6388d 100644 --- a/OpenRA.Game/FileFormats/TmpTSReader.cs +++ b/OpenRA.Game/FileFormats/TmpTSReader.cs @@ -21,6 +21,7 @@ namespace OpenRA.FileFormats public Size FrameSize { get { return Size; } } public float2 Offset { get { return float2.Zero; } } public byte[] Data { get; set; } + public bool DisableExportPadding { get { return false; } } public TmpTSTile(Stream s, Size size) { diff --git a/OpenRA.Game/Graphics/SpriteSource.cs b/OpenRA.Game/Graphics/SpriteSource.cs index 0434fd1bde..e930660e49 100644 --- a/OpenRA.Game/Graphics/SpriteSource.cs +++ b/OpenRA.Game/Graphics/SpriteSource.cs @@ -20,6 +20,7 @@ namespace OpenRA.Graphics Size FrameSize { get; } float2 Offset { get; } byte[] Data { get; } + bool DisableExportPadding { get; } } public interface ISpriteSource diff --git a/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs b/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs index 16fac878aa..7b6d1ba2cf 100644 --- a/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs @@ -41,19 +41,17 @@ namespace OpenRA.Mods.Common.UtilityCommands var palette = new ImmutablePalette(args[2], shadowIndex); - ISpriteSource source; - using (var stream = File.OpenRead(src)) - source = SpriteSource.LoadSpriteSource(stream, src); + var frames = new SpriteLoader(new string[0], null) + .LoadAllFrames(src); - // The r8 padding requires external information that we can't access here. - var usePadding = !(args.Contains("--nopadding") || source is R8Reader); + var usePadding = !args.Contains("--nopadding"); var count = 0; var prefix = Path.GetFileNameWithoutExtension(src); - foreach (var frame in source.Frames) + foreach (var frame in frames) { - var frameSize = usePadding ? frame.FrameSize : frame.Size; - var offset = usePadding ? (frame.Offset - 0.5f * new float2(frame.Size - frame.FrameSize)).ToInt2() : int2.Zero; + var frameSize = usePadding && !frame.DisableExportPadding ? frame.FrameSize : frame.Size; + var offset = usePadding && !frame.DisableExportPadding ? (frame.Offset - 0.5f * new float2(frame.Size - frame.FrameSize)).ToInt2() : int2.Zero; // shp(ts) may define empty frames if (frameSize.Width == 0 && frameSize.Height == 0) @@ -69,7 +67,7 @@ namespace OpenRA.Mods.Common.UtilityCommands ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); // Clear the frame - if (usePadding) + if (usePadding && !frame.DisableExportPadding) { var clearRow = new byte[data.Stride]; for (var i = 0; i < frameSize.Height; i++) From ad0da91ecca9fd6cd65aeb646aa34e48d3240e96 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 5 Oct 2014 15:24:42 +1300 Subject: [PATCH 03/15] Remove --transpose utility command. The engine has supported transposed sprites for a long time now. --- OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 - .../UtilityCommands/TransposeShpCommand.cs | 48 ------------------- 2 files changed, 49 deletions(-) delete mode 100644 OpenRA.Mods.Common/UtilityCommands/TransposeShpCommand.cs diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 25a741cc5d..a88493ac08 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -87,7 +87,6 @@ - diff --git a/OpenRA.Mods.Common/UtilityCommands/TransposeShpCommand.cs b/OpenRA.Mods.Common/UtilityCommands/TransposeShpCommand.cs deleted file mode 100644 index 0f5f5be222..0000000000 --- a/OpenRA.Mods.Common/UtilityCommands/TransposeShpCommand.cs +++ /dev/null @@ -1,48 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using OpenRA.FileFormats; - -namespace OpenRA.Mods.Common.UtilityCommands -{ - class TransposeShpCommand : IUtilityCommand - { - public string Name { get { return "--transpose"; } } - - [Desc("SRCSHP DESTSHP START N M [START N M ...]", - "Transpose the N*M block of frames starting at START.")] - public void Run(ModData modData, string[] args) - { - var srcImage = ShpReader.Load(args[1]); - - var srcFrames = srcImage.Frames; - var destFrames = srcImage.Frames.ToArray(); - - for (var z = 3; z < args.Length - 2; z += 3) - { - var start = Exts.ParseIntegerInvariant(args[z]); - var m = Exts.ParseIntegerInvariant(args[z + 1]); - var n = Exts.ParseIntegerInvariant(args[z + 2]); - - for (var i = 0; i < m; i++) - for (var j = 0; j < n; j++) - destFrames[start + i * n + j] = srcFrames[start + j * m + i]; - } - - using (var destStream = File.Create(args[2])) - ShpReader.Write(destStream, srcImage.Size, destFrames.Select(f => f.Data)); - } - } -} From 9cf8328979b5b02420bdfc802b4f58a5becd1c1e Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 5 Oct 2014 15:01:45 +1300 Subject: [PATCH 04/15] Add plumbing for mod-defined sprite loaders. --- OpenRA.Game/Graphics/CursorProvider.cs | 2 +- OpenRA.Game/Graphics/SequenceProvider.cs | 2 +- OpenRA.Game/Graphics/SpriteLoader.cs | 33 ++++++++++++++++++- OpenRA.Game/Graphics/SpriteSource.cs | 14 -------- OpenRA.Game/Graphics/Theater.cs | 2 +- OpenRA.Game/Manifest.cs | 5 +++ OpenRA.Game/ModData.cs | 13 ++++++++ .../ConvertSpriteToPngCommand.cs | 2 +- 8 files changed, 54 insertions(+), 19 deletions(-) diff --git a/OpenRA.Game/Graphics/CursorProvider.cs b/OpenRA.Game/Graphics/CursorProvider.cs index 042e3164d2..28701e2fd4 100644 --- a/OpenRA.Game/Graphics/CursorProvider.cs +++ b/OpenRA.Game/Graphics/CursorProvider.cs @@ -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(); diff --git a/OpenRA.Game/Graphics/SequenceProvider.cs b/OpenRA.Game/Graphics/SequenceProvider.cs index 2f3947e137..bed18baac0 100644 --- a/OpenRA.Game/Graphics/SequenceProvider.cs +++ b/OpenRA.Game/Graphics/SequenceProvider.cs @@ -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) diff --git a/OpenRA.Game/Graphics/SpriteLoader.cs b/OpenRA.Game/Graphics/SpriteLoader.cs index 5414e6c7b5..4e53960f44 100644 --- a/OpenRA.Game/Graphics/SpriteLoader.cs +++ b/OpenRA.Game/Graphics/SpriteLoader.cs @@ -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 Frames { get; } + } + public class SpriteLoader { public readonly SheetBuilder SheetBuilder; + readonly ISpriteLoader[] loaders; readonly Cache sprites; readonly Cache 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]; } diff --git a/OpenRA.Game/Graphics/SpriteSource.cs b/OpenRA.Game/Graphics/SpriteSource.cs index e930660e49..80a224d226 100644 --- a/OpenRA.Game/Graphics/SpriteSource.cs +++ b/OpenRA.Game/Graphics/SpriteSource.cs @@ -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 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 diff --git a/OpenRA.Game/Graphics/Theater.cs b/OpenRA.Game/Graphics/Theater.cs index a5b87b04be..110b27703a 100644 --- a/OpenRA.Game/Graphics/Theater.cs +++ b/OpenRA.Game/Graphics/Theater.cs @@ -38,7 +38,7 @@ namespace OpenRA.Graphics templates = new Dictionary(); // 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); diff --git a/OpenRA.Game/Manifest.cs b/OpenRA.Game/Manifest.cs index 282ae968d1..12fc57a47f 100644 --- a/OpenRA.Game/Manifest.cs +++ b/OpenRA.Game/Manifest.cs @@ -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("SpriteFormats", yaml["SpriteFormats"].Value); } static string[] YamlList(Dictionary yaml, string key) diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index c5b5fc3a0c..288d9ac836 100644 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -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(); + 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) diff --git a/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs b/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs index 7b6d1ba2cf..f70338b257 100644 --- a/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/ConvertSpriteToPngCommand.cs @@ -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"); From d658643b73937bc601a4bf21a28b59d2d19f8f57 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 5 Oct 2014 15:25:39 +1300 Subject: [PATCH 05/15] Move ShpTD sprite loading into Mods.Common. --- OpenRA.Game/Graphics/SpriteSource.cs | 43 +----------- OpenRA.Game/OpenRA.Game.csproj | 1 - OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 + .../SpriteLoaders/ShpTDLoader.cs | 68 ++++++++++++++++--- .../UtilityCommands/ConvertPngToShpCommand.cs | 3 +- .../UtilityCommands/RemapShpCommand.cs | 9 ++- mods/cnc/mod.yaml | 2 + mods/d2k/mod.yaml | 2 + mods/modchooser/mod.yaml | 4 +- mods/ra/mod.yaml | 2 + mods/ts/mod.yaml | 2 + 11 files changed, 78 insertions(+), 59 deletions(-) rename OpenRA.Game/FileFormats/ShpReader.cs => OpenRA.Mods.Common/SpriteLoaders/ShpTDLoader.cs (80%) diff --git a/OpenRA.Game/Graphics/SpriteSource.cs b/OpenRA.Game/Graphics/SpriteSource.cs index 80a224d226..b2e530332e 100644 --- a/OpenRA.Game/Graphics/SpriteSource.cs +++ b/OpenRA.Game/Graphics/SpriteSource.cs @@ -15,7 +15,7 @@ using OpenRA.FileFormats; namespace OpenRA.Graphics { // TODO: Most of this should be moved into the format parsers themselves. - public enum SpriteType { Unknown, ShpTD, ShpTS, ShpD2, TmpTD, TmpRA, TmpTS, R8 } + public enum SpriteType { Unknown, ShpTS, ShpD2, TmpTD, TmpRA, TmpTS, R8 } public static class SpriteSource { static bool IsTmpRA(Stream s) @@ -103,42 +103,6 @@ namespace OpenRA.Graphics return type < 4; } - static bool IsShpTD(Stream s) - { - var start = s.Position; - - // First word is the image count - var imageCount = s.ReadUInt16(); - if (imageCount == 0) - { - s.Position = start; - return false; - } - - // Last offset should point to the end of file - var finalOffset = start + 14 + 8 * imageCount; - if (finalOffset > s.Length) - { - s.Position = start; - return false; - } - - s.Position = finalOffset; - var eof = s.ReadUInt32(); - if (eof != s.Length) - { - s.Position = start; - return false; - } - - // Check the format flag on the first frame - s.Position = start + 17; - var b = s.ReadUInt8(); - - s.Position = start; - return b == 0x20 || b == 0x40 || b == 0x80; - } - static bool IsShpD2(Stream s) { var start = s.Position; @@ -198,9 +162,6 @@ namespace OpenRA.Graphics public static SpriteType DetectSpriteType(Stream s) { - if (IsShpTD(s)) - return SpriteType.ShpTD; - if (IsShpTS(s)) return SpriteType.ShpTS; @@ -227,8 +188,6 @@ namespace OpenRA.Graphics var type = DetectSpriteType(s); switch (type) { - case SpriteType.ShpTD: - return new ShpReader(s); case SpriteType.ShpTS: return new ShpTSReader(s); case SpriteType.R8: diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index e675c54864..aaad4818f0 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -279,7 +279,6 @@ - diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index a88493ac08..984386022d 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -113,6 +113,7 @@ + diff --git a/OpenRA.Game/FileFormats/ShpReader.cs b/OpenRA.Mods.Common/SpriteLoaders/ShpTDLoader.cs similarity index 80% rename from OpenRA.Game/FileFormats/ShpReader.cs rename to OpenRA.Mods.Common/SpriteLoaders/ShpTDLoader.cs index 87da8a92ef..055375889a 100644 --- a/OpenRA.Game/FileFormats/ShpReader.cs +++ b/OpenRA.Mods.Common/SpriteLoaders/ShpTDLoader.cs @@ -13,11 +13,63 @@ using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; +using OpenRA.FileFormats; using OpenRA.Graphics; -namespace OpenRA.FileFormats +namespace OpenRA.Mods.Common.SpriteLoaders { - public class ShpReader : ISpriteSource + public class ShpTDLoader : ISpriteLoader + { + static bool IsShpTD(Stream s) + { + var start = s.Position; + + // First word is the image count + var imageCount = s.ReadUInt16(); + if (imageCount == 0) + { + s.Position = start; + return false; + } + + // Last offset should point to the end of file + var finalOffset = start + 14 + 8 * imageCount; + if (finalOffset > s.Length) + { + s.Position = start; + return false; + } + + s.Position = finalOffset; + var eof = s.ReadUInt32(); + if (eof != s.Length) + { + s.Position = start; + return false; + } + + // Check the format flag on the first frame + s.Position = start + 17; + var b = s.ReadUInt8(); + + s.Position = start; + return b == 0x20 || b == 0x40 || b == 0x80; + } + + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + { + if (!IsShpTD(s)) + { + frames = null; + return false; + } + + frames = new ShpTDSprite(s).Frames.ToArray(); + return true; + } + } + + public class ShpTDSprite { enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 } @@ -36,12 +88,12 @@ namespace OpenRA.FileFormats public Format RefFormat; public ImageHeader RefImage; - ShpReader reader; + ShpTDSprite reader; // Used by ShpWriter public ImageHeader() { } - public ImageHeader(Stream stream, ShpReader reader) + public ImageHeader(Stream stream, ShpTDSprite reader) { this.reader = reader; var data = stream.ReadUInt32(); @@ -69,7 +121,7 @@ namespace OpenRA.FileFormats readonly long shpBytesFileOffset; readonly byte[] shpBytes; - public ShpReader(Stream stream) + public ShpTDSprite(Stream stream) { imageCount = stream.ReadUInt16(); stream.Position += 4; @@ -149,12 +201,6 @@ namespace OpenRA.FileFormats return imageData; } - public static ShpReader Load(string filename) - { - using (var s = File.OpenRead(filename)) - return new ShpReader(s); - } - public static void Write(Stream s, Size size, IEnumerable frames) { var compressedFrames = frames.Select(f => Format80.Encode(f)).ToArray(); diff --git a/OpenRA.Mods.Common/UtilityCommands/ConvertPngToShpCommand.cs b/OpenRA.Mods.Common/UtilityCommands/ConvertPngToShpCommand.cs index 4cef69cec1..d52b7fee69 100644 --- a/OpenRA.Mods.Common/UtilityCommands/ConvertPngToShpCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/ConvertPngToShpCommand.cs @@ -17,6 +17,7 @@ using System.Linq; using System.Runtime.InteropServices; using System.Text; using OpenRA.FileFormats; +using OpenRA.Mods.Common.SpriteLoaders; namespace OpenRA.Mods.Common.UtilityCommands { @@ -36,7 +37,7 @@ namespace OpenRA.Mods.Common.UtilityCommands throw new InvalidOperationException("All frames must be the same size"); using (var destStream = File.Create(dest)) - ShpReader.Write(destStream, size, frames.Select(f => ToBytes(f))); + ShpTDSprite.Write(destStream, size, frames.Select(f => ToBytes(f))); Console.WriteLine(dest + " saved."); } diff --git a/OpenRA.Mods.Common/UtilityCommands/RemapShpCommand.cs b/OpenRA.Mods.Common/UtilityCommands/RemapShpCommand.cs index 59ee1885b6..1bffa57ff2 100644 --- a/OpenRA.Mods.Common/UtilityCommands/RemapShpCommand.cs +++ b/OpenRA.Mods.Common/UtilityCommands/RemapShpCommand.cs @@ -18,6 +18,7 @@ using OpenRA.Traits; using OpenRA.Graphics; using OpenRA.FileFormats; using OpenRA.FileSystem; +using OpenRA.Mods.Common.SpriteLoaders; namespace OpenRA.Mods.Common.UtilityCommands { @@ -65,11 +66,13 @@ namespace OpenRA.Mods.Common.UtilityCommands .Where(a => !remap.ContainsValue(a)) .MinBy(a => ColorDistance(destPalette[a], srcPalette[i])); - var srcImage = ShpReader.Load(args[3]); - + using (var s = File.OpenRead(args[3])) using (var destStream = File.Create(args[4])) - ShpReader.Write(destStream, srcImage.Size, + { + var srcImage = new ShpTDSprite(s); + ShpTDSprite.Write(destStream, srcImage.Size, srcImage.Frames.Select(im => im.Data.Select(px => (byte)remap[px]).ToArray())); + } } static int ColorDistance(uint a, uint b) diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index de38e49e9a..a7e412249e 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -210,3 +210,5 @@ Missions: mods/cnc/missions.yaml SupportsMapsFrom: cnc + +SpriteFormats: ShpTD \ No newline at end of file diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index a459281206..daf9be261f 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -188,3 +188,5 @@ LuaScripts: mods/common/lua/facing.lua SupportsMapsFrom: d2k + +SpriteFormats: ShpTD \ No newline at end of file diff --git a/mods/modchooser/mod.yaml b/mods/modchooser/mod.yaml index 8afb9547eb..596b07afd2 100644 --- a/mods/modchooser/mod.yaml +++ b/mods/modchooser/mod.yaml @@ -49,4 +49,6 @@ Fonts: Font:FreeSansBold.ttf Size:10 -LobbyDefaults: \ No newline at end of file +LobbyDefaults: + +SpriteFormats: ShpTD \ No newline at end of file diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 932dba6f9a..2807d787b6 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -207,3 +207,5 @@ Missions: mods/ra/missions.yaml SupportsMapsFrom: ra + +SpriteFormats: ShpTD \ No newline at end of file diff --git a/mods/ts/mod.yaml b/mods/ts/mod.yaml index 52662647f0..28fcce5127 100644 --- a/mods/ts/mod.yaml +++ b/mods/ts/mod.yaml @@ -229,3 +229,5 @@ LuaScripts: mods/common/lua/facing.lua SupportsMapsFrom: ts + +SpriteFormats: ShpTD \ No newline at end of file From c798b306c4a4ab7f988c95bdcff2bbae502a90e3 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 5 Oct 2014 15:34:56 +1300 Subject: [PATCH 06/15] Move ShpTS sprite loading into Mods.Common. --- OpenRA.Game/Graphics/SpriteSource.cs | 44 +-------- OpenRA.Game/OpenRA.Game.csproj | 1 - OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 + .../SpriteLoaders/ShpTSLoader.cs | 99 ++++++++++++++----- mods/cnc/mod.yaml | 2 +- mods/ra/mod.yaml | 2 +- mods/ts/mod.yaml | 2 +- 7 files changed, 82 insertions(+), 69 deletions(-) rename OpenRA.Game/FileFormats/ShpTSReader.cs => OpenRA.Mods.Common/SpriteLoaders/ShpTSLoader.cs (53%) diff --git a/OpenRA.Game/Graphics/SpriteSource.cs b/OpenRA.Game/Graphics/SpriteSource.cs index b2e530332e..09c6f35e95 100644 --- a/OpenRA.Game/Graphics/SpriteSource.cs +++ b/OpenRA.Game/Graphics/SpriteSource.cs @@ -15,7 +15,7 @@ using OpenRA.FileFormats; namespace OpenRA.Graphics { // TODO: Most of this should be moved into the format parsers themselves. - public enum SpriteType { Unknown, ShpTS, ShpD2, TmpTD, TmpRA, TmpTS, R8 } + public enum SpriteType { Unknown, ShpD2, TmpTD, TmpRA, TmpTS, R8 } public static class SpriteSource { static bool IsTmpRA(Stream s) @@ -66,43 +66,6 @@ namespace OpenRA.Graphics return test == sx * sy / 2 + 52; } - static bool IsShpTS(Stream s) - { - var start = s.Position; - - // First word is zero - if (s.ReadUInt16() != 0) - { - s.Position = start; - return false; - } - - // Sanity Check the image count - s.Position += 4; - var imageCount = s.ReadUInt16(); - if (s.Position + 24 * imageCount > s.Length) - { - s.Position = start; - return false; - } - - // Check the size and format flag - // Some files define bogus frames, so loop until we find a valid one - s.Position += 4; - ushort w, h, f = 0; - byte type; - do - { - w = s.ReadUInt16(); - h = s.ReadUInt16(); - type = s.ReadUInt8(); - } - while (w == 0 && h == 0 && f++ < imageCount); - - s.Position = start; - return type < 4; - } - static bool IsShpD2(Stream s) { var start = s.Position; @@ -162,9 +125,6 @@ namespace OpenRA.Graphics public static SpriteType DetectSpriteType(Stream s) { - if (IsShpTS(s)) - return SpriteType.ShpTS; - if (IsR8(s)) return SpriteType.R8; @@ -188,8 +148,6 @@ namespace OpenRA.Graphics var type = DetectSpriteType(s); switch (type) { - case SpriteType.ShpTS: - return new ShpTSReader(s); case SpriteType.R8: return new R8Reader(s); case SpriteType.TmpRA: diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index aaad4818f0..83112e9a2d 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -279,7 +279,6 @@ - diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 984386022d..98520994d1 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -114,6 +114,7 @@ + diff --git a/OpenRA.Game/FileFormats/ShpTSReader.cs b/OpenRA.Mods.Common/SpriteLoaders/ShpTSLoader.cs similarity index 53% rename from OpenRA.Game/FileFormats/ShpTSReader.cs rename to OpenRA.Mods.Common/SpriteLoaders/ShpTSLoader.cs index f45a412323..6471be0aab 100644 --- a/OpenRA.Game/FileFormats/ShpTSReader.cs +++ b/OpenRA.Mods.Common/SpriteLoaders/ShpTSLoader.cs @@ -8,15 +8,19 @@ */ #endregion +using System; +using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Linq; +using OpenRA.FileFormats; using OpenRA.Graphics; -namespace OpenRA.FileFormats +namespace OpenRA.Mods.Common.SpriteLoaders { - public class ShpTSReader : ISpriteSource + public class ShpTSLoader : ISpriteLoader { - class FrameHeader : ISpriteFrame + class ShpTSFrame : ISpriteFrame { public Size Size { get; private set; } public Size FrameSize { get; private set; } @@ -27,7 +31,7 @@ namespace OpenRA.FileFormats public readonly uint FileOffset; public readonly byte Format; - public FrameHeader(Stream stream, Size frameSize) + public ShpTSFrame(Stream stream, Size frameSize) { var x = stream.ReadUInt16(); var y = stream.ReadUInt16(); @@ -45,20 +49,56 @@ namespace OpenRA.FileFormats } } - public IReadOnlyList Frames { get; private set; } - - public ShpTSReader(Stream stream) + bool IsShpTS(Stream s) { - stream.ReadUInt16(); - var width = stream.ReadUInt16(); - var height = stream.ReadUInt16(); - var size = new Size(width, height); - var frameCount = stream.ReadUInt16(); + var start = s.Position; - var frames = new FrameHeader[frameCount]; - Frames = frames.AsReadOnly(); + // First word is zero + if (s.ReadUInt16() != 0) + { + s.Position = start; + return false; + } + + // Sanity Check the image count + s.Position += 4; + var imageCount = s.ReadUInt16(); + if (s.Position + 24 * imageCount > s.Length) + { + s.Position = start; + return false; + } + + // Check the size and format flag + // Some files define bogus frames, so loop until we find a valid one + s.Position += 4; + ushort w, h, f = 0; + byte type; + do + { + w = s.ReadUInt16(); + h = s.ReadUInt16(); + type = s.ReadUInt8(); + } + while (w == 0 && h == 0 && f++ < imageCount); + + s.Position = start; + return type < 4; + } + + ShpTSFrame[] ParseFrames(Stream s) + { + var start = s.Position; + + s.ReadUInt16(); + var width = s.ReadUInt16(); + var height = s.ReadUInt16(); + var size = new Size(width, height); + var frameCount = s.ReadUInt16(); + + var frames = new ShpTSFrame[frameCount]; for (var i = 0; i < frames.Length; i++) - frames[i] = new FrameHeader(stream, size); + frames[i] = new ShpTSFrame(s, size); for (var i = 0; i < frameCount; i++) { @@ -66,13 +106,13 @@ namespace OpenRA.FileFormats if (f.FileOffset == 0) continue; - stream.Position = f.FileOffset; + s.Position = f.FileOffset; var frameSize = f.Size.Width * f.Size.Height; // Uncompressed if (f.Format == 1 || f.Format == 0) - f.Data = stream.ReadBytes(frameSize); + f.Data = s.ReadBytes(frameSize); // Uncompressed scanlines else if (f.Format == 2) @@ -80,9 +120,9 @@ namespace OpenRA.FileFormats f.Data = new byte[frameSize]; for (var j = 0; j < f.Size.Height; j++) { - var length = stream.ReadUInt16() - 2; + var length = s.ReadUInt16() - 2; var offset = f.Size.Width * j; - stream.ReadBytes(f.Data, offset, length); + s.ReadBytes(f.Data, offset, length); } } @@ -92,12 +132,27 @@ namespace OpenRA.FileFormats f.Data = new byte[frameSize]; for (var j = 0; j < f.Size.Height; j++) { - var length = stream.ReadUInt16() - 2; + var length = s.ReadUInt16() - 2; var offset = f.Size.Width * j; - Format2.DecodeInto(stream.ReadBytes(length), f.Data, offset); + Format2.DecodeInto(s.ReadBytes(length), f.Data, offset); } } } + + s.Position = start; + return frames; + } + + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + { + if (!IsShpTS(s)) + { + frames = null; + return false; + } + + frames = ParseFrames(s); + return true; } } -} \ No newline at end of file +} diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index a7e412249e..2bffd79982 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -211,4 +211,4 @@ Missions: SupportsMapsFrom: cnc -SpriteFormats: ShpTD \ No newline at end of file +SpriteFormats: ShpTD, ShpTS \ No newline at end of file diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 2807d787b6..24882a5e1c 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -208,4 +208,4 @@ Missions: SupportsMapsFrom: ra -SpriteFormats: ShpTD \ No newline at end of file +SpriteFormats: ShpTD, ShpTS \ No newline at end of file diff --git a/mods/ts/mod.yaml b/mods/ts/mod.yaml index 28fcce5127..ce7a0b001e 100644 --- a/mods/ts/mod.yaml +++ b/mods/ts/mod.yaml @@ -230,4 +230,4 @@ LuaScripts: SupportsMapsFrom: ts -SpriteFormats: ShpTD \ No newline at end of file +SpriteFormats: ShpTD, ShpTS \ No newline at end of file From ca38193264b14fdd6c12f3a0b5898484b9c10e6e Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 5 Oct 2014 15:42:14 +1300 Subject: [PATCH 07/15] Move R8 sprite loading into Mods.D2k. --- OpenRA.Game/Graphics/SpriteSource.cs | 26 +--------- OpenRA.Game/OpenRA.Game.csproj | 1 - OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj | 1 + .../R8Loader.cs | 52 ++++++++++++++----- mods/d2k/mod.yaml | 2 +- 5 files changed, 41 insertions(+), 41 deletions(-) rename OpenRA.Game/FileFormats/R8Reader.cs => OpenRA.Mods.D2k/R8Loader.cs (66%) diff --git a/OpenRA.Game/Graphics/SpriteSource.cs b/OpenRA.Game/Graphics/SpriteSource.cs index 09c6f35e95..bf81824d60 100644 --- a/OpenRA.Game/Graphics/SpriteSource.cs +++ b/OpenRA.Game/Graphics/SpriteSource.cs @@ -15,7 +15,7 @@ using OpenRA.FileFormats; namespace OpenRA.Graphics { // TODO: Most of this should be moved into the format parsers themselves. - public enum SpriteType { Unknown, ShpD2, TmpTD, TmpRA, TmpTS, R8 } + public enum SpriteType { Unknown, ShpD2, TmpTD, TmpRA, TmpTS } public static class SpriteSource { static bool IsTmpRA(Stream s) @@ -104,30 +104,8 @@ namespace OpenRA.Graphics return b == 5 || b <= 3; } - static bool IsR8(Stream s) - { - var start = s.Position; - - // First byte is nonzero - if (s.ReadUInt8() == 0) - { - s.Position = start; - return false; - } - - // Check the format of the first frame - s.Position = start + 25; - var d = s.ReadUInt8(); - - s.Position = start; - return d == 8; - } - public static SpriteType DetectSpriteType(Stream s) { - if (IsR8(s)) - return SpriteType.R8; - if (IsTmpRA(s)) return SpriteType.TmpRA; @@ -148,8 +126,6 @@ namespace OpenRA.Graphics var type = DetectSpriteType(s); switch (type) { - case SpriteType.R8: - return new R8Reader(s); case SpriteType.TmpRA: return new TmpRAReader(s); case SpriteType.TmpTD: diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 83112e9a2d..11f17a7361 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -277,7 +277,6 @@ - diff --git a/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj b/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj index e547daf283..9dc1baf04c 100644 --- a/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj +++ b/OpenRA.Mods.D2k/OpenRA.Mods.D2k.csproj @@ -84,6 +84,7 @@ + diff --git a/OpenRA.Game/FileFormats/R8Reader.cs b/OpenRA.Mods.D2k/R8Loader.cs similarity index 66% rename from OpenRA.Game/FileFormats/R8Reader.cs rename to OpenRA.Mods.D2k/R8Loader.cs index fdb6c78623..89ac184489 100644 --- a/OpenRA.Game/FileFormats/R8Reader.cs +++ b/OpenRA.Mods.D2k/R8Loader.cs @@ -1,23 +1,25 @@ #region Copyright & License Information /* * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made + * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, * see COPYING. */ #endregion +using System; using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Linq; using OpenRA.Graphics; -namespace OpenRA.FileFormats +namespace OpenRA.Mods.D2k.SpriteLoaders { - public class R8Reader : ISpriteSource + public class R8Loader : ISpriteLoader { - class R8Image : ISpriteFrame + class R8Frame : ISpriteFrame { public Size Size { get; private set; } public Size FrameSize { get; private set; } @@ -25,7 +27,7 @@ namespace OpenRA.FileFormats public byte[] Data { get; set; } public bool DisableExportPadding { get { return true; } } - public R8Image(Stream s) + public R8Frame(Stream s) { // Scan forward until we find some data var type = s.ReadUInt8(); @@ -62,19 +64,41 @@ namespace OpenRA.FileFormats } } - public IReadOnlyList Frames { get; private set; } - - public readonly int ImageCount; - public R8Reader(Stream stream) + bool IsR8(Stream s) { - var frames = new List(); - while (stream.Position < stream.Length) + var start = s.Position; + + // First byte is nonzero + if (s.ReadUInt8() == 0) { - frames.Add(new R8Image(stream)); - ImageCount++; + s.Position = start; + return false; } - Frames = frames.ToArray().AsReadOnly(); + // Check the format of the first frame + s.Position = start + 25; + var d = s.ReadUInt8(); + + s.Position = start; + return d == 8; + } + + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + { + if (!IsR8(s)) + { + frames = null; + return false; + } + + var start = s.Position; + var tmp = new List(); + while (s.Position < s.Length) + tmp.Add(new R8Frame(s)); + s.Position = start; + + frames = tmp.ToArray(); + return true; } } } diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index daf9be261f..7cb31d3585 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -189,4 +189,4 @@ LuaScripts: SupportsMapsFrom: d2k -SpriteFormats: ShpTD \ No newline at end of file +SpriteFormats: R8, ShpTD \ No newline at end of file From 997c79130ac89b72d00b71b305f297ce0a62b62d Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 5 Oct 2014 15:49:34 +1300 Subject: [PATCH 08/15] Move TmpRA sprite loading into Mods.Common. --- OpenRA.Game/FileFormats/TmpRAReader.cs | 51 --------- OpenRA.Game/Graphics/SpriteSource.cs | 20 +--- OpenRA.Game/OpenRA.Game.csproj | 1 - OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 + .../SpriteLoaders/TmpRALoader.cs | 102 ++++++++++++++++++ mods/cnc/mod.yaml | 2 +- mods/d2k/mod.yaml | 2 +- mods/ra/mod.yaml | 2 +- 8 files changed, 107 insertions(+), 74 deletions(-) delete mode 100644 OpenRA.Game/FileFormats/TmpRAReader.cs create mode 100644 OpenRA.Mods.Common/SpriteLoaders/TmpRALoader.cs diff --git a/OpenRA.Game/FileFormats/TmpRAReader.cs b/OpenRA.Game/FileFormats/TmpRAReader.cs deleted file mode 100644 index cfd761e84a..0000000000 --- a/OpenRA.Game/FileFormats/TmpRAReader.cs +++ /dev/null @@ -1,51 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System.Drawing; -using System.IO; -using OpenRA.Graphics; - -namespace OpenRA.FileFormats -{ - public class TmpRAReader : ISpriteSource - { - public IReadOnlyList Frames { get; private set; } - - public TmpRAReader(Stream s) - { - var width = s.ReadUInt16(); - var height = s.ReadUInt16(); - var size = new Size(width, height); - - s.Position += 12; - var imgStart = s.ReadUInt32(); - s.Position += 8; - var indexEnd = s.ReadInt32(); - s.Position += 4; - var indexStart = s.ReadInt32(); - - s.Position = indexStart; - var count = indexEnd - indexStart; - var tiles = new TmpTile[count]; - Frames = tiles.AsReadOnly(); - var tilesIndex = 0; - foreach (var b in s.ReadBytes(count)) - { - if (b != 255) - { - s.Position = imgStart + b * width * height; - tiles[tilesIndex++] = new TmpTile(s.ReadBytes(width * height), size); - } - else - tiles[tilesIndex++] = new TmpTile(null, size); - } - } - } -} diff --git a/OpenRA.Game/Graphics/SpriteSource.cs b/OpenRA.Game/Graphics/SpriteSource.cs index bf81824d60..8ca32dd6ce 100644 --- a/OpenRA.Game/Graphics/SpriteSource.cs +++ b/OpenRA.Game/Graphics/SpriteSource.cs @@ -15,22 +15,9 @@ using OpenRA.FileFormats; namespace OpenRA.Graphics { // TODO: Most of this should be moved into the format parsers themselves. - public enum SpriteType { Unknown, ShpD2, TmpTD, TmpRA, TmpTS } + public enum SpriteType { Unknown, ShpD2, TmpTD, TmpTS } public static class SpriteSource { - static bool IsTmpRA(Stream s) - { - var start = s.Position; - - s.Position += 20; - var a = s.ReadUInt32(); - s.Position += 2; - var b = s.ReadUInt16(); - - s.Position = start; - return a == 0 && b == 0x2c73; - } - static bool IsTmpTD(Stream s) { var start = s.Position; @@ -106,9 +93,6 @@ namespace OpenRA.Graphics public static SpriteType DetectSpriteType(Stream s) { - if (IsTmpRA(s)) - return SpriteType.TmpRA; - if (IsTmpTD(s)) return SpriteType.TmpTD; @@ -126,8 +110,6 @@ namespace OpenRA.Graphics var type = DetectSpriteType(s); switch (type) { - case SpriteType.TmpRA: - return new TmpRAReader(s); case SpriteType.TmpTD: return new TmpTDReader(s); case SpriteType.TmpTS: diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 11f17a7361..9b63f7b96a 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -278,7 +278,6 @@ - diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index 98520994d1..d27764c409 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -115,6 +115,7 @@ + diff --git a/OpenRA.Mods.Common/SpriteLoaders/TmpRALoader.cs b/OpenRA.Mods.Common/SpriteLoaders/TmpRALoader.cs new file mode 100644 index 0000000000..900c3fdd0c --- /dev/null +++ b/OpenRA.Mods.Common/SpriteLoaders/TmpRALoader.cs @@ -0,0 +1,102 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using OpenRA.FileFormats; +using OpenRA.Graphics; + +namespace OpenRA.Mods.Common.SpriteLoaders +{ + public class TmpRALoader : ISpriteLoader + { + class TmpRAFrame : ISpriteFrame + { + public Size Size { get; private set; } + public Size FrameSize { get; private set; } + public float2 Offset { get { return float2.Zero; } } + public byte[] Data { get; set; } + public bool DisableExportPadding { get { return false; } } + + public TmpRAFrame(byte[] data, Size size) + { + FrameSize = size; + Data = data; + + if (data == null) + Data = new byte[0]; + else + Size = size; + } + } + + bool IsTmpRA(Stream s) + { + var start = s.Position; + + s.Position += 20; + var a = s.ReadUInt32(); + s.Position += 2; + var b = s.ReadUInt16(); + + s.Position = start; + return a == 0 && b == 0x2c73; + } + + TmpRAFrame[] ParseFrames(Stream s) + { + var start = s.Position; + var width = s.ReadUInt16(); + var height = s.ReadUInt16(); + var size = new Size(width, height); + + s.Position += 12; + var imgStart = s.ReadUInt32(); + s.Position += 8; + var indexEnd = s.ReadInt32(); + s.Position += 4; + var indexStart = s.ReadInt32(); + + s.Position = indexStart; + var count = indexEnd - indexStart; + var tiles = new TmpRAFrame[count]; + + var tilesIndex = 0; + foreach (var b in s.ReadBytes(count)) + { + if (b != 255) + { + s.Position = imgStart + b * width * height; + tiles[tilesIndex++] = new TmpRAFrame(s.ReadBytes(width * height), size); + } + else + tiles[tilesIndex++] = new TmpRAFrame(null, size); + } + + s.Position = start; + return tiles; + } + + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + { + if (!IsTmpRA(s)) + { + frames = null; + return false; + } + + frames = ParseFrames(s); + return true; + } + } +} diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index 2bffd79982..676a01bd99 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -211,4 +211,4 @@ Missions: SupportsMapsFrom: cnc -SpriteFormats: ShpTD, ShpTS \ No newline at end of file +SpriteFormats: ShpTD, ShpTS, TmpRA \ No newline at end of file diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index 7cb31d3585..5f27b81cfd 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -189,4 +189,4 @@ LuaScripts: SupportsMapsFrom: d2k -SpriteFormats: R8, ShpTD \ No newline at end of file +SpriteFormats: R8, ShpTD, TmpRA \ No newline at end of file diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 24882a5e1c..51875f95e3 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -208,4 +208,4 @@ Missions: SupportsMapsFrom: ra -SpriteFormats: ShpTD, ShpTS \ No newline at end of file +SpriteFormats: ShpTD, TmpRA, ShpTS \ No newline at end of file From 37cedd88a2033f9e96098ad0b918a65e10afa399 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 5 Oct 2014 16:17:05 +1300 Subject: [PATCH 09/15] Move TmpTD sprite loading into Mods.Common. --- OpenRA.Game/FileFormats/TmpTDReader.cs | 70 ------------- OpenRA.Game/Graphics/SpriteSource.cs | 19 +--- OpenRA.Game/OpenRA.Game.csproj | 1 - OpenRA.Mods.Common/OpenRA.Mods.Common.csproj | 1 + .../SpriteLoaders/TmpTDLoader.cs | 99 +++++++++++++++++++ mods/cnc/mod.yaml | 2 +- mods/ra/mod.yaml | 2 +- 7 files changed, 103 insertions(+), 91 deletions(-) delete mode 100644 OpenRA.Game/FileFormats/TmpTDReader.cs create mode 100644 OpenRA.Mods.Common/SpriteLoaders/TmpTDLoader.cs diff --git a/OpenRA.Game/FileFormats/TmpTDReader.cs b/OpenRA.Game/FileFormats/TmpTDReader.cs deleted file mode 100644 index 44e8ca0872..0000000000 --- a/OpenRA.Game/FileFormats/TmpTDReader.cs +++ /dev/null @@ -1,70 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System.Drawing; -using System.IO; -using OpenRA.Graphics; - -namespace OpenRA.FileFormats -{ - public class TmpTile : ISpriteFrame - { - public Size Size { get; private set; } - public Size FrameSize { get; private set; } - public float2 Offset { get { return float2.Zero; } } - public byte[] Data { get; set; } - public bool DisableExportPadding { get { return false; } } - - public TmpTile(byte[] data, Size size) - { - FrameSize = size; - Data = data; - - if (data == null) - Data = new byte[0]; - else - Size = size; - } - } - - public class TmpTDReader : ISpriteSource - { - public IReadOnlyList Frames { get; private set; } - - public TmpTDReader(Stream s) - { - var width = s.ReadUInt16(); - var height = s.ReadUInt16(); - var size = new Size(width, height); - - s.Position += 8; - var imgStart = s.ReadUInt32(); - s.Position += 8; - var indexEnd = s.ReadInt32(); - var indexStart = s.ReadInt32(); - - s.Position = indexStart; - var count = indexEnd - indexStart; - var tiles = new TmpTile[count]; - Frames = tiles.AsReadOnly(); - var tilesIndex = 0; - foreach (var b in s.ReadBytes(count)) - { - if (b != 255) - { - s.Position = imgStart + b * width * height; - tiles[tilesIndex++] = new TmpTile(s.ReadBytes(width * height), size); - } - else - tiles[tilesIndex++] = new TmpTile(null, size); - } - } - } -} diff --git a/OpenRA.Game/Graphics/SpriteSource.cs b/OpenRA.Game/Graphics/SpriteSource.cs index 8ca32dd6ce..f9c790973f 100644 --- a/OpenRA.Game/Graphics/SpriteSource.cs +++ b/OpenRA.Game/Graphics/SpriteSource.cs @@ -15,21 +15,9 @@ using OpenRA.FileFormats; namespace OpenRA.Graphics { // TODO: Most of this should be moved into the format parsers themselves. - public enum SpriteType { Unknown, ShpD2, TmpTD, TmpTS } + public enum SpriteType { Unknown, ShpD2, TmpTS } public static class SpriteSource { - static bool IsTmpTD(Stream s) - { - var start = s.Position; - - s.Position += 16; - var a = s.ReadUInt32(); - var b = s.ReadUInt32(); - - s.Position = start; - return a == 0 && b == 0x0D1AFFFF; - } - static bool IsTmpTS(Stream s) { var start = s.Position; @@ -93,9 +81,6 @@ namespace OpenRA.Graphics public static SpriteType DetectSpriteType(Stream s) { - if (IsTmpTD(s)) - return SpriteType.TmpTD; - if (IsTmpTS(s)) return SpriteType.TmpTS; @@ -110,8 +95,6 @@ namespace OpenRA.Graphics var type = DetectSpriteType(s); switch (type) { - case SpriteType.TmpTD: - return new TmpTDReader(s); case SpriteType.TmpTS: return new TmpTSReader(s); case SpriteType.ShpD2: diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 9b63f7b96a..1b75b60b4a 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -278,7 +278,6 @@ - diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index d27764c409..4d2c16715a 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -116,6 +116,7 @@ + diff --git a/OpenRA.Mods.Common/SpriteLoaders/TmpTDLoader.cs b/OpenRA.Mods.Common/SpriteLoaders/TmpTDLoader.cs new file mode 100644 index 0000000000..22617faecf --- /dev/null +++ b/OpenRA.Mods.Common/SpriteLoaders/TmpTDLoader.cs @@ -0,0 +1,99 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) + * This file is part of OpenRA, which is free software. It is made + * available to you under the terms of the GNU General Public License + * as published by the Free Software Foundation. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using OpenRA.FileFormats; +using OpenRA.Graphics; + +namespace OpenRA.Mods.Common.SpriteLoaders +{ + public class TmpTDLoader : ISpriteLoader + { + class TmpTDFrame : ISpriteFrame + { + public Size Size { get; private set; } + public Size FrameSize { get; private set; } + public float2 Offset { get { return float2.Zero; } } + public byte[] Data { get; set; } + public bool DisableExportPadding { get { return false; } } + + public TmpTDFrame(byte[] data, Size size) + { + FrameSize = size; + Data = data; + + if (data == null) + Data = new byte[0]; + else + Size = size; + } + } + + bool IsTmpTD(Stream s) + { + var start = s.Position; + + s.Position += 16; + var a = s.ReadUInt32(); + var b = s.ReadUInt32(); + + s.Position = start; + return a == 0 && b == 0x0D1AFFFF; + } + + TmpTDFrame[] ParseFrames(Stream s) + { + var start = s.Position; + var width = s.ReadUInt16(); + var height = s.ReadUInt16(); + var size = new Size(width, height); + + s.Position += 8; + var imgStart = s.ReadUInt32(); + s.Position += 8; + var indexEnd = s.ReadInt32(); + var indexStart = s.ReadInt32(); + + s.Position = indexStart; + var count = indexEnd - indexStart; + var tiles = new TmpTDFrame[count]; + var tilesIndex = 0; + foreach (var b in s.ReadBytes(count)) + { + if (b != 255) + { + s.Position = imgStart + b * width * height; + tiles[tilesIndex++] = new TmpTDFrame(s.ReadBytes(width * height), size); + } + else + tiles[tilesIndex++] = new TmpTDFrame(null, size); + } + + s.Position = start; + return tiles; + } + + public bool TryParseSprite(Stream s, out ISpriteFrame[] frames) + { + if (!IsTmpTD(s)) + { + frames = null; + return false; + } + + frames = ParseFrames(s); + return true; + } + } +} diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index 676a01bd99..9f42c128dd 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -211,4 +211,4 @@ Missions: SupportsMapsFrom: cnc -SpriteFormats: ShpTD, ShpTS, TmpRA \ No newline at end of file +SpriteFormats: ShpTD, TmpTD, ShpTS, TmpRA \ No newline at end of file diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index 51875f95e3..076cc048f8 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -208,4 +208,4 @@ Missions: SupportsMapsFrom: ra -SpriteFormats: ShpTD, TmpRA, ShpTS \ No newline at end of file +SpriteFormats: ShpTD, TmpRA, TmpTD, ShpTS \ No newline at end of file From 533d044755aa6498eed1a547b3512e07a5ffc2ce Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 5 Oct 2014 16:29:30 +1300 Subject: [PATCH 10/15] Move TmpTS sprite loading into Mods.TS. --- OpenRA.Game/FileFormats/TmpTSReader.cs | 76 ------------- OpenRA.Game/Graphics/SpriteSource.cs | 30 +----- OpenRA.Game/OpenRA.Game.csproj | 1 - OpenRA.Mods.TS/OpenRA.Mods.TS.csproj | 1 + OpenRA.Mods.TS/SpriteLoaders/TmpTSLoader.cs | 114 ++++++++++++++++++++ mods/ts/mod.yaml | 2 +- 6 files changed, 117 insertions(+), 107 deletions(-) delete mode 100644 OpenRA.Game/FileFormats/TmpTSReader.cs create mode 100644 OpenRA.Mods.TS/SpriteLoaders/TmpTSLoader.cs diff --git a/OpenRA.Game/FileFormats/TmpTSReader.cs b/OpenRA.Game/FileFormats/TmpTSReader.cs deleted file mode 100644 index 6ad7f6388d..0000000000 --- a/OpenRA.Game/FileFormats/TmpTSReader.cs +++ /dev/null @@ -1,76 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System.Collections.Generic; -using System.Drawing; -using System.IO; -using OpenRA.Graphics; - -namespace OpenRA.FileFormats -{ - public class TmpTSTile : ISpriteFrame - { - public Size Size { get; private set; } - public Size FrameSize { get { return Size; } } - public float2 Offset { get { return float2.Zero; } } - public byte[] Data { get; set; } - public bool DisableExportPadding { get { return false; } } - - public TmpTSTile(Stream s, Size size) - { - Size = size; - - // Ignore tile header for now - s.Position += 52; - - Data = new byte[size.Width * size.Height]; - - // Unpack tile data - var width = 4; - for (var i = 0; i < size.Height; i++) - { - var start = i * size.Width + (size.Width - width) / 2; - for (var j = 0; j < width; j++) - Data[start + j] = s.ReadUInt8(); - - width += (i < size.Height / 2 - 1 ? 1 : -1) * 4; - } - - // Ignore Z-data for now - // Ignore extra data for now - } - } - - public class TmpTSReader : ISpriteSource - { - public IReadOnlyList Frames { get; private set; } - - public TmpTSReader(Stream s) - { - var templateWidth = s.ReadUInt32(); - var templateHeight = s.ReadUInt32(); - var tileWidth = s.ReadInt32(); - var tileHeight = s.ReadInt32(); - var size = new Size(tileWidth, tileHeight); - var offsets = new uint[templateWidth * templateHeight]; - for (var i = 0; i < offsets.Length; i++) - offsets[i] = s.ReadUInt32(); - - var tiles = new List(); - for (var i = 0; i < offsets.Length; i++) - { - s.Position = offsets[i]; - tiles.Add(new TmpTSTile(s, size)); - } - - Frames = tiles.ToArray().AsReadOnly(); - } - } -} diff --git a/OpenRA.Game/Graphics/SpriteSource.cs b/OpenRA.Game/Graphics/SpriteSource.cs index f9c790973f..69e1ec67a1 100644 --- a/OpenRA.Game/Graphics/SpriteSource.cs +++ b/OpenRA.Game/Graphics/SpriteSource.cs @@ -15,32 +15,9 @@ using OpenRA.FileFormats; namespace OpenRA.Graphics { // TODO: Most of this should be moved into the format parsers themselves. - public enum SpriteType { Unknown, ShpD2, TmpTS } + public enum SpriteType { Unknown, ShpD2 } public static class SpriteSource { - static bool IsTmpTS(Stream s) - { - var start = s.Position; - s.Position += 8; - var sx = s.ReadUInt32(); - var sy = s.ReadUInt32(); - - // Find the first frame - var offset = s.ReadUInt32(); - - if (offset > s.Length - 52) - { - s.Position = start; - return false; - } - - s.Position = offset + 12; - var test = s.ReadUInt32(); - - s.Position = start; - return test == sx * sy / 2 + 52; - } - static bool IsShpD2(Stream s) { var start = s.Position; @@ -81,9 +58,6 @@ namespace OpenRA.Graphics public static SpriteType DetectSpriteType(Stream s) { - if (IsTmpTS(s)) - return SpriteType.TmpTS; - if (IsShpD2(s)) return SpriteType.ShpD2; @@ -95,8 +69,6 @@ namespace OpenRA.Graphics var type = DetectSpriteType(s); switch (type) { - case SpriteType.TmpTS: - return new TmpTSReader(s); case SpriteType.ShpD2: return new ShpD2Reader(s); case SpriteType.Unknown: diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 1b75b60b4a..15fceb5035 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -278,7 +278,6 @@ - diff --git a/OpenRA.Mods.TS/OpenRA.Mods.TS.csproj b/OpenRA.Mods.TS/OpenRA.Mods.TS.csproj index 9650418c9d..4dc1e5f23c 100644 --- a/OpenRA.Mods.TS/OpenRA.Mods.TS.csproj +++ b/OpenRA.Mods.TS/OpenRA.Mods.TS.csproj @@ -56,6 +56,7 @@ +