From b1e5d8b5be6a3fef76f405791618933aea25ad04 Mon Sep 17 00:00:00 2001
From: MaxED <j.maxed@gmail.com>
Date: Thu, 12 May 2016 22:35:11 +0000
Subject: [PATCH] Added, Sound Environments mode: sound environments of the
 same type are now colored using the same color. Added, Sound Environments
 mode: current sound environment is now highlighted (can be toggled using
 "Toggle Highlight" action). Added: Tag selectors now have up/down buttons.
 Fixed, Sound Environments mode: sound environments were not updated after
 performing Undo/Redo actions. Fixed, Sound Propagation mode: sound zones were
 not updated after performing Undo/Redo actions. Internal: moved "Toggle
 Highlight" action to the core, also changed it's category to "View".
 Internal: "Toggle Highlight" action state is now saved in the Program
 configuration. Updated ZDoom_DECORATE.cfg (GetZAt). Updated
 ZDoom_linedefs.cfg (Sector_SetPortal args).

---
 .../Includes/ZDoom_linedefs.cfg               |  4 ++-
 Build/Scripting/ZDoom_DECORATE.cfg            |  9 +++++
 Source/Core/Config/ProgramConfiguration.cs    | 17 ++++++++-
 Source/Core/Controls/DebugConsole.cs          |  1 +
 Source/Core/Controls/TagSelector.Designer.cs  | 17 ++++++++-
 Source/Core/Controls/TagSelector.cs           | 19 +++++++++-
 Source/Core/Controls/TagsSelector.Designer.cs | 17 ++++++++-
 Source/Core/Controls/TagsSelector.cs          | 34 +++++++++++++++++-
 Source/Core/Editing/ClassicMode.cs            | 11 ++++++
 Source/Core/Resources/Actions.cfg             | 11 ++++++
 Source/Core/VisualModes/VisualMode.cs         |  8 +++++
 .../ClassicModes/BaseClassicMode.cs           | 11 ------
 .../ClassicModes/MakeSectorMode.cs            |  2 +-
 .../BuilderModes/ClassicModes/SectorsMode.cs  | 22 ++++++------
 .../ErrorChecks/ResultMissingFlat.cs          |  2 +-
 .../ErrorChecks/ResultUnknownFlat.cs          |  2 +-
 .../FindReplace/BaseFindSector.cs             |  2 +-
 .../FindReplace/FindAnyTextureFlat.cs         |  2 +-
 .../BuilderModes/General/BuilderPlug.cs       | 12 -------
 .../BuilderModes/Resources/Actions.cfg        | 11 ------
 .../VisualModes/BaseVisualMode.cs             | 12 ++-----
 Source/Plugins/NodesViewer/NodesViewerMode.cs |  6 ++--
 .../SoundPropagationMode/BuilderPlug.cs       | 25 ++++++++-----
 .../SoundPropagationMode/SoundEnvironment.cs  |  1 +
 .../SoundEnvironmentMode.cs                   | 35 ++++++++++++++++---
 .../SoundPropagationMode.cs                   | 28 ++++++++++++---
 26 files changed, 234 insertions(+), 87 deletions(-)

diff --git a/Build/Configurations/Includes/ZDoom_linedefs.cfg b/Build/Configurations/Includes/ZDoom_linedefs.cfg
index fb52a7568..f4e98121e 100644
--- a/Build/Configurations/Includes/ZDoom_linedefs.cfg
+++ b/Build/Configurations/Includes/ZDoom_linedefs.cfg
@@ -3357,6 +3357,7 @@ zdoom
 					3 = "Plane portal";
 					4 = "Horizon portal";
 					5 = "Copy portal to line";
+					6 = "Interactive portal";
 				}
 			}
 			arg2
@@ -3368,12 +3369,13 @@ zdoom
 					0 = "Floor";
 					1 = "Ceiling";
 					2 = "Both";
-					3 = "Any (Copy portal type only)";
+					3 = "Any (\"Copy portal\" types only)";
 				}
 			}
 			arg3
 			{
 				title = "Misc";
+				tooltip = "For type 0 portal: specifies whether the line belongs to the sector viewed\nthrough the portal (1) or the sector in which the portal is seen (0).\nFor type 1 portal: specifies the sector tag of the portal to copy.";
 			}
 			arg4
 			{
diff --git a/Build/Scripting/ZDoom_DECORATE.cfg b/Build/Scripting/ZDoom_DECORATE.cfg
index 4cf8577db..deed3b470 100644
--- a/Build/Scripting/ZDoom_DECORATE.cfg
+++ b/Build/Scripting/ZDoom_DECORATE.cfg
@@ -423,6 +423,7 @@ keywords
 	CountInv = "int CountInv(str itemclassname[, int ptr_select = AAPTR_DEFAULT])";
 	GetDistance = "float GetDistance(bool checkz[, int ptr_select = AAPTR_TARGET])";
 	GetSpawnHealth = "int GetSpawnHealth()";
+	GetZAt = "float GetZAt([float x = 0.0[, float y = 0.0[, float angle = 0.0[, int flags = 0[, int pick_pointer = AAPTR_TARGET]]]]])";
 	GetGibHealth = "int GetGibHealth()";
 }
 
@@ -1225,6 +1226,7 @@ constants
 	RTF_AFFECTSOURCE;
 	RTF_NOIMPACTDAMAGE;
 	RTF_NOTMISSILE;
+	RTF_THRUSTZ;
 	SF_NOPULLIN;
 	SF_NORANDOM;
 	SF_NOTURN;	
@@ -1327,4 +1329,11 @@ constants
 	QF_WAVE;
 	QF_MAX;
 	QF_FULLINTENSITY;
+//GetZAt flags
+	GZF_ABSOLUTEPOS;
+	GZF_ABSOLUTEANG;
+	GZF_CEILING;
+	GZF_3DRESTRICT;
+	GZF_NOPORTALS;
+	GZF_NO3DFLOOR;
 }
diff --git a/Source/Core/Config/ProgramConfiguration.cs b/Source/Core/Config/ProgramConfiguration.cs
index 2415a6c65..e86cff857 100644
--- a/Source/Core/Config/ProgramConfiguration.cs
+++ b/Source/Core/Config/ProgramConfiguration.cs
@@ -91,6 +91,7 @@ namespace CodeImp.DoomBuilder.Config
 		private bool locatetexturegroup; //mxd
 		private bool keeptexturefilterfocused; //mxd
 		private SplitLineBehavior splitlinebehavior; //mxd
+		private bool usehighlight; //mxd
 
 		//mxd. Script editor settings
 		private string scriptfontname;
@@ -203,6 +204,18 @@ namespace CodeImp.DoomBuilder.Config
 		public bool LocateTextureGroup { get { return locatetexturegroup; } internal set { locatetexturegroup = value; } } //mxd
 		public bool KeepTextureFilterFocused { get { return keeptexturefilterfocused; } internal set { keeptexturefilterfocused = value; } } //mxd
 		public SplitLineBehavior SplitLineBehavior { get { return splitlinebehavior; } set { splitlinebehavior = value; } } //mxd
+		
+		//mxd. Highlight mode
+		public bool UseHighlight
+		{ 
+			get { return usehighlight; } 
+			set
+			{
+				usehighlight = value;
+				General.Map.Renderer3D.ShowSelection = General.Settings.UseHighlight;
+				General.Map.Renderer3D.ShowHighlight = General.Settings.UseHighlight;
+			} 
+		}
 
 		//mxd. Script editor settings
 		public string ScriptFontName { get { return scriptfontname; } internal set { scriptfontname = value; } }
@@ -336,7 +349,8 @@ namespace CodeImp.DoomBuilder.Config
 				showtexturesizes = cfg.ReadSetting("showtexturesizes", true);
 				locatetexturegroup = cfg.ReadSetting("locatetexturegroup", true); //mxd
 				keeptexturefilterfocused = cfg.ReadSetting("keeptexturefilterfocused", true); //mxd
-				splitlinebehavior = (SplitLineBehavior) General.Clamp(cfg.ReadSetting("splitlinebehavior", 0), 0, 3); //mxd
+				splitlinebehavior = (SplitLineBehavior)General.Clamp(cfg.ReadSetting("splitlinebehavior", 0), 0, 3); //mxd
+				usehighlight = cfg.ReadSetting("usehighlight", true); //mxd
 
 				//mxd. Script editor
 				scriptfontname = cfg.ReadSetting("scriptfontname", "Courier New");
@@ -452,6 +466,7 @@ namespace CodeImp.DoomBuilder.Config
 			cfg.WriteSetting("locatetexturegroup", locatetexturegroup); //mxd
 			cfg.WriteSetting("keeptexturefilterfocused", keeptexturefilterfocused); //mxd
 			cfg.WriteSetting("splitlinebehavior", (int)splitlinebehavior); //mxd
+			cfg.WriteSetting("usehighlight", usehighlight); //mxd
 
 			//mxd. Script editor
 			cfg.WriteSetting("scriptfontname", scriptfontname);
diff --git a/Source/Core/Controls/DebugConsole.cs b/Source/Core/Controls/DebugConsole.cs
index a996f15e5..9eb45b7ae 100644
--- a/Source/Core/Controls/DebugConsole.cs
+++ b/Source/Core/Controls/DebugConsole.cs
@@ -51,6 +51,7 @@ namespace CodeImp.DoomBuilder
 		#region ================== Properties
 
 		public bool AlwaysOnTop { get { return alwaysontop.Checked; } }
+		public static int Counter { get { return counter; } }
 
 		#endregion
 
diff --git a/Source/Core/Controls/TagSelector.Designer.cs b/Source/Core/Controls/TagSelector.Designer.cs
index ad548818e..8cdc269a1 100644
--- a/Source/Core/Controls/TagSelector.Designer.cs
+++ b/Source/Core/Controls/TagSelector.Designer.cs
@@ -35,6 +35,7 @@
 			this.unusedTag = new System.Windows.Forms.Button();
 			this.tooltip = new System.Windows.Forms.ToolTip(this.components);
 			this.clear = new System.Windows.Forms.Button();
+			this.buttons = new System.Windows.Forms.VScrollBar();
 			this.SuspendLayout();
 			// 
 			// label1
@@ -58,7 +59,7 @@
 			this.cbTagPicker.FormattingEnabled = true;
 			this.cbTagPicker.Location = new System.Drawing.Point(42, 7);
 			this.cbTagPicker.Name = "cbTagPicker";
-			this.cbTagPicker.Size = new System.Drawing.Size(165, 21);
+			this.cbTagPicker.Size = new System.Drawing.Size(150, 21);
 			this.cbTagPicker.TabIndex = 1;
 			// 
 			// newTag
@@ -101,10 +102,23 @@
 			this.clear.UseVisualStyleBackColor = true;
 			this.clear.Click += new System.EventHandler(this.clear_Click);
 			// 
+			// buttons
+			// 
+			this.buttons.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+			this.buttons.LargeChange = 10000;
+			this.buttons.Location = new System.Drawing.Point(192, 5);
+			this.buttons.Maximum = 10000;
+			this.buttons.Minimum = -10000;
+			this.buttons.Name = "buttons";
+			this.buttons.Size = new System.Drawing.Size(18, 24);
+			this.buttons.TabIndex = 5;
+			this.buttons.ValueChanged += new System.EventHandler(this.buttons_ValueChanged);
+			// 
 			// TagSelector
 			// 
 			this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
 			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+			this.Controls.Add(this.buttons);
 			this.Controls.Add(this.clear);
 			this.Controls.Add(this.unusedTag);
 			this.Controls.Add(this.newTag);
@@ -126,5 +140,6 @@
 		private System.Windows.Forms.Button unusedTag;
 		private System.Windows.Forms.ToolTip tooltip;
 		private System.Windows.Forms.Button clear;
+		private System.Windows.Forms.VScrollBar buttons;
 	}
 }
diff --git a/Source/Core/Controls/TagSelector.cs b/Source/Core/Controls/TagSelector.cs
index 4c6189aab..96e5595e0 100644
--- a/Source/Core/Controls/TagSelector.cs
+++ b/Source/Core/Controls/TagSelector.cs
@@ -257,7 +257,24 @@ namespace CodeImp.DoomBuilder.Controls
 			clear.Left = this.Width - clear.Width - clear.Margin.Right;
 			unusedTag.Left = clear.Left - unusedTag.Margin.Right - unusedTag.Width;
 			newTag.Left = unusedTag.Left - newTag.Margin.Right - newTag.Width;
-			cbTagPicker.Width = newTag.Left - cbTagPicker.Margin.Right - cbTagPicker.Left;
+			buttons.Left = newTag.Left - newTag.Margin.Left - buttons.Width;
+			cbTagPicker.Width = buttons.Left - cbTagPicker.Margin.Right - cbTagPicker.Left;
+		}
+
+		//mxd
+		private void buttons_ValueChanged(object sender, EventArgs e)
+		{
+			if(buttons.Value == 0) return;
+			
+			ValidateTag();
+
+			if(!valid) tag = 0;
+			else tag = General.Clamp(tag + (buttons.Value < 0 ? 1 : -1), General.Map.FormatInterface.MinTag, General.Map.FormatInterface.MaxTag);
+
+			cbTagPicker.SelectedIndex = -1;
+			cbTagPicker.Text = tag.ToString();
+			buttons.Value = 0;
+			valid = true;
 		}
 
 		#endregion
diff --git a/Source/Core/Controls/TagsSelector.Designer.cs b/Source/Core/Controls/TagsSelector.Designer.cs
index 66ba510e8..399e5c27d 100644
--- a/Source/Core/Controls/TagsSelector.Designer.cs
+++ b/Source/Core/Controls/TagsSelector.Designer.cs
@@ -37,6 +37,7 @@
 			this.clearalltags = new System.Windows.Forms.Button();
 			this.tagslist = new System.Windows.Forms.LinkLabel();
 			this.label1 = new System.Windows.Forms.Label();
+			this.buttons = new System.Windows.Forms.VScrollBar();
 			this.SuspendLayout();
 			// 
 			// curtaglabel
@@ -60,7 +61,7 @@
 			this.tagpicker.FormattingEnabled = true;
 			this.tagpicker.Location = new System.Drawing.Point(65, 7);
 			this.tagpicker.Name = "tagpicker";
-			this.tagpicker.Size = new System.Drawing.Size(230, 21);
+			this.tagpicker.Size = new System.Drawing.Size(210, 21);
 			this.tagpicker.TabIndex = 1;
 			this.tagpicker.TextChanged += new System.EventHandler(this.tagpicker_TextChanged);
 			// 
@@ -151,10 +152,23 @@
 			this.label1.TabIndex = 6;
 			this.label1.Text = "Tags:";
 			// 
+			// buttons
+			// 
+			this.buttons.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+			this.buttons.LargeChange = 10000;
+			this.buttons.Location = new System.Drawing.Point(278, 5);
+			this.buttons.Maximum = 10000;
+			this.buttons.Minimum = -10000;
+			this.buttons.Name = "buttons";
+			this.buttons.Size = new System.Drawing.Size(18, 24);
+			this.buttons.TabIndex = 11;
+			this.buttons.ValueChanged += new System.EventHandler(this.buttons_ValueChanged);
+			// 
 			// TagsSelector
 			// 
 			this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
 			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+			this.Controls.Add(this.buttons);
 			this.Controls.Add(this.clearalltags);
 			this.Controls.Add(this.clear);
 			this.Controls.Add(this.addtag);
@@ -186,5 +200,6 @@
 		private System.Windows.Forms.Button addtag;
 		private System.Windows.Forms.Button clear;
 		private System.Windows.Forms.Button clearalltags;
+		private System.Windows.Forms.VScrollBar buttons;
 	}
 }
diff --git a/Source/Core/Controls/TagsSelector.cs b/Source/Core/Controls/TagsSelector.cs
index 215330645..b30f7e37b 100644
--- a/Source/Core/Controls/TagsSelector.cs
+++ b/Source/Core/Controls/TagsSelector.cs
@@ -505,11 +505,43 @@ namespace CodeImp.DoomBuilder.Controls
 			clear.Left = this.Width - clear.Width - clear.Margin.Right;
 			unusedtag.Left = clear.Left - unusedtag.Margin.Right - unusedtag.Width;
 			newtag.Left = unusedtag.Left - newtag.Margin.Right - newtag.Width;
-			tagpicker.Width = newtag.Left - tagpicker.Margin.Right - tagpicker.Left;
+			buttons.Left = newtag.Left - newtag.Margin.Left - buttons.Width;
+			tagpicker.Width = buttons.Left - tagpicker.Margin.Right - tagpicker.Left;
 			removetag.Left = clear.Left;
 			addtag.Left = removetag.Left - addtag.Margin.Right - addtag.Width;
 		}
 
+		//mxd
+		private void buttons_ValueChanged(object sender, EventArgs e)
+		{
+			if(buttons.Value == 0) return;
+			
+			int tag = 0;
+			bool valid = false;
+
+			// Get current tag
+			if(tagpicker.SelectedItem != null)
+			{
+				TagInfo info = (TagInfo) tagpicker.SelectedItem;
+				tag = info.Tag;
+				valid = true;
+			}
+			else
+			{
+				string text = tagpicker.Text.Trim();
+				if(!string.IsNullOrEmpty(text) && int.TryParse(text, out tag))
+					valid = true;
+			}
+
+			// Increment it
+			if(valid) tag = General.Clamp(tag + (buttons.Value < 0 ? 1 : -1), General.Map.FormatInterface.MinTag, General.Map.FormatInterface.MaxTag);
+
+			// Apply it
+			tagpicker.SelectedIndex = -1;
+			tagpicker.Text = tag.ToString();
+			buttons.Value = 0;
+		}
+
 		#endregion
 	}
 }
\ No newline at end of file
diff --git a/Source/Core/Editing/ClassicMode.cs b/Source/Core/Editing/ClassicMode.cs
index c3ebb0848..b378b19e0 100644
--- a/Source/Core/Editing/ClassicMode.cs
+++ b/Source/Core/Editing/ClassicMode.cs
@@ -957,6 +957,17 @@ namespace CodeImp.DoomBuilder.Editing
 			}
 		}
 
+		//mxd
+		[BeginAction("togglehighlight", BaseAction = true)]
+		protected virtual void ToggleHighlight()
+		{
+			General.Settings.UseHighlight = !General.Settings.UseHighlight;
+			General.Interface.DisplayStatus(StatusType.Action, "Highlight is now " + (General.Settings.UseHighlight ? "ON" : "OFF") + ".");
+
+			// Redraw display to show changes
+			General.Interface.RedrawDisplay();
+		}
+
 		#endregion
 	}
 
diff --git a/Source/Core/Resources/Actions.cfg b/Source/Core/Resources/Actions.cfg
index befd4a482..c847d08dd 100644
--- a/Source/Core/Resources/Actions.cfg
+++ b/Source/Core/Resources/Actions.cfg
@@ -1047,6 +1047,17 @@ togglebrightness //mxd
 	default = 66; //B
 }
 
+togglehighlight
+{
+	title = "Toggle Highlight";
+	category = "view"; //mxd
+	description = "Toggles the highlight of the targeted and selected objects.";
+	allowkeys = true;
+	allowmouse = true;
+	allowscroll = true;
+	default = 72;	// H
+}
+
 visualselect
 {
 	title = "Select";
diff --git a/Source/Core/VisualModes/VisualMode.cs b/Source/Core/VisualModes/VisualMode.cs
index 0373721d9..489bf6356 100644
--- a/Source/Core/VisualModes/VisualMode.cs
+++ b/Source/Core/VisualModes/VisualMode.cs
@@ -1157,6 +1157,14 @@ namespace CodeImp.DoomBuilder.VisualModes
 			}
 		}
 
+		//mxd
+		[BeginAction("togglehighlight", BaseAction = true)]
+		public void ToggleHighlight()
+		{
+			General.Settings.UseHighlight = !General.Settings.UseHighlight;
+			General.Interface.DisplayStatus(StatusType.Action, "Highlight is now " + (General.Settings.UseHighlight ? "ON" : "OFF") + ".");
+		}
+
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/ClassicModes/BaseClassicMode.cs b/Source/Plugins/BuilderModes/ClassicModes/BaseClassicMode.cs
index ffb464a6f..6d43e4e95 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/BaseClassicMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/BaseClassicMode.cs
@@ -373,17 +373,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			paintselectpressed = false;
 		}
 
-		//mxd
-		[BeginAction("togglehighlight")]
-		public virtual void ToggleHighlight() 
-		{
-			BuilderPlug.Me.UseHighlight = !BuilderPlug.Me.UseHighlight;
-			General.Interface.DisplayStatus(StatusType.Action, "Highlight is now " + (BuilderPlug.Me.UseHighlight ? "ON" : "OFF") + ".");
-
-			// Redraw display to show changes
-			General.Interface.RedrawDisplay();
-		}
-
 		//mxd
 		[BeginAction("syncedthingedit")]
 		public void ToggleSyncronizedThingsEdit()
diff --git a/Source/Plugins/BuilderModes/ClassicModes/MakeSectorMode.cs b/Source/Plugins/BuilderModes/ClassicModes/MakeSectorMode.cs
index 7a62cceda..fe83eea24 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/MakeSectorMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/MakeSectorMode.cs
@@ -155,7 +155,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				{
 					renderer.RenderGeometry(flashpolygon, null, true);
 				} 
-				else if(BuilderPlug.Me.UseHighlight) //mxd
+				else if(General.Settings.UseHighlight) //mxd
 				{
 					int color = General.Colors.Indication.WithAlpha(64).ToInt();
 					foreach(Sector s in associates.Keys)
diff --git a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs
index 54cd4a19e..f6422ee41 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs
@@ -144,7 +144,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			}
 
 			// Make text labels for sectors
-			PixelColor c = (BuilderPlug.Me.UseHighlight ? General.Colors.Highlight : General.Colors.Selection); //mxd
+			PixelColor c = (General.Settings.UseHighlight ? General.Colors.Highlight : General.Colors.Selection); //mxd
 			labels = new Dictionary<Sector, TextLabel[]>(General.Map.Map.Sectors.Count);
 			foreach(Sector s in General.Map.Map.Sectors)
 			{
@@ -173,13 +173,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				ICollection<Sector> orderedselection = General.Map.Map.GetSelectedSectors(true);
 				
 				//mxd. Render selected sectors
-				if(BuilderPlug.Me.UseHighlight) 
+				if(General.Settings.UseHighlight) 
 				{
 					renderer.RenderHighlight(overlayGeometry, General.Colors.Selection.WithAlpha(64).ToInt());
 				}
 
 				//mxd. Render highlighted sector
-				if(BuilderPlug.Me.UseHighlight && highlighted != null) 
+				if(General.Settings.UseHighlight && highlighted != null) 
 				{
 					renderer.RenderHighlight(highlighted.FlatVertices, General.Colors.Highlight.WithAlpha(64).ToInt());
 				}
@@ -424,7 +424,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			if((highlighted != null) && !highlighted.IsDisposed)
 			{
 				TextLabel[] labelarray = labels[highlighted];
-				PixelColor c = (BuilderPlug.Me.UseHighlight ? General.Colors.Highlight : General.Colors.Selection);
+				PixelColor c = (General.Settings.UseHighlight ? General.Colors.Highlight : General.Colors.Selection);
 				foreach(TextLabel l in labelarray) l.Color = c;
 			}
 			
@@ -432,7 +432,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			if((s != null) && !s.IsDisposed)
 			{
 				TextLabel[] labelarray = labels[s];
-				PixelColor c = (BuilderPlug.Me.UseHighlight ? General.Colors.Selection : General.Colors.Highlight);
+				PixelColor c = (General.Settings.UseHighlight ? General.Colors.Selection : General.Colors.Highlight);
 				foreach(TextLabel l in labelarray) l.Color = c;
 			}
 			
@@ -498,7 +498,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 					{ 
 						//mxd
 						string selectedCount = General.Map.Map.SelectedSectorsCount.ToString();
-						PixelColor c = (BuilderPlug.Me.UseHighlight ? General.Colors.Highlight : General.Colors.Selection);
+						PixelColor c = (General.Settings.UseHighlight ? General.Colors.Highlight : General.Colors.Selection);
 						TextLabel[] labelarray = labels[s];
 						foreach(TextLabel l in labelarray) 
 						{
@@ -559,7 +559,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		{
 			// Go for all labels in all selected sectors
 			ICollection<Sector> orderedselection = General.Map.Map.GetSelectedSectors(true);
-			PixelColor c = (BuilderPlug.Me.UseHighlight ? General.Colors.Highlight : General.Colors.Selection); //mxd
+			PixelColor c = (General.Settings.UseHighlight ? General.Colors.Highlight : General.Colors.Selection); //mxd
 			int index = 0;
 			foreach(Sector s in orderedselection)
 			{
@@ -877,7 +877,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 					// Update overlay
 					TextLabel[] labelarray = labels[highlighted];
-					PixelColor c = (BuilderPlug.Me.UseHighlight ? General.Colors.Selection : General.Colors.Highlight);
+					PixelColor c = (General.Settings.UseHighlight ? General.Colors.Selection : General.Colors.Highlight);
 					foreach(TextLabel l in labelarray) l.Color = c;
 					UpdateOverlaySurfaces(); //mxd
 					UpdateOverlay();
@@ -1401,10 +1401,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		}
 
 		//mxd
-		public override void ToggleHighlight()
+		protected override void ToggleHighlight()
 		{
 			// Update label colors
-			PixelColor c = (BuilderPlug.Me.UseHighlight ? General.Colors.Selection : General.Colors.Highlight);
+			PixelColor c = (General.Settings.UseHighlight ? General.Colors.Selection : General.Colors.Highlight);
 			foreach(TextLabel[] labelarray in labels.Values)
 				foreach(TextLabel l in labelarray) l.Color = c;
 
@@ -1412,7 +1412,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			if((highlighted != null) && !highlighted.IsDisposed)
 			{
 				TextLabel[] labelarray = labels[highlighted];
-				c = (BuilderPlug.Me.UseHighlight ? General.Colors.Highlight : General.Colors.Selection);
+				c = (General.Settings.UseHighlight ? General.Colors.Highlight : General.Colors.Selection);
 				foreach(TextLabel l in labelarray) l.Color = c;
 			}
 			
diff --git a/Source/Plugins/BuilderModes/ErrorChecks/ResultMissingFlat.cs b/Source/Plugins/BuilderModes/ErrorChecks/ResultMissingFlat.cs
index b5ac4f8f6..83010dcbf 100644
--- a/Source/Plugins/BuilderModes/ErrorChecks/ResultMissingFlat.cs
+++ b/Source/Plugins/BuilderModes/ErrorChecks/ResultMissingFlat.cs
@@ -70,7 +70,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		//mxd. More rendering
 		public override void RenderOverlaySelection(IRenderer2D renderer) 
 		{
-			if(!BuilderPlug.Me.UseHighlight) return;
+			if(!General.Settings.UseHighlight) return;
 			renderer.RenderHighlight(sector.FlatVertices, General.Colors.Selection.WithAlpha(64).ToInt());
 		}
 		
diff --git a/Source/Plugins/BuilderModes/ErrorChecks/ResultUnknownFlat.cs b/Source/Plugins/BuilderModes/ErrorChecks/ResultUnknownFlat.cs
index d0f04a927..e108223f4 100644
--- a/Source/Plugins/BuilderModes/ErrorChecks/ResultUnknownFlat.cs
+++ b/Source/Plugins/BuilderModes/ErrorChecks/ResultUnknownFlat.cs
@@ -89,7 +89,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		//mxd. More rendering
 		public override void RenderOverlaySelection(IRenderer2D renderer) 
 		{
-			if(!BuilderPlug.Me.UseHighlight) return;
+			if(!General.Settings.UseHighlight) return;
 			renderer.RenderHighlight(sector.FlatVertices, General.Colors.Selection.WithAlpha(64).ToInt());
 		}
 		
diff --git a/Source/Plugins/BuilderModes/FindReplace/BaseFindSector.cs b/Source/Plugins/BuilderModes/FindReplace/BaseFindSector.cs
index 5405192e2..451e74e63 100644
--- a/Source/Plugins/BuilderModes/FindReplace/BaseFindSector.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/BaseFindSector.cs
@@ -43,7 +43,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		//mxd. Render selection highlight
 		public override void RenderOverlaySelection(IRenderer2D renderer, FindReplaceObject[] selection) 
 		{
-			if(!BuilderPlug.Me.UseHighlight) return;
+			if(!General.Settings.UseHighlight) return;
 
 			int color = General.Colors.Selection.WithAlpha(64).ToInt();
 			foreach(FindReplaceObject o in selection)
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindAnyTextureFlat.cs b/Source/Plugins/BuilderModes/FindReplace/FindAnyTextureFlat.cs
index 18a531afa..05734401b 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindAnyTextureFlat.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindAnyTextureFlat.cs
@@ -193,7 +193,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		//mxd
 		public override void RenderOverlaySelection(IRenderer2D renderer, FindReplaceObject[] selection) 
 		{
-			if(!BuilderPlug.Me.UseHighlight) return;
+			if(!General.Settings.UseHighlight) return;
 
 			int color = General.Colors.Selection.WithAlpha(64).ToInt();
 			foreach(FindReplaceObject o in selection) 
diff --git a/Source/Plugins/BuilderModes/General/BuilderPlug.cs b/Source/Plugins/BuilderModes/General/BuilderPlug.cs
index d03744c5f..a8a5ba4f2 100644
--- a/Source/Plugins/BuilderModes/General/BuilderPlug.cs
+++ b/Source/Plugins/BuilderModes/General/BuilderPlug.cs
@@ -119,7 +119,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		private float highlightrange;
 		private float highlightthingsrange;
 		private float splitlinedefsrange;
-		private bool usehighlight;
 		private bool autodragonpaste;
 		private bool autoAlignTextureOffsetsOnCreate;//mxd
 		private bool dontMoveGeometryOutsideMapBoundary;//mxd
@@ -169,16 +168,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		public float HighlightRange { get { return highlightrange; } }
 		public float HighlightThingsRange { get { return highlightthingsrange; } }
 		public float SplitLinedefsRange { get { return splitlinedefsrange; } }
-		public bool UseHighlight
-		{ 
-			get { return usehighlight; } 
-			set
-			{ 
-				usehighlight = value;
-				General.Map.Renderer3D.ShowSelection = usehighlight;
-				General.Map.Renderer3D.ShowHighlight = usehighlight;
-			} 
-		}
 		public bool AutoDragOnPaste { get { return autodragonpaste; } set { autodragonpaste = value; } }
 		public bool AutoDrawOnEdit { get { return autoDrawOnEdit; } set { autoDrawOnEdit = value; } } //mxd
 		public bool AutoAlignTextureOffsetsOnCreate { get { return autoAlignTextureOffsetsOnCreate; } set { autoAlignTextureOffsetsOnCreate = value; } } //mxd
@@ -204,7 +193,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			// Settings
 			showvisualthings = 2;
 			usegravity = false;
-			usehighlight = true;
 			LoadSettings();
 			LoadUISettings(); //mxd
 			
diff --git a/Source/Plugins/BuilderModes/Resources/Actions.cfg b/Source/Plugins/BuilderModes/Resources/Actions.cfg
index 92627e7ad..c417a4830 100644
--- a/Source/Plugins/BuilderModes/Resources/Actions.cfg
+++ b/Source/Plugins/BuilderModes/Resources/Actions.cfg
@@ -1038,17 +1038,6 @@ togglegravity
 	allowscroll = true;
 }
 
-togglehighlight
-{
-	title = "Toggle Highlight";
-	category = "tools"; //mxd
-	description = "Toggles the highlight of the targeted and selected objects in Visual and Sectors modes.";
-	allowkeys = true;
-	allowmouse = true;
-	allowscroll = true;
-	default = 72;	// H
-}
-
 resettexture
 {
 	title = "Reset Texture Offsets";
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
index 6a1837a01..c8c9a007a 100644
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
@@ -1195,9 +1195,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				renderer.SetFogMode(true);
 
 				// Set target for highlighting
-				renderer.ShowSelection = General.Settings.GZOldHighlightMode || BuilderPlug.Me.UseHighlight; //mxd
+				renderer.ShowSelection = General.Settings.GZOldHighlightMode || General.Settings.UseHighlight; //mxd
 
-				if(BuilderPlug.Me.UseHighlight)
+				if(General.Settings.UseHighlight)
 					renderer.SetHighlightedObject(target.picked);
 				
 				// Begin with geometry
@@ -2873,14 +2873,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			General.Interface.DisplayStatus(StatusType.Action, "Gravity is now " + onoff + ".");
 		}
 
-		[BeginAction("togglehighlight")]
-		public void ToggleHighlight()
-		{
-			BuilderPlug.Me.UseHighlight = !BuilderPlug.Me.UseHighlight;
-			string onoff = BuilderPlug.Me.UseHighlight ? "ON" : "OFF";
-			General.Interface.DisplayStatus(StatusType.Action, "Highlight is now " + onoff + ".");
-		}
-
 		[BeginAction("resettexture")]
 		public void ResetTexture()
 		{
diff --git a/Source/Plugins/NodesViewer/NodesViewerMode.cs b/Source/Plugins/NodesViewer/NodesViewerMode.cs
index 195562b2c..1275296aa 100644
--- a/Source/Plugins/NodesViewer/NodesViewerMode.cs
+++ b/Source/Plugins/NodesViewer/NodesViewerMode.cs
@@ -698,7 +698,7 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer
 			for(int i = 0; i < poly.Length; i++) poly[i].c = intcolor;
 
 			// Draw
-			renderer.RenderGeometry(poly, General.Map.Data.WhiteTexture, true);
+			renderer.RenderGeometry(poly, null, true);
 		}
 
 		// For rendering
@@ -706,7 +706,7 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer
 		{
 			if(vertices == null) return;
 			if(vertices.Length < 3) return;
-			renderer.RenderGeometry(vertices, General.Map.Data.WhiteTexture, true);
+			renderer.RenderGeometry(vertices, null, true);
 		}
 
 		// For rendering
@@ -774,7 +774,7 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer
 				}
 
 				// Draw
-				renderer.RenderGeometry(fverts, General.Map.Data.WhiteTexture, true);
+				renderer.RenderGeometry(fverts, null, true);
 			}
 		}
 
diff --git a/Source/Plugins/SoundPropagationMode/BuilderPlug.cs b/Source/Plugins/SoundPropagationMode/BuilderPlug.cs
index dff04b7c5..44d26efc1 100644
--- a/Source/Plugins/SoundPropagationMode/BuilderPlug.cs
+++ b/Source/Plugins/SoundPropagationMode/BuilderPlug.cs
@@ -243,7 +243,9 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 			// and id, no matter in what order they are discovered
 			for(int i = 0; i < soundenvironmenthings.Count; i++)
 			{
-				secolor[soundenvironmenthings[i]] = distinctcolors[i % distinctcolors.Count];
+				//mxd. Make sure same environments use the same color
+				int seid = (soundenvironmenthings[i].Args[0] << 8) + soundenvironmenthings[i].Args[1];
+				secolor[soundenvironmenthings[i]] = distinctcolors[seid % distinctcolors.Count];
 				senumber.Add(soundenvironmenthings[i], i + 1);
 			}
 
@@ -312,6 +314,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 				environment.ID = senumber[environment.Things[0]];
 
 				// Create the data for the overlay geometry
+				List<FlatVertex> severtslist = new List<FlatVertex>(environment.Sectors.Count * 3); //mxd
 				foreach(Sector s in environment.Sectors)
 				{
 					FlatVertex[] fv = new FlatVertex[s.FlatVertices.Length];
@@ -319,18 +322,22 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 					for(int j = 0; j < fv.Length; j++) fv[j].c = environment.Color.WithAlpha(128).ToInt();
 
 					vertsList.AddRange(fv);
+					severtslist.AddRange(fv); //mxd
 
 					// Get all Linedefs that will block sound environments
 					foreach(Sidedef sd in s.Sidedefs)
 					{
-						if(LinedefBlocksSoundEnvironment(sd.Line))
-							lock (blockinglinedefs)
-							{
-								blockinglinedefs.Add(sd.Line);
-							}
+						if(!LinedefBlocksSoundEnvironment(sd.Line)) continue;
+						lock(blockinglinedefs)
+						{
+							blockinglinedefs.Add(sd.Line);
+						}
 					}
 				}
 
+				//mxd. Store sector environment verts
+				environment.SectorsGeometry = severtslist.ToArray();
+
 				// Update the overlay geometry with the newly added sectors
 				if(overlayGeometry == null)
 				{
@@ -338,7 +345,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 				}
 				else
 				{
-					lock (overlayGeometry)
+					lock(overlayGeometry)
 					{
 						overlayGeometry = vertsList.ToArray();
 					}
@@ -380,7 +387,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 				//mxd. Still no suitable name?..
 				if(environment.Name == SoundEnvironment.DEFAULT_NAME) environment.Name += " " + environment.ID;
 
-				lock (soundenvironments)
+				lock(soundenvironments)
 				{
 					soundenvironments.Add(environment);
 				}
@@ -405,7 +412,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 			}
 			else
 			{
-				lock (overlayGeometry)
+				lock(overlayGeometry)
 				{
 					overlayGeometry = vertsList.ToArray();
 				}
diff --git a/Source/Plugins/SoundPropagationMode/SoundEnvironment.cs b/Source/Plugins/SoundPropagationMode/SoundEnvironment.cs
index aaaa50233..b627e4f3d 100644
--- a/Source/Plugins/SoundPropagationMode/SoundEnvironment.cs
+++ b/Source/Plugins/SoundPropagationMode/SoundEnvironment.cs
@@ -24,6 +24,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 		public PixelColor Color { get; set; }
 		public int ID { get; set; }
 		public string Name { get; set; } //mxd
+		public FlatVertex[] SectorsGeometry; //mxd
 
 		#endregion
 
diff --git a/Source/Plugins/SoundPropagationMode/SoundEnvironmentMode.cs b/Source/Plugins/SoundPropagationMode/SoundEnvironmentMode.cs
index 647f3d4f4..a832a8ff0 100644
--- a/Source/Plugins/SoundPropagationMode/SoundEnvironmentMode.cs
+++ b/Source/Plugins/SoundPropagationMode/SoundEnvironmentMode.cs
@@ -232,6 +232,26 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 			}
 		}
 
+		//mxd
+		public override void OnUndoEnd()
+		{
+			base.OnUndoEnd();
+
+			// Update
+			UpdateData();
+			General.Interface.RedrawDisplay();
+		}
+
+		//mxd
+		public override void OnRedoEnd()
+		{
+			base.OnRedoEnd();
+
+			// Update
+			UpdateData();
+			General.Interface.RedrawDisplay();
+		}
+
 		private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
 		{
 			panel.HighlightSoundEnvironment(highlightedsoundenvironment); //mxd. Expand highlighted node in the treeview
@@ -341,7 +361,12 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 				{
 					if(BuilderPlug.Me.OverlayGeometry.Length > 0 && renderer.StartOverlay(true))
 					{
-						renderer.RenderGeometry(BuilderPlug.Me.OverlayGeometry, General.Map.Data.WhiteTexture, true);
+						renderer.RenderGeometry(BuilderPlug.Me.OverlayGeometry, null, true);
+						
+						//mxd. Render highlighted sound environment
+						if(General.Settings.UseHighlight && highlightedsoundenvironment != null)
+							renderer.RenderHighlight(highlightedsoundenvironment.SectorsGeometry, General.Colors.Highlight.WithAlpha(128).ToInt());
+
 						renderer.Finish();
 					}
 				}
@@ -576,13 +601,13 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 			General.Map.IsChanged = true;
 			General.Map.ThingsFilter.Update();
 
-			// Invoke a new mousemove so that the highlighted item updates
-			MouseEventArgs e = new MouseEventArgs(MouseButtons.None, 0, (int)mousepos.x, (int)mousepos.y, 0);
-			OnMouseMove(e);
-
 			// Update sound environments
 			UpdateData();
 
+			// Invoke a new mousemove so that the highlighted item updates
+			highlightedsoundenvironment = null;
+			OnMouseMove(new MouseEventArgs(MouseButtons.None, 0, (int)mousepos.x, (int)mousepos.y, 0));
+
 			// Redraw screen
 			General.Interface.RedrawDisplay();
 		}
diff --git a/Source/Plugins/SoundPropagationMode/SoundPropagationMode.cs b/Source/Plugins/SoundPropagationMode/SoundPropagationMode.cs
index 4e073fccf..b5e156b3d 100644
--- a/Source/Plugins/SoundPropagationMode/SoundPropagationMode.cs
+++ b/Source/Plugins/SoundPropagationMode/SoundPropagationMode.cs
@@ -288,12 +288,12 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 
 			if(renderer.StartOverlay(true))
 			{
-				renderer.RenderGeometry(overlayGeometry, General.Map.Data.WhiteTexture, true);
+				renderer.RenderGeometry(overlayGeometry, null, true);
 
 				if(highlighted != null && !highlighted.IsDisposed)
 				{
 					SoundPropagationDomain spd = sector2domain[highlighted];
-					renderer.RenderGeometry(spd.Level1Geometry, General.Map.Data.WhiteTexture, true);
+					renderer.RenderGeometry(spd.Level1Geometry, null, true);
 
 					foreach(Sector s in spd.AdjacentSectors)
 					{
@@ -301,7 +301,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 
 						if(!renderedspds.Contains(aspd))
 						{
-							renderer.RenderGeometry(aspd.Level2Geometry, General.Map.Data.WhiteTexture, true);
+							renderer.RenderGeometry(aspd.Level2Geometry, null, true);
 							renderedspds.Add(aspd);
 						}
 					}
@@ -325,7 +325,7 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 			FlatVertex[] fv = new FlatVertex[flatvertices.Length];
 			flatvertices.CopyTo(fv, 0);
 			for(int i = 0; i < fv.Length; i++) fv[i].c = color.ToInt();
-			renderer.RenderGeometry(fv, General.Map.Data.WhiteTexture, true);
+			renderer.RenderGeometry(fv, null, true);
 		}
 
 		//mxd. If a linedef is highlighted, toggle the sound blocking flag 
@@ -344,6 +344,26 @@ namespace CodeImp.DoomBuilder.SoundPropagationMode
 			General.Interface.RedrawDisplay();
 		}
 
+		//mxd
+		public override void OnUndoEnd()
+		{
+			base.OnUndoEnd();
+
+			// Update
+			ResetSoundPropagation();
+			General.Interface.RedrawDisplay();
+		}
+
+		//mxd
+		public override void OnRedoEnd()
+		{
+			base.OnRedoEnd();
+
+			// Update
+			ResetSoundPropagation();
+			General.Interface.RedrawDisplay();
+		}
+
 		// Mouse moves
 		public override void OnMouseMove(MouseEventArgs e)
 		{
-- 
GitLab