Files
OpenRA/OpenRA.Mods.TS/SpriteLoaders/TmpTSLoader.cs
Taryn Hill 4ed53c5952 Simplify return statements.
Remove redundant ‘this’.
Remove unused using directives.
Simplify LINQ chains.
Add some trait property descriptions.
Add readonly where viable.
Add fullstops to some yaml descriptions.
2015-04-01 12:33:17 -05:00

159 lines
3.9 KiB
C#

#region Copyright & License Information
/*
* Copyright 2007-2015 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.Drawing;
using System.IO;
using OpenRA.Graphics;
namespace OpenRA.Mods.TS.SpriteLoaders
{
public class TmpTSLoader : ISpriteLoader
{
class TmpTSFrame : ISpriteFrame
{
public Size Size { get; private set; }
public Size FrameSize { get { return Size; } }
public float2 Offset { get; private set; }
public byte[] Data { get; set; }
public bool DisableExportPadding { get { return false; } }
public TmpTSFrame(Stream s, Size size, int u, int v)
{
if (s.Position != 0)
{
Size = size;
// Skip unnecessary header data
s.Position += 20;
// Extra data is specified relative to the top-left of the template
var extraX = s.ReadInt32() - (u - v) * size.Width / 2;
var extraY = s.ReadInt32() - (u + v) * size.Height / 2;
var extraWidth = s.ReadInt32();
var extraHeight = s.ReadInt32();
var flags = s.ReadUInt32();
var bounds = new Rectangle(0, 0, size.Width, size.Height);
if ((flags & 0x01) != 0)
{
var extraBounds = new Rectangle(extraX, extraY, extraWidth, extraHeight);
bounds = Rectangle.Union(bounds, extraBounds);
Offset = new float2(bounds.X + 0.5f * (bounds.Width - size.Width), bounds.Y + 0.5f * (bounds.Height - size.Height));
Size = new Size(bounds.Width, bounds.Height);
}
// Skip unnecessary header data
s.Position += 12;
Data = new byte[bounds.Width * bounds.Height];
// Unpack tile data
var width = 4;
for (var j = 0; j < size.Height; j++)
{
var start = (j - bounds.Y) * bounds.Width + (size.Width - width) / 2 - bounds.X;
for (var i = 0; i < width; i++)
Data[start + i] = s.ReadUInt8();
width += (j < size.Height / 2 - 1 ? 1 : -1) * 4;
}
// TODO: Load Z-data once the renderer can handle it
s.Position += size.Width * size.Height / 2;
if ((flags & 0x01) == 0)
return;
// Load extra data (cliff faces, etc)
for (var j = 0; j < extraHeight; j++)
{
var start = (j + extraY - bounds.Y) * bounds.Width + extraX - bounds.X;
for (var i = 0; i < extraWidth; i++)
{
var extra = s.ReadUInt8();
if (extra != 0)
Data[start + i] = extra;
}
}
}
else
Data = new byte[0];
}
}
bool IsTmpTS(Stream s)
{
var start = s.Position;
s.Position += 8;
var sx = s.ReadUInt32();
var sy = s.ReadUInt32();
// Find the first non-empty frame
var offset = s.ReadUInt32();
while (offset == 0)
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;
}
TmpTSFrame[] ParseFrames(Stream s)
{
var start = s.Position;
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 TmpTSFrame[offsets.Length];
for (var j = 0; j < templateHeight; j++)
{
for (var i = 0; i < templateWidth; i++)
{
var k = j * templateWidth + i;
s.Position = offsets[k];
tiles[k] = new TmpTSFrame(s, size, i, j);
}
}
s.Position = start;
return tiles;
}
public bool TryParseSprite(Stream s, out ISpriteFrame[] frames)
{
if (!IsTmpTS(s))
{
frames = null;
return false;
}
frames = ParseFrames(s);
return true;
}
}
}