Export selection to image: added progress bar and button to cancel export

This commit is contained in:
biwa 2020-12-24 15:00:16 +01:00 committed by spherallic
parent a4bc90c754
commit e65cc32991
4 changed files with 451 additions and 150 deletions

View File

@ -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

View File

@ -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
@ -219,13 +290,16 @@ namespace CodeImp.DoomBuilder.BuilderModes.IO
// Create the transformation matrix // Create the transformation matrix
Matrix matrix = new Matrix(); Matrix matrix = new Matrix();
matrix.Rotate(rotation); matrix.Rotate(rotation);
matrix.Translate((float)(-offset.x*scale * rotationvector.x), (float)(offset.x*scale * rotationvector.y)); // Left/right offset from the map origin matrix.Translate((float)(-offset.x * scale * rotationvector.x), (float)(offset.x * scale * rotationvector.y)); // Left/right offset from the map origin
matrix.Translate((float)(offset.y*scale * rotationvector.y), (float)(offset.y*scale * rotationvector.x)); // Up/down offset from the map origin matrix.Translate((float)(offset.y * scale * rotationvector.y), (float)(offset.y * scale * rotationvector.x)); // Up/down offset from the map origin
matrix.Translate(-(float)textureoffset.x, -(float)textureoffset.y); // Texture offset matrix.Translate(-(float)textureoffset.x, -(float)textureoffset.y); // Texture offset
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>

View File

@ -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;
} }
} }

View File

@ -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
} }
} }