using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using System; using System.IO; namespace FSO.Common.Utils { public static class CurLoader { public static MouseCursor LoadMonoCursor(GraphicsDevice gd, Stream stream) { var cur = LoadCursor(gd, stream); return MouseCursor.FromTexture2D(cur.Item1, cur.Item2.X, cur.Item2.Y); } public static MouseCursor[] LoadUpgradeCursors(GraphicsDevice gd, Stream stream, int maxStars) { var cur = LoadCursor(gd, stream); Texture2D starTex; using (var str = File.Open("Content/uigraphics/upgrade_star.png", FileMode.Open, FileAccess.Read, FileShare.Read)) { starTex = Texture2D.FromStream(gd, str); } var batch = new SpriteBatch(gd); var results = new MouseCursor[maxStars]; for (int i = 0; i < maxStars; i++) { var starPos = cur.Item1.Width - 12; var width = Math.Max(starPos + 8 * i + 9, cur.Item1.Width); var tex = new RenderTarget2D(gd, width, Math.Max(width, cur.Item1.Height)); gd.SetRenderTarget(tex); gd.Clear(Color.Transparent); batch.Begin(SpriteSortMode.Immediate); batch.Draw(cur.Item1, Vector2.Zero, Color.White); for (int j=0; j<=i; j++) { batch.Draw(starTex, new Vector2(starPos, 5), Color.White); starPos += 8; } batch.End(); gd.SetRenderTarget(null); results[i] = MouseCursor.FromTexture2D(tex, cur.Item2.X, cur.Item2.Y); } starTex.Dispose(); return results; } public static Func BmpLoaderFunc; public static Tuple LoadCursor(GraphicsDevice gd, Stream stream) { using (var io = new BinaryReader(stream)) { //little endian var tempbmp = new MemoryStream(); var outIO = new BinaryWriter(tempbmp); var reserved = io.ReadInt16(); var type = io.ReadInt16(); if (type != 2) throw new Exception("Not a cursor!"); var images = io.ReadInt16(); //currently discard extra images... //read first image var width = io.ReadByte(); var height = io.ReadByte(); var colors = io.ReadByte(); var reserved2 = io.ReadByte(); var xOffset = io.ReadInt16(); var yOffset = io.ReadInt16(); var size = io.ReadInt32(); var offset = io.ReadInt32(); stream.Seek(offset - 22, SeekOrigin.Current); //ok... now write the bitmap data to a fake bitmap outIO.Write(new char[] { 'B', 'M' }); outIO.Write(size + 14); //size, plus header outIO.Write(0); outIO.Write(14); var data = new byte[size]; stream.Read(data, 0, size); outIO.Write(data); tempbmp.Seek(0, SeekOrigin.Begin); var tex = BmpLoaderFunc(gd, tempbmp); //our mask is on top. the image is on bottom. var odata = new byte[tex.Width * tex.Height * 4]; tex.GetData(odata); var ndata = new byte[tex.Width * tex.Height * 2]; var limit = ndata.Length; for (int i=0; i< limit; i+=4) { var j = i + limit; ndata[i] = (byte)((~odata[i]) & odata[j]); ndata[i+1] = ndata[i]; ndata[i+2] = ndata[i]; ndata[i+3] = (byte)(~odata[i]); } var oTex = new Texture2D(gd, width, height); oTex.SetData(ndata); tex.Dispose(); return new Tuple(oTex, new Point(xOffset, yOffset)); } } } }