From 2e88f8f4a5b282372bc0d1855823e173cf48a7fc Mon Sep 17 00:00:00 2001
From: MaxED <j.maxed@gmail.com>
Date: Fri, 10 Jan 2014 15:08:39 +0000
Subject: [PATCH] Nodes Viewer now supports ZNODES in "XNOD", "XGLN", "XGL2"
 and "XGL3" formats. Sector highlight is now shown in many more places. Edit
 area auto-focusing is now disabled when any form is open.

---
 Source/Core/IO/UniversalMapSetIO.cs           |   4 +-
 Source/Core/Map/MapSet.cs                     |   2 +-
 Source/Core/Windows/MainForm.cs               |   2 +-
 .../Plugins/BuilderModes/BuilderModes.csproj  |   3 +
 .../ClassicModes/MakeSectorMode.cs            |  13 +-
 .../BuilderModes/ClassicModes/VerticesMode.cs |   4 +-
 .../ErrorChecks/ResultUnknownFlat.cs          |   6 +
 .../FindReplace/BaseFindLinedef.cs            |  45 +++
 .../FindReplace/BaseFindSector.cs             |  57 ++++
 .../BuilderModes/FindReplace/BaseFindThing.cs |  45 +++
 .../FindReplace/FindAnyTextureFlat.cs         |  27 +-
 .../FindReplace/FindLinedefFlags.cs           |  48 +--
 .../FindReplace/FindLinedefNumber.cs          |  54 +--
 .../FindReplace/FindLinedefSectorRef.cs       |  56 +--
 .../FindReplace/FindLinedefTags.cs            |  56 +--
 .../FindReplace/FindLinedefThingRef.cs        |  56 +--
 .../FindReplace/FindLinedefTypes.cs           |  48 +--
 .../FindReplace/FindReplaceType.cs            |   2 +-
 .../FindReplace/FindSectorBrightness.cs       |  44 +--
 .../FindReplace/FindSectorEffect.cs           |  51 +--
 .../FindReplace/FindSectorFlat.cs             |  49 +--
 .../FindReplace/FindSectorNumber.cs           |  57 +---
 .../FindReplace/FindSectorTags.cs             |  58 +---
 .../FindReplace/FindThingAction.cs            |  47 +--
 .../FindReplace/FindThingAngle.cs             |  47 +--
 .../FindReplace/FindThingFlags.cs             |  47 +--
 .../FindReplace/FindThingNumber.cs            |  53 +--
 .../FindReplace/FindThingSectorRef.cs         |  55 +--
 .../BuilderModes/FindReplace/FindThingTag.cs  |  55 +--
 .../FindReplace/FindThingThingRef.cs          |  55 +--
 .../BuilderModes/FindReplace/FindThingType.cs |  47 +--
 .../FindReplace/FindVertexNumber.cs           |   4 +-
 Source/Plugins/NodesViewer/NodesForm.cs       |  13 +-
 Source/Plugins/NodesViewer/NodesViewerMode.cs | 319 ++++++++++++++----
 34 files changed, 478 insertions(+), 1051 deletions(-)
 create mode 100644 Source/Plugins/BuilderModes/FindReplace/BaseFindLinedef.cs
 create mode 100644 Source/Plugins/BuilderModes/FindReplace/BaseFindSector.cs
 create mode 100644 Source/Plugins/BuilderModes/FindReplace/BaseFindThing.cs

diff --git a/Source/Core/IO/UniversalMapSetIO.cs b/Source/Core/IO/UniversalMapSetIO.cs
index c582c6a80..476c765da 100644
--- a/Source/Core/IO/UniversalMapSetIO.cs
+++ b/Source/Core/IO/UniversalMapSetIO.cs
@@ -120,8 +120,8 @@ namespace CodeImp.DoomBuilder.IO
 		public override int MinBrightness { get { return int.MinValue; } }
 		public override int MaxThingType { get { return int.MaxValue; } }
 		public override int MinThingType { get { return int.MinValue; } }
-		public override float MaxCoordinate { get { return float.MaxValue; } }
-		public override float MinCoordinate { get { return float.MinValue; } }
+		public override float MaxCoordinate { get { return short.MaxValue; } } //mxd. UDMF maps are still bounded to -32768 .. 32767 range
+		public override float MinCoordinate { get { return short.MinValue; } } //mxd
 		public override int MaxThingAngle { get { return int.MaxValue; } }
 		public override int MinThingAngle { get { return int.MinValue; } }
 		public override Dictionary<string, Dictionary<string, UniversalType>> UIFields { get { return uifields; } } //mxd
diff --git a/Source/Core/Map/MapSet.cs b/Source/Core/Map/MapSet.cs
index b9a1b2fdb..bd77b4ed8 100644
--- a/Source/Core/Map/MapSet.cs
+++ b/Source/Core/Map/MapSet.cs
@@ -94,7 +94,7 @@ namespace CodeImp.DoomBuilder.Map
 		private static UniValue virtualsectorvalue;
 		
 		// Disposing
-		private bool isdisposed = false;
+		private bool isdisposed;
 
 		#endregion
 
diff --git a/Source/Core/Windows/MainForm.cs b/Source/Core/Windows/MainForm.cs
index 801b2ef78..dd6517bf5 100644
--- a/Source/Core/Windows/MainForm.cs
+++ b/Source/Core/Windows/MainForm.cs
@@ -1127,7 +1127,7 @@ namespace CodeImp.DoomBuilder.Windows
 			{
 				General.Plugins.OnEditMouseEnter(e);
 				General.Editing.Mode.OnMouseEnter(e);
-				if(!General.Map.IsScriptsWindowOpen) display.Focus(); //mxd
+				if(Application.OpenForms.Count == 1) display.Focus(); //mxd
 			}
 		}
 
diff --git a/Source/Plugins/BuilderModes/BuilderModes.csproj b/Source/Plugins/BuilderModes/BuilderModes.csproj
index f78e9d71a..08e3a88c5 100644
--- a/Source/Plugins/BuilderModes/BuilderModes.csproj
+++ b/Source/Plugins/BuilderModes/BuilderModes.csproj
@@ -241,6 +241,9 @@
     <Compile Include="ErrorChecks\ResultUnknownFlat.cs" />
     <Compile Include="ErrorChecks\ResultUnknownTexture.cs" />
     <Compile Include="ErrorChecks\ResultUnknownThing.cs" />
+    <Compile Include="FindReplace\BaseFindLinedef.cs" />
+    <Compile Include="FindReplace\BaseFindSector.cs" />
+    <Compile Include="FindReplace\BaseFindThing.cs" />
     <Compile Include="FindReplace\FindLinedefFlags.cs" />
     <Compile Include="FindReplace\FindSectorBrightness.cs" />
     <Compile Include="FindReplace\FindThingAngle.cs" />
diff --git a/Source/Plugins/BuilderModes/ClassicModes/MakeSectorMode.cs b/Source/Plugins/BuilderModes/ClassicModes/MakeSectorMode.cs
index 32be7ca1f..74cd99b18 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/MakeSectorMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/MakeSectorMode.cs
@@ -59,6 +59,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// Interface
 		protected bool editpressed;
 
+		//mxd. Used in overlay rendering
+		private Dictionary<Sector, Sector> associates;
+
 		#endregion
 
 		#region ================== Properties
@@ -94,7 +97,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// This draws the geometry
 		private void DrawGeometry()
 		{
-			Dictionary<Sector, Sector> associates = new Dictionary<Sector, Sector>();
+			associates = new Dictionary<Sector, Sector>();
 			
 			// Render lines and vertices
 			if(renderer.StartPlotter(true))
@@ -151,6 +154,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				if((flashpolygon != null) && (flashintensity > 0.0f))
 				{
 					renderer.RenderGeometry(flashpolygon, null, true);
+				} 
+				else if(BuilderPlug.Me.UseHighlight) //mxd
+				{
+					int color = General.Colors.Indication.WithAlpha(64).ToInt();
+					foreach(Sector s in associates.Keys){
+						renderer.RenderHighlight(s.FlatVertices, color);
+					}
 				}
 
 				renderer.Finish();
@@ -201,6 +211,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 						// Redraw overlay
 						DrawGeometry();
+						DrawOverlay(); //mxd
 						renderer.Present();
 					}
 				}
diff --git a/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs b/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs
index 3beaa417a..1700e071d 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs
@@ -474,8 +474,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 					//render preview
 					if(renderer.StartOverlay(true)) {
-						float dist = Vector2D.Distance(mousemappos, insertPreview);
-						byte alpha = (byte)(255 - (dist / BuilderPlug.Me.SplitLinedefsRange) * 192);
+						float dist = Math.Min(Vector2D.Distance(mousemappos, insertPreview), BuilderPlug.Me.SplitLinedefsRange);
+						byte alpha = (byte)(255 - (dist / BuilderPlug.Me.SplitLinedefsRange) * 128);
 						float vsize = (renderer.VertexSize + 1.0f) / renderer.Scale;
 						renderer.RenderRectangleFilled(new RectangleF(insertPreview.x - vsize, insertPreview.y - vsize, vsize * 2.0f, vsize * 2.0f), General.Colors.InfoLine.WithAlpha(alpha), true);
 						renderer.Finish();
diff --git a/Source/Plugins/BuilderModes/ErrorChecks/ResultUnknownFlat.cs b/Source/Plugins/BuilderModes/ErrorChecks/ResultUnknownFlat.cs
index be3d50748..4e7afbb3a 100644
--- a/Source/Plugins/BuilderModes/ErrorChecks/ResultUnknownFlat.cs
+++ b/Source/Plugins/BuilderModes/ErrorChecks/ResultUnknownFlat.cs
@@ -71,6 +71,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		{
 			renderer.PlotSector(sector, General.Colors.Selection);
 		}
+
+		//mxd. More rendering
+		public override void RenderOverlaySelection(IRenderer2D renderer) {
+			if(!BuilderPlug.Me.UseHighlight) return;
+			renderer.RenderHighlight(sector.FlatVertices, General.Colors.Selection.WithAlpha(64).ToInt());
+		}
 		
 		// Fix by setting default flat
 		public override bool Button1Click(bool batchMode)
diff --git a/Source/Plugins/BuilderModes/FindReplace/BaseFindLinedef.cs b/Source/Plugins/BuilderModes/FindReplace/BaseFindLinedef.cs
new file mode 100644
index 000000000..7a0d8846d
--- /dev/null
+++ b/Source/Plugins/BuilderModes/FindReplace/BaseFindLinedef.cs
@@ -0,0 +1,45 @@
+#region ================== Namespaces
+
+using System.Collections.Generic;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Rendering;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.BuilderModes
+{
+	//mxd. Encapsulates boring stuff
+	internal class BaseFindLinedef : FindReplaceType
+	{
+		#region ================== Methods
+
+		// This is called when a specific object is selected from the list
+		public override void ObjectSelected(FindReplaceObject[] selection) {
+			if(selection.Length == 1) {
+				ZoomToSelection(selection);
+				General.Interface.ShowLinedefInfo(selection[0].Linedef);
+			} else {
+				General.Interface.HideInfo();
+			}
+
+			General.Map.Map.ClearAllSelected();
+			foreach(FindReplaceObject obj in selection) obj.Linedef.Selected = true;
+		}
+
+		// Render selection
+		public override void PlotSelection(IRenderer2D renderer, FindReplaceObject[] selection) {
+			foreach(FindReplaceObject o in selection) {
+				renderer.PlotLinedef(o.Linedef, General.Colors.Selection);
+			}
+		}
+
+		// Edit objects
+		public override void EditObjects(FindReplaceObject[] selection) {
+			List<Linedef> linedefs = new List<Linedef>(selection.Length);
+			foreach(FindReplaceObject o in selection) linedefs.Add(o.Linedef);
+			General.Interface.ShowEditLinedefs(linedefs);
+		}
+
+		#endregion
+	}
+}
diff --git a/Source/Plugins/BuilderModes/FindReplace/BaseFindSector.cs b/Source/Plugins/BuilderModes/FindReplace/BaseFindSector.cs
new file mode 100644
index 000000000..351322c7b
--- /dev/null
+++ b/Source/Plugins/BuilderModes/FindReplace/BaseFindSector.cs
@@ -0,0 +1,57 @@
+#region ================== Namespaces
+
+using System.Collections.Generic;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Rendering;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.BuilderModes
+{
+	//mxd. Encapsulates boring stuff
+	internal class BaseFindSector : FindReplaceType
+	{
+		#region ================== Methods
+
+		// This is called when a specific object is selected from the list
+		public override void ObjectSelected(FindReplaceObject[] selection) {
+			if(selection.Length == 1) {
+				ZoomToSelection(selection);
+				General.Interface.ShowSectorInfo(selection[0].Sector);
+			} else {
+				General.Interface.HideInfo();
+			}
+
+			General.Map.Map.ClearAllSelected();
+			foreach(FindReplaceObject obj in selection) obj.Sector.Selected = true;
+		}
+
+		// Render selection
+		public override void PlotSelection(IRenderer2D renderer, FindReplaceObject[] selection) {
+			foreach(FindReplaceObject o in selection) {
+				foreach(Sidedef sd in o.Sector.Sidedefs) {
+					renderer.PlotLinedef(sd.Line, General.Colors.Selection);
+				}
+			}
+		}
+
+		//mxd. Render selection highlight
+		public override void RenderOverlaySelection(IRenderer2D renderer, FindReplaceObject[] selection) {
+			if(!BuilderPlug.Me.UseHighlight) return;
+
+			int color = General.Colors.Selection.WithAlpha(64).ToInt();
+			foreach(FindReplaceObject o in selection) {
+				renderer.RenderHighlight(o.Sector.FlatVertices, color);
+			}
+		}
+
+		// Edit objects
+		public override void EditObjects(FindReplaceObject[] selection) {
+			List<Sector> sectors = new List<Sector>(selection.Length);
+			foreach(FindReplaceObject o in selection) sectors.Add(o.Sector);
+			General.Interface.ShowEditSectors(sectors);
+		}
+
+		#endregion
+	}
+}
diff --git a/Source/Plugins/BuilderModes/FindReplace/BaseFindThing.cs b/Source/Plugins/BuilderModes/FindReplace/BaseFindThing.cs
new file mode 100644
index 000000000..61ce8974c
--- /dev/null
+++ b/Source/Plugins/BuilderModes/FindReplace/BaseFindThing.cs
@@ -0,0 +1,45 @@
+#region ================== Namespaces
+
+using System.Collections.Generic;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Rendering;
+
+#endregion
+
+namespace CodeImp.DoomBuilder.BuilderModes
+{
+	//mxd. Encapsulates boring stuff
+	internal class BaseFindThing : FindReplaceType
+	{
+		#region ================== Methods
+
+		// This is called when a specific object is selected from the list
+		public override void ObjectSelected(FindReplaceObject[] selection) {
+			if(selection.Length == 1) {
+				ZoomToSelection(selection);
+				General.Interface.ShowThingInfo(selection[0].Thing);
+			} else {
+				General.Interface.HideInfo();
+			}
+
+			General.Map.Map.ClearAllSelected();
+			foreach(FindReplaceObject obj in selection) obj.Thing.Selected = true;
+		}
+
+		// Render selection
+		public override void RenderThingsSelection(IRenderer2D renderer, FindReplaceObject[] selection) {
+			foreach(FindReplaceObject o in selection) {
+				renderer.RenderThing(o.Thing, General.Colors.Selection, 1.0f);
+			}
+		}
+
+		// Edit objects
+		public override void EditObjects(FindReplaceObject[] selection) {
+			List<Thing> things = new List<Thing>(selection.Length);
+			foreach(FindReplaceObject o in selection) things.Add(o.Thing);
+			General.Interface.ShowEditThings(things);
+		}
+
+		#endregion
+	}
+}
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindAnyTextureFlat.cs b/Source/Plugins/BuilderModes/FindReplace/FindAnyTextureFlat.cs
index eb2024019..524b5e3d3 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindAnyTextureFlat.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindAnyTextureFlat.cs
@@ -16,7 +16,6 @@
 
 #region ================== Namespaces
 
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.IO;
@@ -47,18 +46,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindAnyTextureFlat()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindAnyTextureFlat()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -88,7 +75,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			if(replacewith != null)
 			{
 				// If it cannot be interpreted, set replacewith to null (not replacing at all)
-				if(replacewith.Length < 0) replacewith = null;
+				if(replacewith.Length < 0) replacewith = null; //mxd. WUT?
 				if(replacewith.Length > 8) replacewith = null;
 				if(replacewith == null)
 				{
@@ -203,6 +190,18 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			}
 		}
 
+		//mxd
+		public override void RenderOverlaySelection(IRenderer2D renderer, FindReplaceObject[] selection) {
+			if(!BuilderPlug.Me.UseHighlight) return;
+
+			int color = General.Colors.Selection.WithAlpha(64).ToInt();
+			foreach(FindReplaceObject o in selection) {
+				if(o.Object is Sector) {
+					renderer.RenderHighlight(o.Sector.FlatVertices, color);
+				}
+			}
+		}
+
 		// Edit objects
 		public override void EditObjects(FindReplaceObject[] selection)
 		{
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindLinedefFlags.cs b/Source/Plugins/BuilderModes/FindReplace/FindLinedefFlags.cs
index 37a326cff..b8545af6f 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindLinedefFlags.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindLinedefFlags.cs
@@ -16,12 +16,10 @@
 
 #region ================== Namespaces
 
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Windows;
 using CodeImp.DoomBuilder.Map;
-using CodeImp.DoomBuilder.Rendering;
 using System.Drawing;
 using CodeImp.DoomBuilder.Config;
 
@@ -30,7 +28,7 @@ using CodeImp.DoomBuilder.Config;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Linedef Flags", BrowseButton = true, Replacable = false)]
-	internal class FindLinedefFlags : FindReplaceType
+	internal class FindLinedefFlags : BaseFindLinedef
 	{
 		#region ================== Constants
 
@@ -48,18 +46,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindLinedefFlags()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindLinedefFlags()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -114,38 +100,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if (selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowLinedefInfo(selection[0].Linedef);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach (FindReplaceObject obj in selection) obj.Linedef.Selected = true;
-		}
-
-		// Render selection
-		public override void PlotSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach (FindReplaceObject o in selection)
-			{
-				renderer.PlotLinedef(o.Linedef, General.Colors.Selection);
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Linedef> lines = new List<Linedef>(selection.Length);
-			foreach (FindReplaceObject o in selection) lines.Add(o.Linedef);
-			General.Interface.ShowEditLinedefs(lines);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindLinedefNumber.cs b/Source/Plugins/BuilderModes/FindReplace/FindLinedefNumber.cs
index e8fc2fa49..7364ec042 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindLinedefNumber.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindLinedefNumber.cs
@@ -18,7 +18,6 @@
 
 using System.Collections.Generic;
 using CodeImp.DoomBuilder.Map;
-using CodeImp.DoomBuilder.Rendering;
 using CodeImp.DoomBuilder.Config;
 
 #endregion
@@ -26,7 +25,7 @@ using CodeImp.DoomBuilder.Config;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Linedef Index", BrowseButton = false, Replacable = false)]
-	internal class FindLinedefNumber : FindReplaceType
+	internal class FindLinedefNumber : BaseFindLinedef
 	{
 		#region ================== Constants
 
@@ -42,29 +41,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindLinedefNumber()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindLinedefNumber()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
 
-		// This is called when the browse button is pressed
-		public override string Browse(string initialvalue)
-		{
-			return "";
-		}
-
-
 		// This is called to perform a search (and replace)
 		// Returns a list of items to show in the results list
 		// replacewith is null when not replacing
@@ -90,38 +70,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowLinedefInfo(selection[0].Linedef);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Linedef.Selected = true;
-		}
-
-		// Render selection
-		public override void PlotSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				renderer.PlotLinedef(o.Linedef, General.Colors.Selection);
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Linedef> linedefs = new List<Linedef>(selection.Length);
-			foreach(FindReplaceObject o in selection) linedefs.Add(o.Linedef);
-			General.Interface.ShowEditLinedefs(linedefs);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindLinedefSectorRef.cs b/Source/Plugins/BuilderModes/FindReplace/FindLinedefSectorRef.cs
index d4e9bbfe7..70536fe55 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindLinedefSectorRef.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindLinedefSectorRef.cs
@@ -16,11 +16,9 @@
 
 #region ================== Namespaces
 
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Map;
-using CodeImp.DoomBuilder.Rendering;
 using CodeImp.DoomBuilder.Config;
 using CodeImp.DoomBuilder.Types;
 
@@ -29,7 +27,7 @@ using CodeImp.DoomBuilder.Types;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Linedef Sector Reference", BrowseButton = false)]
-	internal class FindLinedefSectorRef : FindReplaceType
+	internal class FindLinedefSectorRef : BaseFindLinedef
 	{
 		#region ================== Constants
 
@@ -45,18 +43,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindLinedefSectorRef()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindLinedefSectorRef()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -67,14 +53,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return General.Map.FormatInterface.HasActionArgs;
 		}
 
-
-		// This is called when the browse button is pressed
-		public override string Browse(string initialvalue)
-		{
-			return "";
-		}
-
-
 		// This is called to perform a search (and replace)
 		// Returns a list of items to show in the results list
 		// replacewith is null when not replacing
@@ -142,38 +120,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowLinedefInfo(selection[0].Linedef);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Linedef.Selected = true;
-		}
-
-		// Render selection
-		public override void PlotSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				renderer.PlotLinedef(o.Linedef, General.Colors.Selection);
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Linedef> lines = new List<Linedef>(selection.Length);
-			foreach(FindReplaceObject o in selection) lines.Add(o.Linedef);
-			General.Interface.ShowEditLinedefs(lines);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindLinedefTags.cs b/Source/Plugins/BuilderModes/FindReplace/FindLinedefTags.cs
index 9840f6389..64d8ddffc 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindLinedefTags.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindLinedefTags.cs
@@ -16,11 +16,9 @@
 
 #region ================== Namespaces
 
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Map;
-using CodeImp.DoomBuilder.Rendering;
 using CodeImp.DoomBuilder.Config;
 
 #endregion
@@ -28,7 +26,7 @@ using CodeImp.DoomBuilder.Config;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Linedef Tags", BrowseButton = false)]
-	internal class FindLinedefTags : FindReplaceType
+	internal class FindLinedefTags : BaseFindLinedef
 	{
 		#region ================== Constants
 
@@ -44,18 +42,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindLinedefTags()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindLinedefTags()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -65,14 +51,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		{
 			return General.Map.FormatInterface.HasLinedefTag;
 		}
-		
-		
-		// This is called when the browse button is pressed
-		public override string Browse(string initialvalue)
-		{
-			return "";
-		}
-
 
 		// This is called to perform a search (and replace)
 		// Returns a list of items to show in the results list
@@ -125,38 +103,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowLinedefInfo(selection[0].Linedef);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Linedef.Selected = true;
-		}
-
-		// Render selection
-		public override void PlotSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				renderer.PlotLinedef(o.Linedef, General.Colors.Selection);
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Linedef> lines = new List<Linedef>(selection.Length);
-			foreach(FindReplaceObject o in selection) lines.Add(o.Linedef);
-			General.Interface.ShowEditLinedefs(lines);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindLinedefThingRef.cs b/Source/Plugins/BuilderModes/FindReplace/FindLinedefThingRef.cs
index 3af41b809..2bc00222d 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindLinedefThingRef.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindLinedefThingRef.cs
@@ -16,11 +16,9 @@
 
 #region ================== Namespaces
 
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Map;
-using CodeImp.DoomBuilder.Rendering;
 using CodeImp.DoomBuilder.Config;
 using CodeImp.DoomBuilder.Types;
 
@@ -29,7 +27,7 @@ using CodeImp.DoomBuilder.Types;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Linedef Thing Reference", BrowseButton = false)]
-	internal class FindLinedefThingRef : FindReplaceType
+	internal class FindLinedefThingRef : BaseFindLinedef
 	{
 		#region ================== Constants
 
@@ -45,18 +43,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindLinedefThingRef()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindLinedefThingRef()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -67,14 +53,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return General.Map.FormatInterface.HasActionArgs;
 		}
 
-
-		// This is called when the browse button is pressed
-		public override string Browse(string initialvalue)
-		{
-			return "";
-		}
-
-
 		// This is called to perform a search (and replace)
 		// Returns a list of items to show in the results list
 		// replacewith is null when not replacing
@@ -142,38 +120,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowLinedefInfo(selection[0].Linedef);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Linedef.Selected = true;
-		}
-
-		// Render selection
-		public override void PlotSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				renderer.PlotLinedef(o.Linedef, General.Colors.Selection);
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Linedef> lines = new List<Linedef>(selection.Length);
-			foreach(FindReplaceObject o in selection) lines.Add(o.Linedef);
-			General.Interface.ShowEditLinedefs(lines);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindLinedefTypes.cs b/Source/Plugins/BuilderModes/FindReplace/FindLinedefTypes.cs
index c15b5adf1..4a37974eb 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindLinedefTypes.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindLinedefTypes.cs
@@ -17,11 +17,9 @@
 #region ================== Namespaces
 
 using System;
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Map;
-using CodeImp.DoomBuilder.Rendering;
 using System.Drawing;
 using CodeImp.DoomBuilder.Config;
 
@@ -30,7 +28,7 @@ using CodeImp.DoomBuilder.Config;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Linedef Actions", BrowseButton = true)]
-	internal class FindLinedefTypes : FindReplaceType
+	internal class FindLinedefTypes : BaseFindLinedef
 	{
 		#region ================== Constants
 
@@ -48,18 +46,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindLinedefTypes()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindLinedefTypes()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -168,38 +154,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 		
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowLinedefInfo(selection[0].Linedef);
-			}
-			else
-				General.Interface.HideInfo();
-			
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Linedef.Selected = true;
-		}
-
-		// Render selection
-		public override void PlotSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				renderer.PlotLinedef(o.Linedef, General.Colors.Selection);
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Linedef> lines = new List<Linedef>(selection.Length);
-			foreach(FindReplaceObject o in selection) lines.Add(o.Linedef);
-			General.Interface.ShowEditLinedefs(lines);
-		}
-		
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindReplaceType.cs b/Source/Plugins/BuilderModes/FindReplace/FindReplaceType.cs
index e4c0a1f62..6843c4e12 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindReplaceType.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindReplaceType.cs
@@ -76,7 +76,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// This is called when the browse button is pressed
 		public virtual string Browse(string initialvalue)
 		{
-			return "";
+			return string.Empty;
 		}
 		
 		// This is called to perform a search (and replace)
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindSectorBrightness.cs b/Source/Plugins/BuilderModes/FindReplace/FindSectorBrightness.cs
index fd890a949..8e47359d9 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindSectorBrightness.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindSectorBrightness.cs
@@ -1,18 +1,17 @@
-using System.Collections.Generic;
+#region ================== Namespaces
+
+using System.Collections.Generic;
 using CodeImp.DoomBuilder.Map;
 using System.Windows.Forms;
-using CodeImp.DoomBuilder.Rendering;
 
-namespace CodeImp.DoomBuilder.BuilderModes.FindReplace
+#endregion
+
+namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Sector Brightness", BrowseButton = false)]
-	internal class FindSectorBrightness : FindReplaceType
+	internal class FindSectorBrightness : BaseFindSector
 	{
-		// Constructor
-		public FindSectorBrightness() {}
-
-		// Destructor
-		~FindSectorBrightness() {}
+		#region ================== Methods
 
 		// This is called to perform a search (and replace)
 		// Returns a list of items to show in the results list
@@ -60,32 +59,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.FindReplace
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection) {
-			if(selection.Length == 1) {
-				ZoomToSelection(selection);
-				General.Interface.ShowSectorInfo(selection[0].Sector);
-			} else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Sector.Selected = true;
-		}
-
-		// Render selection
-		public override void PlotSelection(IRenderer2D renderer, FindReplaceObject[] selection) {
-			foreach(FindReplaceObject o in selection) {
-				foreach(Sidedef sd in o.Sector.Sidedefs) {
-					renderer.PlotLinedef(sd.Line, General.Colors.Selection);
-				}
-			}
-		}
+		#endregion
 
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection) {
-			List<Sector> sectors = new List<Sector>(selection.Length);
-			foreach(FindReplaceObject o in selection) sectors.Add(o.Sector);
-			General.Interface.ShowEditSectors(sectors);
-		}
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindSectorEffect.cs b/Source/Plugins/BuilderModes/FindReplace/FindSectorEffect.cs
index 4587e911c..da01f5862 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindSectorEffect.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindSectorEffect.cs
@@ -17,11 +17,9 @@
 #region ================== Namespaces
 
 using System;
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Map;
-using CodeImp.DoomBuilder.Rendering;
 using System.Drawing;
 using CodeImp.DoomBuilder.Config;
 
@@ -30,7 +28,7 @@ using CodeImp.DoomBuilder.Config;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Sector Effect", BrowseButton = true)]
-	internal class FindSectorEffect : FindReplaceType
+	internal class FindSectorEffect : BaseFindSector
 	{
 		#region ================== Constants
 
@@ -48,18 +46,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindSectorEffect()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindSectorEffect()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -124,41 +110,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowSectorInfo(selection[0].Sector);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Sector.Selected = true;
-		}
-
-		// Render selection
-		public override void PlotSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				foreach(Sidedef sd in o.Sector.Sidedefs)
-				{
-					renderer.PlotLinedef(sd.Line, General.Colors.Selection);
-				}
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Sector> sectors = new List<Sector>(selection.Length);
-			foreach(FindReplaceObject o in selection) sectors.Add(o.Sector);
-			General.Interface.ShowEditSectors(sectors);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindSectorFlat.cs b/Source/Plugins/BuilderModes/FindReplace/FindSectorFlat.cs
index 02c46330d..1bc3b17cb 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindSectorFlat.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindSectorFlat.cs
@@ -29,7 +29,7 @@ using System.Drawing;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Sector Flat", BrowseButton = true)]
-	internal class FindSectorFlat : FindReplaceType
+	internal class FindSectorFlat : BaseFindSector
 	{
 		#region ================== Constants
 
@@ -47,18 +47,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindSectorFlat()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindSectorFlat()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -125,41 +113,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowSectorInfo(selection[0].Sector);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Sector.Selected = true;
-		}
-
-		// Render selection
-		public override void PlotSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				foreach(Sidedef sd in o.Sector.Sidedefs)
-				{
-					renderer.PlotLinedef(sd.Line, General.Colors.Selection);
-				}
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Sector> sectors = new List<Sector>(selection.Length);
-			foreach(FindReplaceObject o in selection) sectors.Add(o.Sector);
-			General.Interface.ShowEditSectors(sectors);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindSectorNumber.cs b/Source/Plugins/BuilderModes/FindReplace/FindSectorNumber.cs
index c7e10b475..33f2a54bc 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindSectorNumber.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindSectorNumber.cs
@@ -18,7 +18,6 @@
 
 using System.Collections.Generic;
 using CodeImp.DoomBuilder.Map;
-using CodeImp.DoomBuilder.Rendering;
 using CodeImp.DoomBuilder.Config;
 
 #endregion
@@ -26,7 +25,7 @@ using CodeImp.DoomBuilder.Config;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Sector Index", BrowseButton = false, Replacable = false)]
-	internal class FindSectorNumber : FindReplaceType
+	internal class FindSectorNumber : BaseFindSector
 	{
 		#region ================== Constants
 
@@ -42,29 +41,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindSectorNumber()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindSectorNumber()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
 
-		// This is called when the browse button is pressed
-		public override string Browse(string initialvalue)
-		{
-			return "";
-		}
-
-
 		// This is called to perform a search (and replace)
 		// Returns a list of items to show in the results list
 		// replacewith is null when not replacing
@@ -90,41 +70,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowSectorInfo(selection[0].Sector);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Sector.Selected = true;
-		}
-
-		// Render selection
-		public override void PlotSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				foreach(Sidedef sd in o.Sector.Sidedefs)
-				{
-					renderer.PlotLinedef(sd.Line, General.Colors.Selection);
-				}
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Sector> sectors = new List<Sector>(selection.Length);
-			foreach(FindReplaceObject o in selection) sectors.Add(o.Sector);
-			General.Interface.ShowEditSectors(sectors);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindSectorTags.cs b/Source/Plugins/BuilderModes/FindReplace/FindSectorTags.cs
index 7c0aef68d..552bc9452 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindSectorTags.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindSectorTags.cs
@@ -16,11 +16,9 @@
 
 #region ================== Namespaces
 
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Map;
-using CodeImp.DoomBuilder.Rendering;
 using CodeImp.DoomBuilder.Config;
 
 #endregion
@@ -28,7 +26,7 @@ using CodeImp.DoomBuilder.Config;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Sector Tags", BrowseButton = false)]
-	internal class FindSectorTags : FindReplaceType
+	internal class FindSectorTags : BaseFindSector
 	{
 		#region ================== Constants
 
@@ -44,29 +42,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindSectorTags()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindSectorTags()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
 
-		// This is called when the browse button is pressed
-		public override string Browse(string initialvalue)
-		{
-			return "";
-		}
-
-
 		// This is called to perform a search (and replace)
 		// Returns a list of items to show in the results list
 		// replacewith is null when not replacing
@@ -116,41 +95,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			
 			return objs.ToArray();
 		}
-
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowSectorInfo(selection[0].Sector);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Sector.Selected = true;
-		}
-
-		// Render selection
-		public override void PlotSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				foreach(Sidedef sd in o.Sector.Sidedefs)
-				{
-					renderer.PlotLinedef(sd.Line, General.Colors.Selection);
-				}
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Sector> sectors = new List<Sector>(selection.Length);
-			foreach(FindReplaceObject o in selection) sectors.Add(o.Sector);
-			General.Interface.ShowEditSectors(sectors);
-		}
 		
 		#endregion
 	}
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindThingAction.cs b/Source/Plugins/BuilderModes/FindReplace/FindThingAction.cs
index adfef5047..e8488e21f 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindThingAction.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindThingAction.cs
@@ -17,7 +17,6 @@
 #region ================== Namespaces
 
 using System;
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Map;
@@ -30,7 +29,7 @@ using CodeImp.DoomBuilder.Config;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Thing Action", BrowseButton = true)]
-	internal class FindThingAction : FindReplaceType
+	internal class FindThingAction : BaseFindThing
 	{
 		#region ================== Constants
 
@@ -49,18 +48,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindThingAction()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindThingAction()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -179,38 +166,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowThingInfo(selection[0].Thing);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Thing.Selected = true;
-		}
-
-		// Render selection
-		public override void RenderThingsSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				renderer.RenderThing(o.Thing, General.Colors.Selection, 1.0f);
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Thing> things = new List<Thing>(selection.Length);
-			foreach(FindReplaceObject o in selection) things.Add(o.Thing);
-			General.Interface.ShowEditThings(things);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindThingAngle.cs b/Source/Plugins/BuilderModes/FindReplace/FindThingAngle.cs
index c67bec6e1..275b56359 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindThingAngle.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindThingAngle.cs
@@ -16,7 +16,6 @@
 
 #region ================== Namespaces
 
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Windows;
@@ -31,7 +30,7 @@ using CodeImp.DoomBuilder.Config;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Thing Angle", BrowseButton = true)]
-	internal class FindThingAngle : FindReplaceType
+	internal class FindThingAngle : BaseFindThing
 	{
 		#region ================== Constants
 
@@ -50,18 +49,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindThingAngle()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindThingAngle()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -121,38 +108,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowThingInfo(selection[0].Thing);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Thing.Selected = true;
-		}
-
-		// Render selection
-		public override void RenderThingsSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				renderer.RenderThing(o.Thing, General.Colors.Selection, 1.0f);
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Thing> things = new List<Thing>(selection.Length);
-			foreach(FindReplaceObject o in selection) things.Add(o.Thing);
-			General.Interface.ShowEditThings(things);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindThingFlags.cs b/Source/Plugins/BuilderModes/FindReplace/FindThingFlags.cs
index d41c979c7..a3f8fbe42 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindThingFlags.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindThingFlags.cs
@@ -16,7 +16,6 @@
 
 #region ================== Namespaces
 
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Windows;
@@ -30,7 +29,7 @@ using CodeImp.DoomBuilder.Config;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Thing Flags", BrowseButton = true, Replacable = false)]
-	internal class FindThingFlag : FindReplaceType
+	internal class FindThingFlag : BaseFindThing
 	{
 		#region ================== Constants
 
@@ -49,18 +48,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindThingFlag()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindThingFlag()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -112,38 +99,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if (selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowThingInfo(selection[0].Thing);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach (FindReplaceObject obj in selection) obj.Thing.Selected = true;
-		}
-
-		// Render selection
-		public override void RenderThingsSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach (FindReplaceObject o in selection)
-			{
-				renderer.RenderThing(o.Thing, General.Colors.Selection, 1.0f);
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Thing> things = new List<Thing>(selection.Length);
-			foreach (FindReplaceObject o in selection) things.Add(o.Thing);
-			General.Interface.ShowEditThings(things);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindThingNumber.cs b/Source/Plugins/BuilderModes/FindReplace/FindThingNumber.cs
index a5415444c..a7095b31e 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindThingNumber.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindThingNumber.cs
@@ -26,7 +26,7 @@ using CodeImp.DoomBuilder.Config;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Thing Index", BrowseButton = false, Replacable = false)]
-	internal class FindThingNumber : FindReplaceType
+	internal class FindThingNumber : BaseFindThing
 	{
 		#region ================== Constants
 
@@ -44,29 +44,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindThingNumber()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindThingNumber()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
 
-		// This is called when the browse button is pressed
-		public override string Browse(string initialvalue)
-		{
-			return "";
-		}
-
-
 		// This is called to perform a search (and replace)
 		// Returns a list of items to show in the results list
 		// replacewith is null when not replacing
@@ -89,38 +70,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowThingInfo(selection[0].Thing);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Thing.Selected = true;
-		}
-		
-		// Render selection
-		public override void  RenderThingsSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				renderer.RenderThing(o.Thing, General.Colors.Selection, 1.0f);
-			}
-		}
-		
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Thing> things = new List<Thing>(selection.Length);
-			foreach(FindReplaceObject o in selection) things.Add(o.Thing);
-			General.Interface.ShowEditThings(things);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindThingSectorRef.cs b/Source/Plugins/BuilderModes/FindReplace/FindThingSectorRef.cs
index d76c1026d..f84eeca23 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindThingSectorRef.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindThingSectorRef.cs
@@ -16,7 +16,6 @@
 
 #region ================== Namespaces
 
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Map;
@@ -29,7 +28,7 @@ using CodeImp.DoomBuilder.Types;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Thing Sector Reference", BrowseButton = false)]
-	internal class FindThingSectorRef : FindReplaceType
+	internal class FindThingSectorRef : BaseFindThing
 	{
 		#region ================== Constants
 
@@ -47,18 +46,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindThingSectorRef()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindThingSectorRef()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -69,14 +56,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return General.Map.FormatInterface.HasThingAction && General.Map.FormatInterface.HasActionArgs;
 		}
 
-
-		// This is called when the browse button is pressed
-		public override string Browse(string initialvalue)
-		{
-			return "";
-		}
-
-
 		// This is called to perform a search (and replace)
 		// Returns a list of items to show in the results list
 		// replacewith is null when not replacing
@@ -142,38 +121,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowThingInfo(selection[0].Thing);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Thing.Selected = true;
-		}
-
-		// Render selection
-		public override void RenderThingsSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				renderer.RenderThing(o.Thing, General.Colors.Selection, 1.0f);
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Thing> things = new List<Thing>(selection.Length);
-			foreach(FindReplaceObject o in selection) things.Add(o.Thing);
-			General.Interface.ShowEditThings(things);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindThingTag.cs b/Source/Plugins/BuilderModes/FindReplace/FindThingTag.cs
index 2af7118e3..d1133255e 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindThingTag.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindThingTag.cs
@@ -17,7 +17,6 @@
 #region ================== Namespaces
 
 using System;
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Map;
@@ -29,7 +28,7 @@ using CodeImp.DoomBuilder.Config;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Thing Tag", BrowseButton = false)]
-	internal class FindThingTag : FindReplaceType
+	internal class FindThingTag : BaseFindThing
 	{
 		#region ================== Constants
 
@@ -47,18 +46,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindThingTag()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindThingTag()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -69,14 +56,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return General.Map.FormatInterface.HasThingTag;
 		}
 
-
-		// This is called when the browse button is pressed
-		public override string Browse(string initialvalue)
-		{
-			return "";
-		}
-
-
 		// This is called to perform a search (and replace)
 		// Returns a list of items to show in the results list
 		// replacewith is null when not replacing
@@ -125,38 +104,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowThingInfo(selection[0].Thing);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Thing.Selected = true;
-		}
-
-		// Render selection
-		public override void RenderThingsSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				renderer.RenderThing(o.Thing, General.Colors.Selection, 1.0f);
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Thing> things = new List<Thing>(selection.Length);
-			foreach(FindReplaceObject o in selection) things.Add(o.Thing);
-			General.Interface.ShowEditThings(things);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindThingThingRef.cs b/Source/Plugins/BuilderModes/FindReplace/FindThingThingRef.cs
index 3a395539f..d2e6fdcad 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindThingThingRef.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindThingThingRef.cs
@@ -16,7 +16,6 @@
 
 #region ================== Namespaces
 
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Map;
@@ -29,7 +28,7 @@ using CodeImp.DoomBuilder.Types;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Thing Thing Reference", BrowseButton = false)]
-	internal class FindThingThingRef : FindReplaceType
+	internal class FindThingThingRef : BaseFindThing
 	{
 		#region ================== Constants
 
@@ -47,18 +46,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindThingThingRef()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindThingThingRef()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -69,14 +56,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return General.Map.FormatInterface.HasThingAction && General.Map.FormatInterface.HasThingTag;
 		}
 
-
-		// This is called when the browse button is pressed
-		public override string Browse(string initialvalue)
-		{
-			return "";
-		}
-
-
 		// This is called to perform a search (and replace)
 		// Returns a list of items to show in the results list
 		// replacewith is null when not replacing
@@ -142,38 +121,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowThingInfo(selection[0].Thing);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Thing.Selected = true;
-		}
-
-		// Render selection
-		public override void RenderThingsSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				renderer.RenderThing(o.Thing, General.Colors.Selection, 1.0f);
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Thing> things = new List<Thing>(selection.Length);
-			foreach(FindReplaceObject o in selection) things.Add(o.Thing);
-			General.Interface.ShowEditThings(things);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindThingType.cs b/Source/Plugins/BuilderModes/FindReplace/FindThingType.cs
index 86d1a4748..beb25a2ec 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindThingType.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindThingType.cs
@@ -17,7 +17,6 @@
 #region ================== Namespaces
 
 using System;
-using System.Collections;
 using System.Collections.Generic;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Map;
@@ -30,7 +29,7 @@ using CodeImp.DoomBuilder.Config;
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	[FindReplace("Thing Type", BrowseButton = true)]
-	internal class FindThingType : FindReplaceType
+	internal class FindThingType : BaseFindThing
 	{
 		#region ================== Constants
 
@@ -49,18 +48,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Constructor / Destructor
 
-		// Constructor
-		public FindThingType()
-		{
-			// Initialize
-
-		}
-
-		// Destructor
-		~FindThingType()
-		{
-		}
-
 		#endregion
 
 		#region ================== Methods
@@ -127,38 +114,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			return objs.ToArray();
 		}
 
-		// This is called when a specific object is selected from the list
-		public override void ObjectSelected(FindReplaceObject[] selection)
-		{
-			if(selection.Length == 1)
-			{
-				ZoomToSelection(selection);
-				General.Interface.ShowThingInfo(selection[0].Thing);
-			}
-			else
-				General.Interface.HideInfo();
-
-			General.Map.Map.ClearAllSelected();
-			foreach(FindReplaceObject obj in selection) obj.Thing.Selected = true;
-		}
-
-		// Render selection
-		public override void RenderThingsSelection(IRenderer2D renderer, FindReplaceObject[] selection)
-		{
-			foreach(FindReplaceObject o in selection)
-			{
-				renderer.RenderThing(o.Thing, General.Colors.Selection, 1.0f);
-			}
-		}
-
-		// Edit objects
-		public override void EditObjects(FindReplaceObject[] selection)
-		{
-			List<Thing> things = new List<Thing>(selection.Length);
-			foreach(FindReplaceObject o in selection) things.Add(o.Thing);
-			General.Interface.ShowEditThings(things);
-		}
-
 		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/FindReplace/FindVertexNumber.cs b/Source/Plugins/BuilderModes/FindReplace/FindVertexNumber.cs
index 4a0d32747..09e30ed6c 100644
--- a/Source/Plugins/BuilderModes/FindReplace/FindVertexNumber.cs
+++ b/Source/Plugins/BuilderModes/FindReplace/FindVertexNumber.cs
@@ -58,10 +58,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		#region ================== Methods
 
 		// This is called when the browse button is pressed
-		public override string Browse(string initialvalue)
+		/*public override string Browse(string initialvalue)
 		{
 			return "";
-		}
+		}*/
 
 
 		// This is called to perform a search (and replace)
diff --git a/Source/Plugins/NodesViewer/NodesForm.cs b/Source/Plugins/NodesViewer/NodesForm.cs
index bf6404a42..2848ffdfa 100644
--- a/Source/Plugins/NodesViewer/NodesForm.cs
+++ b/Source/Plugins/NodesViewer/NodesForm.cs
@@ -297,7 +297,8 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer
 		private void segindex_ValueChanged(object sender, EventArgs e)
 		{
 			Seg sg = mode.Segs[(int)segindex.Value];
-			Linedef ld = General.Map.Map.GetLinedefByIndex(sg.lineindex);
+			Linedef ld = null; //mxd
+			if(sg.lineindex != -1) ld = General.Map.Map.GetLinedefByIndex(sg.lineindex); //mxd
 
 			lineindex.Text = sg.lineindex.ToString();
 			startvertex.Text = sg.startvertex + "  (" + mode.Vertices[sg.startvertex].x + ", " + mode.Vertices[sg.startvertex].y + ")";
@@ -305,8 +306,14 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer
 			segside.Text = sg.leftside ? "Back" : "Front";
 			segangle.Text = Angle2D.RealToDoom(sg.angle) + "\u00B0";
 			segoffset.Text = sg.offset + " mp";
-			sideindex.Text = sg.leftside ? ld.Back.Index.ToString() : ld.Front.Index.ToString();
-			sectorindex.Text = sg.leftside ? ld.Back.Sector.Index.ToString() : ld.Front.Sector.Index.ToString();
+
+			if (ld != null) { //mxd
+				sideindex.Text = sg.leftside ? ld.Back.Index.ToString() : ld.Front.Index.ToString();
+				sectorindex.Text = sg.leftside ? ld.Back.Sector.Index.ToString() : ld.Front.Sector.Index.ToString();
+			} else {
+				sideindex.Text = "None";
+				sectorindex.Text = "None";
+			}
 
 			General.Interface.RedrawDisplay();
 		}
diff --git a/Source/Plugins/NodesViewer/NodesViewerMode.cs b/Source/Plugins/NodesViewer/NodesViewerMode.cs
index 7e79e2a78..7c7b21e28 100644
--- a/Source/Plugins/NodesViewer/NodesViewerMode.cs
+++ b/Source/Plugins/NodesViewer/NodesViewerMode.cs
@@ -1,4 +1,4 @@
-#region === Copyright (c) 2010 Pascal van der Heiden ===
+#region ================== Namespaces
 
 using System;
 using System.Collections.Generic;
@@ -9,6 +9,7 @@ using CodeImp.DoomBuilder.Editing;
 using CodeImp.DoomBuilder.Geometry;
 using CodeImp.DoomBuilder.Rendering;
 using CodeImp.DoomBuilder.Windows;
+using CodeImp.DoomBuilder.Map;
 
 #endregion
 
@@ -39,6 +40,7 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer
 		private List<PixelColor> distinctcolors;
 		private NodesForm form;
 		private int mouseinssector = -1;
+		private string nodesformat = "Classic nodes";
 
 		#endregion
 
@@ -61,27 +63,22 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer
 			// display multiple things on the screen
 			// Note that black and white are not in this list, because
 			// these are the most likely colors for the user's background
-			distinctcolors = new List<PixelColor>();
-			distinctcolors.Add(PixelColor.FromColor(Color.Blue));
-			distinctcolors.Add(PixelColor.FromColor(Color.Orange));
-			distinctcolors.Add(PixelColor.FromColor(Color.ForestGreen));
-			distinctcolors.Add(PixelColor.FromColor(Color.Sienna));
-			distinctcolors.Add(PixelColor.FromColor(Color.LightPink));
-			distinctcolors.Add(PixelColor.FromColor(Color.Purple));
-			distinctcolors.Add(PixelColor.FromColor(Color.Cyan));
-			distinctcolors.Add(PixelColor.FromColor(Color.LawnGreen));
-			distinctcolors.Add(PixelColor.FromColor(Color.PaleGoldenrod));
-			distinctcolors.Add(PixelColor.FromColor(Color.Red));
-			distinctcolors.Add(PixelColor.FromColor(Color.Yellow));
-			distinctcolors.Add(PixelColor.FromColor(Color.LightSkyBlue));
-			distinctcolors.Add(PixelColor.FromColor(Color.DarkGray));
-			distinctcolors.Add(PixelColor.FromColor(Color.Magenta));
-		}
-
-		// Disposer
-		public override void Dispose()
-		{
-			base.Dispose();
+			distinctcolors = new List<PixelColor> {
+				PixelColor.FromColor(Color.Blue), 
+				PixelColor.FromColor(Color.Orange), 
+				PixelColor.FromColor(Color.ForestGreen), 
+				PixelColor.FromColor(Color.Sienna), 
+				PixelColor.FromColor(Color.LightPink), 
+				PixelColor.FromColor(Color.Purple),
+				PixelColor.FromColor(Color.Cyan), 
+				PixelColor.FromColor(Color.LawnGreen), 
+				PixelColor.FromColor(Color.PaleGoldenrod), 
+				PixelColor.FromColor(Color.Red), 
+				PixelColor.FromColor(Color.Yellow), 
+				PixelColor.FromColor(Color.LightSkyBlue), 
+				PixelColor.FromColor(Color.DarkGray), 
+				PixelColor.FromColor(Color.Magenta)
+			};
 		}
 
 		#endregion
@@ -105,7 +102,7 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer
 		/// <summary>
 		/// This loads all nodes structures data from the lumps
 		/// </summary>
-		private void LoadStructures()
+		private void LoadClassicStructures()
 		{
 			// Load the nodes structure
 			MemoryStream nodesstream = General.Map.GetLumpData("NODES");
@@ -200,6 +197,181 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer
 			}
 		}
 
+		//mxd. This loads all data from the ZNODES lump
+		private bool LoadZNodes() {
+			List<string> supportedFormats = new List<string> { "XNOD", "XGLN", "XGL2", "XGL3" };
+
+			using(MemoryStream stream = General.Map.GetLumpData("ZNODES")) {
+				//boilerplate...
+				if(stream.Length < 4) {
+					MessageBox.Show("ZNODES lump is empty.", "Nodes Viewer mode", MessageBoxButtons.OK, MessageBoxIcon.Error);
+					return false;
+				}
+
+				using(BinaryReader reader = new BinaryReader(stream)) {
+					//read signature
+					nodesformat = new string(reader.ReadChars(4));
+					if(!supportedFormats.Contains(nodesformat)) {
+						MessageBox.Show("'" + nodesformat + "' node format is not supported.", "Nodes Viewer mode", MessageBoxButtons.OK, MessageBoxIcon.Error);
+						return false;
+					}
+
+					uint vertsCount = reader.ReadUInt32();
+					uint newVertsCount = reader.ReadUInt32();
+
+					//boilerplate...
+					if(vertsCount != General.Map.Map.Vertices.Count) {
+						MessageBox.Show("Error while reading ZNODES: nodes vertices count in ZNODES lump (" + vertsCount + ") doesn't match with map's vertices count (" + General.Map.Map.Vertices.Count + ")!", "Nodes Viewer mode", MessageBoxButtons.OK, MessageBoxIcon.Error);
+						return false;
+					}
+
+					//add map vertices
+					verts = new Vector2D[vertsCount + newVertsCount];
+					int counter = 0;
+					foreach(Vertex v in General.Map.Map.Vertices) {
+						verts[counter++] = v.Position;
+					}
+
+					//read extra vertices
+					for(int i = counter; i < counter + newVertsCount; i++) {
+						verts[i].x = reader.ReadInt32() / 65536.0f;
+						verts[i].y = reader.ReadInt32() / 65536.0f;
+					}
+
+					//read subsectors
+					uint ssecCount = reader.ReadUInt32();
+					ssectors = new Subsector[ssecCount];
+
+					int firstseg = 0;
+					for(int i = 0; i < ssectors.Length; i++) {
+						ssectors[i].numsegs = (int)reader.ReadUInt32();
+						ssectors[i].firstseg = firstseg;
+						firstseg += ssectors[i].numsegs;
+					}
+
+					//read segments. offset and angle are unused anyway
+					uint segsCount = reader.ReadUInt32();
+					segs = new Seg[segsCount];
+
+					switch(nodesformat) {
+						case "XGLN":
+							for(int i = 0; i < segs.Length; i++) {
+								segs[i].startvertex = (int)reader.ReadUInt32();
+								reader.BaseStream.Position += 4; //skip partner
+								segs[i].lineindex = reader.ReadUInt16();
+								segs[i].leftside = reader.ReadBoolean();
+							}
+							break;
+
+						case "XGL3":
+						case "XGL2":
+							for(int i = 0; i < segs.Length; i++) {
+								segs[i].startvertex = (int)reader.ReadUInt32();
+								reader.BaseStream.Position += 4; //skip partner
+								uint lineindex = reader.ReadUInt32();
+								segs[i].lineindex = (lineindex == 0xFFFFFFFF ? -1 : (int)lineindex);
+								segs[i].leftside = reader.ReadBoolean();
+							}
+							break;
+
+						case "XNOD":
+							for(int i = 0; i < segs.Length; i++) {
+								segs[i].startvertex = (int)reader.ReadUInt32();
+								segs[i].endvertex = (int)reader.ReadUInt32();
+								segs[i].lineindex = reader.ReadUInt16();
+								segs[i].leftside = reader.ReadBoolean();
+							}
+							break;
+					}
+
+					//set second vertex, angle and reverse segs order
+					if(nodesformat == "XGLN" || nodesformat == "XGL2" || nodesformat == "XGL3") {
+						int index = 0;
+						foreach(Subsector ss in ssectors) {
+							//set the last vert
+							int lastseg = ss.firstseg + ss.numsegs - 1;
+							segs[lastseg].endvertex = segs[ss.firstseg].startvertex;
+
+							//set the rest
+							for(int i = ss.firstseg + 1; i <= lastseg; i++) {
+								segs[i - 1].endvertex = segs[i].startvertex;
+							}
+
+							//set angle and subsector index
+							for (int i = ss.firstseg; i <= lastseg; i++) {
+								segs[i].angle = Vector2D.GetAngle(verts[segs[i].endvertex], verts[segs[i].startvertex]);
+								segs[i].ssector = index;
+							}
+
+							//reverse segments order
+							Seg[] tmp = new Seg[ss.numsegs - 1];
+							int c = 0;
+							for(int i = ss.firstseg + 1; i <= lastseg; i++) {
+								tmp[c++] = segs[i];
+							}
+
+							//c = ss.numsegs - 1;
+							for (int i = ss.firstseg + 1; i <= lastseg; i++) {
+								segs[i] = tmp[--c];
+							}
+
+							index++;
+						}
+					}
+
+					//read nodes
+					uint nodesCount = reader.ReadUInt32();
+
+					//boilerplate...
+					if(nodesCount < 1) {
+						MessageBox.Show("The map has only one subsector.", "Why are you doing this, Stanley?..", MessageBoxButtons.OK, MessageBoxIcon.Error);
+						return false;
+					}
+
+					nodes = new Node[nodesCount];
+
+					for(int i = 0; i < nodes.Length; i++) {
+						if(nodesformat == "XGL3") {
+							nodes[i].linestart.x = reader.ReadInt32() / 65536.0f;
+							nodes[i].linestart.y = reader.ReadInt32() / 65536.0f;
+							nodes[i].linedelta.x = reader.ReadInt32() / 65536.0f;
+							nodes[i].linedelta.y = reader.ReadInt32() / 65536.0f;
+						} else {
+							nodes[i].linestart.x = reader.ReadInt16();
+							nodes[i].linestart.y = reader.ReadInt16();
+							nodes[i].linedelta.x = reader.ReadInt16();
+							nodes[i].linedelta.y = reader.ReadInt16();
+						}
+
+						float top = reader.ReadInt16();
+						float bot = reader.ReadInt16();
+						float left = reader.ReadInt16();
+						float right = reader.ReadInt16();
+						nodes[i].rightbox = new RectangleF(left, top, (right - left), (bot - top));
+
+						top = reader.ReadInt16();
+						bot = reader.ReadInt16();
+						left = reader.ReadInt16();
+						right = reader.ReadInt16();
+						nodes[i].leftbox = new RectangleF(left, top, (right - left), (bot - top));
+
+						uint rightindex = reader.ReadUInt32();
+						uint leftindex = reader.ReadUInt32();
+						nodes[i].rightchild = (int)(rightindex & 0x7FFFFFFF);
+						nodes[i].leftchild = (int)(leftindex & 0x7FFFFFFF);
+						nodes[i].rightsubsector = (rightindex & 0x80000000) != 0;
+						nodes[i].leftsubsector = (leftindex & 0x80000000) != 0;
+					}
+
+					// Add additional properties to nodes
+					nodes[nodes.Length - 1].parent = -1;
+					RecursiveSetupNodes(nodes.Length - 1);
+				}
+			}
+
+			return true;
+		}
+
 		/// <summary>
 		/// This recursively sets up the nodes structure with additional properties
 		/// </summary>
@@ -470,8 +642,9 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer
 		/// <summary>
 		/// This tests if the given coordinate is inside the specified subsector.
 		/// </summary>
-		private bool PointInSubsector(int index, Vector2D p)
-		{
+		private bool PointInSubsector(int index, Vector2D p) {
+			if (ssectors[index].points.Length == 0) return false; //mxd
+			
 			// Subsectors are convex, so we can simply test if the point is on the front side of all lines.
 			Vector2D[] points = ssectors[index].points;
 			Vector2D prevpoint = points[points.Length - 1];
@@ -595,43 +768,61 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer
 				return;
 			}
 
-			if(!General.Map.LumpExists("NODES") || !General.Map.LumpExists("SSECTORS") || !General.Map.LumpExists("SEGS") || !General.Map.LumpExists("VERTEXES"))
+			//mxd. No need to check for these twice
+			bool haveNodes = General.Map.LumpExists("NODES");
+			bool haveZnodes = General.Map.LumpExists("ZNODES");
+			bool haveSectors = General.Map.LumpExists("SSECTORS");
+			bool haveSegs = General.Map.LumpExists("SEGS");
+			bool haveVerts = General.Map.LumpExists("VERTEXES");
+
+			if(!haveNodes || !haveSectors || !haveSegs || !haveVerts || !haveZnodes)
 			{
 				// We need to build the nodes!
 				BuildNodes();
 			}
 
-			if(!General.Map.LumpExists("NODES"))
-			{
-				MessageBox.Show("Unable to find the NODES lump. It may be that the nodes could not be built correctly.", "Nodes Viewer mode", MessageBoxButtons.OK, MessageBoxIcon.Error);
-				General.Editing.CancelMode();
-				return;
-			}
+			//mxd
+			if(haveZnodes) {
+				General.Interface.DisplayStatus(StatusType.Busy, "Reading map nodes...");
+				if(!LoadZNodes()) {
+					General.Editing.CancelMode();
+					return;
+				}
+			} else {
+				if(!haveNodes) {
+					MessageBox.Show("Unable to find the NODES lump. It may be that the nodes could not be built correctly.", "Nodes Viewer mode", MessageBoxButtons.OK, MessageBoxIcon.Error);
+					General.Editing.CancelMode();
+					return;
+				}
 
-			if(!General.Map.LumpExists("SSECTORS"))
-			{
-				MessageBox.Show("Unable to find the SSECTORS lump. It may be that the nodes could not be built correctly.", "Nodes Viewer mode", MessageBoxButtons.OK, MessageBoxIcon.Error);
-				General.Editing.CancelMode();
-				return;
-			}
+				if(!haveSectors) {
+					MessageBox.Show("Unable to find the SSECTORS lump. It may be that the nodes could not be built correctly.", "Nodes Viewer mode", MessageBoxButtons.OK, MessageBoxIcon.Error);
+					General.Editing.CancelMode();
+					return;
+				}
 
-			if(!General.Map.LumpExists("SEGS"))
-			{
-				MessageBox.Show("Unable to find the SEGS lump. It may be that the nodes could not be built correctly.", "Nodes Viewer mode", MessageBoxButtons.OK, MessageBoxIcon.Error);
-				General.Editing.CancelMode();
-				return;
-			}
+				if(!haveSegs) {
+					MessageBox.Show("Unable to find the SEGS lump. It may be that the nodes could not be built correctly.", "Nodes Viewer mode", MessageBoxButtons.OK, MessageBoxIcon.Error);
+					General.Editing.CancelMode();
+					return;
+				}
 
-			if(!General.Map.LumpExists("VERTEXES"))
-			{
-				MessageBox.Show("Unable to find the VERTEXES lump. It may be that the nodes could not be built correctly.", "Nodes Viewer mode", MessageBoxButtons.OK, MessageBoxIcon.Error);
-				General.Editing.CancelMode();
-				return;
-			}
+				if(!haveVerts) {
+					MessageBox.Show("Unable to find the VERTEXES lump. It may be that the nodes could not be built correctly.", "Nodes Viewer mode", MessageBoxButtons.OK, MessageBoxIcon.Error);
+					General.Editing.CancelMode();
+					return;
+				}
 
-			General.Interface.DisplayStatus(StatusType.Busy, "Reading map nodes...");
+				General.Interface.DisplayStatus(StatusType.Busy, "Reading map nodes...");
+				LoadClassicStructures();
 
-			LoadStructures();
+				//mxd. More boilerplate
+				if (nodes.Length < 1) {
+					MessageBox.Show("The map has only one subsector.", "Why are you doing this, Stanley?..", MessageBoxButtons.OK, MessageBoxIcon.Error);
+					General.Editing.CancelMode();
+					return;
+				}
+			}
 			
 			// Setup presentation
 			CustomPresentation presentation = new CustomPresentation();
@@ -647,6 +838,7 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer
 
 			// Load and display dialog window
 			form = new NodesForm(this);
+			form.Text += " (" + nodesformat + " format)";
 			form.Show((Form)General.Interface);
 
 			Cursor.Current = Cursors.Default;
@@ -751,25 +943,16 @@ namespace CodeImp.DoomBuilder.Plugins.NodesViewer
 			{
 				if(form.SelectedTab == 0)
 				{
-					if(mouseinssector > -1)
+					// Render all subsectors in original color
+					for(int si = 0; si < ssectors.Length; si++) 
 					{
-						// Render all subsectors in original color
-						for(int si = 0; si < ssectors.Length; si++)
-						{
-							Subsector s = ssectors[si];
-							PlotSubsectorLines(s.points, PixelColor.FromColor(Color.Gray));
-						}
-						PlotSubsectorLines(ssectors[mouseinssector].points, General.Colors.Highlight);
+						Subsector s = ssectors[si];
+						PlotSubsectorLines(s.points, PixelColor.FromColor(Color.Gray));
 					}
-					else
+					
+					if(mouseinssector > -1)
 					{
-						// Render all subsectors with distinct colors
-						for(int si = 0; si < ssectors.Length; si++)
-						{
-							Subsector s = ssectors[si];
-							PixelColor color = distinctcolors[si % distinctcolors.Count];
-							PlotSubsectorLines(s.points, color);
-						}
+						PlotSubsectorLines(ssectors[mouseinssector].points, General.Colors.Highlight);
 					}
 
 					// Draw additional vertices
-- 
GitLab