diff --git a/OpenRA.Editor/RenderUtils.cs b/OpenRA.Editor/RenderUtils.cs index ca7c0ca71c..e9d001406f 100644 --- a/OpenRA.Editor/RenderUtils.cs +++ b/OpenRA.Editor/RenderUtils.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * 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, @@ -101,7 +101,7 @@ namespace OpenRA.Editor } bitmap.UnlockBits(data); - return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.Frames.Count() - 1 }; + return new ResourceTemplate { Bitmap = bitmap, Info = info, Value = shp.Frames.Count - 1 }; } } } diff --git a/OpenRA.Editor/TileSetRenderer.cs b/OpenRA.Editor/TileSetRenderer.cs index 06db47d678..effb2258f0 100644 --- a/OpenRA.Editor/TileSetRenderer.cs +++ b/OpenRA.Editor/TileSetRenderer.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * 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, @@ -20,9 +20,9 @@ namespace OpenRA.Editor { public class TileSetRenderer { + public readonly int TileSize; public TileSet TileSet; Dictionary> templates; - public readonly int TileSize; // Extract a square tile that the editor can render byte[] ExtractSquareTile(ISpriteFrame frame) @@ -61,7 +61,7 @@ namespace OpenRA.Editor if (frames != null) { var ret = new List(); - var srcFrames = source.Frames.ToArray(); + var srcFrames = source.Frames; foreach (var i in frames) ret.Add(ExtractSquareTile(srcFrames[i])); diff --git a/OpenRA.Game/FileFormats/R8Reader.cs b/OpenRA.Game/FileFormats/R8Reader.cs index a768c78f4b..0db3ff57ff 100644 --- a/OpenRA.Game/FileFormats/R8Reader.cs +++ b/OpenRA.Game/FileFormats/R8Reader.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * 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, @@ -15,63 +15,66 @@ using OpenRA.Graphics; namespace OpenRA.FileFormats { - class R8Image : ISpriteFrame - { - public Size Size { get; private set; } - public Size FrameSize { get; private set; } - public float2 Offset { get; private set; } - public byte[] Data { get; set; } - - public R8Image(Stream s) - { - // Scan forward until we find some data - var type = s.ReadUInt8(); - while (type == 0) - type = s.ReadUInt8(); - - var width = s.ReadInt32(); - var height = s.ReadInt32(); - var x = s.ReadInt32(); - var y = s.ReadInt32(); - - Size = new Size(width, height); - Offset = new int2(width/2 - x, height/2 - y); - - /*var imageOffset = */s.ReadInt32(); - var paletteOffset = s.ReadInt32(); - var bpp = s.ReadUInt8(); - if (bpp != 8) - throw new InvalidDataException("Error: {0} bits per pixel are not supported.".F(bpp)); - - var frameHeight = s.ReadUInt8(); - var frameWidth = s.ReadUInt8(); - FrameSize = new Size(frameWidth, frameHeight); - - // Skip alignment byte - s.ReadUInt8(); - - Data = s.ReadBytes(width*height); - - // Ignore palette - if (type == 1 && paletteOffset != 0) - s.Seek(520, SeekOrigin.Current); - } - } - public class R8Reader : ISpriteSource { - readonly List frames = new List(); - public IEnumerable Frames { get { return frames; } } + class R8Image : ISpriteFrame + { + public Size Size { get; private set; } + public Size FrameSize { get; private set; } + public float2 Offset { get; private set; } + public byte[] Data { get; set; } + + public R8Image(Stream s) + { + // Scan forward until we find some data + var type = s.ReadUInt8(); + while (type == 0) + type = s.ReadUInt8(); + + var width = s.ReadInt32(); + var height = s.ReadInt32(); + var x = s.ReadInt32(); + var y = s.ReadInt32(); + + Size = new Size(width, height); + Offset = new int2(width / 2 - x, height / 2 - y); + + /*var imageOffset = */ + s.ReadInt32(); + var paletteOffset = s.ReadInt32(); + var bpp = s.ReadUInt8(); + if (bpp != 8) + throw new InvalidDataException("Error: {0} bits per pixel are not supported.".F(bpp)); + + var frameHeight = s.ReadUInt8(); + var frameWidth = s.ReadUInt8(); + FrameSize = new Size(frameWidth, frameHeight); + + // Skip alignment byte + s.ReadUInt8(); + + Data = s.ReadBytes(width * height); + + // Ignore palette + if (type == 1 && paletteOffset != 0) + s.Seek(520, SeekOrigin.Current); + } + } + + public IReadOnlyList Frames { get; private set; } public bool CacheWhenLoadingTileset { get { return true; } } public readonly int ImageCount; public R8Reader(Stream stream) { + var frames = new List(); while (stream.Position < stream.Length) { frames.Add(new R8Image(stream)); ImageCount++; } + + Frames = frames.ToArray().AsReadOnly(); } } } diff --git a/OpenRA.Game/FileFormats/ShpD2Reader.cs b/OpenRA.Game/FileFormats/ShpD2Reader.cs index 979e11f98e..dca7a888d6 100644 --- a/OpenRA.Game/FileFormats/ShpD2Reader.cs +++ b/OpenRA.Game/FileFormats/ShpD2Reader.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * 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, @@ -9,83 +9,81 @@ #endregion using System; -using System.Collections.Generic; using System.Drawing; using System.IO; using OpenRA.Graphics; namespace OpenRA.FileFormats { - [Flags] enum FormatFlags : int - { - PaletteTable = 1, - SkipFormat80 = 2, - VariableLengthTable = 4 - } - - class Frame : 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 Frame(Stream s) - { - var flags = (FormatFlags)s.ReadUInt16(); - s.Position += 1; - var width = s.ReadUInt16(); - var height = s.ReadUInt8(); - Size = new Size(width, height); - - // Subtract header size - var dataLeft = s.ReadUInt16() - 10; - var dataSize = s.ReadUInt16(); - - byte[] table; - if ((flags & FormatFlags.PaletteTable) != 0) - { - var n = (flags & FormatFlags.VariableLengthTable) != 0 ? s.ReadUInt8() : (byte)16; - table = new byte[n]; - for (var i = 0; i < n; i++) - table[i] = s.ReadUInt8(); - - dataLeft -= n; - } - else - { - table = new byte[256]; - for (var i = 0; i < 256; i++) - table[i] = (byte)i; - table[1] = 0x7f; - table[2] = 0x7e; - table[3] = 0x7d; - table[4] = 0x7c; - } - - Data = new byte[width * height]; - - // Decode image data - var compressed = s.ReadBytes(dataLeft); - if ((flags & FormatFlags.SkipFormat80) == 0) - { - var temp = new byte[dataSize]; - Format80.DecodeInto(compressed, temp); - compressed = temp; - } - - Format2.DecodeInto(compressed, Data, 0); - - // Lookup values in lookup table - for (var j = 0; j < Data.Length; j++) - Data[j] = table[Data[j]]; - } - } - public class ShpD2Reader : ISpriteSource { - readonly List frames = new List(); - public IEnumerable Frames { get { return frames; } } + [Flags] enum FormatFlags : int + { + PaletteTable = 1, + SkipFormat80 = 2, + VariableLengthTable = 4 + } + + class Frame : 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 Frame(Stream s) + { + var flags = (FormatFlags)s.ReadUInt16(); + s.Position += 1; + var width = s.ReadUInt16(); + var height = s.ReadUInt8(); + Size = new Size(width, height); + + // Subtract header size + var dataLeft = s.ReadUInt16() - 10; + var dataSize = s.ReadUInt16(); + + byte[] table; + if ((flags & FormatFlags.PaletteTable) != 0) + { + var n = (flags & FormatFlags.VariableLengthTable) != 0 ? s.ReadUInt8() : (byte)16; + table = new byte[n]; + for (var i = 0; i < n; i++) + table[i] = s.ReadUInt8(); + + dataLeft -= n; + } + else + { + table = new byte[256]; + for (var i = 0; i < 256; i++) + table[i] = (byte)i; + table[1] = 0x7f; + table[2] = 0x7e; + table[3] = 0x7d; + table[4] = 0x7c; + } + + Data = new byte[width * height]; + + // Decode image data + var compressed = s.ReadBytes(dataLeft); + if ((flags & FormatFlags.SkipFormat80) == 0) + { + var temp = new byte[dataSize]; + Format80.DecodeInto(compressed, temp); + compressed = temp; + } + + Format2.DecodeInto(compressed, Data, 0); + + // Lookup values in lookup table + for (var j = 0; j < Data.Length; j++) + Data[j] = table[Data[j]]; + } + } + + public IReadOnlyList Frames { get; private set; } public bool CacheWhenLoadingTileset { get { return false; } } public ShpD2Reader(Stream s) @@ -103,10 +101,12 @@ namespace OpenRA.FileFormats for (var i = 0; i < imageCount + 1; i++) offsets[i] = (twoByteOffset ? s.ReadUInt16() : s.ReadUInt32()) + 2; - for (var i = 0; i < imageCount; i++) + var frames = new Frame[imageCount]; + Frames = frames.AsReadOnly(); + for (var i = 0; i < frames.Length; i++) { s.Position = offsets[i]; - frames.Add(new Frame(s)); + frames[i] = new Frame(s); } } } diff --git a/OpenRA.Game/FileFormats/ShpReader.cs b/OpenRA.Game/FileFormats/ShpReader.cs index 0fb933acdb..0d7004cca5 100644 --- a/OpenRA.Game/FileFormats/ShpReader.cs +++ b/OpenRA.Game/FileFormats/ShpReader.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * 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, @@ -17,50 +17,49 @@ using OpenRA.Graphics; namespace OpenRA.FileFormats { - enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 } - - class ImageHeader : ISpriteFrame - { - public Size Size { get { return reader.Size; } } - public Size FrameSize { get { return reader.Size; } } - public float2 Offset { get { return float2.Zero; } } - public byte[] Data { get; set; } - - public uint FileOffset; - public Format Format; - - public uint RefOffset; - public Format RefFormat; - public ImageHeader RefImage; - - ShpReader reader; - // Used by ShpWriter - public ImageHeader() { } - - public ImageHeader(Stream stream, ShpReader reader) - { - this.reader = reader; - var data = stream.ReadUInt32(); - FileOffset = data & 0xffffff; - Format = (Format)(data >> 24); - - RefOffset = stream.ReadUInt16(); - RefFormat = (Format)stream.ReadUInt16(); - } - - public void WriteTo(BinaryWriter writer) - { - writer.Write(FileOffset | ((uint)Format << 24)); - writer.Write((ushort)RefOffset); - writer.Write((ushort)RefFormat); - } - } - public class ShpReader : ISpriteSource { - readonly List headers = new List(); - Lazy> spriteFrames; - public IEnumerable Frames { get { return spriteFrames.Value; } } + enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 } + + class ImageHeader : ISpriteFrame + { + public Size Size { get { return reader.Size; } } + public Size FrameSize { get { return reader.Size; } } + public float2 Offset { get { return float2.Zero; } } + public byte[] Data { get; set; } + + public uint FileOffset; + public Format Format; + + public uint RefOffset; + public Format RefFormat; + public ImageHeader RefImage; + + ShpReader reader; + + // Used by ShpWriter + public ImageHeader() { } + + public ImageHeader(Stream stream, ShpReader reader) + { + this.reader = reader; + var data = stream.ReadUInt32(); + FileOffset = data & 0xffffff; + Format = (Format)(data >> 24); + + RefOffset = stream.ReadUInt16(); + RefFormat = (Format)stream.ReadUInt16(); + } + + public void WriteTo(BinaryWriter writer) + { + writer.Write(FileOffset | ((uint)Format << 24)); + writer.Write((ushort)RefOffset); + writer.Write((ushort)RefFormat); + } + } + + public IReadOnlyList Frames { get; private set; } public bool CacheWhenLoadingTileset { get { return false; } } public readonly Size Size; @@ -79,8 +78,10 @@ namespace OpenRA.FileFormats Size = new Size(width, height); stream.Position += 4; - for (var i = 0; i < imageCount; i++) - headers.Add(new ImageHeader(stream, this)); + var headers = new ImageHeader[imageCount]; + Frames = headers.AsReadOnly(); + for (var i = 0; i < headers.Length; i++) + headers[i] = new ImageHeader(stream, this); // Skip eof and zero headers stream.Position += 16; @@ -91,7 +92,6 @@ namespace OpenRA.FileFormats var h = headers[i]; if (h.Format == Format.Format20) h.RefImage = headers[i - 1]; - else if (h.Format == Format.Format40 && !offsets.TryGetValue(h.RefOffset, out h.RefImage)) throw new InvalidDataException("Reference doesnt point to image data {0}->{1}".F(h.FileOffset, h.RefOffset)); } @@ -101,8 +101,6 @@ namespace OpenRA.FileFormats foreach (var h in headers) Decompress(h); - - spriteFrames = Exts.Lazy(() => headers.Cast()); } void Decompress(ImageHeader h) diff --git a/OpenRA.Game/FileFormats/ShpTSReader.cs b/OpenRA.Game/FileFormats/ShpTSReader.cs index 2b1704711b..f5200947c7 100644 --- a/OpenRA.Game/FileFormats/ShpTSReader.cs +++ b/OpenRA.Game/FileFormats/ShpTSReader.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * 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, @@ -8,47 +8,42 @@ */ #endregion -using System; -using System.Collections.Generic; using System.Drawing; using System.IO; -using System.Linq; using OpenRA.Graphics; namespace OpenRA.FileFormats { - class FrameHeader : ISpriteFrame - { - public Size Size { get; private set; } - public Size FrameSize { get; private set; } - public float2 Offset { get; private set; } - public byte[] Data { get; set; } - - public readonly uint FileOffset; - public readonly byte Format; - - public FrameHeader(Stream stream, Size frameSize) - { - var x = stream.ReadUInt16(); - var y = stream.ReadUInt16(); - var width = stream.ReadUInt16(); - var height = stream.ReadUInt16(); - - Offset = new float2(x + 0.5f * (width - frameSize.Width), y + 0.5f * (height - frameSize.Height)); - Size = new Size(width, height); - FrameSize = frameSize; - - Format = stream.ReadUInt8(); - stream.Position += 11; - FileOffset = stream.ReadUInt32(); - } - } - public class ShpTSReader : ISpriteSource { - readonly List frames = new List(); - Lazy> spriteFrames; - public IEnumerable Frames { get { return spriteFrames.Value; } } + class FrameHeader : ISpriteFrame + { + public Size Size { get; private set; } + public Size FrameSize { get; private set; } + public float2 Offset { get; private set; } + public byte[] Data { get; set; } + + public readonly uint FileOffset; + public readonly byte Format; + + public FrameHeader(Stream stream, Size frameSize) + { + var x = stream.ReadUInt16(); + var y = stream.ReadUInt16(); + var width = stream.ReadUInt16(); + var height = stream.ReadUInt16(); + + Offset = new float2(x + 0.5f * (width - frameSize.Width), y + 0.5f * (height - frameSize.Height)); + Size = new Size(width, height); + FrameSize = frameSize; + + Format = stream.ReadUInt8(); + stream.Position += 11; + FileOffset = stream.ReadUInt32(); + } + } + + public IReadOnlyList Frames { get; private set; } public bool CacheWhenLoadingTileset { get { return false; } } public ShpTSReader(Stream stream) @@ -59,8 +54,10 @@ namespace OpenRA.FileFormats var size = new Size(width, height); var frameCount = stream.ReadUInt16(); - for (var i = 0; i < frameCount; i++) - frames.Add(new FrameHeader(stream, size)); + var frames = new FrameHeader[frameCount]; + Frames = frames.AsReadOnly(); + for (var i = 0; i < frames.Length; i++) + frames[i] = new FrameHeader(stream, size); for (var i = 0; i < frameCount; i++) { @@ -70,14 +67,16 @@ namespace OpenRA.FileFormats stream.Position = f.FileOffset; + var frameSize = f.Size.Width * f.Size.Height; + // Uncompressed if (f.Format == 1 || f.Format == 0) - f.Data = stream.ReadBytes(f.Size.Width * f.Size.Height); + f.Data = stream.ReadBytes(frameSize); // Uncompressed scanlines else if (f.Format == 2) { - f.Data = new byte[f.Size.Width * f.Size.Height]; + f.Data = new byte[frameSize]; for (var j = 0; j < f.Size.Height; j++) { var length = stream.ReadUInt16() - 2; @@ -89,17 +88,15 @@ namespace OpenRA.FileFormats // RLE-zero compressed scanlines else if (f.Format == 3) { - f.Data = new byte[f.Size.Width * f.Size.Height]; - + f.Data = new byte[frameSize]; for (var j = 0; j < f.Size.Height; j++) { var length = stream.ReadUInt16() - 2; - Format2.DecodeInto(stream.ReadBytes(length), f.Data, j * f.Size.Width); + var offset = f.Size.Width * j; + Format2.DecodeInto(stream.ReadBytes(length), f.Data, offset); } } } - - spriteFrames = Exts.Lazy(() => frames.Cast()); } } } \ No newline at end of file diff --git a/OpenRA.Game/FileFormats/TmpRAReader.cs b/OpenRA.Game/FileFormats/TmpRAReader.cs index 6fc1776977..5b8f4b520e 100644 --- a/OpenRA.Game/FileFormats/TmpRAReader.cs +++ b/OpenRA.Game/FileFormats/TmpRAReader.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * 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, @@ -8,7 +8,6 @@ */ #endregion -using System.Collections.Generic; using System.Drawing; using System.IO; using OpenRA.Graphics; @@ -17,8 +16,7 @@ namespace OpenRA.FileFormats { public class TmpRAReader : ISpriteSource { - readonly List tiles = new List(); - public IEnumerable Frames { get { return tiles; } } + public IReadOnlyList Frames { get; private set; } public bool CacheWhenLoadingTileset { get { return false; } } public TmpRAReader(Stream s) @@ -35,15 +33,19 @@ namespace OpenRA.FileFormats var indexStart = s.ReadInt32(); s.Position = indexStart; - foreach (var b in s.ReadBytes(indexEnd - 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.Add(new TmpTile(s.ReadBytes(width * height), size)); + tiles[tilesIndex++] = new TmpTile(s.ReadBytes(width * height), size); } else - tiles.Add(new TmpTile(null, size)); + tiles[tilesIndex++] = new TmpTile(null, size); } } } diff --git a/OpenRA.Game/FileFormats/TmpTDReader.cs b/OpenRA.Game/FileFormats/TmpTDReader.cs index a461a14782..d0521460d2 100644 --- a/OpenRA.Game/FileFormats/TmpTDReader.cs +++ b/OpenRA.Game/FileFormats/TmpTDReader.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * 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, @@ -8,7 +8,6 @@ */ #endregion -using System.Collections.Generic; using System.Drawing; using System.IO; using OpenRA.Graphics; @@ -36,8 +35,7 @@ namespace OpenRA.FileFormats public class TmpTDReader : ISpriteSource { - readonly List tiles = new List(); - public IEnumerable Frames { get { return tiles; } } + public IReadOnlyList Frames { get; private set; } public bool CacheWhenLoadingTileset { get { return false; } } public TmpTDReader(Stream s) @@ -53,15 +51,19 @@ namespace OpenRA.FileFormats var indexStart = s.ReadInt32(); s.Position = indexStart; - foreach (var b in s.ReadBytes(indexEnd - 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.Add(new TmpTile(s.ReadBytes(width * height), size)); + tiles[tilesIndex++] = new TmpTile(s.ReadBytes(width * height), size); } else - tiles.Add(new TmpTile(null, size)); + tiles[tilesIndex++] = new TmpTile(null, size); } } } diff --git a/OpenRA.Game/FileFormats/TmpTSReader.cs b/OpenRA.Game/FileFormats/TmpTSReader.cs index 7d1b07e962..d405e2d01d 100644 --- a/OpenRA.Game/FileFormats/TmpTSReader.cs +++ b/OpenRA.Game/FileFormats/TmpTSReader.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2013 The OpenRA Developers (see AUTHORS) + * 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, @@ -39,7 +39,7 @@ namespace OpenRA.FileFormats for (var j = 0; j < width; j++) Data[start + j] = s.ReadUInt8(); - width += (i < size.Height / 2 - 1? 1 : -1) * 4; + width += (i < size.Height / 2 - 1 ? 1 : -1) * 4; } // Ignore Z-data for now @@ -49,8 +49,7 @@ namespace OpenRA.FileFormats public class TmpTSReader : ISpriteSource { - readonly List tiles = new List(); - public IEnumerable Frames { get { return tiles; } } + public IReadOnlyList Frames { get; private set; } public bool CacheWhenLoadingTileset { get { return false; } } public TmpTSReader(Stream s) @@ -64,11 +63,14 @@ namespace OpenRA.FileFormats 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 086b7cdee1..ae23aa5501 100644 --- a/OpenRA.Game/Graphics/SpriteSource.cs +++ b/OpenRA.Game/Graphics/SpriteSource.cs @@ -1,6 +1,6 @@ #region Copyright & License Information /* - * Copyright 2007-2011 The OpenRA Developers (see AUTHORS) + * 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, @@ -8,7 +8,6 @@ */ #endregion -using System.Collections.Generic; using System.Drawing; using System.IO; using OpenRA.FileFormats; @@ -25,8 +24,7 @@ namespace OpenRA.Graphics public interface ISpriteSource { - // TODO: Change this to IReadOnlyList so users don't need to call .ToArray() - IEnumerable Frames { get; } + IReadOnlyList Frames { get; } bool CacheWhenLoadingTileset { get; } } diff --git a/OpenRA.Game/Primitives/ReadOnlyList.cs b/OpenRA.Game/Primitives/ReadOnlyList.cs index 38dcd13246..0a7f330b2f 100644 --- a/OpenRA.Game/Primitives/ReadOnlyList.cs +++ b/OpenRA.Game/Primitives/ReadOnlyList.cs @@ -21,12 +21,20 @@ namespace OpenRA /// duplicate it but provide a compatible interface that can be replaced /// when we switch to .NET 4.5 or higher. /// - public interface IReadOnlyList : IEnumerable + public interface IReadOnlyList : IEnumerable { int Count { get; } T this[int index] { get; } } + public static class ReadOnlyList + { + public static IReadOnlyList AsReadOnly(this IList list) + { + return list as IReadOnlyList ?? new ReadOnlyList(list); + } + } + /// /// A minimal read only list for .NET 4 implemented as a wrapper /// around an IList. diff --git a/OpenRA.Utility/Command.cs b/OpenRA.Utility/Command.cs index eedf1c2f48..3146a73c30 100644 --- a/OpenRA.Utility/Command.cs +++ b/OpenRA.Utility/Command.cs @@ -233,7 +233,7 @@ namespace OpenRA.Utility { var srcImage = ShpReader.Load(args[1]); - var srcFrames = srcImage.Frames.ToArray(); + var srcFrames = srcImage.Frames; var destFrames = srcImage.Frames.ToArray(); for (var z = 3; z < args.Length - 2; z += 3)