Merge pull request #3684 from pchote/tileset-fixup

TileSet Refactoring
This commit is contained in:
Matthias Mailänder
2013-08-17 01:08:42 -07:00
17 changed files with 289 additions and 200 deletions

View File

@@ -0,0 +1,97 @@
#region Copyright & License Information
/*
* Copyright 2007-2013 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.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
namespace OpenRA.FileFormats
{
public class TileSetRenderer
{
public TileSet TileSet;
Dictionary<ushort, List<byte[]>> templates;
public Size TileSize;
List<byte[]> LoadTemplate(string filename, string[] exts, Cache<string, R8Reader> r8Cache, int[] frames)
{
if (exts.Contains(".R8") && FileSystem.Exists(filename+".R8"))
{
var data = new List<byte[]>();
foreach (var f in frames)
data.Add(f >= 0 ? r8Cache[filename][f].Image : null);
return data;
}
using (var s = FileSystem.OpenWithExts(filename, exts))
return new Terrain(s).TileBitmapBytes;
}
public TileSetRenderer(TileSet tileset, Size tileSize)
{
this.TileSet = tileset;
this.TileSize = tileSize;
templates = new Dictionary<ushort, List<byte[]>>();
var r8Cache = new Cache<string, R8Reader>(s => new R8Reader(FileSystem.OpenWithExts(s, ".R8")));
foreach (var t in TileSet.Templates)
templates.Add(t.Key, LoadTemplate(t.Value.Image, tileset.Extensions, r8Cache, t.Value.Frames));
}
public Bitmap RenderTemplate(ushort id, Palette p)
{
var template = TileSet.Templates[id];
var templateData = templates[id];
var bitmap = new Bitmap(TileSize.Width * template.Size.X, TileSize.Height * template.Size.Y,
PixelFormat.Format8bppIndexed);
bitmap.Palette = p.AsSystemPalette();
var data = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
unsafe
{
var q = (byte*)data.Scan0.ToPointer();
var stride = data.Stride;
for (var u = 0; u < template.Size.X; u++)
for (var v = 0; v < template.Size.Y; v++)
if (templateData[u + v * template.Size.X] != null)
{
var rawImage = templateData[u + v * template.Size.X];
for (var i = 0; i < TileSize.Width; i++)
for (var j = 0; j < TileSize.Height; j++)
q[(v * TileSize.Width + j) * stride + u * TileSize.Width + i] = rawImage[i + TileSize.Width * j];
}
else
{
for (var i = 0; i < TileSize.Width; i++)
for (var j = 0; j < TileSize.Height; j++)
q[(v * TileSize.Width + j) * stride + u * TileSize.Width + i] = 0;
}
}
bitmap.UnlockBits(data);
return bitmap;
}
public List<byte[]> Data(ushort id)
{
return templates[id];
}
}
}

View File

@@ -16,16 +16,15 @@ namespace OpenRA.FileFormats
public class Terrain
{
public readonly List<byte[]> TileBitmapBytes = new List<byte[]>();
public readonly int Width;
public readonly int Height;
public Terrain( Stream stream, int size )
public Terrain(Stream stream)
{
// Try loading as a cnc .tem
BinaryReader reader = new BinaryReader( stream );
int Width = reader.ReadUInt16();
int Height = reader.ReadUInt16();
if( Width != size || Height != size )
throw new InvalidDataException( "{0}x{1} != {2}x{2}".F(Width, Height, size ) );
Width = reader.ReadUInt16();
Height = reader.ReadUInt16();
/*NumTiles = */reader.ReadUInt16();
/*Zero1 = */reader.ReadUInt16();
@@ -65,8 +64,8 @@ namespace OpenRA.FileFormats
{
if (b != 255)
{
stream.Position = ImgStart + b * size * size;
TileBitmapBytes.Add(new BinaryReader(stream).ReadBytes(size * size));
stream.Position = ImgStart + b * Width * Height;
TileBitmapBytes.Add(new BinaryReader(stream).ReadBytes(Width * Height));
}
else
TileBitmapBytes.Add(null);

View File

@@ -35,6 +35,7 @@ namespace OpenRA.FileFormats
{
public ushort Id;
public string Image;
public int[] Frames;
public int2 Size;
public bool PickAny;
public string Category;
@@ -52,7 +53,7 @@ namespace OpenRA.FileFormats
t => t.Value.Value);
}
static readonly string[] Fields = { "Id", "Image", "Size", "PickAny" };
static readonly string[] Fields = { "Id", "Image", "Frames", "Size", "PickAny" };
public MiniYaml Save()
{
@@ -71,24 +72,22 @@ namespace OpenRA.FileFormats
return new MiniYaml(null, root);
}
public Terrain Data;
}
public class TileSet
{
public string Name;
public string Id;
public int SheetSize = 512;
public string Palette;
public string PlayerPalette;
public int TileSize = 24;
public string[] Extensions;
public int WaterPaletteRotationBase = 0x60;
public Dictionary<string, TerrainTypeInfo> Terrain = new Dictionary<string, TerrainTypeInfo>();
public Dictionary<ushort, TileTemplate> Templates = new Dictionary<ushort, TileTemplate>();
public string[] EditorTemplateOrder;
static readonly string[] fields = {"Name", "TileSize", "Id", "Palette", "Extensions"};
static readonly string[] fields = {"Name", "TileSize", "Id", "SheetSize", "Palette", "Extensions"};
public TileSet() {}
@@ -108,14 +107,6 @@ namespace OpenRA.FileFormats
.Select(y => new TileTemplate(y)).ToDictionary(t => t.Id);
}
public void LoadTiles()
{
foreach (var t in Templates)
if (t.Value.Data == null)
using (var s = FileSystem.OpenWithExts(t.Value.Image, Extensions))
t.Value.Data = new Terrain(s, TileSize);
}
public void Save(string filepath)
{
var root = new List<MiniYamlNode>();
@@ -144,23 +135,6 @@ namespace OpenRA.FileFormats
root.WriteToFile(filepath);
}
public byte[] GetBytes(TileReference<ushort,byte> r)
{
TileTemplate tile;
if (Templates.TryGetValue(r.type, out tile))
{
var data = tile.Data.TileBitmapBytes[r.index];
if (data != null)
return data;
}
byte[] missingTile = new byte[TileSize*TileSize];
for (var i = 0; i < missingTile.Length; i++)
missingTile[i] = 0x00;
return missingTile;
}
public string GetTerrainType(TileReference<ushort, byte> r)
{
var tt = Templates[r.type].Tiles;
@@ -170,43 +144,5 @@ namespace OpenRA.FileFormats
return ret;
}
public Bitmap RenderTemplate(ushort n, Palette p)
{
var template = Templates[n];
var bitmap = new Bitmap(TileSize * template.Size.X, TileSize * template.Size.Y,
PixelFormat.Format8bppIndexed);
bitmap.Palette = p.AsSystemPalette();
var data = bitmap.LockBits(bitmap.Bounds(),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
unsafe
{
byte* q = (byte*)data.Scan0.ToPointer();
var stride = data.Stride;
for (var u = 0; u < template.Size.X; u++)
for (var v = 0; v < template.Size.Y; v++)
if (template.Data.TileBitmapBytes[u + v * template.Size.X] != null)
{
var rawImage = template.Data.TileBitmapBytes[u + v * template.Size.X];
for (var i = 0; i < TileSize; i++)
for (var j = 0; j < TileSize; j++)
q[(v * TileSize + j) * stride + u * TileSize + i] = rawImage[i + TileSize * j];
}
else
{
for (var i = 0; i < TileSize; i++)
for (var j = 0; j < TileSize; j++)
q[(v * TileSize + j) * stride + u * TileSize + i] = 0;
}
}
bitmap.UnlockBits(data);
return bitmap;
}
}
}

View File

@@ -146,6 +146,7 @@
<Compile Include="FileFormats\WavLoader.cs" />
<Compile Include="Filesystem\D2kSoundResources.cs" />
<Compile Include="Graphics\R8Reader.cs" />
<Compile Include="Graphics\TileSetRenderer.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">