using System; using System.Collections.Generic; using System.Text; using OpenRa.FileFormats; using System.Drawing; using System.IO; using System.Drawing.Imaging; namespace OpenRa.Game { static class Util { static float2 EncodeVertexAttributes(TextureChannel channel, int paletteLine) { Converter channelEncoder = delegate(TextureChannel c) { switch (c) { case TextureChannel.Red: return 0.75f; case TextureChannel.Green: return 0.25f; case TextureChannel.Blue: return -0.25f; case TextureChannel.Alpha: return -0.75f; default: throw new ArgumentException(); } }; return new float2(paletteLine / 16.0f, channelEncoder(channel)); } public static Vertex MakeVertex(float2 o, float2 uv, Sprite r, int palette) { return new Vertex( float2.Lerp( o, o + new float2(r.bounds.Size), uv ), r.MapTextureCoords(uv), EncodeVertexAttributes(r.channel, palette)); } static float Lerp(float a, float b, float t) { return (1 - t) * a + t * b; } public static string[] ReadAllLines(Stream s) { List result = new List(); using (StreamReader reader = new StreamReader(s)) while (!reader.EndOfStream) result.Add(reader.ReadLine()); return result.ToArray(); } public static T[] MakeArray(int count, Converter f) { T[] result = new T[count]; for (int i = 0; i < count; i++) result[i] = f(i); return result; } static float2[] uv = { new float2( 0,0 ), new float2( 1,0 ), new float2( 0,1 ), new float2( 1,1 ), }; public static void CreateQuad(List vertices, List indices, float2 o, Sprite r, int palette) { ushort offset = (ushort)vertices.Count; foreach( float2 p in uv ) vertices.Add(Util.MakeVertex(o, p, r, palette)); indices.Add(offset); indices.Add((ushort)(offset + 1)); indices.Add((ushort)(offset + 2)); indices.Add((ushort)(offset + 1)); indices.Add((ushort)(offset + 3)); indices.Add((ushort)(offset + 2)); } public static void FastCopyIntoChannel(Sprite dest, byte[] src) { var bitmap = dest.sheet.Bitmap; BitmapData bits = null; uint[] channelMasks = { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }; uint mask = channelMasks[(int)dest.channel]; try { bits = bitmap.LockBits(dest.bounds, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); int width = dest.bounds.Width; int height = dest.bounds.Height; for (int j = 0; j < height; j++) { unsafe { uint* p = (uint*)(bits.Scan0.ToInt32() + j * bits.Stride); for (int i = 0; i < width; i++, p++) *p = ReplaceChannel(*p, mask, src[i + width * j]); } } } finally { bitmap.UnlockBits(bits); } } static uint ReplaceChannel(uint o, uint mask, byte p) { uint pp = (uint)p; pp |= pp << 8; // copy into all channels pp |= pp << 16; o &= ~mask; o |= (mask & pp); return o; } } }