diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj
index 7816fe34..06283a08 100644
--- a/Source/Core/Builder.csproj
+++ b/Source/Core/Builder.csproj
@@ -143,6 +143,7 @@
+
@@ -179,6 +180,12 @@
ArgumentBox.cs
+
+ UserControl
+
+
+ ExternalCommandControl.cs
+
@@ -262,6 +269,18 @@
+
+ Form
+
+
+ PreAndPostCommandsForm.cs
+
+
+ Form
+
+
+ RunExternalCommandForm.cs
+
Form
@@ -637,9 +656,18 @@
+
+ ExternalCommandControl.cs
+
PairedFloatControl.cs
+
+ PreAndPostCommandsForm.cs
+
+
+ RunExternalCommandForm.cs
+
ThingStatisticsForm.cs
diff --git a/Source/Core/BuilderMono.csproj b/Source/Core/BuilderMono.csproj
index f1cd04af..f90f42ea 100644
--- a/Source/Core/BuilderMono.csproj
+++ b/Source/Core/BuilderMono.csproj
@@ -140,6 +140,7 @@
+
@@ -176,6 +177,12 @@
ArgumentBox.cs
+
+ UserControl
+
+
+ ExternalCommandControl.cs
+
@@ -254,6 +261,18 @@
+
+ Form
+
+
+ PreAndPostCommandsForm.cs
+
+
+ Form
+
+
+ RunExternalCommandForm.cs
+
Form
@@ -629,9 +648,18 @@
+
+ ExternalCommandControl.cs
+
PairedFloatControl.cs
+
+ PreAndPostCommandsForm.cs
+
+
+ RunExternalCommandForm.cs
+
ThingStatisticsForm.cs
@@ -941,7 +969,7 @@
-
+
diff --git a/Source/Core/Config/ExternalCommandSettings.cs b/Source/Core/Config/ExternalCommandSettings.cs
new file mode 100644
index 00000000..02f10287
--- /dev/null
+++ b/Source/Core/Config/ExternalCommandSettings.cs
@@ -0,0 +1,122 @@
+#region ================== Copyright (c) 2021 Boris Iwanski
+
+/*
+ * This program is free software: you can redistribute it and/or modify
+ *
+ * it under the terms of the GNU General Public License as published by
+ *
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.If not, see.
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CodeImp.DoomBuilder.IO;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Config
+{
+ public class ExternalCommandSettings
+ {
+ #region ================== Variables
+
+ private string workingdirectory;
+ private string commands;
+ private bool autocloseonsuccess;
+ private bool exitcodeiserror;
+ private bool stderriserror;
+
+ #endregion
+
+ #region ================== Properties
+
+ public string WorkingDirectory { get { return workingdirectory; } set { workingdirectory = value; } }
+ public string Commands { get { return commands; } set { commands = value; } }
+ public bool AutoCloseOnSuccess { get { return autocloseonsuccess; } set { autocloseonsuccess = value; } }
+ public bool ExitCodeIsError { get { return exitcodeiserror; } set { exitcodeiserror = value; } }
+ public bool StdErrIsError { get { return stderriserror; } set { stderriserror = value; } }
+
+ #endregion
+
+ #region ================== Constructors
+
+ public ExternalCommandSettings()
+ {
+ WorkingDirectory = string.Empty;
+ Commands = string.Empty;
+ AutoCloseOnSuccess = true;
+ ExitCodeIsError = true;
+ StdErrIsError = true;
+ }
+
+ ///
+ /// Initialize with the settings loaded from a given section in a configuration.
+ ///
+ /// The configuration
+ /// The section to load the settings from
+ public ExternalCommandSettings(Configuration cfg, string section)
+ {
+ LoadSettings(cfg, section);
+ }
+
+ #endregion
+
+ #region ================== Methods
+
+ ///
+ /// Loads the settings from a given section in a configuration.
+ ///
+ /// The configuration
+ /// The section to load the settings from
+ public void LoadSettings(Configuration cfg, string section)
+ {
+ WorkingDirectory = cfg.ReadSetting(section + ".workingdirectory", string.Empty);
+ Commands = cfg.ReadSetting(section + ".commands", string.Empty);
+ AutoCloseOnSuccess = cfg.ReadSetting(section + ".autocloseonsuccess", true);
+ ExitCodeIsError = cfg.ReadSetting(section + ".exitcodeiserror", true);
+ StdErrIsError = cfg.ReadSetting(section + ".stderriserror", true);
+ }
+
+ ///
+ /// Writes the settings to a given section in a configuration.
+ ///
+ /// The configuration
+ /// The section to write the settings to
+ public void WriteSettings(Configuration cfg, string section)
+ {
+ if (!string.IsNullOrWhiteSpace(Commands))
+ cfg.WriteSetting(section + ".commands", Commands);
+ else
+ cfg.DeleteSetting(section + ".commands");
+
+ if (!string.IsNullOrWhiteSpace(WorkingDirectory))
+ cfg.WriteSetting(section + ".workingdirectory", WorkingDirectory);
+ else
+ cfg.DeleteSetting(section + ".workingdirectory");
+
+ cfg.WriteSetting(section + ".autocloseonsuccess", AutoCloseOnSuccess);
+ cfg.WriteSetting(section + ".exitcodeiserror", ExitCodeIsError);
+ cfg.WriteSetting(section + ".stderriserror", StdErrIsError);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Source/Core/Controls/ExternalCommandControl.Designer.cs b/Source/Core/Controls/ExternalCommandControl.Designer.cs
new file mode 100644
index 00000000..ca16d1ad
--- /dev/null
+++ b/Source/Core/Controls/ExternalCommandControl.Designer.cs
@@ -0,0 +1,147 @@
+namespace CodeImp.DoomBuilder.Controls
+{
+ partial class ExternalCommandControl
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Component Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.tbFolder = new System.Windows.Forms.TextBox();
+ this.tbCommand = new System.Windows.Forms.TextBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.label2 = new System.Windows.Forms.Label();
+ this.btnBrowseFolder = new System.Windows.Forms.Button();
+ this.cbAutoclose = new System.Windows.Forms.CheckBox();
+ this.cbExitCode = new System.Windows.Forms.CheckBox();
+ this.cbStdErr = new System.Windows.Forms.CheckBox();
+ this.SuspendLayout();
+ //
+ // tbFolder
+ //
+ this.tbFolder.Location = new System.Drawing.Point(101, 5);
+ this.tbFolder.Name = "tbFolder";
+ this.tbFolder.Size = new System.Drawing.Size(498, 20);
+ this.tbFolder.TabIndex = 0;
+ //
+ // tbCommand
+ //
+ this.tbCommand.AcceptsReturn = true;
+ this.tbCommand.Location = new System.Drawing.Point(101, 31);
+ this.tbCommand.Multiline = true;
+ this.tbCommand.Name = "tbCommand";
+ this.tbCommand.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+ this.tbCommand.Size = new System.Drawing.Size(498, 160);
+ this.tbCommand.TabIndex = 1;
+ this.tbCommand.WordWrap = false;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(33, 31);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(62, 13);
+ this.label1.TabIndex = 2;
+ this.label1.Text = "Commands:";
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(2, 8);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(93, 13);
+ this.label2.TabIndex = 2;
+ this.label2.Text = "Working directory:";
+ //
+ // btnBrowseFolder
+ //
+ this.btnBrowseFolder.Image = global::CodeImp.DoomBuilder.Properties.Resources.Folder;
+ this.btnBrowseFolder.Location = new System.Drawing.Point(605, 4);
+ this.btnBrowseFolder.Name = "btnBrowseFolder";
+ this.btnBrowseFolder.Size = new System.Drawing.Size(23, 23);
+ this.btnBrowseFolder.TabIndex = 3;
+ this.btnBrowseFolder.UseVisualStyleBackColor = true;
+ this.btnBrowseFolder.Click += new System.EventHandler(this.button1_Click);
+ //
+ // cbAutoclose
+ //
+ this.cbAutoclose.AutoSize = true;
+ this.cbAutoclose.Location = new System.Drawing.Point(101, 197);
+ this.cbAutoclose.Name = "cbAutoclose";
+ this.cbAutoclose.Size = new System.Drawing.Size(243, 17);
+ this.cbAutoclose.TabIndex = 4;
+ this.cbAutoclose.Text = "Automatically close status window on success";
+ this.cbAutoclose.UseVisualStyleBackColor = true;
+ //
+ // cbExitCode
+ //
+ this.cbExitCode.AutoSize = true;
+ this.cbExitCode.Location = new System.Drawing.Point(101, 221);
+ this.cbExitCode.Name = "cbExitCode";
+ this.cbExitCode.Size = new System.Drawing.Size(175, 17);
+ this.cbExitCode.TabIndex = 5;
+ this.cbExitCode.Text = "Exit code not equal 0 is an error";
+ this.cbExitCode.UseVisualStyleBackColor = true;
+ //
+ // cbStdErr
+ //
+ this.cbStdErr.AutoSize = true;
+ this.cbStdErr.Location = new System.Drawing.Point(101, 244);
+ this.cbStdErr.Name = "cbStdErr";
+ this.cbStdErr.Size = new System.Drawing.Size(149, 17);
+ this.cbStdErr.TabIndex = 5;
+ this.cbStdErr.Text = "Writing to stderr is an error";
+ this.cbStdErr.UseVisualStyleBackColor = true;
+ //
+ // ExternalCommandControl
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.cbStdErr);
+ this.Controls.Add(this.cbExitCode);
+ this.Controls.Add(this.cbAutoclose);
+ this.Controls.Add(this.btnBrowseFolder);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.tbCommand);
+ this.Controls.Add(this.tbFolder);
+ this.Name = "ExternalCommandControl";
+ this.Size = new System.Drawing.Size(633, 268);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TextBox tbFolder;
+ private System.Windows.Forms.TextBox tbCommand;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.Button btnBrowseFolder;
+ private System.Windows.Forms.CheckBox cbAutoclose;
+ private System.Windows.Forms.CheckBox cbExitCode;
+ private System.Windows.Forms.CheckBox cbStdErr;
+ }
+}
diff --git a/Source/Core/Controls/ExternalCommandControl.cs b/Source/Core/Controls/ExternalCommandControl.cs
new file mode 100644
index 00000000..60e7649d
--- /dev/null
+++ b/Source/Core/Controls/ExternalCommandControl.cs
@@ -0,0 +1,101 @@
+#region ================== Copyright (c) 2021 Boris Iwanski
+
+/*
+ * This program is free software: you can redistribute it and/or modify
+ *
+ * it under the terms of the GNU General Public License as published by
+ *
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.If not, see.
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using CodeImp.DoomBuilder.Config;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Controls
+{
+ public partial class ExternalCommandControl : UserControl
+ {
+ #region ================== Constructors
+
+ public ExternalCommandControl()
+ {
+ InitializeComponent();
+ }
+
+ #endregion
+
+ #region ================== Methods
+
+ ///
+ /// Fills the controls with the settings from the ExternalCommandSettings.
+ ///
+ /// The settings
+ public void Setup(ExternalCommandSettings ecs)
+ {
+ tbFolder.Text = ecs.WorkingDirectory;
+ tbCommand.Text = ecs.Commands;
+ cbAutoclose.Checked = ecs.AutoCloseOnSuccess;
+ cbExitCode.Checked = ecs.ExitCodeIsError;
+ cbStdErr.Checked = ecs.StdErrIsError;
+ }
+
+ ///
+ /// Returns the external command settings.
+ ///
+ /// The external command settings
+ public ExternalCommandSettings GetSettings()
+ {
+ ExternalCommandSettings ecs = new ExternalCommandSettings();
+ ecs.WorkingDirectory = tbFolder.Text.Trim();
+ ecs.Commands = tbCommand.Text.Trim();
+ ecs.AutoCloseOnSuccess = cbAutoclose.Checked;
+ ecs.ExitCodeIsError = cbExitCode.Checked;
+ ecs.StdErrIsError = cbStdErr.Checked;
+
+ return ecs;
+ }
+
+ #endregion
+
+ #region ================== Events
+
+ private void button1_Click(object sender, EventArgs e)
+ {
+ FolderSelectDialog dirdialog = new FolderSelectDialog();
+ dirdialog.Title = "Select base folder";
+ dirdialog.InitialDirectory = tbFolder.Text;
+
+ if (dirdialog.ShowDialog(this.Handle))
+ {
+ tbFolder.Text = dirdialog.FileName;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/Core/Controls/ExternalCommandControl.resx b/Source/Core/Controls/ExternalCommandControl.resx
new file mode 100644
index 00000000..1af7de15
--- /dev/null
+++ b/Source/Core/Controls/ExternalCommandControl.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Source/Core/General/Launcher.cs b/Source/Core/General/Launcher.cs
index 9408e593..7ea6b076 100755
--- a/Source/Core/General/Launcher.cs
+++ b/Source/Core/General/Launcher.cs
@@ -327,40 +327,71 @@ namespace CodeImp.DoomBuilder
General.Plugins.OnMapSaveBegin(SavePurpose.Testing);
if(General.Map.SaveMap(tempwad, SavePurpose.Testing))
{
+ bool canceled = false;
+
// No compiler errors?
- if(General.Map.Errors.Count == 0)
+ if (General.Map.Errors.Count == 0)
{
- // Make arguments
- string args = ConvertParameters(General.Map.ConfigSettings.TestParameters, skill, General.Map.ConfigSettings.TestShortPaths, General.Map.ConfigSettings.TestLinuxPaths);
-
- // Setup process info
- ProcessStartInfo processinfo = new ProcessStartInfo();
- processinfo.Arguments = args;
- processinfo.FileName = General.Map.ConfigSettings.TestProgram;
- processinfo.CreateNoWindow = false;
- processinfo.ErrorDialog = false;
- processinfo.UseShellExecute = true;
- processinfo.WindowStyle = ProcessWindowStyle.Normal;
- processinfo.WorkingDirectory = Path.GetDirectoryName(processinfo.FileName);
-
- // Output info
- General.WriteLogLine("Running test program: " + processinfo.FileName);
- General.WriteLogLine("Program parameters: " + processinfo.Arguments);
- General.MainWindow.DisplayStatus(StatusType.Info, "Launching " + processinfo.FileName + "...");
-
- try
+ // Check if there's a pre command to run, and try to execute it
+ if (!string.IsNullOrWhiteSpace(General.Map.Options.TestPreCommand.Commands))
{
- // Start the program
- Process process = Process.Start(processinfo);
- process.EnableRaisingEvents = true; //mxd
- process.Exited += ProcessOnExited; //mxd
- processes.Add(process, tempwad); //mxd
- Cursor.Current = oldcursor; //mxd
+ if (!General.Map.ExecuteExternalCommand(General.Map.Options.TestPreCommand, tempwad))
+ {
+ General.WriteLogLine("Testing was canceled when executing the testing pre command.");
+
+ // Reset status
+ General.MainWindow.DisplayStatus(StatusType.Warning, "Testing was canceled.");
+ canceled = true;
+ }
}
- catch(Exception e)
+
+ if (!canceled)
{
- // Unable to start the program
- General.ShowErrorMessage("Unable to start the test program, " + e.GetType().Name + ": " + e.Message, MessageBoxButtons.OK);
+ // Make arguments
+ string args = ConvertParameters(General.Map.ConfigSettings.TestParameters, skill, General.Map.ConfigSettings.TestShortPaths, General.Map.ConfigSettings.TestLinuxPaths);
+
+ // Setup process info
+ ProcessStartInfo processinfo = new ProcessStartInfo();
+ processinfo.Arguments = args;
+ processinfo.FileName = General.Map.ConfigSettings.TestProgram;
+ processinfo.CreateNoWindow = false;
+ processinfo.ErrorDialog = false;
+ processinfo.UseShellExecute = true;
+ processinfo.WindowStyle = ProcessWindowStyle.Normal;
+ processinfo.WorkingDirectory = Path.GetDirectoryName(processinfo.FileName);
+
+ // Output info
+ General.WriteLogLine("Running test program: " + processinfo.FileName);
+ General.WriteLogLine("Program parameters: " + processinfo.Arguments);
+ General.MainWindow.DisplayStatus(StatusType.Info, "Launching " + processinfo.FileName + "...");
+
+ try
+ {
+ // Start the program
+ Process process = Process.Start(processinfo);
+ process.EnableRaisingEvents = true; //mxd
+ process.Exited += ProcessOnExited; //mxd
+ processes.Add(process, tempwad); //mxd
+ Cursor.Current = oldcursor; //mxd
+ }
+ catch (Exception e)
+ {
+ // Unable to start the program
+ General.ShowErrorMessage("Unable to start the test program, " + e.GetType().Name + ": " + e.Message, MessageBoxButtons.OK);
+ }
+
+ // Check if there's a post command to run, and try to execute it
+ // TODO: currently modifying the commands is disabled since it'd have to be executed after the test program ends, which is not
+ // the case in the current situation, since this code here is reached immediately after launching the test program
+ /*
+ if (!string.IsNullOrWhiteSpace(General.Map.Options.TestPostCommand.Commands))
+ {
+ if (!General.Map.ExecuteExternalCommand(General.Map.Options.TestPostCommand, tempwad))
+ {
+ General.WriteLogLine("Failed to execute the test post command successfully.");
+ }
+ }
+ */
}
}
else
diff --git a/Source/Core/General/MapManager.cs b/Source/Core/General/MapManager.cs
index bf1bcb1e..d67f3732 100755
--- a/Source/Core/General/MapManager.cs
+++ b/Source/Core/General/MapManager.cs
@@ -1053,7 +1053,7 @@ namespace CodeImp.DoomBuilder
filetitle = Path.GetFileName(filepathname);
// Reload resources
- ReloadResources(true);
+ ReloadResources(true, false);
}
try
@@ -2300,7 +2300,7 @@ namespace CodeImp.DoomBuilder
DebugConsole.Clear();
#endif
- ReloadResources(true);
+ ReloadResources(true, true);
if(General.ErrorLogger.IsErrorAdded)
{
@@ -2315,12 +2315,27 @@ namespace CodeImp.DoomBuilder
}
- internal void ReloadResources(bool clearerrors) //mxd. clearerrors flag
+ internal void ReloadResources(bool clearerrors, bool runprepostcommands) //mxd. clearerrors flag
{
// Keep old display info
StatusInfo oldstatus = General.MainWindow.Status;
Cursor oldcursor = Cursor.Current;
+ // Check if there's a pre command to run, and try to execute it
+ if (runprepostcommands && !string.IsNullOrWhiteSpace(options.ReloadResourcePreCommand.Commands))
+ {
+ if(!ExecuteExternalCommand(options.ReloadResourcePreCommand))
+ {
+ General.WriteLogLine("Reloading resources was canceled when executing the reload resource pre command.");
+
+ // Reset status
+ General.MainWindow.DisplayStatus(StatusType.Warning, "Reloading resourcess was canceled.");
+ Cursor.Current = oldcursor;
+
+ return;
+ }
+ }
+
// Show status
General.MainWindow.DisplayStatus(StatusType.Busy, "Reloading data resources...");
Cursor.Current = Cursors.WaitCursor;
@@ -2377,11 +2392,46 @@ namespace CodeImp.DoomBuilder
//mxd. Update script names
LoadACS();
+ // Check if there's a post command to run, and try to execute it
+ if (runprepostcommands && !string.IsNullOrWhiteSpace(options.ReloadResourcePostCommand.Commands))
+ {
+ if (!ExecuteExternalCommand(options.ReloadResourcePostCommand))
+ {
+ General.WriteLogLine("Failed to execute the reload resource post command successfully.");
+ }
+ }
+
// Reset status
General.MainWindow.DisplayStatus(oldstatus);
Cursor.Current = oldcursor;
}
+ public bool ExecuteExternalCommand(ExternalCommandSettings cmdsettings, string arguments = "")
+ {
+ string filename;
+
+ do
+ {
+ filename = Path.ChangeExtension(Path.GetTempFileName(), ".cmd");
+ }
+ while (File.Exists(filename));
+
+ File.WriteAllText(filename, cmdsettings.Commands);
+
+ ProcessStartInfo startinfo = new ProcessStartInfo();
+ startinfo.FileName = "cmd.exe";
+ startinfo.Arguments = "/C " + filename + " " + arguments;
+ if(!string.IsNullOrWhiteSpace(cmdsettings.WorkingDirectory))
+ startinfo.WorkingDirectory = cmdsettings.WorkingDirectory;
+
+ RunExternalCommandForm f = new RunExternalCommandForm(startinfo, cmdsettings);
+ f.ShowDialog();
+
+ File.Delete(filename);
+
+ return f.DialogResult == DialogResult.OK;
+ }
+
// Game Configuration action
[BeginAction("mapoptions")]
internal void ShowMapOptions()
@@ -2475,7 +2525,7 @@ namespace CodeImp.DoomBuilder
map.UpdateCustomLinedefColors();
// Reload resources
- ReloadResources(false);
+ ReloadResources(false, false);
// Update interface
General.MainWindow.SetupInterface();
diff --git a/Source/Core/Map/MapOptions.cs b/Source/Core/Map/MapOptions.cs
index e4085840..1cdc691e 100755
--- a/Source/Core/Map/MapOptions.cs
+++ b/Source/Core/Map/MapOptions.cs
@@ -89,6 +89,11 @@ namespace CodeImp.DoomBuilder.Map
//mxd. Position and scale
private readonly Vector2D viewposition;
private readonly float viewscale;
+
+ private ExternalCommandSettings reloadresourceprecommand;
+ private ExternalCommandSettings reloadresourcepostcommand;
+ private ExternalCommandSettings testprecommand;
+ private ExternalCommandSettings testpostcommand;
#endregion
@@ -147,6 +152,11 @@ namespace CodeImp.DoomBuilder.Map
public Vector2D ViewPosition { get { return viewposition; } }
public float ViewScale { get { return viewscale; } }
+ public ExternalCommandSettings ReloadResourcePreCommand { get { return reloadresourceprecommand; } internal set { reloadresourceprecommand = value; } }
+ public ExternalCommandSettings ReloadResourcePostCommand { get { return reloadresourcepostcommand; } internal set { reloadresourcepostcommand = value; } }
+ public ExternalCommandSettings TestPreCommand { get { return testprecommand; } internal set { testprecommand = value; } }
+ public ExternalCommandSettings TestPostCommand { get { return testpostcommand; } internal set { testpostcommand = value; } }
+
#endregion
#region ================== Constructor / Disposer
@@ -167,6 +177,11 @@ namespace CodeImp.DoomBuilder.Map
this.viewposition = new Vector2D(float.NaN, float.NaN); //mxd
this.viewscale = float.NaN; //mxd
+ reloadresourceprecommand = new ExternalCommandSettings();
+ reloadresourcepostcommand = new ExternalCommandSettings();
+ testprecommand = new ExternalCommandSettings();
+ testpostcommand = new ExternalCommandSettings();
+
//mxd. Sector drawing options
this.custombrightness = 196;
this.customceilheight = 128;
@@ -235,6 +250,12 @@ namespace CodeImp.DoomBuilder.Map
//mxd
uselongtexturenames = longtexturenamessupported && this.mapconfig.ReadSetting("uselongtexturenames", false);
+ // Load the pre and post commands
+ reloadresourceprecommand = new ExternalCommandSettings(mapconfig, "reloadresourceprecommand");
+ reloadresourcepostcommand= new ExternalCommandSettings(mapconfig, "reloadresourcepostcommand");
+ testprecommand = new ExternalCommandSettings(mapconfig, "testprecommand");
+ testpostcommand = new ExternalCommandSettings(mapconfig, "testpostcommand");
+
//mxd. Position and scale
float vpx = this.mapconfig.ReadSetting("viewpositionx", float.NaN);
float vpy = this.mapconfig.ReadSetting("viewpositiony", float.NaN);
@@ -386,8 +407,14 @@ namespace CodeImp.DoomBuilder.Map
foreach(ScriptDocumentSettings settings in scriptsettings.Values)
WriteScriptDocumentSettings(mapconfig, "scriptdocuments.document" + (sdcounter++), settings);
+ // Write pre and post commands
+ reloadresourceprecommand.WriteSettings(mapconfig, "reloadresourceprecommand");
+ reloadresourcepostcommand.WriteSettings(mapconfig, "reloadresourcepostcommand");
+ testprecommand.WriteSettings(mapconfig, "testprecommand");
+ testpostcommand.WriteSettings(mapconfig, "testpostcommand");
+
// Load the file or make a new file
- if(File.Exists(settingsfile))
+ if (File.Exists(settingsfile))
wadcfg = new Configuration(settingsfile, true);
else
wadcfg = new Configuration(true);
diff --git a/Source/Core/Windows/MapOptionsForm.Designer.cs b/Source/Core/Windows/MapOptionsForm.Designer.cs
index c06ee0a1..adf58dd8 100755
--- a/Source/Core/Windows/MapOptionsForm.Designer.cs
+++ b/Source/Core/Windows/MapOptionsForm.Designer.cs
@@ -47,6 +47,8 @@ namespace CodeImp.DoomBuilder.Windows
this.strictpatches = new System.Windows.Forms.CheckBox();
this.datalocations = new CodeImp.DoomBuilder.Controls.ResourceListEditor();
this.tooltip = new System.Windows.Forms.ToolTip(this.components);
+ this.label5 = new System.Windows.Forms.Label();
+ this.prepostcommands = new System.Windows.Forms.Button();
label3 = new System.Windows.Forms.Label();
label2 = new System.Windows.Forms.Label();
label1 = new System.Windows.Forms.Label();
@@ -165,7 +167,7 @@ namespace CodeImp.DoomBuilder.Windows
// apply
//
this.apply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.apply.Location = new System.Drawing.Point(179, 399);
+ this.apply.Location = new System.Drawing.Point(179, 429);
this.apply.Name = "apply";
this.apply.Size = new System.Drawing.Size(112, 25);
this.apply.TabIndex = 2;
@@ -177,7 +179,7 @@ namespace CodeImp.DoomBuilder.Windows
//
this.cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.cancel.Location = new System.Drawing.Point(297, 399);
+ this.cancel.Location = new System.Drawing.Point(297, 429);
this.cancel.Name = "cancel";
this.cancel.Size = new System.Drawing.Size(112, 25);
this.cancel.TabIndex = 3;
@@ -229,13 +231,33 @@ namespace CodeImp.DoomBuilder.Windows
this.datalocations.Size = new System.Drawing.Size(368, 127);
this.datalocations.TabIndex = 0;
//
+ // label5
+ //
+ this.label5.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+ this.label5.Location = new System.Drawing.Point(13, 423);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(396, 2);
+ this.label5.TabIndex = 21;
+ //
+ // prepostcommands
+ //
+ this.prepostcommands.Location = new System.Drawing.Point(247, 395);
+ this.prepostcommands.Name = "prepostcommands";
+ this.prepostcommands.Size = new System.Drawing.Size(162, 25);
+ this.prepostcommands.TabIndex = 20;
+ this.prepostcommands.Text = "Edit pre and post commands";
+ this.prepostcommands.UseVisualStyleBackColor = true;
+ this.prepostcommands.Click += new System.EventHandler(this.prepostcommands_Click);
+ //
// MapOptionsForm
//
this.AcceptButton = this.apply;
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.CancelButton = this.cancel;
- this.ClientSize = new System.Drawing.Size(421, 436);
+ this.ClientSize = new System.Drawing.Size(421, 466);
+ this.Controls.Add(this.label5);
+ this.Controls.Add(this.prepostcommands);
this.Controls.Add(this.panelres);
this.Controls.Add(this.cancel);
this.Controls.Add(this.apply);
@@ -272,7 +294,7 @@ namespace CodeImp.DoomBuilder.Windows
private System.Windows.Forms.Label examplelabel;
private System.Windows.Forms.CheckBox longtexturenames;
private System.Windows.Forms.ToolTip tooltip;
-
-
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.Button prepostcommands;
}
}
\ No newline at end of file
diff --git a/Source/Core/Windows/MapOptionsForm.cs b/Source/Core/Windows/MapOptionsForm.cs
index 3bc512ed..825d5edb 100755
--- a/Source/Core/Windows/MapOptionsForm.cs
+++ b/Source/Core/Windows/MapOptionsForm.cs
@@ -34,6 +34,11 @@ namespace CodeImp.DoomBuilder.Windows
// Variables
private readonly MapOptions options;
private readonly bool newmap;
+ private ExternalCommandSettings reloadresourceprecommand;
+ private ExternalCommandSettings reloadresourcepostcommand;
+ private ExternalCommandSettings testprecommand;
+ private ExternalCommandSettings testpostcommand;
+ private bool prepostcommandsmodified;
// Properties
public MapOptions Options { get { return options; } }
@@ -49,8 +54,14 @@ namespace CodeImp.DoomBuilder.Windows
// Keep settings
this.options = options;
+ prepostcommandsmodified = false;
+ reloadresourceprecommand = options.ReloadResourcePreCommand ;
+ reloadresourcepostcommand = options.ReloadResourcePostCommand ;
+ testprecommand = options.TestPreCommand ;
+ testpostcommand = options.TestPostCommand;
+
//mxd. Add script compilers
- foreach(KeyValuePair group in General.CompiledScriptConfigs)
+ foreach (KeyValuePair group in General.CompiledScriptConfigs)
{
scriptcompiler.Items.Add(group.Value);
}
@@ -110,6 +121,8 @@ namespace CodeImp.DoomBuilder.Windows
// Fill the resources list
datalocations.EditResourceLocationList(options.Resources);
+
+ //reloadresourceprecmd.Text = options.ReloadResourcePreCommand;
}
// OK clicked
@@ -247,6 +260,15 @@ namespace CodeImp.DoomBuilder.Windows
options.StrictPatches = strictpatches.Checked;
options.CopyResources(datalocations.GetResources());
+ // Only store the pre and post commands in the map options if they were actually changed (i.e. the user pressed the OK button the the dialog)
+ if (prepostcommandsmodified)
+ {
+ options.ReloadResourcePreCommand = reloadresourceprecommand;
+ options.ReloadResourcePostCommand = reloadresourcepostcommand;
+ options.TestPreCommand = testprecommand;
+ options.TestPostCommand = testpostcommand;
+ }
+
//mxd. Store script compiler
if(scriptcompiler.Enabled)
{
@@ -264,6 +286,8 @@ namespace CodeImp.DoomBuilder.Windows
//mxd. Use long texture names?
if(longtexturenames.Enabled) options.UseLongTextureNames = longtexturenames.Checked;
+ //options.ReloadResourcePreCommand = reloadresourceprecmd.Text;
+
// Hide window
this.DialogResult = DialogResult.OK;
this.Close();
@@ -347,5 +371,22 @@ namespace CodeImp.DoomBuilder.Windows
General.ShowHelp("w_mapoptions.html");
hlpevent.Handled = true;
}
+
+
+ private void prepostcommands_Click(object sender, EventArgs e)
+ {
+ PreAndPostCommandsForm papcf = new PreAndPostCommandsForm(reloadresourceprecommand, reloadresourcepostcommand, testprecommand, testpostcommand);
+ papcf.ShowDialog();
+
+ if (papcf.DialogResult == DialogResult.OK)
+ {
+ reloadresourceprecommand = papcf.GetReloadResourcePreCommand();
+ reloadresourcepostcommand = papcf.GetReloadResourcePostCommand();
+ testprecommand = papcf.GetTestPreCommand();
+ testpostcommand = papcf.GetTestPostCommand();
+
+ prepostcommandsmodified = true;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/Source/Core/Windows/OpenMapOptionsForm.Designer.cs b/Source/Core/Windows/OpenMapOptionsForm.Designer.cs
index e3720437..cb1c44be 100755
--- a/Source/Core/Windows/OpenMapOptionsForm.Designer.cs
+++ b/Source/Core/Windows/OpenMapOptionsForm.Designer.cs
@@ -132,7 +132,7 @@ namespace CodeImp.DoomBuilder.Windows
// apply
//
this.apply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.apply.Location = new System.Drawing.Point(178, 513);
+ this.apply.Location = new System.Drawing.Point(178, 510);
this.apply.Name = "apply";
this.apply.Size = new System.Drawing.Size(112, 25);
this.apply.TabIndex = 3;
@@ -144,7 +144,7 @@ namespace CodeImp.DoomBuilder.Windows
//
this.cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.cancel.Location = new System.Drawing.Point(296, 513);
+ this.cancel.Location = new System.Drawing.Point(296, 510);
this.cancel.Name = "cancel";
this.cancel.Size = new System.Drawing.Size(112, 25);
this.cancel.TabIndex = 4;
@@ -214,7 +214,7 @@ namespace CodeImp.DoomBuilder.Windows
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.CancelButton = this.cancel;
- this.ClientSize = new System.Drawing.Size(420, 544);
+ this.ClientSize = new System.Drawing.Size(420, 541);
this.Controls.Add(this.scriptcompiler);
this.Controls.Add(this.scriptcompilerlabel);
this.Controls.Add(this.mapslist);
@@ -255,7 +255,5 @@ namespace CodeImp.DoomBuilder.Windows
private System.Windows.Forms.Label scriptcompilerlabel;
private System.Windows.Forms.CheckBox longtexturenames;
private System.Windows.Forms.ToolTip tooltip;
-
-
}
}
\ No newline at end of file
diff --git a/Source/Core/Windows/PreAndPostCommandsForm.Designer.cs b/Source/Core/Windows/PreAndPostCommandsForm.Designer.cs
new file mode 100644
index 00000000..514e6259
--- /dev/null
+++ b/Source/Core/Windows/PreAndPostCommandsForm.Designer.cs
@@ -0,0 +1,248 @@
+namespace CodeImp.DoomBuilder.Windows
+{
+ partial class PreAndPostCommandsForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.btnOK = new System.Windows.Forms.Button();
+ this.btnCancel = new System.Windows.Forms.Button();
+ this.tabControl1 = new System.Windows.Forms.TabControl();
+ this.tabPage1 = new System.Windows.Forms.TabPage();
+ this.label2 = new System.Windows.Forms.Label();
+ this.groupBox2 = new System.Windows.Forms.GroupBox();
+ this.reloadpost = new CodeImp.DoomBuilder.Controls.ExternalCommandControl();
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.reloadpre = new CodeImp.DoomBuilder.Controls.ExternalCommandControl();
+ this.tabPage2 = new System.Windows.Forms.TabPage();
+ this.label1 = new System.Windows.Forms.Label();
+ this.groupBox3 = new System.Windows.Forms.GroupBox();
+ this.testpost = new CodeImp.DoomBuilder.Controls.ExternalCommandControl();
+ this.groupBox4 = new System.Windows.Forms.GroupBox();
+ this.testpre = new CodeImp.DoomBuilder.Controls.ExternalCommandControl();
+ this.tabControl1.SuspendLayout();
+ this.tabPage1.SuspendLayout();
+ this.groupBox2.SuspendLayout();
+ this.groupBox1.SuspendLayout();
+ this.tabPage2.SuspendLayout();
+ this.groupBox3.SuspendLayout();
+ this.groupBox4.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // btnOK
+ //
+ this.btnOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnOK.Location = new System.Drawing.Point(524, 678);
+ this.btnOK.Name = "btnOK";
+ this.btnOK.Size = new System.Drawing.Size(75, 23);
+ this.btnOK.TabIndex = 3;
+ this.btnOK.Text = "OK";
+ this.btnOK.UseVisualStyleBackColor = true;
+ this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
+ //
+ // btnCancel
+ //
+ this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.btnCancel.Location = new System.Drawing.Point(605, 678);
+ this.btnCancel.Name = "btnCancel";
+ this.btnCancel.Size = new System.Drawing.Size(75, 23);
+ this.btnCancel.TabIndex = 3;
+ this.btnCancel.Text = "Cancel";
+ this.btnCancel.UseVisualStyleBackColor = true;
+ this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+ //
+ // tabControl1
+ //
+ this.tabControl1.Controls.Add(this.tabPage1);
+ this.tabControl1.Controls.Add(this.tabPage2);
+ this.tabControl1.Location = new System.Drawing.Point(12, 12);
+ this.tabControl1.Name = "tabControl1";
+ this.tabControl1.SelectedIndex = 0;
+ this.tabControl1.Size = new System.Drawing.Size(670, 657);
+ this.tabControl1.TabIndex = 4;
+ //
+ // tabPage1
+ //
+ this.tabPage1.Controls.Add(this.label2);
+ this.tabPage1.Controls.Add(this.groupBox2);
+ this.tabPage1.Controls.Add(this.groupBox1);
+ this.tabPage1.Location = new System.Drawing.Point(4, 22);
+ this.tabPage1.Name = "tabPage1";
+ this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
+ this.tabPage1.Size = new System.Drawing.Size(662, 631);
+ this.tabPage1.TabIndex = 0;
+ this.tabPage1.Text = "Reload resources commands";
+ this.tabPage1.UseVisualStyleBackColor = true;
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(6, 15);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(431, 13);
+ this.label2.TabIndex = 8;
+ this.label2.Text = "The commands will be automatically stored in a temporary CMD file and executed as" +
+ " such.";
+ //
+ // groupBox2
+ //
+ this.groupBox2.Controls.Add(this.reloadpost);
+ this.groupBox2.Location = new System.Drawing.Point(6, 336);
+ this.groupBox2.Name = "groupBox2";
+ this.groupBox2.Size = new System.Drawing.Size(649, 289);
+ this.groupBox2.TabIndex = 4;
+ this.groupBox2.TabStop = false;
+ this.groupBox2.Text = "Post commands";
+ //
+ // reloadpost
+ //
+ this.reloadpost.Location = new System.Drawing.Point(6, 19);
+ this.reloadpost.Name = "reloadpost";
+ this.reloadpost.Size = new System.Drawing.Size(633, 268);
+ this.reloadpost.TabIndex = 1;
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this.reloadpre);
+ this.groupBox1.Location = new System.Drawing.Point(6, 41);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Size = new System.Drawing.Size(649, 289);
+ this.groupBox1.TabIndex = 3;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "Pre commands";
+ //
+ // reloadpre
+ //
+ this.reloadpre.Location = new System.Drawing.Point(7, 19);
+ this.reloadpre.Name = "reloadpre";
+ this.reloadpre.Size = new System.Drawing.Size(633, 268);
+ this.reloadpre.TabIndex = 1;
+ //
+ // tabPage2
+ //
+ this.tabPage2.Controls.Add(this.label1);
+ this.tabPage2.Controls.Add(this.groupBox3);
+ this.tabPage2.Controls.Add(this.groupBox4);
+ this.tabPage2.Location = new System.Drawing.Point(4, 22);
+ this.tabPage2.Name = "tabPage2";
+ this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
+ this.tabPage2.Size = new System.Drawing.Size(662, 631);
+ this.tabPage2.TabIndex = 1;
+ this.tabPage2.Text = "Test map commands";
+ this.tabPage2.UseVisualStyleBackColor = true;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(6, 15);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(637, 13);
+ this.label1.TabIndex = 7;
+ this.label1.Text = "The commands will be automatically stored in a temporary CMD file and executed as" +
+ " such. %1 is the full path to the temporary map file.";
+ //
+ // groupBox3
+ //
+ this.groupBox3.Controls.Add(this.testpost);
+ this.groupBox3.Enabled = false;
+ this.groupBox3.Location = new System.Drawing.Point(6, 336);
+ this.groupBox3.Name = "groupBox3";
+ this.groupBox3.Size = new System.Drawing.Size(649, 289);
+ this.groupBox3.TabIndex = 6;
+ this.groupBox3.TabStop = false;
+ this.groupBox3.Text = "Post commands";
+ //
+ // testpost
+ //
+ this.testpost.Location = new System.Drawing.Point(6, 19);
+ this.testpost.Name = "testpost";
+ this.testpost.Size = new System.Drawing.Size(633, 268);
+ this.testpost.TabIndex = 1;
+ //
+ // groupBox4
+ //
+ this.groupBox4.Controls.Add(this.testpre);
+ this.groupBox4.Location = new System.Drawing.Point(6, 41);
+ this.groupBox4.Name = "groupBox4";
+ this.groupBox4.Size = new System.Drawing.Size(649, 289);
+ this.groupBox4.TabIndex = 5;
+ this.groupBox4.TabStop = false;
+ this.groupBox4.Text = "Pre commands";
+ //
+ // testpre
+ //
+ this.testpre.Location = new System.Drawing.Point(7, 19);
+ this.testpre.Name = "testpre";
+ this.testpre.Size = new System.Drawing.Size(633, 268);
+ this.testpre.TabIndex = 1;
+ //
+ // PreAndPostCommandsForm
+ //
+ this.AcceptButton = this.btnOK;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this.btnCancel;
+ this.ClientSize = new System.Drawing.Size(692, 713);
+ this.Controls.Add(this.tabControl1);
+ this.Controls.Add(this.btnOK);
+ this.Controls.Add(this.btnCancel);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "PreAndPostCommandsForm";
+ this.Text = "Pre and post commands";
+ this.tabControl1.ResumeLayout(false);
+ this.tabPage1.ResumeLayout(false);
+ this.tabPage1.PerformLayout();
+ this.groupBox2.ResumeLayout(false);
+ this.groupBox1.ResumeLayout(false);
+ this.tabPage2.ResumeLayout(false);
+ this.tabPage2.PerformLayout();
+ this.groupBox3.ResumeLayout(false);
+ this.groupBox4.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ private System.Windows.Forms.Button btnCancel;
+ private System.Windows.Forms.Button btnOK;
+ private System.Windows.Forms.TabControl tabControl1;
+ private System.Windows.Forms.TabPage tabPage1;
+ private System.Windows.Forms.GroupBox groupBox2;
+ private Controls.ExternalCommandControl reloadpost;
+ private System.Windows.Forms.GroupBox groupBox1;
+ private Controls.ExternalCommandControl reloadpre;
+ private System.Windows.Forms.TabPage tabPage2;
+ private System.Windows.Forms.GroupBox groupBox3;
+ private Controls.ExternalCommandControl testpost;
+ private System.Windows.Forms.GroupBox groupBox4;
+ private Controls.ExternalCommandControl testpre;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.Label label1;
+ }
+}
\ No newline at end of file
diff --git a/Source/Core/Windows/PreAndPostCommandsForm.cs b/Source/Core/Windows/PreAndPostCommandsForm.cs
new file mode 100644
index 00000000..03e6688e
--- /dev/null
+++ b/Source/Core/Windows/PreAndPostCommandsForm.cs
@@ -0,0 +1,97 @@
+#region ================== Copyright (c) 2021 Boris Iwanski
+
+/*
+ * This program is free software: you can redistribute it and/or modify
+ *
+ * it under the terms of the GNU General Public License as published by
+ *
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.If not, see.
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using CodeImp.DoomBuilder.Config;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Windows
+{
+ public partial class PreAndPostCommandsForm : DelayedForm
+ {
+ #region ================== Constructors
+
+ public PreAndPostCommandsForm(ExternalCommandSettings reloadresourceprecommand, ExternalCommandSettings reloadresourcepostcommand, ExternalCommandSettings testprecommand, ExternalCommandSettings testpostcommand)
+ {
+ InitializeComponent();
+
+ reloadpre.Setup(reloadresourceprecommand);
+ reloadpost.Setup(reloadresourcepostcommand);
+ testpre.Setup(testprecommand);
+ testpost.Setup(testpostcommand);
+ }
+
+ #endregion
+
+ #region ================== Methods
+
+ public ExternalCommandSettings GetReloadResourcePreCommand()
+ {
+ return reloadpre.GetSettings();
+ }
+
+ public ExternalCommandSettings GetReloadResourcePostCommand()
+ {
+ return reloadpost.GetSettings();
+ }
+
+ public ExternalCommandSettings GetTestPreCommand()
+ {
+ return testpre.GetSettings();
+ }
+
+ public ExternalCommandSettings GetTestPostCommand()
+ {
+ return testpost.GetSettings();
+ }
+
+ #endregion
+
+ #region ================== Events
+
+ private void btnCancel_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+
+ private void btnOK_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/Core/Windows/PreAndPostCommandsForm.resx b/Source/Core/Windows/PreAndPostCommandsForm.resx
new file mode 100644
index 00000000..1af7de15
--- /dev/null
+++ b/Source/Core/Windows/PreAndPostCommandsForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Source/Core/Windows/RunExternalCommandForm.Designer.cs b/Source/Core/Windows/RunExternalCommandForm.Designer.cs
new file mode 100644
index 00000000..784735c1
--- /dev/null
+++ b/Source/Core/Windows/RunExternalCommandForm.Designer.cs
@@ -0,0 +1,114 @@
+namespace CodeImp.DoomBuilder.Windows
+{
+ partial class RunExternalCommandForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.btnContinue = new System.Windows.Forms.Button();
+ this.btnCancel = new System.Windows.Forms.Button();
+ this.rtbOutput = new System.Windows.Forms.RichTextBox();
+ this.btnRetry = new System.Windows.Forms.Button();
+ this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
+ this.SuspendLayout();
+ //
+ // btnContinue
+ //
+ this.btnContinue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnContinue.Enabled = false;
+ this.btnContinue.Location = new System.Drawing.Point(596, 459);
+ this.btnContinue.Name = "btnContinue";
+ this.btnContinue.Size = new System.Drawing.Size(75, 23);
+ this.btnContinue.TabIndex = 1;
+ this.btnContinue.Text = "Continue";
+ this.toolTip1.SetToolTip(this.btnContinue, "Continues loading the resources");
+ this.btnContinue.UseVisualStyleBackColor = true;
+ this.btnContinue.Click += new System.EventHandler(this.btnContinue_Click);
+ //
+ // btnCancel
+ //
+ this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnCancel.Location = new System.Drawing.Point(677, 459);
+ this.btnCancel.Name = "btnCancel";
+ this.btnCancel.Size = new System.Drawing.Size(75, 23);
+ this.btnCancel.TabIndex = 1;
+ this.btnCancel.Text = "Cancel";
+ this.toolTip1.SetToolTip(this.btnCancel, "Cancels the running command, or cancels loading the resources");
+ this.btnCancel.UseVisualStyleBackColor = true;
+ this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+ //
+ // rtbOutput
+ //
+ this.rtbOutput.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.rtbOutput.Location = new System.Drawing.Point(12, 12);
+ this.rtbOutput.Name = "rtbOutput";
+ this.rtbOutput.ReadOnly = true;
+ this.rtbOutput.Size = new System.Drawing.Size(740, 441);
+ this.rtbOutput.TabIndex = 2;
+ this.rtbOutput.Text = "";
+ //
+ // btnRetry
+ //
+ this.btnRetry.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.btnRetry.Enabled = false;
+ this.btnRetry.Location = new System.Drawing.Point(515, 459);
+ this.btnRetry.Name = "btnRetry";
+ this.btnRetry.Size = new System.Drawing.Size(75, 23);
+ this.btnRetry.TabIndex = 1;
+ this.btnRetry.Text = "Run again";
+ this.toolTip1.SetToolTip(this.btnRetry, "Runs the command again");
+ this.btnRetry.UseVisualStyleBackColor = true;
+ this.btnRetry.Click += new System.EventHandler(this.btnRetry_Click);
+ //
+ // RunExternalCommandForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(766, 494);
+ this.Controls.Add(this.rtbOutput);
+ this.Controls.Add(this.btnRetry);
+ this.Controls.Add(this.btnContinue);
+ this.Controls.Add(this.btnCancel);
+ this.Name = "RunExternalCommandForm";
+ this.ShowIcon = false;
+ this.Text = "Running external command";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.RunExternalCommandForm_FormClosing);
+ this.Shown += new System.EventHandler(this.RunExternalCommandForm_Shown);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ private System.Windows.Forms.Button btnCancel;
+ private System.Windows.Forms.Button btnContinue;
+ private System.Windows.Forms.RichTextBox rtbOutput;
+ private System.Windows.Forms.Button btnRetry;
+ private System.Windows.Forms.ToolTip toolTip1;
+ }
+}
\ No newline at end of file
diff --git a/Source/Core/Windows/RunExternalCommandForm.cs b/Source/Core/Windows/RunExternalCommandForm.cs
new file mode 100644
index 00000000..b6a5343c
--- /dev/null
+++ b/Source/Core/Windows/RunExternalCommandForm.cs
@@ -0,0 +1,290 @@
+#region ================== Copyright (c) 2021 Boris Iwanski
+
+/*
+ * This program is free software: you can redistribute it and/or modify
+ *
+ * it under the terms of the GNU General Public License as published by
+ *
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ *
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.If not, see.
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Diagnostics;
+using System.Drawing;
+using System.Management;
+using System.Threading;
+using System.Windows.Forms;
+using CodeImp.DoomBuilder.Config;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Windows
+{
+ public partial class RunExternalCommandForm : DelayedForm
+ {
+ #region ================== Variables
+
+ private Process process;
+ private ProcessStartInfo startinfo;
+ private Thread runthread;
+ private object lockobj;
+ private bool haserrors;
+ private ExternalCommandSettings settings;
+
+ #endregion
+
+ #region ================== Delegates
+
+ private delegate void CallStringBoolMethodDeletage(string s, bool iserror);
+ private delegate void CallVoidMethodDeletage();
+
+ #endregion
+
+ #region ================== Constructors
+
+ public RunExternalCommandForm(ProcessStartInfo startinfo, ExternalCommandSettings settings)
+ {
+ InitializeComponent();
+
+ lockobj = new object();
+ haserrors = false;
+
+ rtbOutput.Font = new Font(FontFamily.GenericMonospace, rtbOutput.Font.Size);
+
+ this.startinfo = startinfo;
+ this.settings = settings;
+ }
+
+ #endregion
+
+ #region ================== Methods
+
+ ///
+ /// Starts execution of the external command
+ ///
+ private void Start()
+ {
+ rtbOutput.Clear();
+ haserrors = false;
+ btnContinue.Enabled = false;
+ btnRetry.Enabled = false;
+
+ runthread = new Thread(() => Run());
+ runthread.Name = "Run external command";
+ runthread.Priority = ThreadPriority.Normal;
+ runthread.Start();
+ }
+
+ ///
+ /// Stops execution of the external command
+ ///
+ private void Stop()
+ {
+ haserrors = true;
+ process.CancelOutputRead();
+ process.CancelErrorRead();
+ KillProcessAndChildren(process.Id);
+ FinishRun();
+ }
+
+ ///
+ /// Runs the external command
+ ///
+ private void Run()
+ {
+ process = new Process();
+ process.StartInfo = startinfo;
+ process.StartInfo.UseShellExecute = false;
+ process.StartInfo.RedirectStandardOutput = true;
+ process.StartInfo.RedirectStandardError = true;
+ process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ process.StartInfo.CreateNoWindow = true;
+
+ process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
+ process.ErrorDataReceived += new DataReceivedEventHandler(ErrorHandler);
+
+ process.Start();
+ process.BeginOutputReadLine();
+ process.BeginErrorReadLine();
+ process.WaitForExit();
+
+ if (process.ExitCode != 0 && settings.ExitCodeIsError)
+ haserrors = true;
+
+ FinishRun();
+ }
+
+ ///
+ /// Finishes after running the external command. Closes the window if there were no errors
+ ///
+ private void FinishRun()
+ {
+ if(InvokeRequired)
+ {
+ CallVoidMethodDeletage d = FinishRun;
+ Invoke(d);
+ }
+ else
+ {
+ btnContinue.Enabled = true;
+ btnRetry.Enabled = true;
+
+ if(haserrors)
+ {
+ AppendText(Environment.NewLine + Environment.NewLine + "There were errors during the execution of the external commands.", true);
+ AppendText(Environment.NewLine + "Exit code: " + process.ExitCode, true);
+ }
+
+ if(!haserrors && settings.AutoCloseOnSuccess)
+ {
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+ }
+ }
+
+ ///
+ /// Handles lines going to stdout
+ ///
+ /// Process the line is coming from
+ /// The received line event
+ private void OutputHandler(object sendingprocess, DataReceivedEventArgs outline)
+ {
+ if(outline.Data != null)
+ AppendText(outline.Data + Environment.NewLine, false);
+ }
+
+ ///
+ /// handles lines going to stderr
+ ///
+ /// Process the line is coming from
+ /// The received line event
+ private void ErrorHandler(object sendingprocess, DataReceivedEventArgs outline)
+ {
+ if (outline.Data != null)
+ {
+ AppendText(outline.Data + Environment.NewLine, true);
+
+ if(settings.StdErrIsError)
+ haserrors = true;
+ }
+ }
+
+ ///
+ /// Adds a line to the output text box and scrolls to the bottom. Colors the text red if it's an error
+ ///
+ /// Text to append
+ /// If it's an error or not
+ private void AppendText(string text, bool iserror)
+ {
+ if(InvokeRequired)
+ {
+ CallStringBoolMethodDeletage d = AppendText;
+ Invoke(d, text, iserror);
+ }
+ else
+ {
+ lock (lockobj)
+ {
+ rtbOutput.AppendText(text);
+
+ if(iserror)
+ {
+ rtbOutput.Select(rtbOutput.Text.Length - text.Length, text.Length);
+ rtbOutput.SelectionColor = Color.Red;
+ //haserrors = true;
+ }
+
+ rtbOutput.Select(rtbOutput.Text.Length, 0);
+ rtbOutput.ScrollToCaret();
+ }
+ }
+ }
+
+ ///
+ /// Recursively kill a process and its childern. Taken from https://stackoverflow.com/a/40265540
+ ///
+ /// Process id
+ private static void KillProcessAndChildren(int pid)
+ {
+ ManagementObjectSearcher processSearcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid);
+ ManagementObjectCollection processCollection = processSearcher.Get();
+
+ // We must kill child processes first!
+ if (processCollection != null)
+ {
+ foreach (ManagementObject mo in processCollection)
+ {
+ KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"])); //kill child processes(also kills childrens of childrens etc.)
+ }
+ }
+
+ // Then kill parents.
+ try
+ {
+ Process proc = Process.GetProcessById(pid);
+ if (!proc.HasExited) proc.Kill();
+ }
+ catch (ArgumentException)
+ {
+ // Process already exited.
+ }
+ }
+
+ #endregion
+
+ #region ================== Events
+
+ private void RunExternalCommandForm_Shown(object sender, EventArgs e)
+ {
+ Start();
+ }
+
+ private void btnCancel_Click(object sender, EventArgs e)
+ {
+ if (process.HasExited)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+ else
+ {
+ Stop();
+ }
+ }
+
+ private void btnRetry_Click(object sender, EventArgs e)
+ {
+ Start();
+ }
+
+ private void btnContinue_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+
+ private void RunExternalCommandForm_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ if (!process.HasExited)
+ e.Cancel = true;
+ }
+
+ #endregion
+ }
+}
diff --git a/Source/Core/Windows/RunExternalCommandForm.resx b/Source/Core/Windows/RunExternalCommandForm.resx
new file mode 100644
index 00000000..d54ad1e4
--- /dev/null
+++ b/Source/Core/Windows/RunExternalCommandForm.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 17, 17
+
+
\ No newline at end of file