Changes ISpriteSource.Frames to be of type IReadOnlyList<ISpriteFrame>.
- Updated implementations to return a ReadOnlyList around an array (to reduce wasted memory from exposing lists or lazy enumerators around lists). - Protect non-public ISpriteFrame classes by making them inner classes to prevent casting. - Added an AsReadOnly extension method for lists.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#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
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -101,7 +101,7 @@ namespace OpenRA.Editor
|
|||||||
}
|
}
|
||||||
|
|
||||||
bitmap.UnlockBits(data);
|
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 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#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
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -20,9 +20,9 @@ namespace OpenRA.Editor
|
|||||||
{
|
{
|
||||||
public class TileSetRenderer
|
public class TileSetRenderer
|
||||||
{
|
{
|
||||||
|
public readonly int TileSize;
|
||||||
public TileSet TileSet;
|
public TileSet TileSet;
|
||||||
Dictionary<ushort, List<byte[]>> templates;
|
Dictionary<ushort, List<byte[]>> templates;
|
||||||
public readonly int TileSize;
|
|
||||||
|
|
||||||
// Extract a square tile that the editor can render
|
// Extract a square tile that the editor can render
|
||||||
byte[] ExtractSquareTile(ISpriteFrame frame)
|
byte[] ExtractSquareTile(ISpriteFrame frame)
|
||||||
@@ -61,7 +61,7 @@ namespace OpenRA.Editor
|
|||||||
if (frames != null)
|
if (frames != null)
|
||||||
{
|
{
|
||||||
var ret = new List<byte[]>();
|
var ret = new List<byte[]>();
|
||||||
var srcFrames = source.Frames.ToArray();
|
var srcFrames = source.Frames;
|
||||||
foreach (var i in frames)
|
foreach (var i in frames)
|
||||||
ret.Add(ExtractSquareTile(srcFrames[i]));
|
ret.Add(ExtractSquareTile(srcFrames[i]));
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#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
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -15,63 +15,66 @@ using OpenRA.Graphics;
|
|||||||
|
|
||||||
namespace OpenRA.FileFormats
|
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
|
public class R8Reader : ISpriteSource
|
||||||
{
|
{
|
||||||
readonly List<ISpriteFrame> frames = new List<ISpriteFrame>();
|
class R8Image : ISpriteFrame
|
||||||
public IEnumerable<ISpriteFrame> Frames { get { return frames; } }
|
{
|
||||||
|
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<ISpriteFrame> Frames { get; private set; }
|
||||||
public bool CacheWhenLoadingTileset { get { return true; } }
|
public bool CacheWhenLoadingTileset { get { return true; } }
|
||||||
|
|
||||||
public readonly int ImageCount;
|
public readonly int ImageCount;
|
||||||
public R8Reader(Stream stream)
|
public R8Reader(Stream stream)
|
||||||
{
|
{
|
||||||
|
var frames = new List<R8Image>();
|
||||||
while (stream.Position < stream.Length)
|
while (stream.Position < stream.Length)
|
||||||
{
|
{
|
||||||
frames.Add(new R8Image(stream));
|
frames.Add(new R8Image(stream));
|
||||||
ImageCount++;
|
ImageCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Frames = frames.ToArray().AsReadOnly();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#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
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -9,83 +9,81 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
|
|
||||||
namespace OpenRA.FileFormats
|
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
|
public class ShpD2Reader : ISpriteSource
|
||||||
{
|
{
|
||||||
readonly List<ISpriteFrame> frames = new List<ISpriteFrame>();
|
[Flags] enum FormatFlags : int
|
||||||
public IEnumerable<ISpriteFrame> Frames { get { return frames; } }
|
{
|
||||||
|
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<ISpriteFrame> Frames { get; private set; }
|
||||||
public bool CacheWhenLoadingTileset { get { return false; } }
|
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||||
|
|
||||||
public ShpD2Reader(Stream s)
|
public ShpD2Reader(Stream s)
|
||||||
@@ -103,10 +101,12 @@ namespace OpenRA.FileFormats
|
|||||||
for (var i = 0; i < imageCount + 1; i++)
|
for (var i = 0; i < imageCount + 1; i++)
|
||||||
offsets[i] = (twoByteOffset ? s.ReadUInt16() : s.ReadUInt32()) + 2;
|
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];
|
s.Position = offsets[i];
|
||||||
frames.Add(new Frame(s));
|
frames[i] = new Frame(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#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
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -17,50 +17,49 @@ using OpenRA.Graphics;
|
|||||||
|
|
||||||
namespace OpenRA.FileFormats
|
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
|
public class ShpReader : ISpriteSource
|
||||||
{
|
{
|
||||||
readonly List<ImageHeader> headers = new List<ImageHeader>();
|
enum Format { Format20 = 0x20, Format40 = 0x40, Format80 = 0x80 }
|
||||||
Lazy<IEnumerable<ISpriteFrame>> spriteFrames;
|
|
||||||
public IEnumerable<ISpriteFrame> Frames { get { return spriteFrames.Value; } }
|
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<ISpriteFrame> Frames { get; private set; }
|
||||||
public bool CacheWhenLoadingTileset { get { return false; } }
|
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||||
public readonly Size Size;
|
public readonly Size Size;
|
||||||
|
|
||||||
@@ -79,8 +78,10 @@ namespace OpenRA.FileFormats
|
|||||||
Size = new Size(width, height);
|
Size = new Size(width, height);
|
||||||
|
|
||||||
stream.Position += 4;
|
stream.Position += 4;
|
||||||
for (var i = 0; i < imageCount; i++)
|
var headers = new ImageHeader[imageCount];
|
||||||
headers.Add(new ImageHeader(stream, this));
|
Frames = headers.AsReadOnly();
|
||||||
|
for (var i = 0; i < headers.Length; i++)
|
||||||
|
headers[i] = new ImageHeader(stream, this);
|
||||||
|
|
||||||
// Skip eof and zero headers
|
// Skip eof and zero headers
|
||||||
stream.Position += 16;
|
stream.Position += 16;
|
||||||
@@ -91,7 +92,6 @@ namespace OpenRA.FileFormats
|
|||||||
var h = headers[i];
|
var h = headers[i];
|
||||||
if (h.Format == Format.Format20)
|
if (h.Format == Format.Format20)
|
||||||
h.RefImage = headers[i - 1];
|
h.RefImage = headers[i - 1];
|
||||||
|
|
||||||
else if (h.Format == Format.Format40 && !offsets.TryGetValue(h.RefOffset, out h.RefImage))
|
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));
|
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)
|
foreach (var h in headers)
|
||||||
Decompress(h);
|
Decompress(h);
|
||||||
|
|
||||||
spriteFrames = Exts.Lazy(() => headers.Cast<ISpriteFrame>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decompress(ImageHeader h)
|
void Decompress(ImageHeader h)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#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
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -8,47 +8,42 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
|
|
||||||
namespace OpenRA.FileFormats
|
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
|
public class ShpTSReader : ISpriteSource
|
||||||
{
|
{
|
||||||
readonly List<FrameHeader> frames = new List<FrameHeader>();
|
class FrameHeader : ISpriteFrame
|
||||||
Lazy<IEnumerable<ISpriteFrame>> spriteFrames;
|
{
|
||||||
public IEnumerable<ISpriteFrame> Frames { get { return spriteFrames.Value; } }
|
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<ISpriteFrame> Frames { get; private set; }
|
||||||
public bool CacheWhenLoadingTileset { get { return false; } }
|
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||||
|
|
||||||
public ShpTSReader(Stream stream)
|
public ShpTSReader(Stream stream)
|
||||||
@@ -59,8 +54,10 @@ namespace OpenRA.FileFormats
|
|||||||
var size = new Size(width, height);
|
var size = new Size(width, height);
|
||||||
var frameCount = stream.ReadUInt16();
|
var frameCount = stream.ReadUInt16();
|
||||||
|
|
||||||
for (var i = 0; i < frameCount; i++)
|
var frames = new FrameHeader[frameCount];
|
||||||
frames.Add(new FrameHeader(stream, size));
|
Frames = frames.AsReadOnly();
|
||||||
|
for (var i = 0; i < frames.Length; i++)
|
||||||
|
frames[i] = new FrameHeader(stream, size);
|
||||||
|
|
||||||
for (var i = 0; i < frameCount; i++)
|
for (var i = 0; i < frameCount; i++)
|
||||||
{
|
{
|
||||||
@@ -70,14 +67,16 @@ namespace OpenRA.FileFormats
|
|||||||
|
|
||||||
stream.Position = f.FileOffset;
|
stream.Position = f.FileOffset;
|
||||||
|
|
||||||
|
var frameSize = f.Size.Width * f.Size.Height;
|
||||||
|
|
||||||
// Uncompressed
|
// Uncompressed
|
||||||
if (f.Format == 1 || f.Format == 0)
|
if (f.Format == 1 || f.Format == 0)
|
||||||
f.Data = stream.ReadBytes(f.Size.Width * f.Size.Height);
|
f.Data = stream.ReadBytes(frameSize);
|
||||||
|
|
||||||
// Uncompressed scanlines
|
// Uncompressed scanlines
|
||||||
else if (f.Format == 2)
|
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++)
|
for (var j = 0; j < f.Size.Height; j++)
|
||||||
{
|
{
|
||||||
var length = stream.ReadUInt16() - 2;
|
var length = stream.ReadUInt16() - 2;
|
||||||
@@ -89,17 +88,15 @@ namespace OpenRA.FileFormats
|
|||||||
// RLE-zero compressed scanlines
|
// RLE-zero compressed scanlines
|
||||||
else if (f.Format == 3)
|
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++)
|
for (var j = 0; j < f.Size.Height; j++)
|
||||||
{
|
{
|
||||||
var length = stream.ReadUInt16() - 2;
|
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<ISpriteFrame>());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#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
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -8,7 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
@@ -17,8 +16,7 @@ namespace OpenRA.FileFormats
|
|||||||
{
|
{
|
||||||
public class TmpRAReader : ISpriteSource
|
public class TmpRAReader : ISpriteSource
|
||||||
{
|
{
|
||||||
readonly List<ISpriteFrame> tiles = new List<ISpriteFrame>();
|
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
|
||||||
public IEnumerable<ISpriteFrame> Frames { get { return tiles; } }
|
|
||||||
public bool CacheWhenLoadingTileset { get { return false; } }
|
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||||
|
|
||||||
public TmpRAReader(Stream s)
|
public TmpRAReader(Stream s)
|
||||||
@@ -35,15 +33,19 @@ namespace OpenRA.FileFormats
|
|||||||
var indexStart = s.ReadInt32();
|
var indexStart = s.ReadInt32();
|
||||||
|
|
||||||
s.Position = indexStart;
|
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)
|
if (b != 255)
|
||||||
{
|
{
|
||||||
s.Position = imgStart + b * width * height;
|
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
|
else
|
||||||
tiles.Add(new TmpTile(null, size));
|
tiles[tilesIndex++] = new TmpTile(null, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#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
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -8,7 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
@@ -36,8 +35,7 @@ namespace OpenRA.FileFormats
|
|||||||
|
|
||||||
public class TmpTDReader : ISpriteSource
|
public class TmpTDReader : ISpriteSource
|
||||||
{
|
{
|
||||||
readonly List<ISpriteFrame> tiles = new List<ISpriteFrame>();
|
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
|
||||||
public IEnumerable<ISpriteFrame> Frames { get { return tiles; } }
|
|
||||||
public bool CacheWhenLoadingTileset { get { return false; } }
|
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||||
|
|
||||||
public TmpTDReader(Stream s)
|
public TmpTDReader(Stream s)
|
||||||
@@ -53,15 +51,19 @@ namespace OpenRA.FileFormats
|
|||||||
var indexStart = s.ReadInt32();
|
var indexStart = s.ReadInt32();
|
||||||
|
|
||||||
s.Position = indexStart;
|
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)
|
if (b != 255)
|
||||||
{
|
{
|
||||||
s.Position = imgStart + b * width * height;
|
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
|
else
|
||||||
tiles.Add(new TmpTile(null, size));
|
tiles[tilesIndex++] = new TmpTile(null, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#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
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -39,7 +39,7 @@ namespace OpenRA.FileFormats
|
|||||||
for (var j = 0; j < width; j++)
|
for (var j = 0; j < width; j++)
|
||||||
Data[start + j] = s.ReadUInt8();
|
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
|
// Ignore Z-data for now
|
||||||
@@ -49,8 +49,7 @@ namespace OpenRA.FileFormats
|
|||||||
|
|
||||||
public class TmpTSReader : ISpriteSource
|
public class TmpTSReader : ISpriteSource
|
||||||
{
|
{
|
||||||
readonly List<ISpriteFrame> tiles = new List<ISpriteFrame>();
|
public IReadOnlyList<ISpriteFrame> Frames { get; private set; }
|
||||||
public IEnumerable<ISpriteFrame> Frames { get { return tiles; } }
|
|
||||||
public bool CacheWhenLoadingTileset { get { return false; } }
|
public bool CacheWhenLoadingTileset { get { return false; } }
|
||||||
|
|
||||||
public TmpTSReader(Stream s)
|
public TmpTSReader(Stream s)
|
||||||
@@ -64,11 +63,14 @@ namespace OpenRA.FileFormats
|
|||||||
for (var i = 0; i < offsets.Length; i++)
|
for (var i = 0; i < offsets.Length; i++)
|
||||||
offsets[i] = s.ReadUInt32();
|
offsets[i] = s.ReadUInt32();
|
||||||
|
|
||||||
|
var tiles = new List<TmpTSTile>();
|
||||||
for (var i = 0; i < offsets.Length; i++)
|
for (var i = 0; i < offsets.Length; i++)
|
||||||
{
|
{
|
||||||
s.Position = offsets[i];
|
s.Position = offsets[i];
|
||||||
tiles.Add(new TmpTSTile(s, size));
|
tiles.Add(new TmpTSTile(s, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Frames = tiles.ToArray().AsReadOnly();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#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
|
* 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
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -8,7 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using OpenRA.FileFormats;
|
using OpenRA.FileFormats;
|
||||||
@@ -25,8 +24,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public interface ISpriteSource
|
public interface ISpriteSource
|
||||||
{
|
{
|
||||||
// TODO: Change this to IReadOnlyList so users don't need to call .ToArray()
|
IReadOnlyList<ISpriteFrame> Frames { get; }
|
||||||
IEnumerable<ISpriteFrame> Frames { get; }
|
|
||||||
bool CacheWhenLoadingTileset { get; }
|
bool CacheWhenLoadingTileset { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,20 @@ namespace OpenRA
|
|||||||
/// duplicate it but provide a compatible interface that can be replaced
|
/// duplicate it but provide a compatible interface that can be replaced
|
||||||
/// when we switch to .NET 4.5 or higher.
|
/// when we switch to .NET 4.5 or higher.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public interface IReadOnlyList<T> : IEnumerable<T>
|
public interface IReadOnlyList<out T> : IEnumerable<T>
|
||||||
{
|
{
|
||||||
int Count { get; }
|
int Count { get; }
|
||||||
T this[int index] { get; }
|
T this[int index] { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ReadOnlyList
|
||||||
|
{
|
||||||
|
public static IReadOnlyList<T> AsReadOnly<T>(this IList<T> list)
|
||||||
|
{
|
||||||
|
return list as IReadOnlyList<T> ?? new ReadOnlyList<T>(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A minimal read only list for .NET 4 implemented as a wrapper
|
/// A minimal read only list for .NET 4 implemented as a wrapper
|
||||||
/// around an IList.
|
/// around an IList.
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ namespace OpenRA.Utility
|
|||||||
{
|
{
|
||||||
var srcImage = ShpReader.Load(args[1]);
|
var srcImage = ShpReader.Load(args[1]);
|
||||||
|
|
||||||
var srcFrames = srcImage.Frames.ToArray();
|
var srcFrames = srcImage.Frames;
|
||||||
var destFrames = srcImage.Frames.ToArray();
|
var destFrames = srcImage.Frames.ToArray();
|
||||||
|
|
||||||
for (var z = 3; z < args.Length - 2; z += 3)
|
for (var z = 3; z < args.Length - 2; z += 3)
|
||||||
|
|||||||
Reference in New Issue
Block a user