From 54e3b4ff3fceaacd9bc8ec66cbc44ab316b6970a Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Fri, 30 Dec 2022 17:53:17 +0100
Subject: [PATCH] Implement thing edit form

---
 Build/Configurations/Includes/SRB222_misc.cfg |  35 -
 Source/Core/Builder.csproj                    |   9 +
 Source/Core/BuilderMono.csproj                |   9 +
 Source/Core/Controls/ArgumentsControlSRB2.cs  |  49 +-
 Source/Core/Map/Thing.cs                      |   2 +-
 Source/Core/Resources/UDMF_UI.cfg             |   3 +
 Source/Core/Windows/MainForm.cs               |   9 +-
 .../Windows/ThingEditFormSRB2.Designer.cs     | 807 ++++++++++++++++
 Source/Core/Windows/ThingEditFormSRB2.cs      | 877 ++++++++++++++++++
 Source/Core/Windows/ThingEditFormSRB2.resx    | 123 +++
 10 files changed, 1873 insertions(+), 50 deletions(-)
 create mode 100644 Source/Core/Windows/ThingEditFormSRB2.Designer.cs
 create mode 100644 Source/Core/Windows/ThingEditFormSRB2.cs
 create mode 100644 Source/Core/Windows/ThingEditFormSRB2.resx

diff --git a/Build/Configurations/Includes/SRB222_misc.cfg b/Build/Configurations/Includes/SRB222_misc.cfg
index 6c41303bd..65ce70c60 100644
--- a/Build/Configurations/Includes/SRB222_misc.cfg
+++ b/Build/Configurations/Includes/SRB222_misc.cfg
@@ -235,41 +235,6 @@ universalfields
 
 	thing
 	{
-		arg5
-		{
-			type = 0;
-			default = 0;
-		}
-		arg6
-		{
-			type = 0;
-			default = 0;
-		}
-		arg7
-		{
-			type = 0;
-			default = 0;
-		}
-		arg8
-		{
-			type = 0;
-			default = 0;
-		}
-		arg9
-		{
-			type = 0;
-			default = 0;
-		}
-		stringarg0
-		{
-			type = 2;
-			default = "";
-		}
-		stringarg1
-		{
-			type = 2;
-			default = "";
-		}
 	}
 }
 
diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj
index 6d412764f..675b6ad35 100644
--- a/Source/Core/Builder.csproj
+++ b/Source/Core/Builder.csproj
@@ -307,6 +307,12 @@
     <Compile Include="Windows\SectorEditFormSRB2.Designer.cs">
       <DependentUpon>SectorEditFormSRB2.cs</DependentUpon>
     </Compile>
+    <Compile Include="Windows\ThingEditFormSRB2.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Windows\ThingEditFormSRB2.Designer.cs">
+      <DependentUpon>ThingEditFormSRB2.cs</DependentUpon>
+    </Compile>
     <Compile Include="Windows\ThingStatisticsForm.cs">
       <SubType>Form</SubType>
     </Compile>
@@ -705,6 +711,9 @@
     <EmbeddedResource Include="Windows\SectorEditFormSRB2.resx">
       <DependentUpon>SectorEditFormSRB2.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="Windows\ThingEditFormSRB2.resx">
+      <DependentUpon>ThingEditFormSRB2.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="Windows\ThingStatisticsForm.resx">
       <DependentUpon>ThingStatisticsForm.cs</DependentUpon>
     </EmbeddedResource>
diff --git a/Source/Core/BuilderMono.csproj b/Source/Core/BuilderMono.csproj
index cb64c5bdc..2c2dd38d6 100644
--- a/Source/Core/BuilderMono.csproj
+++ b/Source/Core/BuilderMono.csproj
@@ -299,6 +299,12 @@
     <Compile Include="Windows\SectorEditFormSRB2.Designer.cs">
       <DependentUpon>SectorEditFormSRB2.cs</DependentUpon>
     </Compile>
+    <Compile Include="Windows\ThingEditFormSRB2.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Windows\ThingEditFormSRB2.Designer.cs">
+      <DependentUpon>ThingEditFormSRB2.cs</DependentUpon>
+    </Compile>
     <Compile Include="Windows\ThingStatisticsForm.cs">
       <SubType>Form</SubType>
     </Compile>
@@ -697,6 +703,9 @@
     <EmbeddedResource Include="Windows\SectorEditFormSRB2.resx">
       <DependentUpon>SectorEditFormSRB2.cs</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="Windows\ThingEditFormSRB2.resx">
+      <DependentUpon>ThingEditFormSRB2.cs</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="Windows\ThingStatisticsForm.resx">
       <DependentUpon>ThingStatisticsForm.cs</DependentUpon>
     </EmbeddedResource>
diff --git a/Source/Core/Controls/ArgumentsControlSRB2.cs b/Source/Core/Controls/ArgumentsControlSRB2.cs
index 3d8e9ca01..f9e0c6412 100644
--- a/Source/Core/Controls/ArgumentsControlSRB2.cs
+++ b/Source/Core/Controls/ArgumentsControlSRB2.cs
@@ -123,13 +123,8 @@ namespace CodeImp.DoomBuilder.Controls
 
 		#region ================== Update
 
-		public void UpdateAction(int action, bool setuponly)
-		{
-			UpdateAction(action, setuponly, null);
-		}
-
 		//TODO: Info for string args
-		public void UpdateAction(int action, bool setuponly, ThingTypeInfo info)
+		public void UpdateAction(int action, bool setuponly)
 		{
 			// Update arguments
 			int showaction = 0;
@@ -139,11 +134,7 @@ namespace CodeImp.DoomBuilder.Controls
 			if (General.Map.Config.LinedefActions.ContainsKey(action)) showaction = action;
 
 			// Update argument infos
-			if ((showaction == 0) && (info != null)) arginfo = info.Args;
-			else arginfo = General.Map.Config.LinedefActions[showaction].Args;
-
-			// Don't update action args when thing type is changed
-			if (info != null && showaction != 0 && this.action == showaction) return;
+			arginfo = General.Map.Config.LinedefActions[showaction].Args;
 
 			//mxd. Don't update action args when old and new argument infos match
 			if (arginfo != null && oldarginfo != null && ArgumentInfosMatch(arginfo, oldarginfo)) return;
@@ -156,8 +147,8 @@ namespace CodeImp.DoomBuilder.Controls
 
 			if (!setuponly)
 			{
-				// Apply action's or thing's default arguments
-				if (showaction != 0 || info != null)
+				// Apply action's default arguments
+				if (showaction != 0)
 				{
 					for (int i = 0; i < args.Length; i++)
 						args[i].SetDefaultValue();
@@ -175,6 +166,38 @@ namespace CodeImp.DoomBuilder.Controls
 			this.EndUpdate();
 		}
 
+		public void UpdateThingType(ThingTypeInfo info)
+		{
+			// Update arguments
+			ArgumentInfo[] oldarginfo = (arginfo != null ? (ArgumentInfo[])arginfo.Clone() : null); //mxd
+
+			// Update argument infos
+			arginfo = info.Args;
+
+			//mxd. Don't update args when old and new argument infos match
+			if (arginfo != null && oldarginfo != null && ArgumentInfosMatch(arginfo, oldarginfo)) return;
+
+			// Change the argument descriptions
+			this.BeginUpdate();
+
+			for (int i = 0; i < args.Length; i++)
+				UpdateArgument(args[i], labels[i], arginfo[i]);
+
+			// Apply thing's default arguments
+			if (info != null)
+			{
+				for (int i = 0; i < args.Length; i++)
+					args[i].SetDefaultValue();
+			}
+			else //or set them to 0
+			{
+				for (int i = 0; i < args.Length; i++)
+					args[i].SetValue(0);
+			}
+
+			this.EndUpdate();
+		}
+
 		public void UpdateScriptControls()
 		{
 		}
diff --git a/Source/Core/Map/Thing.cs b/Source/Core/Map/Thing.cs
index fa929814b..d98caa2cf 100755
--- a/Source/Core/Map/Thing.cs
+++ b/Source/Core/Map/Thing.cs
@@ -36,7 +36,7 @@ namespace CodeImp.DoomBuilder.Map
 	{
 		#region ================== Constants
 
-		public const int NUM_ARGS = 5;
+		public const int NUM_ARGS = 10;
 		public static readonly HashSet<ThingRenderMode> AlignableRenderModes = new HashSet<ThingRenderMode>
 		{
 			ThingRenderMode.FLATSPRITE, ThingRenderMode.WALLSPRITE, ThingRenderMode.MODEL
diff --git a/Source/Core/Resources/UDMF_UI.cfg b/Source/Core/Resources/UDMF_UI.cfg
index 8409793b7..5df1c6985 100755
--- a/Source/Core/Resources/UDMF_UI.cfg
+++ b/Source/Core/Resources/UDMF_UI.cfg
@@ -105,5 +105,8 @@ uifields
 		comment = 2;
 		scalex = 1;
 		scaley = 1;
+		scale = 1;
+		stringarg0 = 2;
+		stringarg1 = 2;
 	}
 }
\ No newline at end of file
diff --git a/Source/Core/Windows/MainForm.cs b/Source/Core/Windows/MainForm.cs
index a06db934c..71bc4dded 100755
--- a/Source/Core/Windows/MainForm.cs
+++ b/Source/Core/Windows/MainForm.cs
@@ -4261,7 +4261,14 @@ namespace CodeImp.DoomBuilder.Windows
 		{
 			if (General.Map.UDMF)
 			{
-				return new ThingEditFormUDMF();
+				if (General.Map.Config.EngineName == "srb2")
+				{
+					return new ThingEditFormSRB2();
+				}
+				else
+				{
+					return new ThingEditFormUDMF();
+				}
 			}
 			else
 			{
diff --git a/Source/Core/Windows/ThingEditFormSRB2.Designer.cs b/Source/Core/Windows/ThingEditFormSRB2.Designer.cs
new file mode 100644
index 000000000..b4131d477
--- /dev/null
+++ b/Source/Core/Windows/ThingEditFormSRB2.Designer.cs
@@ -0,0 +1,807 @@
+namespace CodeImp.DoomBuilder.Windows
+{
+	partial class ThingEditFormSRB2
+	{
+		/// <summary>
+		/// Required designer variable.
+		/// </summary>
+		private System.ComponentModel.IContainer components = null;
+
+		/// <summary>
+		/// Clean up any resources being used.
+		/// </summary>
+		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+		protected override void Dispose(bool disposing) 
+		{
+			if(disposing && (components != null)) 
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Windows Form Designer generated code
+
+		/// <summary>
+		/// Required method for Designer support - do not modify
+		/// the contents of this method with the code editor.
+		/// </summary>
+		private void InitializeComponent() 
+		{
+			this.components = new System.ComponentModel.Container();
+			this.groupBox1 = new System.Windows.Forms.GroupBox();
+			this.thingtype = new CodeImp.DoomBuilder.Controls.ThingBrowserControl();
+			this.groupBox2 = new System.Windows.Forms.GroupBox();
+			this.cbrandomroll = new System.Windows.Forms.CheckBox();
+			this.cbrandompitch = new System.Windows.Forms.CheckBox();
+			this.cbrandomangle = new System.Windows.Forms.CheckBox();
+			this.roll = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+			this.labelroll = new System.Windows.Forms.Label();
+			this.pitch = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+			this.labelpitch = new System.Windows.Forms.Label();
+			this.angle = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+			this.labelAngle = new System.Windows.Forms.Label();
+			this.anglecontrol = new CodeImp.DoomBuilder.Controls.AngleControlEx();
+			this.tabs = new System.Windows.Forms.TabControl();
+			this.tabproperties = new System.Windows.Forms.TabPage();
+			this.settingsgroup = new System.Windows.Forms.GroupBox();
+			this.missingflags = new System.Windows.Forms.PictureBox();
+			this.flags = new CodeImp.DoomBuilder.Controls.CheckboxArrayControl();
+			this.grouproll = new System.Windows.Forms.GroupBox();
+			this.rollControl = new CodeImp.DoomBuilder.Controls.AngleControlEx();
+			this.grouppitch = new System.Windows.Forms.GroupBox();
+			this.pitchControl = new CodeImp.DoomBuilder.Controls.AngleControlEx();
+			this.groupangle = new System.Windows.Forms.GroupBox();
+			this.groupBox4 = new System.Windows.Forms.GroupBox();
+			this.cbAbsoluteHeight = new System.Windows.Forms.CheckBox();
+			this.label4 = new System.Windows.Forms.Label();
+			this.label5 = new System.Windows.Forms.Label();
+			this.posX = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+			this.posY = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+			this.posZ = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+			this.zlabel = new System.Windows.Forms.Label();
+			this.tabeffects = new System.Windows.Forms.TabPage();
+			this.grouprendering = new System.Windows.Forms.GroupBox();
+			this.labelScale = new System.Windows.Forms.Label();
+			this.scale = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+			this.actiongroup = new System.Windows.Forms.GroupBox();
+			this.argscontrol = new CodeImp.DoomBuilder.Controls.ArgumentsControlSRB2();
+			this.grouptag = new System.Windows.Forms.GroupBox();
+			this.tagSelector = new CodeImp.DoomBuilder.Controls.TagSelector();
+			this.tabcomment = new System.Windows.Forms.TabPage();
+			this.commenteditor = new CodeImp.DoomBuilder.Controls.CommentEditor();
+			this.tabcustom = new System.Windows.Forms.TabPage();
+			this.hidefixedfields = new System.Windows.Forms.CheckBox();
+			this.fieldslist = new CodeImp.DoomBuilder.Controls.FieldsEditorControl();
+			this.cancel = new System.Windows.Forms.Button();
+			this.apply = new System.Windows.Forms.Button();
+			this.hint = new System.Windows.Forms.PictureBox();
+			this.hintlabel = new System.Windows.Forms.Label();
+			this.tooltip = new System.Windows.Forms.ToolTip(this.components);
+			this.groupBox1.SuspendLayout();
+			this.groupBox2.SuspendLayout();
+			this.tabs.SuspendLayout();
+			this.tabproperties.SuspendLayout();
+			this.settingsgroup.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.missingflags)).BeginInit();
+			this.grouproll.SuspendLayout();
+			this.grouppitch.SuspendLayout();
+			this.groupangle.SuspendLayout();
+			this.groupBox4.SuspendLayout();
+			this.tabeffects.SuspendLayout();
+			this.grouprendering.SuspendLayout();
+			this.actiongroup.SuspendLayout();
+			this.grouptag.SuspendLayout();
+			this.tabcomment.SuspendLayout();
+			this.tabcustom.SuspendLayout();
+			((System.ComponentModel.ISupportInitialize)(this.hint)).BeginInit();
+			this.SuspendLayout();
+			// 
+			// groupBox1
+			// 
+			this.groupBox1.Controls.Add(this.thingtype);
+			this.groupBox1.Location = new System.Drawing.Point(6, 6);
+			this.groupBox1.Name = "groupBox1";
+			this.groupBox1.Size = new System.Drawing.Size(230, 390);
+			this.groupBox1.TabIndex = 0;
+			this.groupBox1.TabStop = false;
+			this.groupBox1.Text = " Thing ";
+			// 
+			// thingtype
+			// 
+			this.thingtype.Location = new System.Drawing.Point(9, 13);
+			this.thingtype.Margin = new System.Windows.Forms.Padding(6);
+			this.thingtype.Name = "thingtype";
+			this.thingtype.Size = new System.Drawing.Size(212, 374);
+			this.thingtype.TabIndex = 0;
+			this.thingtype.UseMultiSelection = true;
+			this.thingtype.OnTypeChanged += new CodeImp.DoomBuilder.Controls.ThingBrowserControl.TypeChangedDeletegate(this.thingtype_OnTypeChanged);
+			this.thingtype.OnTypeDoubleClicked += new CodeImp.DoomBuilder.Controls.ThingBrowserControl.TypeDoubleClickDeletegate(this.thingtype_OnTypeDoubleClicked);
+			// 
+			// groupBox2
+			// 
+			this.groupBox2.Controls.Add(this.cbrandomroll);
+			this.groupBox2.Controls.Add(this.cbrandompitch);
+			this.groupBox2.Controls.Add(this.cbrandomangle);
+			this.groupBox2.Controls.Add(this.roll);
+			this.groupBox2.Controls.Add(this.labelroll);
+			this.groupBox2.Controls.Add(this.pitch);
+			this.groupBox2.Controls.Add(this.labelpitch);
+			this.groupBox2.Controls.Add(this.angle);
+			this.groupBox2.Controls.Add(this.labelAngle);
+			this.groupBox2.Location = new System.Drawing.Point(428, 298);
+			this.groupBox2.Name = "groupBox2";
+			this.groupBox2.Size = new System.Drawing.Size(193, 98);
+			this.groupBox2.TabIndex = 6;
+			this.groupBox2.TabStop = false;
+			this.groupBox2.Text = " Rotation ";
+			// 
+			// cbrandomroll
+			// 
+			this.cbrandomroll.AutoSize = true;
+			this.cbrandomroll.Location = new System.Drawing.Point(120, 71);
+			this.cbrandomroll.Name = "cbrandomroll";
+			this.cbrandomroll.Size = new System.Drawing.Size(66, 17);
+			this.cbrandomroll.TabIndex = 5;
+			this.cbrandomroll.Text = "Random";
+			this.cbrandomroll.UseVisualStyleBackColor = true;
+			this.cbrandomroll.CheckedChanged += new System.EventHandler(this.cbrandomroll_CheckedChanged);
+			// 
+			// cbrandompitch
+			// 
+			this.cbrandompitch.AutoSize = true;
+			this.cbrandompitch.Location = new System.Drawing.Point(120, 46);
+			this.cbrandompitch.Name = "cbrandompitch";
+			this.cbrandompitch.Size = new System.Drawing.Size(66, 17);
+			this.cbrandompitch.TabIndex = 3;
+			this.cbrandompitch.Text = "Random";
+			this.cbrandompitch.UseVisualStyleBackColor = true;
+			this.cbrandompitch.CheckedChanged += new System.EventHandler(this.cbrandompitch_CheckedChanged);
+			// 
+			// cbrandomangle
+			// 
+			this.cbrandomangle.AutoSize = true;
+			this.cbrandomangle.Location = new System.Drawing.Point(120, 21);
+			this.cbrandomangle.Name = "cbrandomangle";
+			this.cbrandomangle.Size = new System.Drawing.Size(66, 17);
+			this.cbrandomangle.TabIndex = 1;
+			this.cbrandomangle.Text = "Random";
+			this.cbrandomangle.UseVisualStyleBackColor = true;
+			this.cbrandomangle.CheckedChanged += new System.EventHandler(this.cbrandomangle_CheckedChanged);
+			// 
+			// roll
+			// 
+			this.roll.AllowDecimal = false;
+			this.roll.AllowExpressions = true;
+			this.roll.AllowNegative = true;
+			this.roll.AllowRelative = true;
+			this.roll.ButtonStep = 5;
+			this.roll.ButtonStepBig = 15F;
+			this.roll.ButtonStepFloat = 1F;
+			this.roll.ButtonStepSmall = 1F;
+			this.roll.ButtonStepsUseModifierKeys = true;
+			this.roll.ButtonStepsWrapAround = false;
+			this.roll.Location = new System.Drawing.Point(55, 66);
+			this.roll.Name = "roll";
+			this.roll.Size = new System.Drawing.Size(60, 24);
+			this.roll.StepValues = null;
+			this.roll.TabIndex = 4;
+			this.roll.WhenTextChanged += new System.EventHandler(this.roll_WhenTextChanged);
+			// 
+			// labelroll
+			// 
+			this.labelroll.Location = new System.Drawing.Point(5, 71);
+			this.labelroll.Name = "labelroll";
+			this.labelroll.Size = new System.Drawing.Size(44, 14);
+			this.labelroll.TabIndex = 23;
+			this.labelroll.Text = "Roll:";
+			this.labelroll.TextAlign = System.Drawing.ContentAlignment.TopRight;
+			// 
+			// pitch
+			// 
+			this.pitch.AllowDecimal = false;
+			this.pitch.AllowExpressions = true;
+			this.pitch.AllowNegative = true;
+			this.pitch.AllowRelative = true;
+			this.pitch.ButtonStep = 5;
+			this.pitch.ButtonStepBig = 15F;
+			this.pitch.ButtonStepFloat = 1F;
+			this.pitch.ButtonStepSmall = 1F;
+			this.pitch.ButtonStepsUseModifierKeys = true;
+			this.pitch.ButtonStepsWrapAround = false;
+			this.pitch.Location = new System.Drawing.Point(55, 41);
+			this.pitch.Name = "pitch";
+			this.pitch.Size = new System.Drawing.Size(60, 24);
+			this.pitch.StepValues = null;
+			this.pitch.TabIndex = 2;
+			this.pitch.WhenTextChanged += new System.EventHandler(this.pitch_WhenTextChanged);
+			// 
+			// labelpitch
+			// 
+			this.labelpitch.Location = new System.Drawing.Point(5, 46);
+			this.labelpitch.Name = "labelpitch";
+			this.labelpitch.Size = new System.Drawing.Size(44, 14);
+			this.labelpitch.TabIndex = 21;
+			this.labelpitch.Text = "Pitch:";
+			this.labelpitch.TextAlign = System.Drawing.ContentAlignment.TopRight;
+			// 
+			// angle
+			// 
+			this.angle.AllowDecimal = false;
+			this.angle.AllowExpressions = true;
+			this.angle.AllowNegative = true;
+			this.angle.AllowRelative = true;
+			this.angle.ButtonStep = 5;
+			this.angle.ButtonStepBig = 15F;
+			this.angle.ButtonStepFloat = 1F;
+			this.angle.ButtonStepSmall = 1F;
+			this.angle.ButtonStepsUseModifierKeys = true;
+			this.angle.ButtonStepsWrapAround = false;
+			this.angle.Location = new System.Drawing.Point(55, 16);
+			this.angle.Name = "angle";
+			this.angle.Size = new System.Drawing.Size(60, 24);
+			this.angle.StepValues = null;
+			this.angle.TabIndex = 0;
+			this.angle.WhenTextChanged += new System.EventHandler(this.angle_WhenTextChanged);
+			// 
+			// labelAngle
+			// 
+			this.labelAngle.Location = new System.Drawing.Point(5, 21);
+			this.labelAngle.Name = "labelAngle";
+			this.labelAngle.Size = new System.Drawing.Size(44, 14);
+			this.labelAngle.TabIndex = 8;
+			this.labelAngle.Text = "Angle:";
+			this.labelAngle.TextAlign = System.Drawing.ContentAlignment.TopRight;
+			// 
+			// anglecontrol
+			// 
+			this.anglecontrol.Angle = 0;
+			this.anglecontrol.AngleOffset = 0;
+			this.anglecontrol.DoomAngleClamping = false;
+			this.anglecontrol.Location = new System.Drawing.Point(7, 17);
+			this.anglecontrol.Name = "anglecontrol";
+			this.anglecontrol.Size = new System.Drawing.Size(64, 64);
+			this.anglecontrol.TabIndex = 20;
+			this.anglecontrol.AngleChanged += new System.EventHandler(this.anglecontrol_AngleChanged);
+			// 
+			// tabs
+			// 
+			this.tabs.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.tabs.Controls.Add(this.tabproperties);
+			this.tabs.Controls.Add(this.tabeffects);
+			this.tabs.Controls.Add(this.tabcomment);
+			this.tabs.Controls.Add(this.tabcustom);
+			this.tabs.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+			this.tabs.Location = new System.Drawing.Point(10, 10);
+			this.tabs.Margin = new System.Windows.Forms.Padding(1);
+			this.tabs.Name = "tabs";
+			this.tabs.Padding = new System.Drawing.Point(24, 3);
+			this.tabs.SelectedIndex = 0;
+			this.tabs.Size = new System.Drawing.Size(635, 425);
+			this.tabs.TabIndex = 0;
+			// 
+			// tabproperties
+			// 
+			this.tabproperties.Controls.Add(this.settingsgroup);
+			this.tabproperties.Controls.Add(this.grouproll);
+			this.tabproperties.Controls.Add(this.grouppitch);
+			this.tabproperties.Controls.Add(this.groupangle);
+			this.tabproperties.Controls.Add(this.groupBox4);
+			this.tabproperties.Controls.Add(this.groupBox2);
+			this.tabproperties.Controls.Add(this.groupBox1);
+			this.tabproperties.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+			this.tabproperties.Location = new System.Drawing.Point(4, 22);
+			this.tabproperties.Name = "tabproperties";
+			this.tabproperties.Padding = new System.Windows.Forms.Padding(3);
+			this.tabproperties.Size = new System.Drawing.Size(627, 399);
+			this.tabproperties.TabIndex = 0;
+			this.tabproperties.Text = "Properties";
+			this.tabproperties.UseVisualStyleBackColor = true;
+			// 
+			// settingsgroup
+			// 
+			this.settingsgroup.Controls.Add(this.missingflags);
+			this.settingsgroup.Controls.Add(this.flags);
+			this.settingsgroup.Location = new System.Drawing.Point(242, 6);
+			this.settingsgroup.Name = "settingsgroup";
+			this.settingsgroup.Size = new System.Drawing.Size(295, 286);
+			this.settingsgroup.TabIndex = 1;
+			this.settingsgroup.TabStop = false;
+			this.settingsgroup.Text = " Flags ";
+			// 
+			// missingflags
+			// 
+			this.missingflags.BackColor = System.Drawing.SystemColors.Window;
+			this.missingflags.Image = global::CodeImp.DoomBuilder.Properties.Resources.Warning;
+			this.missingflags.Location = new System.Drawing.Point(42, -2);
+			this.missingflags.Name = "missingflags";
+			this.missingflags.Size = new System.Drawing.Size(16, 16);
+			this.missingflags.TabIndex = 5;
+			this.missingflags.TabStop = false;
+			this.missingflags.Visible = false;
+			// 
+			// flags
+			// 
+			this.flags.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.flags.AutoScroll = true;
+			this.flags.Columns = 2;
+			this.flags.Location = new System.Drawing.Point(6, 19);
+			this.flags.Name = "flags";
+			this.flags.Size = new System.Drawing.Size(283, 260);
+			this.flags.TabIndex = 0;
+			this.flags.VerticalSpacing = 1;
+			this.flags.OnValueChanged += new System.EventHandler(this.flags_OnValueChanged);
+			// 
+			// grouproll
+			// 
+			this.grouproll.Controls.Add(this.rollControl);
+			this.grouproll.Location = new System.Drawing.Point(543, 16);
+			this.grouproll.Name = "grouproll";
+			this.grouproll.Size = new System.Drawing.Size(78, 88);
+			this.grouproll.TabIndex = 2;
+			this.grouproll.TabStop = false;
+			this.grouproll.Text = " Roll ";
+			// 
+			// rollControl
+			// 
+			this.rollControl.Angle = -90;
+			this.rollControl.AngleOffset = 0;
+			this.rollControl.DoomAngleClamping = false;
+			this.rollControl.Location = new System.Drawing.Point(7, 17);
+			this.rollControl.Name = "rollControl";
+			this.rollControl.Size = new System.Drawing.Size(64, 64);
+			this.rollControl.TabIndex = 20;
+			this.rollControl.AngleChanged += new System.EventHandler(this.rollControl_AngleChanged);
+			// 
+			// grouppitch
+			// 
+			this.grouppitch.Controls.Add(this.pitchControl);
+			this.grouppitch.Location = new System.Drawing.Point(543, 110);
+			this.grouppitch.Name = "grouppitch";
+			this.grouppitch.Size = new System.Drawing.Size(78, 88);
+			this.grouppitch.TabIndex = 3;
+			this.grouppitch.TabStop = false;
+			this.grouppitch.Text = " Pitch ";
+			// 
+			// pitchControl
+			// 
+			this.pitchControl.Angle = -90;
+			this.pitchControl.AngleOffset = 0;
+			this.pitchControl.DoomAngleClamping = false;
+			this.pitchControl.Location = new System.Drawing.Point(7, 17);
+			this.pitchControl.Name = "pitchControl";
+			this.pitchControl.Size = new System.Drawing.Size(64, 64);
+			this.pitchControl.TabIndex = 20;
+			this.pitchControl.AngleChanged += new System.EventHandler(this.pitchControl_AngleChanged);
+			// 
+			// groupangle
+			// 
+			this.groupangle.Controls.Add(this.anglecontrol);
+			this.groupangle.Location = new System.Drawing.Point(543, 204);
+			this.groupangle.Name = "groupangle";
+			this.groupangle.Size = new System.Drawing.Size(78, 88);
+			this.groupangle.TabIndex = 4;
+			this.groupangle.TabStop = false;
+			this.groupangle.Text = " Angle";
+			// 
+			// groupBox4
+			// 
+			this.groupBox4.Controls.Add(this.cbAbsoluteHeight);
+			this.groupBox4.Controls.Add(this.label4);
+			this.groupBox4.Controls.Add(this.label5);
+			this.groupBox4.Controls.Add(this.posX);
+			this.groupBox4.Controls.Add(this.posY);
+			this.groupBox4.Controls.Add(this.posZ);
+			this.groupBox4.Controls.Add(this.zlabel);
+			this.groupBox4.Location = new System.Drawing.Point(242, 298);
+			this.groupBox4.Name = "groupBox4";
+			this.groupBox4.Size = new System.Drawing.Size(180, 98);
+			this.groupBox4.TabIndex = 5;
+			this.groupBox4.TabStop = false;
+			this.groupBox4.Text = " Position";
+			// 
+			// cbAbsoluteHeight
+			// 
+			this.cbAbsoluteHeight.AutoSize = true;
+			this.cbAbsoluteHeight.Location = new System.Drawing.Point(109, 71);
+			this.cbAbsoluteHeight.Name = "cbAbsoluteHeight";
+			this.cbAbsoluteHeight.Size = new System.Drawing.Size(67, 17);
+			this.cbAbsoluteHeight.TabIndex = 3;
+			this.cbAbsoluteHeight.Text = "Absolute";
+			this.cbAbsoluteHeight.UseVisualStyleBackColor = true;
+			this.cbAbsoluteHeight.CheckedChanged += new System.EventHandler(this.cbAbsoluteHeight_CheckedChanged);
+			// 
+			// label4
+			// 
+			this.label4.Location = new System.Drawing.Point(4, 21);
+			this.label4.Name = "label4";
+			this.label4.Size = new System.Drawing.Size(22, 14);
+			this.label4.TabIndex = 15;
+			this.label4.Text = "X:";
+			this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+			// 
+			// label5
+			// 
+			this.label5.Location = new System.Drawing.Point(4, 46);
+			this.label5.Name = "label5";
+			this.label5.Size = new System.Drawing.Size(22, 14);
+			this.label5.TabIndex = 14;
+			this.label5.Text = "Y:";
+			this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+			// 
+			// posX
+			// 
+			this.posX.AllowDecimal = true;
+			this.posX.AllowExpressions = true;
+			this.posX.AllowNegative = true;
+			this.posX.AllowRelative = true;
+			this.posX.ButtonStep = 8;
+			this.posX.ButtonStepBig = 8F;
+			this.posX.ButtonStepFloat = 1F;
+			this.posX.ButtonStepSmall = 0.1F;
+			this.posX.ButtonStepsUseModifierKeys = true;
+			this.posX.ButtonStepsWrapAround = false;
+			this.posX.Location = new System.Drawing.Point(32, 16);
+			this.posX.Name = "posX";
+			this.posX.Size = new System.Drawing.Size(72, 24);
+			this.posX.StepValues = null;
+			this.posX.TabIndex = 0;
+			this.posX.WhenTextChanged += new System.EventHandler(this.posX_WhenTextChanged);
+			// 
+			// posY
+			// 
+			this.posY.AllowDecimal = true;
+			this.posY.AllowExpressions = true;
+			this.posY.AllowNegative = true;
+			this.posY.AllowRelative = true;
+			this.posY.ButtonStep = 8;
+			this.posY.ButtonStepBig = 8F;
+			this.posY.ButtonStepFloat = 1F;
+			this.posY.ButtonStepSmall = 0.1F;
+			this.posY.ButtonStepsUseModifierKeys = true;
+			this.posY.ButtonStepsWrapAround = false;
+			this.posY.Location = new System.Drawing.Point(32, 41);
+			this.posY.Name = "posY";
+			this.posY.Size = new System.Drawing.Size(72, 24);
+			this.posY.StepValues = null;
+			this.posY.TabIndex = 1;
+			this.posY.WhenTextChanged += new System.EventHandler(this.posY_WhenTextChanged);
+			// 
+			// posZ
+			// 
+			this.posZ.AllowDecimal = true;
+			this.posZ.AllowExpressions = true;
+			this.posZ.AllowNegative = true;
+			this.posZ.AllowRelative = true;
+			this.posZ.ButtonStep = 8;
+			this.posZ.ButtonStepBig = 8F;
+			this.posZ.ButtonStepFloat = 1F;
+			this.posZ.ButtonStepSmall = 0.1F;
+			this.posZ.ButtonStepsUseModifierKeys = true;
+			this.posZ.ButtonStepsWrapAround = false;
+			this.posZ.Location = new System.Drawing.Point(32, 66);
+			this.posZ.Name = "posZ";
+			this.posZ.Size = new System.Drawing.Size(72, 24);
+			this.posZ.StepValues = null;
+			this.posZ.TabIndex = 2;
+			this.posZ.WhenTextChanged += new System.EventHandler(this.posZ_WhenTextChanged);
+			// 
+			// zlabel
+			// 
+			this.zlabel.Location = new System.Drawing.Point(4, 71);
+			this.zlabel.Name = "zlabel";
+			this.zlabel.Size = new System.Drawing.Size(22, 14);
+			this.zlabel.TabIndex = 9;
+			this.zlabel.Text = "Z:";
+			this.zlabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+			// 
+			// tabeffects
+			// 
+			this.tabeffects.Controls.Add(this.grouprendering);
+			this.tabeffects.Controls.Add(this.actiongroup);
+			this.tabeffects.Controls.Add(this.grouptag);
+			this.tabeffects.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+			this.tabeffects.Location = new System.Drawing.Point(4, 22);
+			this.tabeffects.Name = "tabeffects";
+			this.tabeffects.Padding = new System.Windows.Forms.Padding(3);
+			this.tabeffects.Size = new System.Drawing.Size(627, 399);
+			this.tabeffects.TabIndex = 1;
+			this.tabeffects.Text = "Args / Tag / Misc.";
+			this.tabeffects.UseVisualStyleBackColor = true;
+			// 
+			// grouprendering
+			// 
+			this.grouprendering.Controls.Add(this.labelScale);
+			this.grouprendering.Controls.Add(this.scale);
+			this.grouprendering.Location = new System.Drawing.Point(3, 6);
+			this.grouprendering.Name = "grouprendering";
+			this.grouprendering.Size = new System.Drawing.Size(276, 61);
+			this.grouprendering.TabIndex = 22;
+			this.grouprendering.TabStop = false;
+			this.grouprendering.Text = " Rendering ";
+			// 
+			// labelScale
+			// 
+			this.labelScale.Location = new System.Drawing.Point(5, 27);
+			this.labelScale.Name = "labelScale";
+			this.labelScale.Size = new System.Drawing.Size(80, 14);
+			this.labelScale.TabIndex = 32;
+			this.labelScale.Text = "Scale:";
+			this.labelScale.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+			// 
+			// scale
+			// 
+			this.scale.AllowDecimal = true;
+			this.scale.AllowExpressions = false;
+			this.scale.AllowNegative = false;
+			this.scale.AllowRelative = true;
+			this.scale.ButtonStep = 1;
+			this.scale.ButtonStepBig = 0.25F;
+			this.scale.ButtonStepFloat = 0.1F;
+			this.scale.ButtonStepSmall = 0.01F;
+			this.scale.ButtonStepsUseModifierKeys = true;
+			this.scale.ButtonStepsWrapAround = false;
+			this.scale.Location = new System.Drawing.Point(89, 22);
+			this.scale.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
+			this.scale.Name = "scale";
+			this.scale.Size = new System.Drawing.Size(72, 24);
+			this.scale.StepValues = null;
+			this.scale.TabIndex = 0;
+			this.scale.WhenTextChanged += new System.EventHandler(this.scale_WhenTextChanged);
+			// 
+			// actiongroup
+			// 
+			this.actiongroup.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.actiongroup.Controls.Add(this.argscontrol);
+			this.actiongroup.Location = new System.Drawing.Point(3, 73);
+			this.actiongroup.Name = "actiongroup";
+			this.actiongroup.Size = new System.Drawing.Size(615, 251);
+			this.actiongroup.TabIndex = 22;
+			this.actiongroup.TabStop = false;
+			this.actiongroup.Text = "Arguments";
+			// 
+			// argscontrol
+			// 
+			this.argscontrol.Location = new System.Drawing.Point(6, 21);
+			this.argscontrol.Name = "argscontrol";
+			this.argscontrol.Size = new System.Drawing.Size(603, 215);
+			this.argscontrol.TabIndex = 15;
+			this.argscontrol.Load += new System.EventHandler(this.argscontrol_Load);
+			// 
+			// grouptag
+			// 
+			this.grouptag.Controls.Add(this.tagSelector);
+			this.grouptag.Location = new System.Drawing.Point(3, 330);
+			this.grouptag.Name = "grouptag";
+			this.grouptag.Size = new System.Drawing.Size(615, 66);
+			this.grouptag.TabIndex = 0;
+			this.grouptag.TabStop = false;
+			this.grouptag.Text = " Identification ";
+			// 
+			// tagSelector
+			// 
+			this.tagSelector.Location = new System.Drawing.Point(6, 21);
+			this.tagSelector.Name = "tagSelector";
+			this.tagSelector.Size = new System.Drawing.Size(603, 35);
+			this.tagSelector.TabIndex = 8;
+			// 
+			// tabcomment
+			// 
+			this.tabcomment.Controls.Add(this.commenteditor);
+			this.tabcomment.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+			this.tabcomment.Location = new System.Drawing.Point(4, 22);
+			this.tabcomment.Name = "tabcomment";
+			this.tabcomment.Size = new System.Drawing.Size(627, 399);
+			this.tabcomment.TabIndex = 3;
+			this.tabcomment.Text = "Comment";
+			this.tabcomment.UseVisualStyleBackColor = true;
+			// 
+			// commenteditor
+			// 
+			this.commenteditor.Location = new System.Drawing.Point(3, 3);
+			this.commenteditor.Name = "commenteditor";
+			this.commenteditor.Size = new System.Drawing.Size(621, 396);
+			this.commenteditor.TabIndex = 0;
+			// 
+			// tabcustom
+			// 
+			this.tabcustom.Controls.Add(this.hidefixedfields);
+			this.tabcustom.Controls.Add(this.fieldslist);
+			this.tabcustom.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+			this.tabcustom.Location = new System.Drawing.Point(4, 22);
+			this.tabcustom.Name = "tabcustom";
+			this.tabcustom.Size = new System.Drawing.Size(627, 399);
+			this.tabcustom.TabIndex = 2;
+			this.tabcustom.Text = "Custom";
+			this.tabcustom.UseVisualStyleBackColor = true;
+			this.tabcustom.MouseEnter += new System.EventHandler(this.tabcustom_MouseEnter);
+			// 
+			// hidefixedfields
+			// 
+			this.hidefixedfields.AutoSize = true;
+			this.hidefixedfields.Location = new System.Drawing.Point(10, 381);
+			this.hidefixedfields.Name = "hidefixedfields";
+			this.hidefixedfields.Size = new System.Drawing.Size(195, 17);
+			this.hidefixedfields.TabIndex = 2;
+			this.hidefixedfields.Text = "Show user-added custom fields only";
+			this.hidefixedfields.UseVisualStyleBackColor = true;
+			this.hidefixedfields.CheckedChanged += new System.EventHandler(this.hidefixedfields_CheckedChanged);
+			// 
+			// fieldslist
+			// 
+			this.fieldslist.AllowInsert = true;
+			this.fieldslist.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.fieldslist.AutoInsertUserPrefix = true;
+			this.fieldslist.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+			this.fieldslist.Location = new System.Drawing.Point(8, 9);
+			this.fieldslist.Margin = new System.Windows.Forms.Padding(8, 9, 8, 9);
+			this.fieldslist.Name = "fieldslist";
+			this.fieldslist.PropertyColumnVisible = true;
+			this.fieldslist.PropertyColumnWidth = 150;
+			this.fieldslist.ShowFixedFields = true;
+			this.fieldslist.Size = new System.Drawing.Size(611, 368);
+			this.fieldslist.TabIndex = 1;
+			this.fieldslist.TypeColumnVisible = true;
+			this.fieldslist.TypeColumnWidth = 100;
+			this.fieldslist.ValueColumnVisible = true;
+			// 
+			// cancel
+			// 
+			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(533, 442);
+			this.cancel.Name = "cancel";
+			this.cancel.Size = new System.Drawing.Size(112, 25);
+			this.cancel.TabIndex = 2;
+			this.cancel.Text = "Cancel";
+			this.cancel.UseVisualStyleBackColor = true;
+			this.cancel.Click += new System.EventHandler(this.cancel_Click);
+			// 
+			// 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(415, 442);
+			this.apply.Name = "apply";
+			this.apply.Size = new System.Drawing.Size(112, 25);
+			this.apply.TabIndex = 1;
+			this.apply.Text = "OK";
+			this.apply.UseVisualStyleBackColor = true;
+			this.apply.Click += new System.EventHandler(this.apply_Click);
+			// 
+			// hint
+			// 
+			this.hint.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+			this.hint.Image = global::CodeImp.DoomBuilder.Properties.Resources.Lightbulb;
+			this.hint.Location = new System.Drawing.Point(10, 446);
+			this.hint.Name = "hint";
+			this.hint.Size = new System.Drawing.Size(16, 16);
+			this.hint.TabIndex = 3;
+			this.hint.TabStop = false;
+			// 
+			// hintlabel
+			// 
+			this.hintlabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+			this.hintlabel.AutoSize = true;
+			this.hintlabel.Location = new System.Drawing.Point(24, 447);
+			this.hintlabel.Name = "hintlabel";
+			this.hintlabel.Size = new System.Drawing.Size(365, 13);
+			this.hintlabel.TabIndex = 4;
+			this.hintlabel.Text = "Select categories or several thing types to randomly assign them to selection";
+			// 
+			// tooltip
+			// 
+			this.tooltip.AutomaticDelay = 10;
+			this.tooltip.AutoPopDelay = 10000;
+			this.tooltip.InitialDelay = 10;
+			this.tooltip.ReshowDelay = 100;
+			// 
+			// ThingEditFormSRB2
+			// 
+			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(655, 470);
+			this.Controls.Add(this.hint);
+			this.Controls.Add(this.cancel);
+			this.Controls.Add(this.apply);
+			this.Controls.Add(this.hintlabel);
+			this.Controls.Add(this.tabs);
+			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+			this.MaximizeBox = false;
+			this.MinimizeBox = false;
+			this.Name = "ThingEditFormSRB2";
+			this.Opacity = 0D;
+			this.ShowIcon = false;
+			this.ShowInTaskbar = false;
+			this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+			this.Text = "Edit Thing";
+			this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ThingEditForm_FormClosing);
+			this.Shown += new System.EventHandler(this.ThingEditFormUDMF_Shown);
+			this.HelpRequested += new System.Windows.Forms.HelpEventHandler(this.ThingEditForm_HelpRequested);
+			this.groupBox1.ResumeLayout(false);
+			this.groupBox2.ResumeLayout(false);
+			this.groupBox2.PerformLayout();
+			this.tabs.ResumeLayout(false);
+			this.tabproperties.ResumeLayout(false);
+			this.settingsgroup.ResumeLayout(false);
+			((System.ComponentModel.ISupportInitialize)(this.missingflags)).EndInit();
+			this.grouproll.ResumeLayout(false);
+			this.grouppitch.ResumeLayout(false);
+			this.groupangle.ResumeLayout(false);
+			this.groupBox4.ResumeLayout(false);
+			this.groupBox4.PerformLayout();
+			this.tabeffects.ResumeLayout(false);
+			this.grouprendering.ResumeLayout(false);
+			this.actiongroup.ResumeLayout(false);
+			this.grouptag.ResumeLayout(false);
+			this.tabcomment.ResumeLayout(false);
+			this.tabcustom.ResumeLayout(false);
+			this.tabcustom.PerformLayout();
+			((System.ComponentModel.ISupportInitialize)(this.hint)).EndInit();
+			this.ResumeLayout(false);
+			this.PerformLayout();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.TabControl tabs;
+		private System.Windows.Forms.TabPage tabproperties;
+		private System.Windows.Forms.TabPage tabeffects;
+		private System.Windows.Forms.Button cancel;
+		private System.Windows.Forms.Button apply;
+        private System.Windows.Forms.TabPage tabcustom;
+		private System.Windows.Forms.GroupBox grouptag;
+		private System.Windows.Forms.GroupBox actiongroup;
+		private CodeImp.DoomBuilder.Controls.FieldsEditorControl fieldslist;
+		private CodeImp.DoomBuilder.Controls.ThingBrowserControl thingtype;
+		private CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox angle;
+		private System.Windows.Forms.Label labelAngle;
+		private CodeImp.DoomBuilder.Controls.TagSelector tagSelector;
+		private CodeImp.DoomBuilder.Controls.AngleControlEx anglecontrol;
+		private System.Windows.Forms.PictureBox hint;
+		private System.Windows.Forms.Label hintlabel;
+        private System.Windows.Forms.GroupBox groupBox1;
+        private System.Windows.Forms.GroupBox groupBox2;
+        private System.Windows.Forms.GroupBox groupBox4;
+        private System.Windows.Forms.CheckBox cbAbsoluteHeight;
+        private System.Windows.Forms.Label label4;
+        private System.Windows.Forms.Label label5;
+        private Controls.ButtonsNumericTextbox posX;
+        private Controls.ButtonsNumericTextbox posY;
+        private Controls.ButtonsNumericTextbox posZ;
+        private System.Windows.Forms.Label zlabel;
+        private Controls.ButtonsNumericTextbox roll;
+        private System.Windows.Forms.Label labelroll;
+        private Controls.ButtonsNumericTextbox pitch;
+        private System.Windows.Forms.Label labelpitch;
+        private System.Windows.Forms.GroupBox grouprendering;
+        private System.Windows.Forms.GroupBox settingsgroup;
+        private Controls.CheckboxArrayControl flags;
+        private System.Windows.Forms.GroupBox grouproll;
+        private CodeImp.DoomBuilder.Controls.AngleControlEx rollControl;
+        private System.Windows.Forms.GroupBox grouppitch;
+        private CodeImp.DoomBuilder.Controls.AngleControlEx pitchControl;
+        private System.Windows.Forms.GroupBox groupangle;
+        private CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox scale;
+		private System.Windows.Forms.PictureBox missingflags;
+		private System.Windows.Forms.ToolTip tooltip;
+		private System.Windows.Forms.Label labelScale;
+		private System.Windows.Forms.CheckBox cbrandomangle;
+		private System.Windows.Forms.CheckBox cbrandomroll;
+		private System.Windows.Forms.CheckBox cbrandompitch;
+		private System.Windows.Forms.TabPage tabcomment;
+		private CodeImp.DoomBuilder.Controls.CommentEditor commenteditor;
+		private CodeImp.DoomBuilder.Controls.ArgumentsControlSRB2 argscontrol;
+		private System.Windows.Forms.CheckBox hidefixedfields;
+	}
+}
\ No newline at end of file
diff --git a/Source/Core/Windows/ThingEditFormSRB2.cs b/Source/Core/Windows/ThingEditFormSRB2.cs
new file mode 100644
index 000000000..c0c051003
--- /dev/null
+++ b/Source/Core/Windows/ThingEditFormSRB2.cs
@@ -0,0 +1,877 @@
+
+#region ================== Copyright (c) 2007 Pascal vd Heiden
+
+/*
+ * Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
+ * This program is released under GNU General Public License
+ * 
+ * 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.
+ * 
+ */
+
+#endregion
+
+#region ================== Namespaces
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Windows.Forms;
+using CodeImp.DoomBuilder.Config;
+using CodeImp.DoomBuilder.Controls;
+using CodeImp.DoomBuilder.Geometry;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Types;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.Windows
+{
+	/// <summary>
+	/// Dialog window that allows viewing and editing of Thing properties.
+	/// </summary>
+	internal partial class ThingEditFormSRB2 : DelayedForm, IThingEditForm
+	{
+		#region ================== Events
+
+		public event EventHandler OnValuesChanged; //mxd
+
+		#endregion
+
+		#region ================== Variables
+
+		private ICollection<Thing> things;
+		private ThingTypeInfo thinginfo;
+		private bool preventchanges;
+		private bool preventmapchange; //mxd
+		private bool undocreated; //mxd
+		private List<ThingProperties> thingprops; //mxd
+		private Dictionary<string, string> flagsrename; //mxd
+		private bool oldmapischanged;
+
+		//mxd. Persistent settings
+		private bool useabsoluteheight;
+
+		private struct ThingProperties //mxd
+		{
+			//public readonly int Type;
+			public readonly int AngleDoom;
+			public readonly int Pitch;
+			public readonly int Roll;
+			public readonly double Scale;
+			public readonly double Alpha;
+			public readonly double X;
+			public readonly double Y;
+			public readonly double Z;
+			public readonly Dictionary<string, bool> Flags;
+
+			public ThingProperties(Thing t) 
+			{
+				X = t.Position.x;
+				Y = t.Position.y;
+				Z = t.Position.z;
+				//Type = t.Type;
+				AngleDoom = t.AngleDoom;
+				Pitch = t.Pitch;
+				Roll = t.Roll;
+				Scale = UniFields.GetFloat(t.Fields, "scale", 1.0f);
+				Alpha = UniFields.GetFloat(t.Fields, "alpha", 1.0f);
+				Flags = t.GetFlags();
+			}
+		}
+
+		#endregion
+
+		#region ================== Constructor
+
+		// Constructor
+		public ThingEditFormSRB2() 
+		{
+			// Initialize
+			InitializeComponent();
+
+			//mxd. Load settings
+			useabsoluteheight = General.Settings.ReadSetting("windows." + configname + ".useabsoluteheight", false);
+
+			//mxd. Widow setup
+			if(General.Settings.StoreSelectedEditTab)
+			{
+				int activetab = General.Settings.ReadSetting("windows." + configname + ".activetab", 0);
+				tabs.SelectTab(activetab);
+			}
+
+			// Fill flags list
+			foreach(KeyValuePair<string, string> tf in General.Map.Config.ThingFlags)
+				flags.Add(tf.Value, tf.Key);
+			flags.Enabled = (General.Map.Config.ThingFlags.Count > 0);
+
+			// Initialize custom fields editor
+			fieldslist.Setup("thing");
+
+			// Fill universal fields list
+			fieldslist.ListFixedFields(General.Map.Config.ThingFields);
+
+			//mxd. Show fixed fields?
+			hidefixedfields.Checked = !General.Settings.ReadSetting("windows." + configname + ".customfieldsshowfixed", true);
+
+			// Thing height?
+			posZ.Visible = General.Map.FormatInterface.HasThingHeight;
+			zlabel.Visible = General.Map.FormatInterface.HasThingHeight;
+			cbAbsoluteHeight.Visible = General.Map.FormatInterface.HasThingHeight; //mxd
+
+			//mxd. Decimals allowed?
+			if(General.Map.FormatInterface.VertexDecimals > 0) 
+			{
+				posX.AllowDecimal = true;
+				posY.AllowDecimal = true;
+				posZ.AllowDecimal = true;
+			}
+
+			//mxd. Use doom angle clamping?
+			anglecontrol.DoomAngleClamping = General.Map.Config.DoomThingRotationAngles;
+
+			// Setup types list
+			thingtype.Setup();
+		}
+
+		#endregion
+
+		#region ================== Methods
+
+		// This sets up the form to edit the given things
+		public void Setup(ICollection<Thing> things) 
+		{
+			preventchanges = true;
+			oldmapischanged = General.Map.IsChanged;
+            undocreated = false;
+            argscontrol.Reset();
+
+            // Keep this list
+            this.things = things;
+			if(things.Count > 1) this.Text = "Edit Things (" + things.Count + ")";
+			hint.Visible = things.Count > 1; //mxd
+			hintlabel.Visible = things.Count > 1; //mxd
+			thingtype.UseMultiSelection = things.Count > 1; //mxd
+
+			////////////////////////////////////////////////////////////////////////
+			// Set all options to the first thing properties
+			////////////////////////////////////////////////////////////////////////
+
+			Thing ft = General.GetByIndex(things, 0);
+
+			// Set type
+			thingtype.SelectType(ft.Type);
+
+			// Flags
+			foreach(CheckBox c in flags.Checkboxes) 
+			{
+				if(ft.Flags.ContainsKey(c.Tag.ToString())) c.Checked = ft.Flags[c.Tag.ToString()];
+			}
+
+			// Coordination
+			angle.Text = ft.AngleDoom.ToString();
+			cbAbsoluteHeight.Checked = useabsoluteheight; //mxd
+
+			//mxd
+			ft.DetermineSector();
+			double floorheight = (ft.Sector != null ? Sector.GetFloorPlane(ft.Sector).GetZ(ft.Position) : 0);
+			posX.Text = (ft.Position.x).ToString();
+			posY.Text = (ft.Position.y).ToString();
+			posZ.Text = (useabsoluteheight ? (Math.Round(ft.Position.z + floorheight, General.Map.FormatInterface.VertexDecimals)).ToString() : (ft.Position.z).ToString());
+			posX.ButtonStep = General.Map.Grid.GridSize;
+			posY.ButtonStep = General.Map.Grid.GridSize;
+			posZ.ButtonStep = General.Map.Grid.GridSize;
+
+			//mxd. User vars. Should be done before adding regular fields
+			ThingTypeInfo fti = General.Map.Data.GetThingInfoEx(ft.Type);
+			if (fti != null && fti.Actor != null)
+			{
+				Dictionary<string, UniversalType> uservars = fti.Actor.GetAllUserVars();
+				Dictionary<string, object> uservardefaults = fti.Actor.GetAllUserVarDefaults();
+
+				if (uservars.Count > 0)
+					fieldslist.SetUserVars(uservars, uservardefaults, ft.Fields, true);
+			}
+			thinginfo = fti; //mxd
+
+			// Custom fields
+			fieldslist.SetValues(ft.Fields, true);
+			commenteditor.SetValues(ft.Fields, true);
+			scale.Text = ft.Fields.GetValue("scale", 1.0).ToString();
+			pitch.Text = ft.Pitch.ToString();
+			roll.Text = ft.Roll.ToString();
+
+			// Action/tags
+			tagSelector.Setup(UniversalType.ThingTag);
+			tagSelector.SetTag(ft.Tag);
+
+			//mxd. Args
+			argscontrol.UpdateThingType(thinginfo);
+			argscontrol.SetValue(ft, true);
+
+			////////////////////////////////////////////////////////////////////////
+			// Now go for all lines and change the options when a setting is different
+			////////////////////////////////////////////////////////////////////////
+
+			thingprops = new List<ThingProperties>();
+
+			// Go for all things
+			foreach(Thing t in things) 
+			{
+				//mxd. Update sector info
+				t.DetermineSector();
+
+				// Type does not match?
+				ThingTypeInfo info = thingtype.GetSelectedInfo(); //mxd
+				if(info != null && info.Index != t.Type)
+				{
+					thingtype.ClearSelectedType();
+					thinginfo = null; //mxd
+				}
+
+				// Flags
+				foreach(CheckBox c in flags.Checkboxes) 
+				{
+					if(c.CheckState == CheckState.Indeterminate) continue; //mxd
+					if(t.IsFlagSet(c.Tag.ToString()) != c.Checked) 
+					{
+						c.ThreeState = true;
+						c.CheckState = CheckState.Indeterminate;
+					}
+				}
+
+				// Coordination
+				if(t.AngleDoom.ToString() != angle.Text) angle.Text = "";
+
+				//mxd. Position
+				if((t.Position.x).ToString() != posX.Text) posX.Text = "";
+				if((t.Position.y).ToString() != posY.Text) posY.Text = "";
+				if(useabsoluteheight && t.Sector != null) 
+				{
+					if((Math.Round(Sector.GetFloorPlane(t.Sector).GetZ(t.Position) + t.Position.z, General.Map.FormatInterface.VertexDecimals)).ToString() != posZ.Text)
+						posZ.Text = "";
+				} 
+				else if((t.Position.z).ToString() != posZ.Text) 
+				{
+					posZ.Text = "";
+				}
+
+				// Tags
+				if(t.Tag != ft.Tag) tagSelector.ClearTag(); //mxd
+
+				//mxd. Arguments
+				argscontrol.SetValue(t, false);
+
+				//mxd. User vars. Should be done before adding regular fields
+				ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
+				if (ti != null && ti.Actor != null)
+				{
+					Dictionary<string, UniversalType> uservars = ti.Actor.GetAllUserVars();
+					Dictionary<string, object> uservardefaults = ti.Actor.GetAllUserVarDefaults();
+
+					if (uservars.Count > 0)
+						fieldslist.SetUserVars(uservars, uservardefaults, t.Fields, false);
+				}
+
+				//mxd. Custom fields
+				fieldslist.SetValues(t.Fields, false);
+				commenteditor.SetValues(t.Fields, false); //mxd. Comments
+				if (!string.IsNullOrEmpty(scale.Text))
+					UniFields.SetFloat(t.Fields, "scale", scale.GetResultFloat(t.Fields.GetValue("scale", 1.0)), 1.0);
+
+				if(t.Pitch.ToString() != pitch.Text) pitch.Text = "";
+				if(t.Roll.ToString() != roll.Text) roll.Text = "";
+
+				//mxd. Store initial properties
+				thingprops.Add(new ThingProperties(t));
+			}
+
+			preventchanges = false;
+
+			//mxd. Trigger updates manually...
+			preventmapchange = true;
+			angle_WhenTextChanged(angle, EventArgs.Empty);
+			pitch_WhenTextChanged(pitch, EventArgs.Empty);
+			roll_WhenTextChanged(roll, EventArgs.Empty);
+			flags_OnValueChanged(flags, EventArgs.Empty);
+			preventmapchange = false;
+
+			argscontrol.UpdateScriptControls(); //mxd
+			commenteditor.FinishSetup(); //mxd
+			UpdateFlagNames(); //mxd
+		}
+
+		//mxd
+		private void MakeUndo() 
+		{
+			if(undocreated) return;
+			undocreated = true;
+
+			//mxd. Make undo
+			General.Map.UndoRedo.CreateUndo("Edit " + (things.Count > 1 ? things.Count + " things" : "thing"));
+			foreach(Thing t in things) t.Fields.BeforeFieldsChange();
+		}
+
+		//mxd
+		private void UpdateFlagNames()
+		{
+			Dictionary<string, string> newflagsrename = (thinginfo != null ? thinginfo.FlagsRename : null);
+			
+			// Update flag names?
+			if(flagsrename != null || newflagsrename != null)
+			{
+				flags.SuspendLayout();
+
+				// Restore default flags?
+				if(flagsrename != null)
+				{
+					foreach(CheckBox cb in flags.Checkboxes)
+					{
+						string flag = cb.Tag.ToString();
+						if(flagsrename.ContainsKey(flag))
+						{
+							cb.Text = General.Map.Config.ThingFlags[flag];
+							cb.ForeColor = SystemColors.WindowText;
+						}
+					}
+				}
+
+				// Apply new renaming?
+				if(newflagsrename != null)
+				{
+					foreach(CheckBox cb in flags.Checkboxes)
+					{
+						string flag = cb.Tag.ToString();
+						if(newflagsrename.ContainsKey(flag))
+						{
+							cb.Text = newflagsrename[flag];
+							cb.ForeColor = SystemColors.HotTrack;
+						}
+					}
+				}
+
+				flags.ResumeLayout();
+			}
+
+			// Store current flag names
+			flagsrename = newflagsrename;
+		}
+
+		#endregion
+
+		#region ================== Events
+
+		//mxd
+		private void thingtype_OnTypeDoubleClicked() 
+		{
+			apply_Click(this, EventArgs.Empty);
+		}
+
+		// Angle text changes
+		private void angle_WhenTextChanged(object sender, EventArgs e) 
+		{
+			if(preventchanges) return;
+			preventchanges = true;
+			anglecontrol.Angle = angle.GetResult(AngleControlEx.NO_ANGLE);
+			preventchanges = false;
+			if(!preventmapchange) ApplyAngleChange(); //mxd
+		}
+
+		//mxd. Angle control clicked
+		private void anglecontrol_AngleChanged(object sender, EventArgs e) 
+		{
+			if(preventchanges) return;
+			angle.Text = anglecontrol.Angle.ToString();
+			if(!preventmapchange) ApplyAngleChange();
+		}
+
+		private void pitch_WhenTextChanged(object sender, EventArgs e) 
+		{
+			if(preventchanges) return;
+			int p = pitch.GetResult(AngleControlEx.NO_ANGLE);
+			preventchanges = true;
+			pitchControl.Angle = (p == AngleControlEx.NO_ANGLE ? p : p + 90);
+			preventchanges = false;
+			if(!preventmapchange) ApplyPitchChange();
+		}
+
+		private void pitchControl_AngleChanged(object sender, EventArgs e) 
+		{
+			if(preventchanges) return;
+			pitch.Text = (General.ClampAngle(pitchControl.Angle - 90)).ToString();
+			if(!preventmapchange) ApplyPitchChange();
+		}
+
+		private void roll_WhenTextChanged(object sender, EventArgs e) 
+		{
+			if(preventchanges) return;
+			int r = roll.GetResult(AngleControlEx.NO_ANGLE);
+			preventchanges = true;
+			rollControl.Angle = (r == AngleControlEx.NO_ANGLE ? r : r + 90);
+			preventchanges = false;
+			if(!preventmapchange) ApplyRollChange();
+		}
+
+		private void rollControl_AngleChanged(object sender, EventArgs e) 
+		{
+			if(preventchanges) return;
+			roll.Text = (General.ClampAngle(rollControl.Angle - 90)).ToString();
+			if(!preventmapchange) ApplyRollChange();
+		}
+
+		// Apply clicked
+		private void apply_Click(object sender, EventArgs e) 
+		{
+			//mxd. Make Undo
+			MakeUndo();
+			
+			List<string> defaultflags = new List<string>();
+
+			// Verify the tag
+			if(General.Map.FormatInterface.HasThingTag) //mxd
+			{
+				tagSelector.ValidateTag();//mxd
+				if(((tagSelector.GetTag(0) < General.Map.FormatInterface.MinTag) || (tagSelector.GetTag(0) > General.Map.FormatInterface.MaxTag))) 
+				{
+					General.ShowWarningMessage("Thing tag must be between " + General.Map.FormatInterface.MinTag + " and " + General.Map.FormatInterface.MaxTag + ".", MessageBoxButtons.OK);
+					return;
+				}
+			}
+
+			// Verify the type
+			if(!string.IsNullOrEmpty(thingtype.TypeStringValue) && ((thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType) || (thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType))) 
+			{
+				General.ShowWarningMessage("Thing type must be between " + General.Map.FormatInterface.MinThingType + " and " + General.Map.FormatInterface.MaxThingType + ".", MessageBoxButtons.OK);
+				return;
+			}
+
+			// Go for all the things
+			int offset = 0; //mxd
+			foreach(Thing t in things) 
+			{
+				// Coordination
+				//mxd. Randomize rotations?
+				if(cbrandomangle.Checked)
+				{
+					int newangle = General.Random(0, 359);
+					if(General.Map.Config.DoomThingRotationAngles) newangle = newangle / 45 * 45;
+					t.Rotate(newangle);
+				}
+				if(cbrandompitch.Checked) t.SetPitch(General.Random(0, 359));
+				if(cbrandomroll.Checked) t.SetRoll(General.Random(0, 359));
+
+				//mxd. Check position
+				double px = General.Clamp(t.Position.x, General.Map.Config.LeftBoundary, General.Map.Config.RightBoundary);
+				double py = General.Clamp(t.Position.y, General.Map.Config.BottomBoundary, General.Map.Config.TopBoundary);
+				if(t.Position.x != px || t.Position.y != py) t.Move(new Vector2D(px, py));
+
+				// Tags
+				t.Tag = General.Clamp(tagSelector.GetSmartTag(t.Tag, offset), General.Map.FormatInterface.MinTag, General.Map.FormatInterface.MaxTag); //mxd
+
+				//mxd. Apply args
+				argscontrol.Apply(t, offset);
+
+				//mxd. Custom fields
+				fieldslist.Apply(t.Fields);
+
+				//mxd. User vars. Should be called after fieldslist.Apply()
+				ThingTypeInfo ti = General.Map.Data.GetThingInfoEx(t.Type);
+				if (ti != null && ti.Actor != null)
+				{
+					Dictionary<string, UniversalType> uservars = ti.Actor.GetAllUserVars();
+
+					if(uservars.Count > 0)
+						fieldslist.ApplyUserVars(uservars, t.Fields);
+				}
+
+				//mxd. Comments
+				commenteditor.Apply(t.Fields);
+
+				// Update settings
+				t.UpdateConfiguration();
+
+				//mxd. Increase offset...
+				offset++;
+			}
+
+			// Set as defaults
+			foreach(CheckBox c in flags.Checkboxes) 
+			{
+				if(c.CheckState == CheckState.Checked) defaultflags.Add(c.Tag.ToString());
+			}
+			General.Settings.DefaultThingType = thingtype.GetResult(General.Settings.DefaultThingType);
+			General.Settings.DefaultThingAngle = Angle2D.DegToRad((float)angle.GetResult((int)Angle2D.RadToDeg(General.Settings.DefaultThingAngle) - 90) + 90);
+			General.Settings.SetDefaultThingFlags(defaultflags);
+
+			// Done
+			General.Map.IsChanged = true;
+			if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty); //mxd
+			this.DialogResult = DialogResult.OK;
+			this.Close();
+		}
+
+		// Cancel clicked
+		private void cancel_Click(object sender, EventArgs e) 
+		{
+			//mxd. Perform undo?
+			if (undocreated)
+			{
+				General.Map.UndoRedo.WithdrawUndo();
+
+				// Changing certain properties of the sector, like its type, will set General.Map.IsChanged to true.
+				// But if cancel is pressed and the changes are discarded, and the map was not changed before, we have to force
+				// General.Map.IsChanged back to false
+				if (General.Map.IsChanged && oldmapischanged == false)
+					General.Map.ForceMapIsChangedFalse();
+			}
+
+			// Be gone
+			this.DialogResult = DialogResult.Cancel;
+			this.Close();
+		}
+
+		//mxd
+		private void cbAbsoluteHeight_CheckedChanged(object sender, EventArgs e) 
+		{
+			if(preventchanges) return;
+			MakeUndo();
+
+			useabsoluteheight = cbAbsoluteHeight.Checked;
+
+			preventchanges = true;
+
+			//update label text
+			Thing ft = General.GetByIndex(things, 0);
+			double z = ft.Position.z;
+			if(useabsoluteheight && ft.Sector != null) z += Sector.GetFloorPlane(ft.Sector).GetZ(ft.Position);
+			posZ.Text = Math.Round(z, General.Map.FormatInterface.VertexDecimals).ToString();
+
+			foreach(Thing t in things) 
+			{
+				z = t.Position.z;
+				if(useabsoluteheight && t.Sector != null) z += Sector.GetFloorPlane(t.Sector).GetZ(t.Position);
+				string ztext = Math.Round(z, General.Map.FormatInterface.VertexDecimals).ToString();
+				if(posZ.Text != ztext) 
+				{
+					posZ.Text = "";
+					break;
+				}
+			}
+
+			preventchanges = false;
+		}
+
+		//mxd
+		private void tabcustom_MouseEnter(object sender, EventArgs e) 
+		{
+			fieldslist.Focus();
+		}
+
+		//mxd
+		private void ThingEditFormUDMF_Shown(object sender, EventArgs e)
+		{
+			if(tabs.SelectedIndex == 0)
+			{
+				thingtype.Focus();
+				thingtype.FocusTextbox();
+			}
+		}
+
+		//mxd
+		private void ThingEditForm_FormClosing(object sender, FormClosingEventArgs e) 
+		{
+			// Save settings
+			General.Settings.WriteSetting("windows." + configname + ".activetab", tabs.SelectedIndex);
+			General.Settings.WriteSetting("windows." + configname + ".useabsoluteheight", useabsoluteheight);
+			General.Settings.WriteSetting("windows." + configname + ".customfieldsshowfixed", !hidefixedfields.Checked);
+		}
+
+		// Help
+		private void ThingEditForm_HelpRequested(object sender, HelpEventArgs hlpevent) 
+		{
+			General.ShowHelp("w_thingedit.html");
+			hlpevent.Handled = true;
+		}
+
+		#endregion
+
+		#region ================== mxd. Realtime events
+
+		private void posX_WhenTextChanged(object sender, EventArgs e) 
+		{
+			if(preventchanges) return;
+			MakeUndo(); //mxd
+			int i = 0;
+
+			// Reset increment steps, otherwise it's just keep counting and counting
+			posX.ResetIncrementStep();
+
+			// Update values
+			foreach (Thing t in things)
+				t.Move(new Vector2D(posX.GetResultFloat(thingprops[i++].X), t.Position.y));
+
+			General.Map.IsChanged = true;
+			if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
+		}
+
+		private void posY_WhenTextChanged(object sender, EventArgs e) 
+		{
+			if(preventchanges) return;
+			MakeUndo(); //mxd
+			int i = 0;
+
+			// Reset increment steps, otherwise it's just keep counting and counting
+			posY.ResetIncrementStep();
+
+			// Update values
+			foreach (Thing t in things)
+				t.Move(new Vector2D(t.Position.x, posY.GetResultFloat(thingprops[i++].Y)));
+
+			General.Map.IsChanged = true;
+			if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
+		}
+
+		private void posZ_WhenTextChanged(object sender, EventArgs e) 
+		{
+			if(preventchanges) return;
+			MakeUndo(); //mxd
+			int i = 0;
+
+			// Reset increment steps, otherwise it's just keep counting and counting
+			posZ.ResetIncrementStep();
+
+			if (string.IsNullOrEmpty(posZ.Text)) 
+			{
+				// Restore values
+				foreach(Thing t in things)
+					t.Move(new Vector3D(t.Position.x, t.Position.y, thingprops[i++].Z));
+			} 
+			else 
+			{
+				// Update values
+				foreach(Thing t in things) 
+				{
+					double z = posZ.GetResultFloat(thingprops[i++].Z);
+					if(useabsoluteheight && !posZ.CheckIsRelative() && t.Sector != null)
+						z -= Math.Round(Sector.GetFloorPlane(t.Sector).GetZ(t.Position.x, t.Position.y), General.Map.FormatInterface.VertexDecimals);
+					t.Move(new Vector3D(t.Position.x, t.Position.y, z));
+				}
+			}
+
+			General.Map.IsChanged = true;
+			if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
+		}
+
+		private void scale_WhenTextChanged(object sender, EventArgs e) 
+		{
+			if(preventchanges) return;
+			MakeUndo(); //mxd
+			int i = 0;
+
+			foreach (Thing t in things)
+			{
+				double s = scale.GetResultFloat(thingprops[i].Scale);
+				if (s == 0) s = 1.0f;
+				UniFields.SetFloat(t.Fields, "scale", s);
+				t.SetScale(s, s);
+				i++;
+			}
+
+			General.Map.IsChanged = true;
+			if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
+		}
+
+		// Selected type changes
+		private void thingtype_OnTypeChanged(ThingTypeInfo value) 
+		{
+			thinginfo = value;
+
+			//mxd. Update things
+			if(preventchanges ||
+					(!string.IsNullOrEmpty(thingtype.TypeStringValue) && 
+					thingtype.GetResult(0) < General.Map.FormatInterface.MinThingType 
+					|| thingtype.GetResult(0) > General.Map.FormatInterface.MaxThingType))
+				return;
+
+			MakeUndo(); //mxd
+
+			foreach(Thing t in things) 
+			{
+				//Set type
+				t.Type = thingtype.GetResult(t.Type);
+
+				// Update settings
+				t.UpdateConfiguration();
+			}
+
+			UpdateFlagNames(); //mxd
+			argscontrol.UpdateThingType(thinginfo);
+
+			General.Map.IsChanged = true;
+			if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
+		}
+
+		//mxd
+		private void ApplyAngleChange() 
+		{
+			if(preventchanges) return;
+			MakeUndo(); //mxd
+			int i = 0;
+
+			// Reset increment steps, otherwise it's just keep counting and counting
+			angle.ResetIncrementStep();
+
+			//restore values
+			if (string.IsNullOrEmpty(angle.Text)) 
+			{
+				foreach(Thing t in things) t.Rotate(thingprops[i++].AngleDoom);
+			} 
+			else //update values
+			{
+				foreach(Thing t in things)
+					t.Rotate(angle.GetResult(thingprops[i++].AngleDoom));
+			}
+
+			General.Map.IsChanged = true;
+			if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
+		}
+
+		private void ApplyPitchChange() 
+		{
+			if(preventchanges) return;
+			MakeUndo(); //mxd
+			int i = 0;
+
+			// Reset increment steps, otherwise it's just keep counting and counting
+			pitch.ResetIncrementStep();
+
+			//restore values
+			if (string.IsNullOrEmpty(pitch.Text)) 
+			{
+				foreach(Thing t in things) t.SetPitch(thingprops[i++].Pitch);
+			} 
+			else //update values
+			{ 
+				foreach(Thing t in things)
+					t.SetPitch(pitch.GetResult(thingprops[i++].Pitch));
+			}
+
+			General.Map.IsChanged = true;
+			if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
+		}
+
+		//mxd
+		private void ApplyRollChange() 
+		{
+			if(preventchanges) return;
+			MakeUndo(); //mxd
+			int i = 0;
+
+			// Reset increment steps, otherwise it's just keep counting and counting
+			roll.ResetIncrementStep();
+
+			//restore values
+			if (string.IsNullOrEmpty(roll.Text)) 
+			{
+				foreach(Thing t in things) t.SetRoll(thingprops[i++].Roll);
+			} 
+			else //update values
+			{ 
+				foreach(Thing t in things)
+					t.SetRoll(roll.GetResult(thingprops[i++].Roll));
+			}
+
+			General.Map.IsChanged = true;
+			if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
+		}
+
+		private void flags_OnValueChanged(object sender, EventArgs e) 
+		{
+			if(preventchanges) return;
+			if(!preventmapchange) //mxd
+			{
+				MakeUndo();
+				int i = 0;
+
+				// Apply flags
+				foreach(Thing t in things)
+				{
+					// Apply all flags
+					foreach(CheckBox c in flags.Checkboxes)
+					{
+						if(c.CheckState == CheckState.Checked)
+							t.SetFlag(c.Tag.ToString(), true);
+						else if(c.CheckState == CheckState.Unchecked)
+							t.SetFlag(c.Tag.ToString(), false);
+						else if(thingprops[i].Flags.ContainsKey(c.Tag.ToString()))
+							t.SetFlag(c.Tag.ToString(), thingprops[i].Flags[c.Tag.ToString()]);
+						else //things created in the editor have empty Flags by default
+							t.SetFlag(c.Tag.ToString(), false);
+					}
+
+					i++;
+				}
+
+				// Dispatch event
+				General.Map.IsChanged = true;
+				if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
+			}
+
+			// Gather enabled flags
+			HashSet<string> activeflags = new HashSet<string>();
+			foreach(CheckBox cb in flags.Checkboxes)
+			{
+				if(cb.CheckState != CheckState.Unchecked) activeflags.Add(cb.Tag.ToString());
+			}
+
+			// Check em
+			List<string> warnings = ThingFlagsCompare.CheckFlags(activeflags);
+			if(warnings.Count > 0) 
+			{
+				// Got missing flags
+				tooltip.SetToolTip(missingflags, string.Join(Environment.NewLine, warnings.ToArray()));
+				missingflags.Visible = true;
+				settingsgroup.ForeColor = Color.DarkRed;
+				return;
+			}
+
+			// Everything is OK
+			missingflags.Visible = false;
+			settingsgroup.ForeColor = SystemColors.ControlText;
+		}
+
+		private void cbrandomangle_CheckedChanged(object sender, EventArgs e)
+		{
+			angle.Enabled = !cbrandomangle.Checked;
+			groupangle.Enabled = !cbrandomangle.Checked;
+		}
+
+		private void cbrandompitch_CheckedChanged(object sender, EventArgs e)
+		{
+			pitch.Enabled = !cbrandompitch.Checked;
+			grouppitch.Enabled = !cbrandompitch.Checked;
+		}
+
+		private void cbrandomroll_CheckedChanged(object sender, EventArgs e)
+		{
+			roll.Enabled = !cbrandomroll.Checked;
+			grouproll.Enabled = !cbrandomroll.Checked;
+		}
+
+		private void hidefixedfields_CheckedChanged(object sender, EventArgs e)
+		{
+			fieldslist.ShowFixedFields = !hidefixedfields.Checked;
+		}
+
+		#endregion
+
+		private void argscontrol_Load(object sender, EventArgs e)
+		{
+
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/Source/Core/Windows/ThingEditFormSRB2.resx b/Source/Core/Windows/ThingEditFormSRB2.resx
new file mode 100644
index 000000000..023cd0c7d
--- /dev/null
+++ b/Source/Core/Windows/ThingEditFormSRB2.resx
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="tooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
-- 
GitLab