private void UpdatePreview() { int pal = (int)palSelector.Value; BitmapBits levelImg8bpp = new BitmapBits(maxwidth * 8, Lines.Length * texmap.Height * 8); int y = 0; for (int l = 0; l < Lines.Length; l++) { int x = 0; for (int i = 0; i < Lines[l].Length; i++) { CharMapInfo cm = texmap.Characters[Lines[l][i]]; int w = cm.Width ?? texmap.DefaultWidth; for (int y2 = 0; y2 < texmap.Height; y2++) { for (int x2 = 0; x2 < w; x2++) { levelImg8bpp.DrawBitmap(LevelData.TileToBmp8bpp(LevelData.TileArray, cm.Map[x2, y2], pal), (x + x2) * 8, (y + y2) * 8); } } x += w; } y += texmap.Height; } pictureBox1.Image = levelImg8bpp.ToBitmap(LevelData.BmpPal); }
private void DrawPreview() { if (!showPreview || suppressDraw) { return; } List <ObjectInfo> selected = objectList; if (showOnlySelectedObjectsToolStripMenuItem.Checked) { selected = objectListView.CheckedIndices.OfType <int>().Select(a => objectList[a]).ToList(); if (objectListView.SelectedIndices.Count > 0 && !selected.Contains(objectList[objectListView.SelectedIndices[0]])) { selected.Add(objectList[objectListView.SelectedIndices[0]]); } LevelData.Objects = new List <ObjectEntry>(selected.Where(a => a.Entry is ObjectEntry).Select(a => (ObjectEntry)a.Entry)); LevelData.Rings = new List <RingEntry>(selected.Where(a => a.Entry is RingEntry).Select(a => (RingEntry)a.Entry)); } Point camera = new Point(previewPanel.HScrollValue, previewPanel.VScrollValue); Rectangle dispRect = new Rectangle(camera.X, camera.Y, previewPanel.PanelWidth, previewPanel.PanelHeight); BitmapBits img8 = LevelData.DrawForeground(dispRect, true, true, true, true, true, false, false, false); Bitmap bmp = img8.ToBitmap(LevelData.BmpPal).To32bpp(); Graphics gfx = Graphics.FromImage(bmp); gfx.SetOptions(); if (showOverlaysToolStripMenuItem.Checked) { foreach (ObjectInfo obj in selected) { Rectangle bnd = obj.Entry.Bounds; if (!dispRect.IntersectsWith(bnd)) { continue; } bnd.Offset(-camera.X, -camera.Y); SolidBrush brush = null; switch (obj.Source) { case Source.A: brush = brushA; break; case Source.B: brush = brushB; break; } if (brush != null) { gfx.FillRectangle(brush, bnd); } if (objectListView.SelectedIndices.Count > 0 && obj == objectList[objectListView.SelectedIndices[0]]) { gfx.FillRectangle(selectionBrush, bnd); bnd.Width--; bnd.Height--; gfx.DrawRectangle(selectionPen, bnd); } } } previewPanel.PanelGraphics.DrawImage(bmp, 0, 0, previewPanel.PanelWidth, previewPanel.PanelHeight); }
static void Main(string[] args) { byte[] art; ColorPalette palette; List <MappingsFrame> map; List <DPLCFrame> dplc; SpriteInfo spriteInfo; LevelData.littleendian = false; LongOpt[] opts = new[] { new LongOpt("help", Argument.No, null, 'h'), new LongOpt("padding", Argument.Required, null, 'p'), new LongOpt("columns", Argument.Required, null, 'c'), new LongOpt("width", Argument.Required, null, 'w'), new LongOpt("background", Argument.Required, null, 'b'), new LongOpt("grid", Argument.No, null, 'g') }; Getopt getopt = new Getopt("SpriteSheetGen", args, Getopt.digest(opts), opts); int padding = 2; int columns = 8; int width = 0; bool fixedwidth = false; int gridsize = -1; Color background = Color.Transparent; int opt = getopt.getopt(); while (opt != -1) { switch (opt) { case 'h': Console.Write(Properties.Resources.HelpText); return; case 'p': padding = int.Parse(getopt.Optarg); break; case 'c': columns = int.Parse(getopt.Optarg); break; case 'w': width = int.Parse(getopt.Optarg); columns = -1; fixedwidth = true; break; case 'g': gridsize = 0; break; case 'b': if (getopt.Optarg.StartsWith("#")) { background = Color.FromArgb((int)(0xFF000000 | uint.Parse(getopt.Optarg.Substring(1), System.Globalization.NumberStyles.HexNumber))); } else { background = Color.FromName(getopt.Optarg.Replace(" ", "")); } break; } opt = getopt.getopt(); } string filename; Console.Write("File: "); if (getopt.Optind == args.Length) { filename = Console.ReadLine(); } else { filename = args[getopt.Optind]; Console.WriteLine(filename); } filename = Path.GetFullPath(filename); Environment.CurrentDirectory = Path.GetDirectoryName(filename); spriteInfo = IniSerializer.Deserialize <SpriteInfo>(filename); if (spriteInfo.MappingsGame == EngineVersion.Invalid) { spriteInfo.MappingsGame = spriteInfo.Game; } if (spriteInfo.DPLCGame == EngineVersion.Invalid) { spriteInfo.DPLCGame = spriteInfo.Game; } MultiFileIndexer <byte> tiles = new MultiFileIndexer <byte>(); foreach (SonicRetro.SonLVL.API.FileInfo file in spriteInfo.Art) { tiles.AddFile(new List <byte>(Compression.Decompress(file.Filename, spriteInfo.ArtCompression)), file.Offset); } art = tiles.ToArray(); tiles.Clear(); byte[] tmp = null; using (Bitmap palbmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed)) palette = palbmp.Palette; for (int i = 0; i < 256; i++) { palette.Entries[i] = Color.Black; } foreach (PaletteInfo palent in spriteInfo.Palette) { tmp = File.ReadAllBytes(palent.Filename); SonLVLColor[] palfile; palfile = new SonLVLColor[tmp.Length / 2]; for (int pi = 0; pi < tmp.Length; pi += 2) { palfile[pi / 2] = new SonLVLColor(SonicRetro.SonLVL.API.ByteConverter.ToUInt16(tmp, pi)); } for (int pa = 0; pa < palent.Length; pa++) { palette.Entries[pa + palent.Destination] = palfile[pa + palent.Source].RGBColor; } } palette.Entries[0] = background; Dictionary <string, int> labels = new Dictionary <string, int>(); tmp = null; switch (spriteInfo.MappingsFormat) { case MappingsFormat.Binary: tmp = File.ReadAllBytes(spriteInfo.MappingsFile); break; case MappingsFormat.ASM: case MappingsFormat.Macro: tmp = LevelData.ASMToBin(spriteInfo.MappingsFile, spriteInfo.MappingsGame, out labels); break; } map = MappingsFrame.Load(tmp, spriteInfo.MappingsGame, labels); if (!string.IsNullOrEmpty(spriteInfo.DPLCFile)) { labels = new Dictionary <string, int>(); tmp = null; switch (spriteInfo.DPLCFormat) { case MappingsFormat.Binary: tmp = File.ReadAllBytes(spriteInfo.DPLCFile); break; case MappingsFormat.ASM: case MappingsFormat.Macro: tmp = LevelData.ASMToBin(spriteInfo.DPLCFile, spriteInfo.DPLCGame, out labels); break; } dplc = DPLCFrame.Load(tmp, spriteInfo.DPLCGame, labels); } else { dplc = null; } List <BitmapBits> spritesLow = new List <BitmapBits>(map.Count); List <BitmapBits> spritesHigh = new List <BitmapBits>(map.Count); List <BitmapBits> spritesMerged = new List <BitmapBits>(map.Count); List <Point> offsets = new List <Point>(map.Count); List <Point> centers = new List <Point>(map.Count); for (int i = 0; i < map.Count; i++) { if (map[i].TileCount == 0) { //File.AppendAllText("log.txt", "Frame " + i + " empty.\r\n"); continue; } Sprite spr; if (dplc != null) { spr = LevelData.MapFrameToBmp(art, map[i], dplc[i], spriteInfo.StartPalette); } else { spr = LevelData.MapFrameToBmp(art, map[i], spriteInfo.StartPalette); } BitmapBits sprLow = spr.GetBitmapLow(); BitmapBits sprHigh = spr.GetBitmapHigh(); BitmapBits sprMerged = spr.GetBitmap(); int cx = -spr.X; int cy = -spr.Y; for (int _x = 0; _x < sprMerged.Width; _x++) { for (int _y = 0; _y < sprMerged.Height; _y++) { if (sprMerged[_x, _y] != 0) { sprMerged = sprMerged.GetSection(_x, 0, sprMerged.Width - _x, sprMerged.Height); sprLow = sprLow.GetSection(_x, 0, sprLow.Width - _x, sprLow.Height); sprHigh = sprHigh.GetSection(_x, 0, sprHigh.Width - _x, sprHigh.Height); cx -= _x; goto checkright; } } } checkright: for (int _x = sprMerged.Width - 1; _x >= 0; _x--) { for (int _y = 0; _y < sprMerged.Height; _y++) { if (sprMerged[_x, _y] != 0) { sprMerged = sprMerged.GetSection(0, 0, _x + 1, sprMerged.Height); sprLow = sprLow.GetSection(0, 0, _x + 1, sprLow.Height); sprHigh = sprHigh.GetSection(0, 0, _x + 1, sprHigh.Height); goto checktop; } } } checktop: for (int _y = 0; _y < sprMerged.Height; _y++) { for (int _x = 0; _x < sprMerged.Width; _x++) { if (sprMerged[_x, _y] != 0) { sprMerged = sprMerged.GetSection(0, _y, sprMerged.Width, sprMerged.Height - _y); sprLow = sprLow.GetSection(0, _y, sprLow.Width, sprLow.Height - _y); sprHigh = sprHigh.GetSection(0, _y, sprHigh.Width, sprHigh.Height - _y); cy -= _y; goto checkbottom; } } } checkbottom: for (int _y = sprMerged.Height - 1; _y >= 0; _y--) { for (int _x = 0; _x < sprMerged.Width; _x++) { if (sprMerged[_x, _y] != 0) { sprMerged = sprMerged.GetSection(0, 0, sprMerged.Width, _y + 1); sprLow = sprLow.GetSection(0, 0, sprLow.Width, _y + 1); sprHigh = sprHigh.GetSection(0, 0, sprHigh.Width, _y + 1); goto checkdone; } } } checkdone: spritesMerged.Add(sprMerged); spritesLow.Add(sprLow); spritesHigh.Add(sprHigh); centers.Add(new Point(cx, cy)); } if (gridsize == 0) { for (int i = 0; i < spritesMerged.Count; i++) { gridsize = Math.Max(gridsize, Math.Max(spritesMerged[i].Width, spritesMerged[i].Height)); } if (!fixedwidth) { width = (padding * 2 + gridsize) * columns; } } int x = padding; int y = padding; int height = 0; int rowcnt = 0; int rowheight = 0; for (int i = 0; i < spritesMerged.Count; i++) { BitmapBits spr = spritesMerged[i]; Point off; if (gridsize == -1) { if (fixedwidth && x + spr.Width + padding > width) { x = padding; y += rowheight; rowheight = 0; } off = new System.Drawing.Point(x, y); centers[i] = new Point(centers[i].X + off.X, centers[i].Y + off.Y); if (!fixedwidth) { width = Math.Max(width, x + spr.Width + padding); } height = Math.Max(height, y + spr.Height + padding); if (spr.Height + 2 * padding > rowheight) { rowheight = spr.Height + 2 * padding; } if (!fixedwidth && ++rowcnt == columns) { x = padding; y += rowheight; rowcnt = 0; rowheight = 0; } else { x += spr.Width + 2 * padding; } } else { if (fixedwidth && x + gridsize + padding > width) { x = padding; y += gridsize + 2 * padding; } off = new Point(x + (gridsize - spr.Width) / 2, y + (gridsize - spr.Height) / 2); centers[i] = new Point(centers[i].X + off.X, centers[i].Y + off.Y); height = Math.Max(height, y + gridsize + padding); if (!fixedwidth && ++rowcnt == columns) { x = padding; y += gridsize + 2 * padding; rowcnt = 0; } else { x += gridsize + 2 * padding; } } offsets.Add(off); } BitmapBits bmpMerged = new BitmapBits(width, height); for (int i = 0; i < spritesMerged.Count; i++) { bmpMerged.DrawBitmap(spritesMerged[i], offsets[i]); } BitmapBits bmpLow = new BitmapBits(width, height); for (int i = 0; i < spritesLow.Count; i++) { bmpLow.DrawBitmap(spritesLow[i], offsets[i]); } BitmapBits bmpHigh = new BitmapBits(width, height); for (int i = 0; i < spritesHigh.Count; i++) { bmpHigh.DrawBitmap(spritesHigh[i], offsets[i]); } BitmapBits bmpCenter = new BitmapBits(width, height); for (int i = 0; i < centers.Count; i++) { bmpCenter[centers[i].X, centers[i].Y] = 1; } Console.Write("Save as: "); if (getopt.Optind + 1 >= args.Length) { filename = Console.ReadLine(); } else { filename = args[getopt.Optind + 1]; Console.WriteLine(filename); } filename = Path.GetFullPath(filename); bmpMerged.ToBitmap(palette).Save(filename); if (!bmpLow.Bits.FastArrayEqual(0) && !bmpHigh.Bits.FastArrayEqual(0)) { bmpLow.ToBitmap(palette).Save(Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename) + "_low" + Path.GetExtension(filename))); bmpHigh.ToBitmap(palette).Save(Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename) + "_high" + Path.GetExtension(filename))); } bmpCenter.ToBitmap1bpp(Color.Black, Color.White).Save(Path.Combine(Path.GetDirectoryName(filename), Path.GetFileNameWithoutExtension(filename) + "_center" + Path.GetExtension(filename))); }