From 179f72068f9b4cc841f458d277279ed36a2272df Mon Sep 17 00:00:00 2001
From: biwa <6475593+biwa@users.noreply.github.com>
Date: Sun, 18 Sep 2022 16:54:09 +0200
Subject: [PATCH] Things/Linedefs/Sectors/Vertices Modes: standardized how
 editing and selection works: - editing a highlighted, not selected map
 element will deselect other selected map elements, then start editing the
 highlighted map element - dragging a highlighted, not selected map element
 will deselect other selected map elements, then start dragging the
 highlighted map element - dragging a single map element will keep its
 selection state. I.e. dragging a selected map element will not deselect it
 after dragging anymore   - dragging a highlighted, not selected thing will
 not select it after dragging - dragging a highlighted, not selected sector,
 while other sectors are selected, will only drag the highlighted sector, and
 not the selected sector (and deselect the selected sectors)

---
 .../ClassicModes/DragLinedefsMode.cs          | 58 +++++++---------
 .../ClassicModes/DragSectorsMode.cs           | 64 +++++------------
 .../ClassicModes/DragThingsMode.cs            | 42 ++++++------
 .../ClassicModes/DragVerticesMode.cs          | 23 +------
 .../BuilderModes/ClassicModes/LinedefsMode.cs | 51 +++++++-------
 .../BuilderModes/ClassicModes/SectorsMode.cs  | 60 +++++++---------
 .../BuilderModes/ClassicModes/ThingsMode.cs   | 68 +++++++++----------
 .../BuilderModes/ClassicModes/VerticesMode.cs | 44 ++++++------
 8 files changed, 172 insertions(+), 238 deletions(-)

diff --git a/Source/Plugins/BuilderModes/ClassicModes/DragLinedefsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DragLinedefsMode.cs
index b8bc0a389..56d972bf3 100755
--- a/Source/Plugins/BuilderModes/ClassicModes/DragLinedefsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DragLinedefsMode.cs
@@ -45,8 +45,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Variables
 
-		private ICollection<Linedef> selectedlines;
-		private ICollection<Linedef> unselectedlines;
+		private ICollection<Linedef> draglines;
+		private ICollection<Linedef> unmovinglines;
 
 		#endregion
 
@@ -57,21 +57,27 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		#region ================== Constructor / Disposer
 
 		// Constructor to start dragging immediately
-		public DragLinedefsMode(Vector2D dragstartmappos)
+		public DragLinedefsMode(Vector2D dragstartmappos, List<Linedef> lines)
 		{
 			// Mark what we are dragging
 			General.Map.Map.ClearAllMarks(false);
-			General.Map.Map.MarkSelectedLinedefs(true, true);
+
+			draglines = new List<Linedef>(lines.Count);
+			foreach(Linedef ld in lines)
+			{
+				ld.Marked = true;
+				draglines.Add(ld);
+			}
+
 			ICollection<Vertex> verts = General.Map.Map.GetVerticesFromLinesMarks(true);
-			foreach(Vertex v in verts) v.Marked = true;
-			
+			foreach (Vertex v in verts) v.Marked = true;
+
 			// Get line collections
-			selectedlines = General.Map.Map.GetSelectedLinedefs(true);
-			unselectedlines = General.Map.Map.GetSelectedLinedefs(false);
+			unmovinglines = General.Map.Map.GetSelectedLinedefs(false);
 
 			// Initialize
 			base.StartDrag(dragstartmappos);
-			undodescription = (selectedlines.Count == 1 ? "Drag linedef" : "Drag " + selectedlines.Count + " linedefs"); //mxd
+			undodescription = (draglines.Count == 1 ? "Drag linedef" : "Drag " + draglines.Count + " linedefs"); //mxd
 			
 			// We have no destructor
 			GC.SuppressFinalize(this);
@@ -94,28 +100,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Methods
 		
-		// Disenagaging
-		public override void OnDisengage()
-		{
-			// Select vertices from lines selection
-			General.Map.Map.ClearSelectedVertices();
-			ICollection<Vertex> verts = General.Map.Map.GetVerticesFromLinesMarks(true);
-			foreach(Vertex v in verts) v.Selected = true;
-
-			// Perform normal disengage
-			base.OnDisengage();
-
-			// Clear vertex selection
-			General.Map.Map.ClearSelectedVertices();
-			
-			// When not cancelled
-			if(!cancelled)
-			{
-				// If only a single linedef was selected, deselect it now
-				if(selectedlines.Count == 1) General.Map.Map.ClearSelectedLinedefs();
-			}
-		}
-
 		// This redraws the display
 		public override void OnRedrawDisplay()
 		{
@@ -143,8 +127,16 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			if(renderer.StartPlotter(true))
 			{
 				// Render lines and vertices
-				renderer.PlotLinedefSet(unselectedlines);
-				renderer.PlotLinedefSet(selectedlines);
+				renderer.PlotLinedefSet(unmovinglines);
+
+				foreach (Linedef ld in draglines)
+				{
+					if (ld.Selected)
+						renderer.PlotLinedef(ld, General.Colors.Selection);
+					else
+						renderer.PlotLinedef(ld, General.Colors.Highlight);
+				}
+
 				renderer.PlotVerticesSet(General.Map.Map.Vertices);
 
 				// Draw the dragged item highlighted
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DragSectorsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DragSectorsMode.cs
index 9fce09c74..73b90d788 100755
--- a/Source/Plugins/BuilderModes/ClassicModes/DragSectorsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DragSectorsMode.cs
@@ -45,8 +45,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Variables
 
-		private ICollection<Linedef> selectedlines;
-		private ICollection<Sector> selectedsectors;
+		private ICollection<Linedef> draglines;
+		private ICollection<Sector> dragsectors;
 
 		#endregion
 
@@ -57,21 +57,27 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		#region ================== Constructor / Disposer
 
 		// Constructor to start dragging immediately
-		public DragSectorsMode(Vector2D dragstartmappos)
+		public DragSectorsMode(Vector2D dragstartmappos, List<Sector> sectors)
 		{
 			// Mark what we are dragging
 			General.Map.Map.ClearAllMarks(false);
-			General.Map.Map.MarkSelectedLinedefs(true, true);
-			ICollection<Vertex> verts = General.Map.Map.GetVerticesFromLinesMarks(true);
-			foreach(Vertex v in verts) v.Marked = true;
-			
-			// Get selected lines
-			selectedlines = General.Map.Map.GetSelectedLinedefs(true);
-			selectedsectors = General.Map.Map.GetSelectedSectors(true);
+
+			// Get geometry to drag
+			dragsectors = new List<Sector>(sectors);
+			draglines = new HashSet<Linedef>();
+			foreach (Sector s in sectors)
+			{
+				foreach (Sidedef sd in s.Sidedefs)
+				{
+					draglines.Add(sd.Line);
+					sd.Line.Start.Marked = true;
+					sd.Line.End.Marked = true;
+				}
+			}
 			
 			// Initialize
 			base.StartDrag(dragstartmappos);
-			undodescription = (selectedsectors.Count == 1 ? "Drag sector" : "Drag " + selectedsectors.Count + " sectors"); //mxd
+			undodescription = (dragsectors.Count == 1 ? "Drag sector" : "Drag " + dragsectors.Count + " sectors"); //mxd
 			
 			// We have no destructor
 			GC.SuppressFinalize(this);
@@ -101,40 +107,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			renderer.SetPresentation(Presentation.Standard);
 		}
 		
-		// Disenagaging
-		public override void OnDisengage()
-		{
-			// Select vertices from lines selection
-			General.Map.Map.ClearSelectedVertices();
-			ICollection<Vertex> verts = General.Map.Map.GetVerticesFromLinesMarks(true);
-			foreach(Vertex v in verts) v.Selected = true;
-
-			// Perform normal disengage
-			base.OnDisengage();
-
-			// Clear vertex selection
-			General.Map.Map.ClearSelectedVertices();
-			
-			// When not cancelled
-			if(!cancelled)
-			{
-				// If only a single sector was selected, deselect it now
-				if(selectedsectors.Count == 1)
-				{
-					General.Map.Map.ClearSelectedSectors();
-					General.Map.Map.ClearSelectedLinedefs();
-
-					//mxd. Also (de)select things?
-					if(BuilderPlug.Me.SyncronizeThingEdit)
-					{
-						Sector s = General.GetByIndex(selectedsectors, 0);
-						foreach(Thing t in General.Map.Map.Things)
-							if(t.Sector == s && t.Selected) t.Selected = false;
-					}
-				}
-			}
-		}
-
 		// This redraws the display
 		public override void OnRedrawDisplay()
 		{
@@ -164,7 +136,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				// Render lines and vertices
 				renderer.PlotLinedefSet(snaptolines);
 				renderer.PlotLinedefSet(unstablelines);
-				renderer.PlotLinedefSet(selectedlines);
+				renderer.PlotLinedefSet(draglines);
 				renderer.PlotVerticesSet(General.Map.Map.Vertices);
 
 				// Draw the dragged item highlighted
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DragThingsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DragThingsMode.cs
index ee3e0721c..25cc237c1 100755
--- a/Source/Plugins/BuilderModes/ClassicModes/DragThingsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DragThingsMode.cs
@@ -86,10 +86,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		private AlignData aligndata;
 
 		// List of selected items
-		private readonly ICollection<Thing> selectedthings;
+		private readonly ICollection<Thing> dragthings;
 
 		// List of non-selected items
-		private readonly ICollection<Thing> unselectedthings;
+		private readonly ICollection<Thing> unmovingthings;
 		
 		// Keep track of view changes
 		private double lastoffsetx;
@@ -114,7 +114,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		#region ================== Constructor / Disposer
 
 		// Constructor to start dragging immediately
-		public DragThingsMode(EditMode basemode, Vector2D dragstartmappos, bool makeundo)
+		public DragThingsMode(EditMode basemode, Vector2D dragstartmappos, List<Thing> things, bool makeundo)
 		{
 			// Initialize
 			this.dragstartmappos = dragstartmappos;
@@ -125,20 +125,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 			// Mark what we are dragging
 			General.Map.Map.ClearAllMarks(false);
-			General.Map.Map.MarkSelectedThings(true, true);
+			dragthings = new List<Thing>();
+			foreach (Thing t in things)
+			{
+				t.Marked = true;
+				dragthings.Add(t);
+			}
 			
-			// Get selected things
-			selectedthings = General.Map.Map.GetMarkedThings(true);
-			unselectedthings = new List<Thing>();
-			foreach(Thing t in General.Map.ThingsFilter.VisibleThings) if(!t.Marked) unselectedthings.Add(t);
+			// Get things we're not dragging
+			unmovingthings = new List<Thing>();
+			foreach(Thing t in General.Map.ThingsFilter.VisibleThings) if(!t.Marked) unmovingthings.Add(t);
 			
 			// Get the nearest thing for snapping
-			dragitem = MapSet.NearestThing(selectedthings, dragstartmappos);
+			dragitem = MapSet.NearestThing(dragthings, dragstartmappos);
 
 			// Make old positions list
 			// We will use this as reference to move the vertices, or to move them back on cancel
-			oldpositions = new List<Vector2D>(selectedthings.Count);
-			foreach(Thing t in selectedthings) oldpositions.Add(t.Position);
+			oldpositions = new List<Vector2D>(dragthings.Count);
+			foreach(Thing t in dragthings) oldpositions.Add(t.Position);
 
 			// Also keep old position of the dragged item
 			dragitemposition = dragitem.Position;
@@ -206,7 +210,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			if(snapnearest)
 			{
 				// Find nearest unselected item within selection range
-				Thing nearest = MapSet.NearestThingSquareRange(unselectedthings, mousemappos, BuilderPlug.Me.StitchRange / renderer.Scale);
+				Thing nearest = MapSet.NearestThingSquareRange(unmovingthings, mousemappos, BuilderPlug.Me.StitchRange / renderer.Scale);
 				if(nearest != null)
 				{
 					// Move the dragged item
@@ -253,7 +257,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				int i = 0;
 
 				// Move selected geometry
-				foreach(Thing t in selectedthings)
+				foreach(Thing t in dragthings)
 				{
 					// Move vertex from old position relative to the
 					// mouse position change since drag start
@@ -314,8 +318,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			{
 				// Render things
 				renderer.RenderThingSet(General.Map.ThingsFilter.HiddenThings, General.Settings.HiddenThingsAlpha);
-				renderer.RenderThingSet(unselectedthings, General.Settings.ActiveThingsAlpha);
-				renderer.RenderThingSet(selectedthings, General.Settings.ActiveThingsAlpha);
+				renderer.RenderThingSet(unmovingthings, General.Settings.ActiveThingsAlpha);
+				renderer.RenderThingSet(dragthings, General.Settings.ActiveThingsAlpha);
 
 				// Draw the dragged item highlighted
 				// This is important to know, because this item is used
@@ -334,7 +338,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			MoveThingsRelative(new Vector2D(0f, 0f), false, false, false, false);
 
 			// If only a single vertex was selected, deselect it now
-			if(selectedthings.Count == 1) General.Map.Map.ClearSelectedThings();
+			//if(dragthings.Count == 1) General.Map.Map.ClearSelectedThings();
 			
 			// Update cached values
 			General.Map.Map.Update();
@@ -376,7 +380,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 				// Make undo for the dragging
 				if(makeundo) //mxd
-					General.Map.UndoRedo.CreateUndo((selectedthings.Count == 1 ? "Drag thing" : "Drag " + selectedthings.Count + " things"));
+					General.Map.UndoRedo.CreateUndo((dragthings.Count == 1 ? "Drag thing" : "Drag " + dragthings.Count + " things"));
 
 				// Move selected geometry to final position
 				if(aligndata != null && aligndata.Active) //mxd. Apply aligning
@@ -393,7 +397,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				}
 
 				//mxd. Snap selected things to map format accuracy
-				foreach(Thing thing in selectedthings) thing.SnapToAccuracy(false);
+				foreach(Thing thing in dragthings) thing.SnapToAccuracy(false);
 
 				// Map is changed
 				General.Map.IsChanged = true;
@@ -430,7 +434,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			snaptogridincrement = (!snaptocardinaldirection && General.Interface.AltState); //mxd
 
 			//mxd. Snap to nearest linedef
-			if(selectedthings.Count == 1 && snaptonearest && !snaptocardinaldirection 
+			if(dragthings.Count == 1 && snaptonearest && !snaptocardinaldirection 
 				&& Thing.AlignableRenderModes.Contains(dragitem.RenderMode)
 				&& MoveThingsRelative(mousemappos - dragstartmappos, snaptogrid, snaptogridincrement, false, false)) 
 			{
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DragVerticesMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DragVerticesMode.cs
index aac82aece..422650a5f 100755
--- a/Source/Plugins/BuilderModes/ClassicModes/DragVerticesMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DragVerticesMode.cs
@@ -59,11 +59,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		#region ================== Constructor / Disposer
 
 		// Constructor to start dragging immediately
-		public DragVerticesMode(Vector2D dragstartmappos)
+		public DragVerticesMode(Vector2D dragstartmappos, List<Vertex> vertices)
 		{
 			// Mark what we are dragging
 			General.Map.Map.ClearAllMarks(false);
-			General.Map.Map.MarkSelectedVertices(true, true);
+			foreach (Vertex v in vertices)
+				v.Marked = true;
 
 			// Initialize
 			base.StartDrag(dragstartmappos);
@@ -90,24 +91,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		#region ================== Methods
 		
-		// Disenagaging
-		public override void OnDisengage()
-		{
-			// Select vertices from marks
-			General.Map.Map.ClearSelectedVertices();
-			General.Map.Map.SelectMarkedVertices(true, true);
-
-			// Perform normal disengage
-			base.OnDisengage();
-			
-			// When not cancelled
-			if(!cancelled)
-			{
-				// If only a single vertex was selected, deselect it now
-				if(selectedverts.Count == 1) General.Map.Map.ClearSelectedVertices();
-			}
-		}
-
 		// This redraws the display
 		public override void OnRedrawDisplay()
 		{
diff --git a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs
index bb47dea45..14bbba565 100755
--- a/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/LinedefsMode.cs
@@ -64,7 +64,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		
 		// Interface
 		new private bool editpressed;
-		private bool selectionfromhighlight; //mxd
 
 		// The blockmap makes is used to make finding lines faster
 		BlockMap<BlockEntry> blockmap;
@@ -438,13 +437,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			{
 				// Dispose old labels
 				foreach(SelectionLabel l in labels.Values) l.Dispose();
-				
-				// Don't show lables for selected-from-highlight item
-				if(selectionfromhighlight)
-				{
-					labels.Clear();
-					return;
-				}
 			}
 
 			// Make text labels for selected linedefs
@@ -785,22 +777,28 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				// Edit pressed in this mode
 				editpressed = true;
 
+				// We use the marks to determine what to edit/drag, so clear it first
+				General.Map.Map.ClearMarkedLinedefs(false);
+
 				// Highlighted item not selected?
-				if(!highlighted.Selected && (BuilderPlug.Me.AutoClearSelection || (General.Map.Map.SelectedLinedefsCount == 0)))
+				if(!highlighted.Selected)
 				{
 					// Make this the only selection
-					selectionfromhighlight = true; //mxd
 					General.Map.Map.ClearSelectedLinedefs();
-					highlighted.Selected = true;
+					highlighted.Marked = true;
 					UpdateSelectionInfo(); //mxd
 					General.Interface.RedrawDisplay();
 				}
+				else
+				{
+					General.Map.Map.MarkSelectedLinedefs(true, true);
+				}
 
 				// Update display
 				if(renderer.StartPlotter(false))
 				{
 					// Redraw highlight to show selection
-					renderer.PlotLinedef(highlighted, renderer.DetermineLinedefColor(highlighted));
+					renderer.PlotLinedef(highlighted, General.Colors.Highlight);
 					renderer.PlotVertex(highlighted.Start, renderer.DetermineVertexColor(highlighted.Start));
 					renderer.PlotVertex(highlighted.End, renderer.DetermineVertexColor(highlighted.End));
 					renderer.Finish();
@@ -831,28 +829,19 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			if(editpressed)
 			{
 				// Anything selected?
-				ICollection<Linedef> selected = General.Map.Map.GetSelectedLinedefs(true);
-				if(selected.Count > 0)
+				ICollection<Linedef> editlines = General.Map.Map.GetMarkedLinedefs(true);
+
+				if(editlines.Count > 0)
 				{
 					if(General.Interface.IsActiveWindow)
 					{
 						// Show line edit dialog
 						General.Interface.OnEditFormValuesChanged += linedefEditForm_OnValuesChanged;
-						DialogResult result = General.Interface.ShowEditLinedefs(selected);
+						DialogResult result = General.Interface.ShowEditLinedefs(editlines);
 						General.Interface.OnEditFormValuesChanged -= linedefEditForm_OnValuesChanged;
 
 						General.Map.Map.Update();
 						
-						// When a single line was selected, deselect it now
-						if(selected.Count == 1 && selectionfromhighlight) 
-						{
-							General.Map.Map.ClearSelectedLinedefs();
-						} 
-						else if(result == DialogResult.Cancel) //mxd. Restore selection...
-						{ 
-							foreach(Linedef l in selected) l.Selected = true;
-						}
-
 						// Update entire display
 						SetupSectorLabels();
 						General.Map.Renderer2D.UpdateExtraFloorFlag(); //mxd
@@ -863,7 +852,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			}
 
 			editpressed = false;
-			selectionfromhighlight = false; //mxd
 			base.OnEditEnd();
 		}
 
@@ -1075,17 +1063,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				// Anything highlighted?
 				if((highlighted != null) && !highlighted.IsDisposed)
 				{
+					List<Linedef> draglines = new List<Linedef>();
+
 					// Highlighted item not selected?
 					if(!highlighted.Selected)
 					{
 						// Select only this linedef for dragging
 						General.Map.Map.ClearSelectedLinedefs();
-						highlighted.Selected = true;
+						draglines.Add(highlighted);
+					}
+					else
+					{
+						// Add all selected linedefs to the linedefs we want to drag
+						draglines.AddRange(General.Map.Map.GetSelectedLinedefs(true));
 					}
 
 					// Start dragging the selection
 					if(!BuilderPlug.Me.DontMoveGeometryOutsideMapBoundary || CanDrag()) //mxd
-						General.Editing.ChangeMode(new DragLinedefsMode(mousedownmappos));
+						General.Editing.ChangeMode(new DragLinedefsMode(mousedownmappos, draglines));
 				}
 			}
 		}
diff --git a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs
index 6ffef2842..c47ff7a9e 100755
--- a/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/SectorsMode.cs
@@ -61,7 +61,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		// Interface
 		new private bool editpressed;
-		private bool selectionfromhighlight; //mxd
 
 		// Labels
 		private Dictionary<Sector, TextLabel[]> labels;
@@ -631,9 +630,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// This updates labels from the selected sectors
 		private void UpdateSelectedLabels()
 		{
-			// Don't show lables for selected-from-highlight item
-			if(selectionfromhighlight) return;
-			
 			// Go for all labels in all selected sectors
 			ICollection<Sector> orderedselection = General.Map.Map.GetSelectedSectors(true);
 			PixelColor c = (General.Settings.UseHighlight ? General.Colors.Highlight : General.Colors.Selection); //mxd
@@ -1060,25 +1056,31 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				// Edit pressed in this mode
 				editpressed = true;
 
+				// We use the marks to determine what to edit/drag, so clear it first
+				General.Map.Map.ClearMarkedSectors(false);
+
 				// Highlighted item not selected?
-				if(!highlighted.Selected && (BuilderPlug.Me.AutoClearSelection || (General.Map.Map.SelectedSectorsCount == 0)))
+				if (!highlighted.Selected)
 				{
 					// Make this the only selection
-					selectionfromhighlight = true; //mxd
 					General.Map.Map.ClearSelectedSectors();
 					General.Map.Map.ClearSelectedLinedefs();
-					SelectSector(highlighted, true, false);
+					highlighted.Marked = true;
 					UpdateSelectedLabels(); //mxd
 					UpdateOverlaySurfaces(); //mxd
 					UpdateSelectionInfo(); //mxd
 					General.Interface.RedrawDisplay();
 				}
+				else
+				{
+					General.Map.Map.MarkSelectedSectors(true, true);
+				}
 
 				// Update display
 				if(renderer.StartPlotter(false))
 				{
 					// Redraw highlight to show selection
-					renderer.PlotSector(highlighted);
+					renderer.PlotSector(highlighted, General.Colors.Highlight);
 					renderer.Finish();
 					renderer.Present();
 				}
@@ -1107,40 +1109,19 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			if(editpressed)
 			{
 				// Anything selected?
-				ICollection<Sector> selected = General.Map.Map.GetSelectedSectors(true);
-				if(selected.Count > 0)
+				ICollection<Sector> editsectors = General.Map.Map.GetMarkedSectors(true);
+
+				if(editsectors.Count > 0)
 				{
 					if(General.Interface.IsActiveWindow)
 					{
 						//mxd. Show realtime vertex edit dialog
 						General.Interface.OnEditFormValuesChanged += sectorEditForm_OnValuesChanged;
-						DialogResult result = General.Interface.ShowEditSectors(selected);
+						DialogResult result = General.Interface.ShowEditSectors(editsectors);
 						General.Interface.OnEditFormValuesChanged -= sectorEditForm_OnValuesChanged;
 
 						General.Map.Renderer2D.UpdateExtraFloorFlag(); //mxd
 
-						// When a single sector was selected, deselect it now
-						if(selected.Count == 1 && selectionfromhighlight) 
-						{
-							General.Map.Map.ClearSelectedSectors();
-							General.Map.Map.ClearSelectedLinedefs();
-
-							//mxd. Also deselect things?
-							if(BuilderPlug.Me.SyncronizeThingEdit)
-							{
-								Sector s = General.GetByIndex(selected, 0);
-								foreach(Thing t in General.Map.Map.Things)
-									if(t.Sector == s && t.Selected) t.Selected = false;
-							}
-
-							UpdateEffectLabels(); //mxd
-						} 
-						else if(result == DialogResult.Cancel) //mxd. Restore selection...
-						{ 
-							foreach(Sector s in selected) SelectSector(s, true, false);
-							UpdateSelectedLabels(); //mxd
-						}
-
 						UpdateOverlaySurfaces(); //mxd
 						General.Interface.RedrawDisplay();
 					}
@@ -1150,7 +1131,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			}
 
 			editpressed = false;
-			selectionfromhighlight = false; //mxd
 			base.OnEditEnd();
 		}
 
@@ -1335,18 +1315,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				// Anything highlighted?
 				if((highlighted != null) && !highlighted.IsDisposed)
 				{
+					List<Sector> dragsectors = new List<Sector>();
+
 					// Highlighted item not selected?
-					if(!highlighted.Selected)
+					if (!highlighted.Selected)
 					{
 						// Select only this sector for dragging
 						General.Map.Map.ClearSelectedSectors();
-						SelectSector(highlighted, true, true);
+						dragsectors.Add(highlighted);
 						UpdateOverlaySurfaces(); //mxd
 					}
+					else
+					{
+						dragsectors.AddRange(General.Map.Map.GetSelectedSectors(true));
+					}
 
 					// Start dragging the selection
 					if(!BuilderPlug.Me.DontMoveGeometryOutsideMapBoundary || CanDrag()) //mxd
-						General.Editing.ChangeMode(new DragSectorsMode(mousedownmappos));
+						General.Editing.ChangeMode(new DragSectorsMode(mousedownmappos, dragsectors));
 				}
 			}
 		}
diff --git a/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs
index 30685b553..bad36e873 100755
--- a/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs
@@ -62,7 +62,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		new private bool editpressed;
 		private bool thinginserted;
 		private bool awaitingMouseClick; //mxd
-		private bool selectionfromhighlight; //mxd
 
 		//mxd. Helper shapes
 		private List<Line3D> persistenteventlines;
@@ -484,23 +483,29 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			{
 				// Edit pressed in this mode
 				editpressed = true;
+
+				// We use the marks to determine what do edit/drag, so clear it first
+				General.Map.Map.ClearMarkedThings(false);
 				
 				// Highlighted item not selected?
-				if(!highlighted.Selected && (BuilderPlug.Me.AutoClearSelection || (General.Map.Map.SelectedThingsCount == 0)))
+				if(!highlighted.Selected)
 				{
 					// Make this the only selection
-					selectionfromhighlight = true; //mxd
 					General.Map.Map.ClearSelectedThings();
-					highlighted.Selected = true;
+					highlighted.Marked = true;
 					UpdateSelectionInfo(); //mxd
 					General.Interface.RedrawDisplay();
 				}
+				else
+				{
+					General.Map.Map.MarkSelectedThings(true, true);
+				}
 
 				// Update display
 				if(renderer.StartThings(false))
 				{
 					// Redraw highlight to show selection
-					renderer.RenderThing(highlighted, renderer.DetermineThingColor(highlighted), General.Settings.FixedThingsScale ? Presentation.THINGS_ALPHA : General.Settings.ActiveThingsAlpha);
+					renderer.RenderThing(highlighted, General.Colors.Highlight, General.Settings.FixedThingsScale ? Presentation.THINGS_ALPHA : General.Settings.ActiveThingsAlpha);
 					renderer.Finish();
 					renderer.Present();
 				}
@@ -522,7 +527,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				else 
 				{
 					General.Map.Map.ClearSelectedThings();
-					t.Selected = true;
+					General.Map.Map.ClearMarkedThings(false);
+					t.Marked = true;
 					Highlight(t);
 					General.Interface.RedrawDisplay();
 				}
@@ -538,8 +544,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			if(editpressed)
 			{
 				// Anything selected?
-				ICollection<Thing> selected = General.Map.Map.GetSelectedThings(true);
-				if(selected.Count > 0)
+				ICollection<Thing> editthings = General.Map.Map.GetMarkedThings(true);
+
+				if(editthings.Count > 0)
 				{
 					if(General.Interface.IsActiveWindow)
 					{
@@ -548,19 +555,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 						{
 							//mxd. Show realtime thing edit dialog
 							General.Interface.OnEditFormValuesChanged += thingEditForm_OnValuesChanged;
-							DialogResult result = General.Interface.ShowEditThings(selected);
+							DialogResult result = General.Interface.ShowEditThings(editthings);
 							General.Interface.OnEditFormValuesChanged -= thingEditForm_OnValuesChanged;
 
-							// When a single thing was selected, deselect it now
-							if(selected.Count == 1 && selectionfromhighlight) 
-							{
-								General.Map.Map.ClearSelectedThings();
-							} 
-							else if(result == DialogResult.Cancel) //mxd. Restore selection...
-							{ 
-								foreach(Thing t in selected) t.Selected = true;
-							}
-
 							//mxd. Update helper lines
 							UpdateHelperObjects();
 
@@ -575,7 +572,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			}
 
 			editpressed = false;
-			selectionfromhighlight = false; //mxd
 			base.OnEditEnd();
 		}
 
@@ -747,12 +743,19 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				// Anything highlighted?
 				if((highlighted != null) && !highlighted.IsDisposed)
 				{
+					List<Thing> dragthings = new List<Thing>();
+
 					// Highlighted item not selected?
 					if(!highlighted.Selected)
 					{
 						// Select only this thing for dragging
 						General.Map.Map.ClearSelectedThings();
-						highlighted.Selected = true;
+						dragthings.Add(highlighted);
+					}
+					else
+					{
+						// Add all selected things to the things we want to drag
+						dragthings.AddRange(General.Map.Map.GetSelectedThings(true));
 					}
 
 					// Start dragging the selection
@@ -762,14 +765,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
 						bool thingscloned = false;
 						if(General.Interface.ShiftState) 
 						{
-							ICollection<Thing> selection = General.Map.Map.GetSelectedThings(true);
-							if(selection.Count > 0)
+							List<Thing> clonedthings = new List<Thing>(dragthings.Count);
+							if(dragthings.Count > 0)
 							{
 								// Make undo
-								General.Map.UndoRedo.CreateUndo((selection.Count == 1 ? "Clone-drag thing" : "Clone-drag " + selection.Count + " things"));
+								General.Map.UndoRedo.CreateUndo((dragthings.Count == 1 ? "Clone-drag thing" : "Clone-drag " + dragthings.Count + " things"));
 
 								// Clone things
-								foreach(Thing t in selection)
+								foreach(Thing t in dragthings)
 								{
 									Thing clone = InsertThing(t.Position);
 									t.CopyPropertiesTo(clone);
@@ -798,15 +801,19 @@ namespace CodeImp.DoomBuilder.BuilderModes
 									}
 
 									t.Selected = false;
-									clone.Selected = true;
+
+									clonedthings.Add(clone);
 								}
 
 								// We'll want to skip creating additional Undo in DragThingsMode
 								thingscloned = true;
+
+								// All the cloned things are now the things we want to drag
+								dragthings = clonedthings;
 							}
 						}
 
-						General.Editing.ChangeMode(new DragThingsMode(new ThingsMode(), mousedownmappos, !thingscloned));
+						General.Editing.ChangeMode(new DragThingsMode(new ThingsMode(), mousedownmappos, dragthings, !thingscloned));
 					}
 				}
 			}
@@ -1048,13 +1055,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			{
 				// Dispose old labels
 				foreach(TextLabel l in labels.Values) l.Dispose();
-
-				// Don't show lables for selected-from-highlight item
-				if(selectionfromhighlight)
-				{
-					labels.Clear();
-					return;
-				}
 			}
 
 			// Make text labels for selected linedefs
diff --git a/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs b/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs
index c1ac8a3c5..d206cd460 100755
--- a/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/VerticesMode.cs
@@ -55,7 +55,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		// Interface
 		new private bool editpressed;
-		private bool selectionfromhighlight; //mxd
 
 		// The blockmap makes is used to make finding lines faster
 		BlockMap<BlockEntry> blockmap;
@@ -287,22 +286,28 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				// Edit pressed in this mode
 				editpressed = true;
 
+				// We use the marks to determine what to edit/drag, so clear it first
+				General.Map.Map.ClearMarkedVertices(false);
+
 				// Highlighted item not selected?
-				if(!highlighted.Selected && (BuilderPlug.Me.AutoClearSelection || (General.Map.Map.SelectedVerticessCount == 0)))
+				if(!highlighted.Selected)
 				{
 					// Make this the only selection
-					selectionfromhighlight = true; //mxd
 					General.Map.Map.ClearSelectedVertices();
-					highlighted.Selected = true;
+					highlighted.Marked = true;
 					UpdateSelectionInfo(); //mxd
 					General.Interface.RedrawDisplay();
 				}
+				else
+				{
+					General.Map.Map.MarkSelectedVertices(true, true);
+				}
 
 				// Update display
 				if(renderer.StartPlotter(false))
 				{
 					// Redraw highlight to show selection
-					renderer.PlotVertex(highlighted, renderer.DetermineVertexColor(highlighted));
+					renderer.PlotVertex(highlighted, ColorCollection.HIGHLIGHT);
 					renderer.Finish();
 					renderer.Present();
 				}
@@ -396,26 +401,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			if(editpressed)
 			{
 				// Anything selected?
-				ICollection<Vertex> selected = General.Map.Map.GetSelectedVertices(true);
-				if(selected.Count > 0)
+				ICollection<Vertex> editvertices = General.Map.Map.GetMarkedVertices(true);
+
+				if(editvertices.Count > 0)
 				{
 					if(General.Interface.IsActiveWindow)
 					{
 						//mxd. Show realtime vertex edit dialog
 						General.Interface.OnEditFormValuesChanged += vertexEditForm_OnValuesChanged;
-						DialogResult result = General.Interface.ShowEditVertices(selected);
+						DialogResult result = General.Interface.ShowEditVertices(editvertices);
 						General.Interface.OnEditFormValuesChanged -= vertexEditForm_OnValuesChanged;
 
-						// When a single vertex was selected, deselect it now
-						if(selected.Count == 1 && selectionfromhighlight) 
-						{
-							General.Map.Map.ClearSelectedVertices();
-						} 
-						else if(result == DialogResult.Cancel) //mxd. Restore selection...
-						{ 
-							foreach(Vertex v in selected) v.Selected = true;
-						}
-
 						// Update entire display
 						UpdateSelectionInfo(); //mxd
 						General.Interface.RedrawDisplay();
@@ -424,7 +420,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			}
 
 			editpressed = false;
-			selectionfromhighlight = false; //mxd
 			base.OnEditEnd();
 		}
 
@@ -640,17 +635,24 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				// Anything highlighted?
 				if((highlighted != null) && !highlighted.IsDisposed)
 				{
+					List<Vertex> dragvertices = new List<Vertex>();
+
 					// Highlighted item not selected?
 					if(!highlighted.Selected)
 					{
 						// Select only this vertex for dragging
 						General.Map.Map.ClearSelectedVertices();
-						highlighted.Selected = true;
+						dragvertices.Add(highlighted);
+					}
+					else
+					{
+						// Add all selected vertices to the vertices we want to drag
+						dragvertices.AddRange(General.Map.Map.GetSelectedVertices(true));
 					}
 
 					// Start dragging the selection
 					if(!BuilderPlug.Me.DontMoveGeometryOutsideMapBoundary || CanDrag()) //mxd
-						General.Editing.ChangeMode(new DragVerticesMode(mousedownmappos));
+						General.Editing.ChangeMode(new DragVerticesMode(mousedownmappos, dragvertices));
 				}
 			}
 		}
-- 
GitLab