using System; using System.Collections.Generic; using System.IO; using Oni.Imaging; namespace Oni.Akira { internal class RoomGrid { #region Private data private static readonly Color[] gridColors = new[] { new Color(255, 255, 255), new Color(0x90, 0xee, 0x90), new Color(0xad, 0xd8, 0xe6), new Color(0x87, 0xce, 0xfa), new Color(0, 255, 0), new Color(0, 0, 255), new Color(0, 0, 128), new Color(0, 128, 0), new Color(255, 165, 0), new Color(255, 0, 0) }; private const int origin = -2; private const float tileSize = 4.0f; private readonly int xOrigin = -2; private readonly int xTiles; private readonly int zOrigin = -2; private readonly int zTiles; private readonly byte[] data; private readonly byte[] debugData; #endregion public RoomGrid(int xTiles, int zTiles, byte[] data, byte[] debugData) { this.xTiles = xTiles; this.zTiles = zTiles; this.data = data; this.debugData = debugData; } public static RoomGrid FromImage(Surface image) { var data = new byte[image.Width * image.Height]; for (int z = 0; z < image.Height; z++) { for (int x = 0; x < image.Width; x++) { int type = Array.IndexOf(gridColors, image[x, z]); if (type == -1) throw new InvalidDataException(string.Format("Color '{0}' does not match a valid tile type", image[x, z])); data[z * image.Width + x] = (byte)type; } } return new RoomGrid(image.Width, image.Height, data, null); } public static RoomGrid FromCompressedData(int xTiles, int zTiles, byte[] compressedData) { var data = new byte[xTiles * zTiles]; if (compressedData != null) { int k = 0; for (int i = 0; i < compressedData.Length;) { byte run = compressedData[i++]; byte type = (byte)(run & 0x0f); byte count = (byte)(run >> 4); if (count == 0) count = compressedData[i++]; for (int j = 0; j < count; j++) data[k++] = type; } } return new RoomGrid(xTiles, zTiles, data, null); } public int XTiles => xTiles; public int ZTiles => zTiles; public float TileSize => tileSize; public int XOrigin => xOrigin; public int ZOrigin => zOrigin; public byte[] DebugData => debugData; public byte[] Compress() { var compressed = new List(data.Length); for (int i = 0; i < data.Length;) { byte type = data[i]; int count = 1; while (count < 255 && i + count < data.Length && data[i + count] == type) count++; if (count < 16) { compressed.Add((byte)((count << 4) | type)); } else { compressed.Add(type); compressed.Add((byte)count); } i += count; } return compressed.ToArray(); } public Surface ToImage() { var image = new Surface(xTiles, zTiles, SurfaceFormat.BGRX); for (int z = 0; z < zTiles; z++) { for (int x = 0; x < xTiles; x++) image[x, z] = gridColors[data[z * xTiles + x]]; } return image; } } }