mirror of
https://git.do.srb2.org/STJr/ZoneBuilder.git
synced 2024-11-10 06:41:49 +00:00
Export selection to image: added progress bar and button to cancel export
This commit is contained in:
parent
a4bc90c754
commit
e65cc32991
4 changed files with 451 additions and 150 deletions
|
@ -890,29 +890,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageExportSettingsForm form = new ImageExportSettingsForm();
|
ImageExportSettingsForm form = new ImageExportSettingsForm();
|
||||||
if (form.ShowDialog() == DialogResult.OK)
|
form.ShowDialog();
|
||||||
{
|
|
||||||
ImageExportSettings settings = new ImageExportSettings(Path.GetDirectoryName(form.FilePath), Path.GetFileNameWithoutExtension(form.FilePath), Path.GetExtension(form.FilePath), form.Floor, form.Fullbright, form.Brightmap, form.Tiles, form.ImageScale, form.GetPixelFormat(), form.GetImageFormat());
|
|
||||||
ImageExporter exporter = new ImageExporter(sectors, settings);
|
|
||||||
|
|
||||||
string text = "The following images will be created:\n\n" + string.Join("\n", exporter.GetImageNames().ToArray());
|
|
||||||
|
|
||||||
DialogResult result = MessageBox.Show(text, "Export to image", MessageBoxButtons.OKCancel);
|
|
||||||
|
|
||||||
if (result == DialogResult.OK)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
exporter.Export();
|
|
||||||
|
|
||||||
MessageBox.Show("Export successful.", "Export to image", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
|
||||||
catch (ArgumentException e) // Happens if there's not enough consecutive memory to create the file
|
|
||||||
{
|
|
||||||
MessageBox.Show("Exporting failed. There's likely not enough consecutive free memory to create the image. Try a lower color depth or file format", "Export failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -27,6 +27,7 @@ using System.Drawing;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using CodeImp.DoomBuilder.Data;
|
using CodeImp.DoomBuilder.Data;
|
||||||
|
@ -68,12 +69,29 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Exceptions
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class ImageExportCanceledException : Exception { }
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class ImageExportImageTooBigException : Exception { }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
internal class ImageExporter
|
internal class ImageExporter
|
||||||
{
|
{
|
||||||
#region ================== Variables
|
#region ================== Variables
|
||||||
|
|
||||||
private ICollection<Sector> sectors;
|
private ICollection<Sector> sectors;
|
||||||
private ImageExportSettings settings;
|
private ImageExportSettings settings;
|
||||||
|
private int numitems;
|
||||||
|
private int doneitems;
|
||||||
|
private int donepercent;
|
||||||
|
private Action addprogress;
|
||||||
|
private Action<string> showphase;
|
||||||
|
private Func<bool> checkcanelexport;
|
||||||
|
private bool cancelexport;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -85,10 +103,14 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
|
|
||||||
#region ================== Constructors
|
#region ================== Constructors
|
||||||
|
|
||||||
public ImageExporter(ICollection<Sector> sectors, ImageExportSettings settings)
|
public ImageExporter(ICollection<Sector> sectors, ImageExportSettings settings, Action addprogress, Action<string> showphase, Func<bool> checkcanelexport)
|
||||||
{
|
{
|
||||||
this.sectors = sectors;
|
this.sectors = sectors;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
|
this.addprogress = addprogress;
|
||||||
|
this.showphase = showphase;
|
||||||
|
this.checkcanelexport = checkcanelexport;
|
||||||
|
cancelexport = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -105,26 +127,63 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
|
|
||||||
GetSizeAndOffset(out size, out offset);
|
GetSizeAndOffset(out size, out offset);
|
||||||
|
|
||||||
|
// Count the number of triangles for reporting progress
|
||||||
|
numitems = 0;
|
||||||
|
doneitems = 0;
|
||||||
|
donepercent = 0;
|
||||||
|
foreach (Sector s in sectors)
|
||||||
|
numitems += s.Triangles.Vertices.Count / 3;
|
||||||
|
|
||||||
|
if (settings.Tiles)
|
||||||
|
numitems += GetNumTiles();
|
||||||
|
|
||||||
|
// If exporting a brightmap everything has to be done twice
|
||||||
|
if (settings.Brightmap)
|
||||||
|
numitems *= 2;
|
||||||
|
|
||||||
// Use the same image for the normal texture and the brightmap because of memory concerns
|
// Use the same image for the normal texture and the brightmap because of memory concerns
|
||||||
|
showphase("Preparing");
|
||||||
using (Bitmap image = new Bitmap((int)(size.x * settings.Scale), (int)(size.y * settings.Scale), settings.PixelFormat))
|
using (Bitmap image = new Bitmap((int)(size.x * settings.Scale), (int)(size.y * settings.Scale), settings.PixelFormat))
|
||||||
{
|
{
|
||||||
|
showphase("Creating normal image");
|
||||||
// Normal texture image
|
// Normal texture image
|
||||||
CreateImage(image, offset, settings.Scale, false);
|
CreateImage(image, offset, settings.Scale, false);
|
||||||
|
|
||||||
if (settings.Tiles)
|
if (settings.Tiles)
|
||||||
|
{
|
||||||
|
showphase("Saving 64x64 tile images (" + GetNumTiles() + ")");
|
||||||
SaveImageAsTiles(image);
|
SaveImageAsTiles(image);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
showphase("Saving normal image");
|
||||||
|
try
|
||||||
|
{
|
||||||
image.Save(Path.Combine(settings.Path, settings.Name) + settings.Extension, settings.ImageFormat);
|
image.Save(Path.Combine(settings.Path, settings.Name) + settings.Extension, settings.ImageFormat);
|
||||||
|
}
|
||||||
|
catch(ExternalException)
|
||||||
|
{
|
||||||
|
throw new ImageExportImageTooBigException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The brightmap
|
// The brightmap
|
||||||
if (settings.Brightmap)
|
if (settings.Brightmap)
|
||||||
{
|
{
|
||||||
|
showphase("Creating brightmap image");
|
||||||
CreateImage(image, offset, settings.Scale, true);
|
CreateImage(image, offset, settings.Scale, true);
|
||||||
|
|
||||||
|
showphase("Saving brightmap image");
|
||||||
if (settings.Tiles)
|
if (settings.Tiles)
|
||||||
|
{
|
||||||
|
showphase("Saving 64x64 tile images (" + GetNumTiles() + ")");
|
||||||
SaveImageAsTiles(image, "_brightmap");
|
SaveImageAsTiles(image, "_brightmap");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
image.Save(Path.Combine(settings.Path, settings.Name) + "_brightmap" + settings.Extension, settings.ImageFormat);
|
image.Save(Path.Combine(settings.Path, settings.Name) + "_brightmap" + settings.Extension, settings.ImageFormat);
|
||||||
|
showphase("Saving normal image");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,18 +197,17 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
/// <returns>The image to be exported</returns>
|
/// <returns>The image to be exported</returns>
|
||||||
private void CreateImage(Bitmap texturebitmap, Vector2D offset, float scale, bool asbrightmap)
|
private void CreateImage(Bitmap texturebitmap, Vector2D offset, float scale, bool asbrightmap)
|
||||||
{
|
{
|
||||||
Graphics gtexture = null;
|
|
||||||
|
|
||||||
// The texture
|
// The texture
|
||||||
gtexture = Graphics.FromImage(texturebitmap);
|
using (Graphics gtexture = Graphics.FromImage(texturebitmap))
|
||||||
|
{
|
||||||
gtexture.Clear(Color.Black); // If we don't clear to black we'll see seams where the sectors touch, due to the AA
|
gtexture.Clear(Color.Black); // If we don't clear to black we'll see seams where the sectors touch, due to the AA
|
||||||
gtexture.InterpolationMode = InterpolationMode.HighQualityBilinear;
|
gtexture.InterpolationMode = InterpolationMode.HighQualityBilinear;
|
||||||
gtexture.CompositingQuality = CompositingQuality.HighQuality;
|
gtexture.CompositingQuality = CompositingQuality.HighQuality;
|
||||||
gtexture.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
gtexture.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||||
gtexture.SmoothingMode = SmoothingMode.AntiAlias; // Without AA the sector edges will be quite rough
|
gtexture.SmoothingMode = SmoothingMode.AntiAlias; // Without AA the sector edges will be quite rough
|
||||||
|
|
||||||
GraphicsPath gpath = new GraphicsPath();
|
using (GraphicsPath gpath = new GraphicsPath())
|
||||||
|
{
|
||||||
foreach (Sector s in sectors)
|
foreach (Sector s in sectors)
|
||||||
{
|
{
|
||||||
float rotation = (float)s.Fields.GetValue("rotationfloor", 0.0);
|
float rotation = (float)s.Fields.GetValue("rotationfloor", 0.0);
|
||||||
|
@ -169,12 +227,25 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
gpath.AddLine((float)v1.x, (float)v1.y, (float)v2.x, (float)v2.y);
|
gpath.AddLine((float)v1.x, (float)v1.y, (float)v2.x, (float)v2.y);
|
||||||
gpath.AddLine((float)v2.x, (float)v2.y, (float)v3.x, (float)v3.y);
|
gpath.AddLine((float)v2.x, (float)v2.y, (float)v3.x, (float)v3.y);
|
||||||
gpath.CloseFigure();
|
gpath.CloseFigure();
|
||||||
|
|
||||||
|
doneitems++;
|
||||||
|
|
||||||
|
int newpercent = (int)(((double)doneitems / numitems) * 100);
|
||||||
|
if (newpercent > donepercent)
|
||||||
|
{
|
||||||
|
donepercent = newpercent;
|
||||||
|
addprogress();
|
||||||
|
|
||||||
|
if (checkcanelexport())
|
||||||
|
throw new ImageExportCanceledException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asbrightmap)
|
if (asbrightmap)
|
||||||
{
|
{
|
||||||
// Create the brightmap based on the sector brightness
|
// Create the brightmap based on the sector brightness
|
||||||
using (SolidBrush sbrush = new SolidBrush(Color.FromArgb(255, s.Brightness, s.Brightness, s.Brightness)))
|
int brightness = General.Clamp(s.Brightness, 0, 255);
|
||||||
|
using (SolidBrush sbrush = new SolidBrush(Color.FromArgb(255, brightness, brightness, brightness)))
|
||||||
gtexture.FillPath(sbrush, gpath);
|
gtexture.FillPath(sbrush, gpath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -225,7 +296,10 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
matrix.Scale((float)texturescale.x, (float)texturescale.y);
|
matrix.Scale((float)texturescale.x, (float)texturescale.y);
|
||||||
|
|
||||||
if (!settings.Fullbright)
|
if (!settings.Fullbright)
|
||||||
AdjustBrightness(ref brushtexture, s.Brightness > 0 ? s.Brightness / 255.0f : 0.0f);
|
{
|
||||||
|
int brightness = General.Clamp(s.Brightness, 0, 255);
|
||||||
|
AdjustBrightness(ref brushtexture, brightness > 0 ? brightness / 255.0f : 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
if (scale > 1.0f)
|
if (scale > 1.0f)
|
||||||
ResizeImage(ref brushtexture, brushtexture.Width * (int)scale, brushtexture.Height * (int)scale);
|
ResizeImage(ref brushtexture, brushtexture.Width * (int)scale, brushtexture.Height * (int)scale);
|
||||||
|
@ -246,10 +320,8 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
// Reset the graphics path
|
// Reset the graphics path
|
||||||
gpath.Reset();
|
gpath.Reset();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Dispose unneeded objects
|
}
|
||||||
gpath.Dispose();
|
|
||||||
gtexture.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -277,7 +349,6 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
if(y * TILE_SIZE + TILE_SIZE > image.Size.Height)
|
if(y * TILE_SIZE + TILE_SIZE > image.Size.Height)
|
||||||
height = image.Size.Height - (y * TILE_SIZE);
|
height = image.Size.Height - (y * TILE_SIZE);
|
||||||
|
|
||||||
|
|
||||||
using (Bitmap bitmap = new Bitmap(TILE_SIZE, TILE_SIZE))
|
using (Bitmap bitmap = new Bitmap(TILE_SIZE, TILE_SIZE))
|
||||||
using (Graphics g = Graphics.FromImage(bitmap))
|
using (Graphics g = Graphics.FromImage(bitmap))
|
||||||
{
|
{
|
||||||
|
@ -288,6 +359,21 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
}
|
}
|
||||||
|
|
||||||
imagenum++;
|
imagenum++;
|
||||||
|
|
||||||
|
doneitems++;
|
||||||
|
|
||||||
|
int newpercent = (int)(((double)doneitems / numitems) * 100);
|
||||||
|
if (newpercent > donepercent)
|
||||||
|
{
|
||||||
|
donepercent = newpercent;
|
||||||
|
addprogress();
|
||||||
|
|
||||||
|
if (checkcanelexport())
|
||||||
|
throw new ImageExportCanceledException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkcanelexport())
|
||||||
|
throw new ImageExportCanceledException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,7 +411,23 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
|
||||||
}
|
}
|
||||||
|
|
||||||
return imagenames;
|
return imagenames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the total number of tiles
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Number of tiles</returns>
|
||||||
|
public int GetNumTiles()
|
||||||
|
{
|
||||||
|
Vector2D size;
|
||||||
|
Vector2D offset;
|
||||||
|
|
||||||
|
GetSizeAndOffset(out size, out offset);
|
||||||
|
|
||||||
|
int xnum = (int)Math.Ceiling(size.x * settings.Scale / (double)TILE_SIZE);
|
||||||
|
int ynum = (int)Math.Ceiling(size.y * settings.Scale / (double)TILE_SIZE);
|
||||||
|
|
||||||
|
return xnum * ynum;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
this.tbExportPath = new System.Windows.Forms.TextBox();
|
this.tbExportPath = new System.Windows.Forms.TextBox();
|
||||||
this.browse = new System.Windows.Forms.Button();
|
this.browse = new System.Windows.Forms.Button();
|
||||||
this.label1 = new System.Windows.Forms.Label();
|
this.label1 = new System.Windows.Forms.Label();
|
||||||
this.cancel = new System.Windows.Forms.Button();
|
this.close = new System.Windows.Forms.Button();
|
||||||
this.export = new System.Windows.Forms.Button();
|
this.export = new System.Windows.Forms.Button();
|
||||||
this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
|
this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
|
||||||
this.cbImageFormat = new System.Windows.Forms.ComboBox();
|
this.cbImageFormat = new System.Windows.Forms.ComboBox();
|
||||||
|
@ -45,6 +45,8 @@
|
||||||
this.cbTiles = new System.Windows.Forms.CheckBox();
|
this.cbTiles = new System.Windows.Forms.CheckBox();
|
||||||
this.cbScale = new System.Windows.Forms.ComboBox();
|
this.cbScale = new System.Windows.Forms.ComboBox();
|
||||||
this.label4 = new System.Windows.Forms.Label();
|
this.label4 = new System.Windows.Forms.Label();
|
||||||
|
this.progress = new System.Windows.Forms.ProgressBar();
|
||||||
|
this.lbPhase = new System.Windows.Forms.Label();
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// tbExportPath
|
// tbExportPath
|
||||||
|
@ -73,16 +75,16 @@
|
||||||
this.label1.TabIndex = 4;
|
this.label1.TabIndex = 4;
|
||||||
this.label1.Text = "Path:";
|
this.label1.Text = "Path:";
|
||||||
//
|
//
|
||||||
// cancel
|
// close
|
||||||
//
|
//
|
||||||
this.cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
this.close.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||||
this.cancel.Location = new System.Drawing.Point(360, 153);
|
this.close.Location = new System.Drawing.Point(360, 153);
|
||||||
this.cancel.Name = "cancel";
|
this.close.Name = "close";
|
||||||
this.cancel.Size = new System.Drawing.Size(75, 23);
|
this.close.Size = new System.Drawing.Size(75, 23);
|
||||||
this.cancel.TabIndex = 7;
|
this.close.TabIndex = 7;
|
||||||
this.cancel.Text = "Cancel";
|
this.close.Text = "Close";
|
||||||
this.cancel.UseVisualStyleBackColor = true;
|
this.close.UseVisualStyleBackColor = true;
|
||||||
this.cancel.Click += new System.EventHandler(this.cancel_Click);
|
this.close.Click += new System.EventHandler(this.close_Click);
|
||||||
//
|
//
|
||||||
// export
|
// export
|
||||||
//
|
//
|
||||||
|
@ -219,13 +221,34 @@
|
||||||
this.label4.TabIndex = 18;
|
this.label4.TabIndex = 18;
|
||||||
this.label4.Text = "Scale:";
|
this.label4.Text = "Scale:";
|
||||||
//
|
//
|
||||||
|
// progress
|
||||||
|
//
|
||||||
|
this.progress.Location = new System.Drawing.Point(12, 153);
|
||||||
|
this.progress.Name = "progress";
|
||||||
|
this.progress.Size = new System.Drawing.Size(261, 23);
|
||||||
|
this.progress.Step = 1;
|
||||||
|
this.progress.TabIndex = 19;
|
||||||
|
this.progress.Visible = false;
|
||||||
|
//
|
||||||
|
// lbPhase
|
||||||
|
//
|
||||||
|
this.lbPhase.AutoSize = true;
|
||||||
|
this.lbPhase.Location = new System.Drawing.Point(14, 127);
|
||||||
|
this.lbPhase.Name = "lbPhase";
|
||||||
|
this.lbPhase.Size = new System.Drawing.Size(45, 13);
|
||||||
|
this.lbPhase.TabIndex = 20;
|
||||||
|
this.lbPhase.Text = "lbPhase";
|
||||||
|
this.lbPhase.Visible = false;
|
||||||
|
//
|
||||||
// ImageExportSettingsForm
|
// ImageExportSettingsForm
|
||||||
//
|
//
|
||||||
this.AcceptButton = this.export;
|
this.AcceptButton = this.export;
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.CancelButton = this.cancel;
|
this.CancelButton = this.close;
|
||||||
this.ClientSize = new System.Drawing.Size(447, 188);
|
this.ClientSize = new System.Drawing.Size(447, 188);
|
||||||
|
this.Controls.Add(this.lbPhase);
|
||||||
|
this.Controls.Add(this.progress);
|
||||||
this.Controls.Add(this.label4);
|
this.Controls.Add(this.label4);
|
||||||
this.Controls.Add(this.cbScale);
|
this.Controls.Add(this.cbScale);
|
||||||
this.Controls.Add(this.cbTiles);
|
this.Controls.Add(this.cbTiles);
|
||||||
|
@ -237,7 +260,7 @@
|
||||||
this.Controls.Add(this.label2);
|
this.Controls.Add(this.label2);
|
||||||
this.Controls.Add(this.cbPixelFormat);
|
this.Controls.Add(this.cbPixelFormat);
|
||||||
this.Controls.Add(this.cbImageFormat);
|
this.Controls.Add(this.cbImageFormat);
|
||||||
this.Controls.Add(this.cancel);
|
this.Controls.Add(this.close);
|
||||||
this.Controls.Add(this.export);
|
this.Controls.Add(this.export);
|
||||||
this.Controls.Add(this.label1);
|
this.Controls.Add(this.label1);
|
||||||
this.Controls.Add(this.browse);
|
this.Controls.Add(this.browse);
|
||||||
|
@ -247,6 +270,7 @@
|
||||||
this.MinimizeBox = false;
|
this.MinimizeBox = false;
|
||||||
this.Name = "ImageExportSettingsForm";
|
this.Name = "ImageExportSettingsForm";
|
||||||
this.Text = "Image export settings";
|
this.Text = "Image export settings";
|
||||||
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ImageExportSettingsForm_FormClosing);
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
this.PerformLayout();
|
this.PerformLayout();
|
||||||
|
|
||||||
|
@ -257,7 +281,7 @@
|
||||||
private System.Windows.Forms.Button browse;
|
private System.Windows.Forms.Button browse;
|
||||||
private System.Windows.Forms.TextBox tbExportPath;
|
private System.Windows.Forms.TextBox tbExportPath;
|
||||||
private System.Windows.Forms.Label label1;
|
private System.Windows.Forms.Label label1;
|
||||||
private System.Windows.Forms.Button cancel;
|
private System.Windows.Forms.Button close;
|
||||||
private System.Windows.Forms.Button export;
|
private System.Windows.Forms.Button export;
|
||||||
private System.Windows.Forms.SaveFileDialog saveFileDialog;
|
private System.Windows.Forms.SaveFileDialog saveFileDialog;
|
||||||
private System.Windows.Forms.ComboBox cbImageFormat;
|
private System.Windows.Forms.ComboBox cbImageFormat;
|
||||||
|
@ -271,5 +295,7 @@
|
||||||
private System.Windows.Forms.CheckBox cbTiles;
|
private System.Windows.Forms.CheckBox cbTiles;
|
||||||
private System.Windows.Forms.ComboBox cbScale;
|
private System.Windows.Forms.ComboBox cbScale;
|
||||||
private System.Windows.Forms.Label label4;
|
private System.Windows.Forms.Label label4;
|
||||||
|
private System.Windows.Forms.ProgressBar progress;
|
||||||
|
private System.Windows.Forms.Label lbPhase;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -31,9 +31,19 @@ using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using CodeImp.DoomBuilder.Map;
|
||||||
|
using CodeImp.DoomBuilder.BuilderModes.IO;
|
||||||
|
|
||||||
namespace CodeImp.DoomBuilder.BuilderModes.Interface
|
namespace CodeImp.DoomBuilder.BuilderModes.Interface
|
||||||
{
|
{
|
||||||
|
enum ImageExportResult
|
||||||
|
{
|
||||||
|
OK,
|
||||||
|
Canceled,
|
||||||
|
OutOfMemory,
|
||||||
|
ImageTooBig
|
||||||
|
}
|
||||||
|
|
||||||
public partial class ImageExportSettingsForm : Form
|
public partial class ImageExportSettingsForm : Form
|
||||||
{
|
{
|
||||||
#region ================== Properties
|
#region ================== Properties
|
||||||
|
@ -47,6 +57,20 @@ namespace CodeImp.DoomBuilder.BuilderModes.Interface
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Delegates
|
||||||
|
|
||||||
|
private delegate void CallVoidMethodDeletage();
|
||||||
|
private delegate void CallStringMethodDeletage(string s);
|
||||||
|
private delegate void CallImageExportResultMethodDeletage(ImageExportResult ier);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Variables
|
||||||
|
|
||||||
|
bool exporting;
|
||||||
|
bool cancelexport;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region ================== Constructor
|
#region ================== Constructor
|
||||||
|
|
||||||
|
@ -56,6 +80,8 @@ namespace CodeImp.DoomBuilder.BuilderModes.Interface
|
||||||
|
|
||||||
cbImageFormat.SelectedIndex = 0;
|
cbImageFormat.SelectedIndex = 0;
|
||||||
cbPixelFormat.SelectedIndex = 0;
|
cbPixelFormat.SelectedIndex = 0;
|
||||||
|
exporting = false;
|
||||||
|
cancelexport = false;
|
||||||
|
|
||||||
string name = Path.GetFileNameWithoutExtension(General.Map.FileTitle) + "_" + General.Map.Options.LevelName + "_" + Path.GetFileNameWithoutExtension(Path.GetRandomFileName());
|
string name = Path.GetFileNameWithoutExtension(General.Map.FileTitle) + "_" + General.Map.Options.LevelName + "_" + Path.GetFileNameWithoutExtension(Path.GetRandomFileName());
|
||||||
|
|
||||||
|
@ -104,6 +130,153 @@ namespace CodeImp.DoomBuilder.BuilderModes.Interface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Starts exporting the image(s). Disables all controls and starts the thread that does the actual exporting.
|
||||||
|
/// </summary>
|
||||||
|
private void StartExport()
|
||||||
|
{
|
||||||
|
ICollection<Sector> sectors = General.Map.Map.SelectedSectorsCount == 0 ? General.Map.Map.Sectors : General.Map.Map.GetSelectedSectors(true);
|
||||||
|
|
||||||
|
exporting = true;
|
||||||
|
cancelexport = false;
|
||||||
|
|
||||||
|
progress.Maximum = 100; //sectors.Count * (Brightmap ? 2 : 1);
|
||||||
|
progress.Value = 0;
|
||||||
|
progress.Visible = true;
|
||||||
|
|
||||||
|
lbPhase.Text = "";
|
||||||
|
lbPhase.Visible = true;
|
||||||
|
|
||||||
|
foreach (Control c in Controls)
|
||||||
|
{
|
||||||
|
if (!(c is ProgressBar || c is Label))
|
||||||
|
c.Enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export.Enabled = true;
|
||||||
|
export.Text = "Cancel";
|
||||||
|
|
||||||
|
ImageExportSettings settings = new ImageExportSettings(Path.GetDirectoryName(FilePath), Path.GetFileNameWithoutExtension(FilePath), Path.GetExtension(FilePath), Floor, Fullbright, Brightmap, Tiles, ImageScale, GetPixelFormat(), GetImageFormat());
|
||||||
|
|
||||||
|
RunExport(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables all controls. This has to be called when the export is finished (either successfully or unsuccessfully)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ier">Image export result</param>
|
||||||
|
private void StopExport(ImageExportResult ier)
|
||||||
|
{
|
||||||
|
if (this.InvokeRequired)
|
||||||
|
{
|
||||||
|
CallImageExportResultMethodDeletage d = StopExport;
|
||||||
|
this.Invoke(d, ier);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
progress.Visible = false;
|
||||||
|
lbPhase.Visible = false;
|
||||||
|
|
||||||
|
foreach (Control c in Controls)
|
||||||
|
{
|
||||||
|
if (!(c is ProgressBar || c is Label))
|
||||||
|
c.Enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export.Text = "Export";
|
||||||
|
|
||||||
|
if (ier == ImageExportResult.OK)
|
||||||
|
MessageBox.Show("Export successful.", "Export to image", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
else if(ier == ImageExportResult.Canceled)
|
||||||
|
MessageBox.Show("Export canceled.", "Export to image", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
else if (ier == ImageExportResult.OutOfMemory)
|
||||||
|
MessageBox.Show("Exporting failed. There's likely not enough consecutive free memory to create the image. Try a lower color depth or file format", "Export failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
else if(ier == ImageExportResult.ImageTooBig)
|
||||||
|
MessageBox.Show("Exporting failed. The image is likely too big for the current settings. Try a lower color depth or file format", "Export failed", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
exporting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckCancelExport()
|
||||||
|
{
|
||||||
|
return cancelexport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shows the current phase in textual form. Is called by the exporter
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text"></param>
|
||||||
|
private void ShowPhase(string text)
|
||||||
|
{
|
||||||
|
if (this.InvokeRequired)
|
||||||
|
{
|
||||||
|
CallStringMethodDeletage d = ShowPhase;
|
||||||
|
this.Invoke(d, text);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lbPhase.Text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds progress to the progress bar. Is called by the exporter
|
||||||
|
/// </summary>
|
||||||
|
private void AddProgress()
|
||||||
|
{
|
||||||
|
if (progress.InvokeRequired)
|
||||||
|
{
|
||||||
|
CallVoidMethodDeletage d = AddProgress;
|
||||||
|
progress.Invoke(d);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Just winforms things to make the progress bar animation not lag behind
|
||||||
|
int value = progress.Value + 1;
|
||||||
|
progress.Value = value;
|
||||||
|
progress.Value = value - 1;
|
||||||
|
progress.Value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs the actual exporter
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="settings">Export settings</param>
|
||||||
|
private void RunExport(ImageExportSettings settings)
|
||||||
|
{
|
||||||
|
ICollection<Sector> sectors = General.Map.Map.SelectedSectorsCount == 0 ? General.Map.Map.Sectors : General.Map.Map.GetSelectedSectors(true);
|
||||||
|
|
||||||
|
ImageExporter exporter = new ImageExporter(sectors, settings, AddProgress, ShowPhase, CheckCancelExport);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
exporter.Export();
|
||||||
|
}
|
||||||
|
catch (ArgumentException) // Happens if there's not enough consecutive memory to create the file
|
||||||
|
{
|
||||||
|
StopExport(ImageExportResult.OutOfMemory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch(ImageExportCanceledException)
|
||||||
|
{
|
||||||
|
StopExport(ImageExportResult.Canceled);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch(ImageExportImageTooBigException)
|
||||||
|
{
|
||||||
|
StopExport(ImageExportResult.ImageTooBig);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StopExport(ImageExportResult.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ================== Events
|
||||||
|
|
||||||
private void browse_Click(object sender, EventArgs e)
|
private void browse_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
||||||
|
@ -124,23 +297,35 @@ namespace CodeImp.DoomBuilder.BuilderModes.Interface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
private void close_Click(object sender, EventArgs e)
|
||||||
|
|
||||||
private void cancel_Click(object sender, EventArgs e)
|
|
||||||
{
|
{
|
||||||
this.DialogResult = DialogResult.Cancel;
|
this.DialogResult = DialogResult.Cancel;
|
||||||
this.Close();
|
this.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void export_Click(object sender, EventArgs e)
|
private void export_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (exporting)
|
||||||
|
{
|
||||||
|
cancelexport = true;
|
||||||
|
export.Enabled = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
General.Settings.WritePluginSetting("imageexportfullbright", cbFullbright.Checked);
|
General.Settings.WritePluginSetting("imageexportfullbright", cbFullbright.Checked);
|
||||||
General.Settings.WritePluginSetting("imageexportbrightmap", cbBrightmap.Checked);
|
General.Settings.WritePluginSetting("imageexportbrightmap", cbBrightmap.Checked);
|
||||||
General.Settings.WritePluginSetting("imageexporttiles", cbTiles.Checked);
|
General.Settings.WritePluginSetting("imageexporttiles", cbTiles.Checked);
|
||||||
General.Settings.WritePluginSetting("imageexportscale", cbScale.SelectedIndex);
|
General.Settings.WritePluginSetting("imageexportscale", cbScale.SelectedIndex);
|
||||||
|
|
||||||
this.DialogResult = DialogResult.OK;
|
// Exporting works like this:
|
||||||
this.Close();
|
// In here StartExport() is called
|
||||||
|
// StartExport() disables all controls and creates a thread that runs RunExport() in the background; then the StartExport method ends
|
||||||
|
// RunExport() creates an instance of ImageExporter and starts the actual export
|
||||||
|
// When ImageExporter finishes its job it runs StopExport()
|
||||||
|
// StopExport() enables all controls again
|
||||||
|
|
||||||
|
StartExport();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cbImageFormat_SelectedIndexChanged(object sender, EventArgs e)
|
private void cbImageFormat_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
|
@ -159,5 +344,15 @@ namespace CodeImp.DoomBuilder.BuilderModes.Interface
|
||||||
|
|
||||||
tbExportPath.Text = Path.ChangeExtension(tbExportPath.Text, newextension);
|
tbExportPath.Text = Path.ChangeExtension(tbExportPath.Text, newextension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void ImageExportSettingsForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||||
|
{
|
||||||
|
// Do not allow closing the form while the export is running
|
||||||
|
if (exporting)
|
||||||
|
e.Cancel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue