From d658643b73937bc601a4bf21a28b59d2d19f8f57 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 5 Oct 2014 15:25:39 +1300 Subject: [PATCH] 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