From 184c13a56354f7cbaf19f2d8ad85955dfea2304b Mon Sep 17 00:00:00 2001
From: Xaser Acheron <xaser.88@gmail.com>
Date: Mon, 1 May 2023 02:32:09 -0500
Subject: [PATCH] Automap Mode: improved support for GZDoom (#876)

- A new "Show Textures" option up on the top bar, which draws any sector not flagged to be hidden on the textured automap
- Holding Shift will highlight sectors instead of lines
- Left-clicking on a highlighted sector will toggle the "Not shown on textured automap" flag
- Textures will be shown when Shift is held down even if the "Show Textures" toggle is off
---
 Source/Core/Map/MapSet.cs                     |   4 +-
 Source/Core/Map/Sector.cs                     |  11 +-
 Source/Core/Rendering/Presentation.cs         |   5 +
 Source/Core/Rendering/Renderer2D.cs           |   6 +-
 Source/Core/Rendering/SurfaceEntry.cs         |   3 +
 Source/Core/Rendering/SurfaceManager.cs       |  23 +-
 Source/Core/Rendering/SurfaceUpdate.cs        |   8 +-
 Source/Plugins/AutomapMode/AutomapMode.cs     | 208 ++++++++++++++----
 Source/Plugins/AutomapMode/AutomapMode.csproj |   3 +
 .../Interface/MenusForm.Designer.cs           | 177 ++++++++-------
 .../AutomapMode/Interface/MenusForm.cs        |  17 +-
 .../Properties/Resources.Designer.cs          |  10 +
 .../AutomapMode/Properties/Resources.resx     |   3 +
 .../Plugins/AutomapMode/Resources/Hints.cfg   |   3 +-
 .../AutomapMode/Resources/ShowTextures.png    | Bin 0 -> 541 bytes
 15 files changed, 337 insertions(+), 144 deletions(-)
 create mode 100644 Source/Plugins/AutomapMode/Resources/ShowTextures.png

diff --git a/Source/Core/Map/MapSet.cs b/Source/Core/Map/MapSet.cs
index 0ff4ff1bf..40cbfcb15 100755
--- a/Source/Core/Map/MapSet.cs
+++ b/Source/Core/Map/MapSet.cs
@@ -3710,7 +3710,7 @@ namespace CodeImp.DoomBuilder.Map
 			// Return result
 			return closest;
 		}
-		
+
 		#endregion
 
 		#region ================== Tools
@@ -4172,7 +4172,7 @@ namespace CodeImp.DoomBuilder.Map
 			// Return result
 			return closest;
 		}
-		
+
 		// This performs sidedefs compression
 		// Note: Only use this for saving, because this messes up the expected data structure horribly.
 		internal void CompressSidedefs()
diff --git a/Source/Core/Map/Sector.cs b/Source/Core/Map/Sector.cs
index 5111e9ea1..af750648b 100755
--- a/Source/Core/Map/Sector.cs
+++ b/Source/Core/Map/Sector.cs
@@ -409,7 +409,8 @@ namespace CodeImp.DoomBuilder.Map
 				General.Plugins.OnSectorCeilingSurfaceUpdate(this, ref updateinfo.ceilvertices);
 				updateinfo.floortexture = longfloortexname;
 				updateinfo.ceiltexture = longceiltexname;
-                updateinfo.desaturation = this.Desaturation;
+				updateinfo.hidden = IsFlagSet("hidden");
+				updateinfo.desaturation = this.Desaturation;
 
                 // Update surfaces
                 General.Map.CRenderer2D.Surfaces.UpdateSurfaces(surfaceentries, updateinfo);
@@ -429,6 +430,7 @@ namespace CodeImp.DoomBuilder.Map
 			flatvertices.CopyTo(updateinfo.floorvertices, 0);
 			General.Plugins.OnSectorFloorSurfaceUpdate(this, ref updateinfo.floorvertices);
 			updateinfo.floortexture = longfloortexname;
+			updateinfo.hidden = IsFlagSet("hidden");
 			updateinfo.desaturation = this.Desaturation;
 
 			// Update entry
@@ -446,7 +448,8 @@ namespace CodeImp.DoomBuilder.Map
 			flatvertices.CopyTo(updateinfo.ceilvertices, 0);
 			General.Plugins.OnSectorCeilingSurfaceUpdate(this, ref updateinfo.ceilvertices);
 			updateinfo.ceiltexture = longceiltexname;
-            updateinfo.desaturation = this.Desaturation;
+			updateinfo.hidden = IsFlagSet("hidden");
+			updateinfo.desaturation = this.Desaturation;
 			
 			// Update entry
 			General.Map.CRenderer2D.Surfaces.UpdateSurfaces(surfaceentries, updateinfo);
@@ -517,6 +520,10 @@ namespace CodeImp.DoomBuilder.Map
 				BeforePropsChange();
 
 				flags[flagname] = value;
+
+				// [XA] TODO: de-hardcode this special case thing
+				if(flagname == "hidden")
+					updateneeded = true;
 			}
 		}
 
diff --git a/Source/Core/Rendering/Presentation.cs b/Source/Core/Rendering/Presentation.cs
index b9bca7486..767c06879 100755
--- a/Source/Core/Rendering/Presentation.cs
+++ b/Source/Core/Rendering/Presentation.cs
@@ -39,6 +39,9 @@ namespace CodeImp.DoomBuilder.Rendering
 		// Static properties
 		public static Presentation Standard { get { return standard; } }
 		public static Presentation Things { get { return things; } }
+
+		// Public properties
+		public bool SkipHiddenSectors { get; set; } // Skip drawing sectors with the "hidden" flag set (i.e. UDMF's "hide on textured automap" property)
 		
 		// Variables
 		protected internal List<PresentLayer> layers;
@@ -48,12 +51,14 @@ namespace CodeImp.DoomBuilder.Rendering
 		{
 			// Initialize
 			layers = new List<PresentLayer>();
+			SkipHiddenSectors = false;
 		}
 
 		// Copy constructor
 		public Presentation(Presentation p)
 		{
 			layers = new List<PresentLayer>(p.layers);
+			SkipHiddenSectors = p.SkipHiddenSectors;
 		}
 
 		// This creates the static instances
diff --git a/Source/Core/Rendering/Renderer2D.cs b/Source/Core/Rendering/Renderer2D.cs
index 3ba127669..b8757de5f 100755
--- a/Source/Core/Rendering/Renderer2D.cs
+++ b/Source/Core/Rendering/Renderer2D.cs
@@ -1618,17 +1618,17 @@ namespace CodeImp.DoomBuilder.Rendering
 				switch(viewmode)
 				{
 					case ViewMode.Brightness:
-						surfaces.RenderSectorBrightness(yviewport);
+						surfaces.RenderSectorBrightness(yviewport, present.SkipHiddenSectors);
 						surfaces.RenderSectorSurfaces(graphics);
 						break;
 							
 					case ViewMode.FloorTextures:
-						surfaces.RenderSectorFloors(yviewport);
+						surfaces.RenderSectorFloors(yviewport, present.SkipHiddenSectors);
 						surfaces.RenderSectorSurfaces(graphics);
 						break;
 							
 					case ViewMode.CeilingTextures:
-						surfaces.RenderSectorCeilings(yviewport);
+						surfaces.RenderSectorCeilings(yviewport, present.SkipHiddenSectors);
 						surfaces.RenderSectorSurfaces(graphics);
 						break;
 				}
diff --git a/Source/Core/Rendering/SurfaceEntry.cs b/Source/Core/Rendering/SurfaceEntry.cs
index add84fe28..305c820e0 100755
--- a/Source/Core/Rendering/SurfaceEntry.cs
+++ b/Source/Core/Rendering/SurfaceEntry.cs
@@ -49,6 +49,9 @@ namespace CodeImp.DoomBuilder.Rendering
 		public long floortexture;
 		public long ceiltexture;
 
+		// Sector flags
+		public bool hidden; // sector is hidden on textured automap
+
         //
         public double desaturation;
 		
diff --git a/Source/Core/Rendering/SurfaceManager.cs b/Source/Core/Rendering/SurfaceManager.cs
index 5fbec73b2..558537106 100755
--- a/Source/Core/Rendering/SurfaceManager.cs
+++ b/Source/Core/Rendering/SurfaceManager.cs
@@ -405,6 +405,7 @@ namespace CodeImp.DoomBuilder.Rendering
 					Array.Copy(update.ceilvertices, update.numvertices - vertsremaining, e.ceilvertices, 0, vertsinentry);
 					e.floortexture = update.floortexture;
 					e.ceiltexture = update.ceiltexture;
+					e.hidden = update.hidden;
                     e.desaturation = update.desaturation;
 					
 					entries.Add(e);
@@ -429,6 +430,7 @@ namespace CodeImp.DoomBuilder.Rendering
 						e.ceiltexture = update.ceiltexture;
 					}
 
+					e.hidden = update.hidden;
                     e.desaturation = update.desaturation;
 
                     vertsremaining -= e.numvertices;
@@ -510,7 +512,7 @@ namespace CodeImp.DoomBuilder.Rendering
 		#region ================== Rendering
 		
 		// This renders all sector floors
-		internal void RenderSectorFloors(RectangleF viewport)
+		internal void RenderSectorFloors(RectangleF viewport, bool skipHidden)
 		{
 			surfaces = new Dictionary<ImageData, List<SurfaceEntry>>();
 			surfacevertexoffsetmul = 0;
@@ -521,14 +523,14 @@ namespace CodeImp.DoomBuilder.Rendering
 			{
 				foreach(SurfaceEntry entry in set.Value.entries)
 				{
-					if(entry.bbox.IntersectsWith(viewport))
+					if(SurfaceEntryIsVisible(entry, viewport, skipHidden))
 						AddSurfaceEntryForRendering(entry, entry.floortexture);
 				}
 			}
 		}
 		
 		// This renders all sector ceilings
-		internal void RenderSectorCeilings(RectangleF viewport)
+		internal void RenderSectorCeilings(RectangleF viewport, bool skipHidden)
 		{
 			surfaces = new Dictionary<ImageData, List<SurfaceEntry>>();
 			surfacevertexoffsetmul = 1;
@@ -539,14 +541,14 @@ namespace CodeImp.DoomBuilder.Rendering
 			{
 				foreach(SurfaceEntry entry in set.Value.entries)
 				{
-					if(entry.bbox.IntersectsWith(viewport))
+					if(SurfaceEntryIsVisible(entry, viewport, skipHidden))
 						AddSurfaceEntryForRendering(entry, entry.ceiltexture);
 				}
 			}
 		}
 
 		// This renders all sector brightness levels
-		internal void RenderSectorBrightness(RectangleF viewport)
+		internal void RenderSectorBrightness(RectangleF viewport, bool skipHidden)
 		{
 			surfaces = new Dictionary<ImageData, List<SurfaceEntry>>();
 			surfacevertexoffsetmul = 0;
@@ -557,12 +559,21 @@ namespace CodeImp.DoomBuilder.Rendering
 			{
 				foreach(SurfaceEntry entry in set.Value.entries)
 				{
-					if(entry.bbox.IntersectsWith(viewport))
+					if(SurfaceEntryIsVisible(entry, viewport, skipHidden))
 						AddSurfaceEntryForRendering(entry, 0);
 				}
 			}
 		}
 
+		// Checks to see if a particular surface entry is visible in the viewport
+		private bool SurfaceEntryIsVisible(SurfaceEntry entry, RectangleF viewport, bool skipHidden)
+		{
+			if (skipHidden && entry.hidden)
+				return false;
+
+			return entry.bbox.IntersectsWith(viewport);
+		}
+
 		// This adds a surface entry to the list of surfaces
 		private void AddSurfaceEntryForRendering(SurfaceEntry entry, long longimagename)
 		{
diff --git a/Source/Core/Rendering/SurfaceUpdate.cs b/Source/Core/Rendering/SurfaceUpdate.cs
index 969f8bc89..6964da3c4 100755
--- a/Source/Core/Rendering/SurfaceUpdate.cs
+++ b/Source/Core/Rendering/SurfaceUpdate.cs
@@ -36,8 +36,11 @@ namespace CodeImp.DoomBuilder.Rendering
 		public long floortexture;
 		public long ceiltexture;
 
-        //
-        public double desaturation;
+		// Sector flags
+		public bool hidden;
+
+		//
+		public double desaturation;
 		
 		// Constructor
 		internal SurfaceUpdate(int numvertices, bool updatefloor, bool updateceiling)
@@ -49,6 +52,7 @@ namespace CodeImp.DoomBuilder.Rendering
 			this.floorvertices = (updatefloor ? new FlatVertex[numvertices] : null);
 			this.ceilvertices = (updateceiling ? new FlatVertex[numvertices] : null);
 
+			this.hidden = false;
             this.desaturation = 0f;
 		}
 	}
diff --git a/Source/Plugins/AutomapMode/AutomapMode.cs b/Source/Plugins/AutomapMode/AutomapMode.cs
index 1077b856a..f49c57432 100755
--- a/Source/Plugins/AutomapMode/AutomapMode.cs
+++ b/Source/Plugins/AutomapMode/AutomapMode.cs
@@ -61,8 +61,9 @@ namespace CodeImp.DoomBuilder.AutomapMode
 		private List<Linedef> validlinedefs;
 		private HashSet<Sector> secretsectors; //mxd
 
-		// Highlighted item
-		private Linedef highlighted;
+		// Highlighted items
+		private Linedef highlightedLine;
+		private Sector highlightedSector;
 
 		//mxd. UI
 		private MenusForm menusform;
@@ -76,12 +77,25 @@ namespace CodeImp.DoomBuilder.AutomapMode
 		private PixelColor ColorHiddenFlag;
 		private PixelColor ColorInvisible;
 		private PixelColor ColorBackground;
-		
+
+		// Options
+		private bool invertLineVisibility; // CTRL to toggle
+		private bool editSectors; // SHIFT to toggle
+
 		#endregion
 
 		#region ================== Properties
 
-		public override object HighlightedObject { get { return highlighted; } }
+		public override object HighlightedObject
+		{
+			get
+			{
+				if(highlightedLine != null)
+					return highlightedLine;
+				else
+					return highlightedSector;
+			}
+		}
 		
 		#endregion
 
@@ -95,7 +109,8 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			menusform.ShowHiddenLines = General.Settings.ReadPluginSetting("automapmode.showhiddenlines", false);
 			menusform.ShowSecretSectors = General.Settings.ReadPluginSetting("automapmode.showsecretsectors", false);
 			menusform.ShowLocks = General.Settings.ReadPluginSetting("automapmode.showlocks", true);
-			menusform.ColorPreset = (ColorPreset)General.Settings.ReadPluginSetting("automapmode.colorpreset", (int)ColorPreset.DOOM);
+            menusform.ShowTextures = General.Settings.ReadPluginSetting("automapmode.showtextures", true);
+            menusform.ColorPreset = (ColorPreset)General.Settings.ReadPluginSetting("automapmode.colorpreset", (int)ColorPreset.DOOM);
 
 			// Handle events
 			menusform.OnShowHiddenLinesChanged += delegate
@@ -106,8 +121,9 @@ namespace CodeImp.DoomBuilder.AutomapMode
 
 			menusform.OnShowSecretSectorsChanged += delegate { General.Interface.RedrawDisplay(); };
 			menusform.OnShowLocksChanged += delegate { General.Interface.RedrawDisplay(); };
+            menusform.OnShowTexturesChanged += delegate { General.Interface.RedrawDisplay(); };
 
-			menusform.OnColorPresetChanged += delegate
+            menusform.OnColorPresetChanged += delegate
 			{
 				ApplyColorPreset(menusform.ColorPreset);
 				General.Interface.RedrawDisplay();
@@ -121,26 +137,48 @@ namespace CodeImp.DoomBuilder.AutomapMode
 
 		#region ================== Methods
 
-		// This highlights a new item
-		private void Highlight(Linedef l)
+		// Update the current highlight
+		private void UpdateHighlight()
+		{
+			if (EditSectors())
+			{
+				// Get the nearest sector to the cursor; don't factor in the
+				// highlight range since we really just want to capture
+				// whichever sector is under the cursor.
+				Sector s = General.Map.Map.GetSectorByCoordinates(mousemappos);
+
+				if (s != highlightedSector) HighlightSector(s);
+			}
+			else
+			{
+				// Find the nearest linedef within highlight range
+				Linedef l = MapSet.NearestLinedefRange(validlinedefs, mousemappos, BuilderPlug.Me.HighlightRange / renderer.Scale);
+
+				// Highlight if not the same
+				if (l != highlightedLine) HighlightLine(l);
+			}
+		}
+
+		// This highlights a new line
+		private void HighlightLine(Linedef l)
 		{
 			// Update display
 			if(renderer.StartPlotter(false))
 			{
 				// Undraw previous highlight
-				if((highlighted != null) && !highlighted.IsDisposed)
+				if((highlightedLine != null) && !highlightedLine.IsDisposed)
 				{
-					PixelColor c = LinedefIsValid(highlighted) ? DetermineLinedefColor(highlighted) : PixelColor.Transparent;
-					renderer.PlotLine(highlighted.Start.Position, highlighted.End.Position, c, LINE_LENGTH_SCALER);
+					PixelColor c = LinedefIsValid(highlightedLine) ? DetermineLinedefColor(highlightedLine) : PixelColor.Transparent;
+					renderer.PlotLine(highlightedLine.Start.Position, highlightedLine.End.Position, c, LINE_LENGTH_SCALER);
 				}
 
 				// Set new highlight
-				highlighted = l;
+				highlightedLine = l;
 
 				// Render highlighted item
-				if((highlighted != null) && !highlighted.IsDisposed && LinedefIsValid(highlighted))
+				if((highlightedLine != null) && !highlightedLine.IsDisposed && LinedefIsValid(highlightedLine))
 				{
-					renderer.PlotLine(highlighted.Start.Position, highlighted.End.Position, General.Colors.InfoLine, LINE_LENGTH_SCALER);
+					renderer.PlotLine(highlightedLine.Start.Position, highlightedLine.End.Position, General.Colors.InfoLine, LINE_LENGTH_SCALER);
 				}
 
 				// Done
@@ -149,8 +187,48 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			}
 
 			// Show highlight info
-			if((highlighted != null) && !highlighted.IsDisposed)
-				General.Interface.ShowLinedefInfo(highlighted);
+			if((highlightedLine != null) && !highlightedLine.IsDisposed)
+				General.Interface.ShowLinedefInfo(highlightedLine);
+			else
+				General.Interface.HideInfo();
+		}
+
+		// This highlights a new sector
+		private void HighlightSector(Sector sector)
+		{
+			// Update display
+			if (renderer.StartPlotter(false))
+			{
+				// Undraw previous highlight
+				if ((highlightedSector != null) && !highlightedSector.IsDisposed)
+				{
+					foreach(Sidedef sd in highlightedSector.Sidedefs)
+					{
+						if ((sd.Line != null) && !sd.Line.IsDisposed)
+						{
+							PixelColor c = LinedefIsValid(sd.Line) ? DetermineLinedefColor(sd.Line) : PixelColor.Transparent;
+							renderer.PlotLine(sd.Line.Start.Position, sd.Line.End.Position, c, LINE_LENGTH_SCALER);
+						}
+					}
+				}
+
+				// Set new highlight
+				highlightedSector = sector;
+
+				// Render highlighted sector's lines
+				if ((highlightedSector != null) && !highlightedSector.IsDisposed)
+					foreach (Sidedef sd in highlightedSector.Sidedefs)
+						if ((sd.Line != null) && !sd.Line.IsDisposed)
+							renderer.PlotLine(sd.Line.Start.Position, sd.Line.End.Position, General.Colors.Highlight, LINE_LENGTH_SCALER);
+
+				// Done
+				renderer.Finish();
+				renderer.Present();
+			}
+
+			// Show highlight info
+			if ((highlightedSector != null) && !highlightedSector.IsDisposed)
+				General.Interface.ShowSectorInfo(highlightedSector);
 			else
 				General.Interface.HideInfo();
 		}
@@ -193,14 +271,14 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			if(ld.Front.Sector.CeilHeight == ld.Back.Sector.CeilHeight && ld.Front.Sector.FloorHeight == ld.Back.Sector.FloorHeight)
 				return ColorMatchingHeight;
 
-			if(menusform.ShowHiddenLines ^ General.Interface.CtrlState) return ColorInvisible; 
+			if(menusform.ShowHiddenLines ^ invertLineVisibility) return ColorInvisible; 
 
 			return new PixelColor(255, 255, 255, 255);
 		}
 
 		private bool LinedefIsValid(Linedef ld)
 		{
-			if(menusform.ShowHiddenLines ^ General.Interface.CtrlState) return true;
+			if(menusform.ShowHiddenLines ^ invertLineVisibility) return true;
 			if(ld.IsFlagSet(BuilderPlug.Me.HiddenFlag)) return false;
 			if(ld.Back == null || ld.Front == null || ld.IsFlagSet(BuilderPlug.Me.SecretFlag)) return true;
 			if(ld.Back != null && ld.Front != null && (ld.Front.Sector.FloorHeight != ld.Back.Sector.FloorHeight || ld.Front.Sector.CeilHeight != ld.Back.Sector.CeilHeight)) return true;
@@ -208,6 +286,21 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			return false;
 		}
 
+		private bool SectorIsVisible(Sector s)
+		{
+			return(s != null && !s.IsFlagSet("hidden"));
+		}
+
+		private bool ShowTextures()
+		{
+			return menusform.ShowTextures || EditSectors();
+		}
+
+		private bool EditSectors()
+		{
+			return editSectors && General.Map.UDMF;
+		}
+
 		//mxd
 		private static bool SectorIsSecret(Sector s)
 		{
@@ -318,11 +411,14 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			base.OnEngage();
 			renderer.DrawMapCenter = false; //mxd
 
-			// Automap presentation without the surfaces
+			// Automap presentation; now draws surfaces for textured mode support,
+			// but the surfaces are covered up with a background layer.
 			automappresentation = new CustomPresentation();
+			automappresentation.AddLayer(new PresentLayer(RendererLayer.Surface, BlendingMode.Mask));
 			automappresentation.AddLayer(new PresentLayer(RendererLayer.Overlay, BlendingMode.Mask));
 			automappresentation.AddLayer(new PresentLayer(RendererLayer.Grid, BlendingMode.Mask));
 			automappresentation.AddLayer(new PresentLayer(RendererLayer.Geometry, BlendingMode.Alpha, 1f, true));
+			automappresentation.SkipHiddenSectors = true;
 			renderer.SetPresentation(automappresentation);
 
 			UpdateValidLinedefs();
@@ -341,7 +437,8 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			General.Settings.WritePluginSetting("automapmode.showhiddenlines", menusform.ShowHiddenLines);
 			General.Settings.WritePluginSetting("automapmode.showsecretsectors", menusform.ShowSecretSectors);
 			General.Settings.WritePluginSetting("automapmode.showlocks", menusform.ShowLocks);
-			General.Settings.WritePluginSetting("automapmode.colorpreset", (int)menusform.ColorPreset);
+            General.Settings.WritePluginSetting("automapmode.showtextures", menusform.ShowTextures);
+            General.Settings.WritePluginSetting("automapmode.colorpreset", (int)menusform.ColorPreset);
 
 			//mxd. Hide UI
 			menusform.Unregister();
@@ -382,9 +479,9 @@ namespace CodeImp.DoomBuilder.AutomapMode
 						renderer.PlotLine(ld.Start.Position, ld.End.Position, DetermineLinedefColor(ld), LINE_LENGTH_SCALER);
 				}
 
-				if((highlighted != null) && !highlighted.IsDisposed && LinedefIsValid(highlighted))
+				if((highlightedLine != null) && !highlightedLine.IsDisposed && LinedefIsValid(highlightedLine))
 				{
-					renderer.PlotLine(highlighted.Start.Position, highlighted.End.Position, General.Colors.InfoLine, LINE_LENGTH_SCALER);
+					renderer.PlotLine(highlightedLine.Start.Position, highlightedLine.End.Position, General.Colors.InfoLine, LINE_LENGTH_SCALER);
 				}
 
 				renderer.Finish();
@@ -393,8 +490,10 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			//mxd. Render background
 			if(renderer.StartOverlay(true))
 			{
-				RectangleF screenrect = new RectangleF(0, 0, General.Interface.Display.Width, General.Interface.Display.Height);
-				renderer.RenderRectangleFilled(screenrect, ColorBackground, false);
+				if(!ShowTextures()) {
+					RectangleF screenrect = new RectangleF(0, 0, General.Interface.Display.Width, General.Interface.Display.Height);
+					renderer.RenderRectangleFilled(screenrect, ColorBackground, false);
+				}
 				renderer.Finish();
 			}
 
@@ -403,28 +502,44 @@ namespace CodeImp.DoomBuilder.AutomapMode
 
 		protected override void OnSelectEnd()
 		{
-			// Item highlighted?
-			if((highlighted != null) && !highlighted.IsDisposed)
+			// Line highlighted?
+			if((highlightedLine != null) && !highlightedLine.IsDisposed)
 			{
 				General.Map.UndoRedo.CreateUndo("Toggle \"Shown as 1-sided on automap\" linedef flag");
 
 				// Toggle flag
-				highlighted.SetFlag(BuilderPlug.Me.SecretFlag, !highlighted.IsFlagSet(BuilderPlug.Me.SecretFlag));
+				highlightedLine.SetFlag(BuilderPlug.Me.SecretFlag, !highlightedLine.IsFlagSet(BuilderPlug.Me.SecretFlag));
 				UpdateValidLinedefs();
 			}
 
+			// Sector highlighted?
+			if((highlightedSector != null) && !highlightedSector.IsDisposed)
+			{
+				General.Map.UndoRedo.CreateUndo("Toggle \"Not shown on textured automap\" sector flag");
+
+				// Toggle flag
+				highlightedSector.SetFlag("hidden", !highlightedSector.IsFlagSet("hidden"));
+
+				// Redraw the universe
+				General.Map.Map.Update();
+				General.Interface.RedrawDisplay();
+
+				// Re-highlight the sector since it gets lost after RedrawDisplay
+				HighlightSector(highlightedSector);
+			}
+
 			base.OnSelectEnd();
 		}
 		
 		protected override void OnEditEnd()
 		{
-			// Item highlighted?
-			if((highlighted != null) && !highlighted.IsDisposed)
+			// Line highlighted?
+			if ((highlightedLine != null) && !highlightedLine.IsDisposed)
 			{
 				General.Map.UndoRedo.CreateUndo("Toggle \"Not shown on automap\" linedef flag");
 
 				// Toggle flag
-				highlighted.SetFlag(BuilderPlug.Me.HiddenFlag, !highlighted.IsFlagSet(BuilderPlug.Me.HiddenFlag));
+				highlightedLine.SetFlag(BuilderPlug.Me.HiddenFlag, !highlightedLine.IsFlagSet(BuilderPlug.Me.HiddenFlag));
 				UpdateValidLinedefs();
 				General.Interface.RedrawDisplay();
 			}
@@ -440,11 +555,7 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			// Not holding any buttons?
 			if(e.Button == MouseButtons.None)
 			{
-				// Find the nearest linedef within highlight range
-				Linedef l = MapSet.NearestLinedefRange(validlinedefs, mousemappos, BuilderPlug.Me.HighlightRange / renderer.Scale);
-
-				// Highlight if not the same
-				if(l != highlighted) Highlight(l);
+				UpdateHighlight();
 			}
 		}
 
@@ -454,29 +565,42 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			base.OnMouseLeave(e);
 
 			// Highlight nothing
-			Highlight(null);
+			HighlightLine(null);
+			HighlightSector(null);
 		}
 
+		// Keyboard input handling; toggles a couple of options
+
 		public override void OnKeyDown(KeyEventArgs e)
 		{
 			base.OnKeyDown(e);
 
-			if(e.Control)
-			{
-				UpdateValidLinedefs();
-				General.Interface.RedrawDisplay();
-			}
+			UpdateOptions();
 		}
 
 		public override void OnKeyUp(KeyEventArgs e)
 		{
 			base.OnKeyUp(e);
 
-			if(!e.Control)
+			UpdateOptions();
+		}
+
+		private void UpdateOptions()
+		{
+			if(invertLineVisibility != General.Interface.CtrlState)
 			{
+				invertLineVisibility = General.Interface.CtrlState;
 				UpdateValidLinedefs();
 				General.Interface.RedrawDisplay();
 			}
+			if(editSectors != General.Interface.ShiftState)
+			{
+				editSectors = General.Interface.ShiftState;
+				HighlightLine(null);
+				HighlightSector(null);
+				General.Interface.RedrawDisplay();
+				UpdateHighlight();
+			}
 		}
 
 		#endregion
diff --git a/Source/Plugins/AutomapMode/AutomapMode.csproj b/Source/Plugins/AutomapMode/AutomapMode.csproj
index b934f67b7..b8adf955d 100755
--- a/Source/Plugins/AutomapMode/AutomapMode.csproj
+++ b/Source/Plugins/AutomapMode/AutomapMode.csproj
@@ -122,4 +122,7 @@
   <ItemGroup>
     <None Include="Resources\ShowLocks.png" />
   </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\ShowTextures.png" />
+  </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/Source/Plugins/AutomapMode/Interface/MenusForm.Designer.cs b/Source/Plugins/AutomapMode/Interface/MenusForm.Designer.cs
index 28bcf0947..7e8f7f8ff 100755
--- a/Source/Plugins/AutomapMode/Interface/MenusForm.Designer.cs
+++ b/Source/Plugins/AutomapMode/Interface/MenusForm.Designer.cs
@@ -28,96 +28,108 @@
 		/// </summary>
 		private void InitializeComponent()
 		{
-			this.toolStrip1 = new System.Windows.Forms.ToolStrip();
-			this.colorpresetseparator = new System.Windows.Forms.ToolStripSeparator();
-			this.colorpresetlabel = new System.Windows.Forms.ToolStripLabel();
-			this.colorpreset = new System.Windows.Forms.ToolStripComboBox();
-			this.showhiddenlines = new System.Windows.Forms.ToolStripButton();
-			this.showsecretsectors = new System.Windows.Forms.ToolStripButton();
-			this.showlocks = new System.Windows.Forms.ToolStripButton();
-			this.toolStrip1.SuspendLayout();
-			this.SuspendLayout();
-			// 
-			// toolStrip1
-			// 
-			this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.toolStrip1 = new System.Windows.Forms.ToolStrip();
+            this.showhiddenlines = new System.Windows.Forms.ToolStripButton();
+            this.showsecretsectors = new System.Windows.Forms.ToolStripButton();
+            this.showlocks = new System.Windows.Forms.ToolStripButton();
+            this.colorpresetseparator = new System.Windows.Forms.ToolStripSeparator();
+            this.colorpresetlabel = new System.Windows.Forms.ToolStripLabel();
+            this.colorpreset = new System.Windows.Forms.ToolStripComboBox();
+            this.showtextures = new System.Windows.Forms.ToolStripButton();
+            this.toolStrip1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // toolStrip1
+            // 
+            this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.showhiddenlines,
             this.showsecretsectors,
             this.showlocks,
+            this.showtextures,
             this.colorpresetseparator,
             this.colorpresetlabel,
             this.colorpreset});
-			this.toolStrip1.Location = new System.Drawing.Point(0, 0);
-			this.toolStrip1.Name = "toolStrip1";
-			this.toolStrip1.Size = new System.Drawing.Size(731, 25);
-			this.toolStrip1.TabIndex = 0;
-			this.toolStrip1.Text = "toolStrip1";
-			// 
-			// colorpresetseparator
-			// 
-			this.colorpresetseparator.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
-			this.colorpresetseparator.Name = "colorpresetseparator";
-			this.colorpresetseparator.Size = new System.Drawing.Size(6, 25);
-			// 
-			// colorpresetlabel
-			// 
-			this.colorpresetlabel.Name = "colorpresetlabel";
-			this.colorpresetlabel.Size = new System.Drawing.Size(74, 22);
-			this.colorpresetlabel.Text = "Color preset:";
-			// 
-			// colorpreset
-			// 
-			this.colorpreset.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-			this.colorpreset.Items.AddRange(new object[] {
+            this.toolStrip1.Location = new System.Drawing.Point(0, 0);
+            this.toolStrip1.Name = "toolStrip1";
+            this.toolStrip1.Size = new System.Drawing.Size(731, 25);
+            this.toolStrip1.TabIndex = 0;
+            this.toolStrip1.Text = "toolStrip1";
+            // 
+            // showhiddenlines
+            // 
+            this.showhiddenlines.CheckOnClick = true;
+            this.showhiddenlines.Image = global::CodeImp.DoomBuilder.AutomapMode.Properties.Resources.ShowHiddenLines;
+            this.showhiddenlines.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.showhiddenlines.Margin = new System.Windows.Forms.Padding(0, 1, 2, 2);
+            this.showhiddenlines.Name = "showhiddenlines";
+            this.showhiddenlines.Size = new System.Drawing.Size(123, 22);
+            this.showhiddenlines.Text = "Show hidden lines";
+            this.showhiddenlines.CheckedChanged += new System.EventHandler(this.showhiddenlines_CheckedChanged);
+            // 
+            // showsecretsectors
+            // 
+            this.showsecretsectors.CheckOnClick = true;
+            this.showsecretsectors.Image = global::CodeImp.DoomBuilder.AutomapMode.Properties.Resources.ShowSecrets;
+            this.showsecretsectors.Margin = new System.Windows.Forms.Padding(0, 1, 2, 2);
+            this.showsecretsectors.Name = "showsecretsectors";
+            this.showsecretsectors.Size = new System.Drawing.Size(95, 22);
+            this.showsecretsectors.Text = "Show secrets";
+            this.showsecretsectors.CheckedChanged += new System.EventHandler(this.showsecretsectors_CheckedChanged);
+            // 
+            // showlocks
+            // 
+            this.showlocks.CheckOnClick = true;
+            this.showlocks.Image = global::CodeImp.DoomBuilder.AutomapMode.Properties.Resources.ShowLocks;
+            this.showlocks.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.showlocks.Name = "showlocks";
+            this.showlocks.Size = new System.Drawing.Size(86, 22);
+            this.showlocks.Text = "Show locks";
+            this.showlocks.CheckedChanged += new System.EventHandler(this.showlocks_CheckedChanged);
+            // 
+            // colorpresetseparator
+            // 
+            this.colorpresetseparator.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
+            this.colorpresetseparator.Name = "colorpresetseparator";
+            this.colorpresetseparator.Size = new System.Drawing.Size(6, 25);
+            // 
+            // colorpresetlabel
+            // 
+            this.colorpresetlabel.Name = "colorpresetlabel";
+            this.colorpresetlabel.Size = new System.Drawing.Size(74, 22);
+            this.colorpresetlabel.Text = "Color preset:";
+            // 
+            // colorpreset
+            // 
+            this.colorpreset.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.colorpreset.Items.AddRange(new object[] {
             "Doom",
             "Hexen",
             "Strife"});
-			this.colorpreset.Name = "colorpreset";
-			this.colorpreset.Size = new System.Drawing.Size(75, 25);
-			this.colorpreset.SelectedIndexChanged += new System.EventHandler(this.colorpreset_SelectedIndexChanged);
-			// 
-			// showhiddenlines
-			// 
-			this.showhiddenlines.CheckOnClick = true;
-			this.showhiddenlines.Image = global::CodeImp.DoomBuilder.AutomapMode.Properties.Resources.ShowHiddenLines;
-			this.showhiddenlines.ImageTransparentColor = System.Drawing.Color.Magenta;
-			this.showhiddenlines.Margin = new System.Windows.Forms.Padding(0, 1, 2, 2);
-			this.showhiddenlines.Name = "showhiddenlines";
-			this.showhiddenlines.Size = new System.Drawing.Size(123, 22);
-			this.showhiddenlines.Text = "Show hidden lines";
-			this.showhiddenlines.CheckedChanged += new System.EventHandler(this.showhiddenlines_CheckedChanged);
-			// 
-			// showsecretsectors
-			// 
-			this.showsecretsectors.CheckOnClick = true;
-			this.showsecretsectors.Image = global::CodeImp.DoomBuilder.AutomapMode.Properties.Resources.ShowSecrets;
-			this.showsecretsectors.Margin = new System.Windows.Forms.Padding(0, 1, 2, 2);
-			this.showsecretsectors.Name = "showsecretsectors";
-			this.showsecretsectors.Size = new System.Drawing.Size(95, 22);
-			this.showsecretsectors.Text = "Show secrets";
-			this.showsecretsectors.CheckedChanged += new System.EventHandler(this.showsecretsectors_CheckedChanged);
-			// 
-			// showlocks
-			// 
-			this.showlocks.CheckOnClick = true;
-			this.showlocks.Image = global::CodeImp.DoomBuilder.AutomapMode.Properties.Resources.ShowLocks;
-			this.showlocks.ImageTransparentColor = System.Drawing.Color.Magenta;
-			this.showlocks.Name = "showlocks";
-			this.showlocks.Size = new System.Drawing.Size(86, 22);
-			this.showlocks.Text = "Show locks";
-			this.showlocks.CheckedChanged += new System.EventHandler(this.showlocks_CheckedChanged);
-			// 
-			// MenusForm
-			// 
-			this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-			this.Controls.Add(this.toolStrip1);
-			this.Name = "MenusForm";
-			this.Size = new System.Drawing.Size(731, 65);
-			this.toolStrip1.ResumeLayout(false);
-			this.toolStrip1.PerformLayout();
-			this.ResumeLayout(false);
-			this.PerformLayout();
+            this.colorpreset.Name = "colorpreset";
+            this.colorpreset.Size = new System.Drawing.Size(75, 25);
+            this.colorpreset.SelectedIndexChanged += new System.EventHandler(this.colorpreset_SelectedIndexChanged);
+            // 
+            // showtextures
+            // 
+            this.showtextures.CheckOnClick = true;
+            this.showtextures.Image = global::CodeImp.DoomBuilder.AutomapMode.Properties.Resources.ShowTextures;
+            this.showtextures.ImageTransparentColor = System.Drawing.Color.Magenta;
+            this.showtextures.Name = "showtextures";
+            this.showtextures.Size = new System.Drawing.Size(101, 22);
+            this.showtextures.Text = "Show textures";
+            this.showtextures.CheckedChanged += new System.EventHandler(this.showtextures_CheckedChanged);
+            // 
+            // MenusForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.toolStrip1);
+            this.Name = "MenusForm";
+            this.Size = new System.Drawing.Size(731, 65);
+            this.toolStrip1.ResumeLayout(false);
+            this.toolStrip1.PerformLayout();
+            this.ResumeLayout(false);
+            this.PerformLayout();
 
 		}
 
@@ -130,5 +142,6 @@
 		private System.Windows.Forms.ToolStripLabel colorpresetlabel;
 		private System.Windows.Forms.ToolStripComboBox colorpreset;
 		private System.Windows.Forms.ToolStripButton showlocks;
-	}
+        private System.Windows.Forms.ToolStripButton showtextures;
+    }
 }
diff --git a/Source/Plugins/AutomapMode/Interface/MenusForm.cs b/Source/Plugins/AutomapMode/Interface/MenusForm.cs
index 7fef86447..93781797a 100755
--- a/Source/Plugins/AutomapMode/Interface/MenusForm.cs
+++ b/Source/Plugins/AutomapMode/Interface/MenusForm.cs
@@ -8,11 +8,13 @@ namespace CodeImp.DoomBuilder.AutomapMode
 		public event EventHandler OnShowHiddenLinesChanged;
 		public event EventHandler OnShowSecretSectorsChanged;
 		public event EventHandler OnShowLocksChanged;
-		internal event EventHandler OnColorPresetChanged;
+        public event EventHandler OnShowTexturesChanged;
+        internal event EventHandler OnColorPresetChanged;
 
 		public bool ShowHiddenLines { get { return showhiddenlines.Checked; } set { showhiddenlines.Checked = value; } }
 		public bool ShowSecretSectors { get { return showsecretsectors.Checked; } set { showsecretsectors.Checked = value; } }
 		public bool ShowLocks { get { return showlocks.Checked; } set { showlocks.Checked = value; } }
+		public bool ShowTextures { get { return showtextures.Checked; } set { showtextures.Checked = value; } }
 		internal AutomapMode.ColorPreset ColorPreset { get { return (AutomapMode.ColorPreset)colorpreset.SelectedIndex; } set { colorpreset.SelectedIndex = (int)value; } }
 		
 		public MenusForm()
@@ -26,6 +28,7 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			General.Interface.AddButton(showhiddenlines);
 			General.Interface.AddButton(showsecretsectors);
 			if(!General.Map.DOOM) General.Interface.AddButton(showlocks);
+			General.Interface.AddButton(showtextures);
 			General.Interface.AddButton(colorpresetseparator);
 			General.Interface.AddButton(colorpresetlabel);
 			General.Interface.AddButton(colorpreset);
@@ -39,7 +42,8 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			General.Interface.RemoveButton(colorpresetlabel);
 			General.Interface.RemoveButton(colorpresetseparator);
 			General.Interface.RemoveButton(showlocks);
-			General.Interface.RemoveButton(showsecretsectors);
+            General.Interface.RemoveButton(showtextures);
+            General.Interface.RemoveButton(showsecretsectors);
 			General.Interface.RemoveButton(showhiddenlines);
 			General.Interface.EndToolbarUpdate(); //mxd
 		}
@@ -57,9 +61,14 @@ namespace CodeImp.DoomBuilder.AutomapMode
 		private void showlocks_CheckedChanged(object sender, EventArgs e)
 		{
 			if(OnShowLocksChanged != null) OnShowLocksChanged(showlocks.Checked, EventArgs.Empty);
-		}
+        }
+
+        private void showtextures_CheckedChanged(object sender, EventArgs e)
+        {
+            if (OnShowTexturesChanged != null) OnShowTexturesChanged(showtextures.Checked, EventArgs.Empty);
+        }
 
-		private void colorpreset_SelectedIndexChanged(object sender, EventArgs e)
+        private void colorpreset_SelectedIndexChanged(object sender, EventArgs e)
 		{
 			if(OnColorPresetChanged != null) OnColorPresetChanged(colorpreset.SelectedIndex, EventArgs.Empty);
 		}
diff --git a/Source/Plugins/AutomapMode/Properties/Resources.Designer.cs b/Source/Plugins/AutomapMode/Properties/Resources.Designer.cs
index b2dedc6fc..14565e517 100755
--- a/Source/Plugins/AutomapMode/Properties/Resources.Designer.cs
+++ b/Source/Plugins/AutomapMode/Properties/Resources.Designer.cs
@@ -89,5 +89,15 @@ namespace CodeImp.DoomBuilder.AutomapMode.Properties {
                 return ((System.Drawing.Bitmap)(obj));
             }
         }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap ShowTextures {
+            get {
+                object obj = ResourceManager.GetObject("ShowTextures", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
     }
 }
diff --git a/Source/Plugins/AutomapMode/Properties/Resources.resx b/Source/Plugins/AutomapMode/Properties/Resources.resx
index 80e0c05eb..3feae91bc 100755
--- a/Source/Plugins/AutomapMode/Properties/Resources.resx
+++ b/Source/Plugins/AutomapMode/Properties/Resources.resx
@@ -127,4 +127,7 @@
   <data name="ShowLocks" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\ShowLocks.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
+  <data name="ShowTextures" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\ShowTextures.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
 </root>
\ No newline at end of file
diff --git a/Source/Plugins/AutomapMode/Resources/Hints.cfg b/Source/Plugins/AutomapMode/Resources/Hints.cfg
index f004af3eb..b5810457d 100755
--- a/Source/Plugins/AutomapMode/Resources/Hints.cfg
+++ b/Source/Plugins/AutomapMode/Resources/Hints.cfg
@@ -8,4 +8,5 @@ class AutomapMode
 group general
 "<b>Left click</b> on a line to toggle the <b>'Shown as 1-sided on automap'</b> flag."
 "<b>Right click</b> on a line to toggle the <b>'Not shown on automap'</b> flag."
-"Hold <b>Ctrl</b> to toggle the display of the lines that are not drawn, either because there was no height change (gray) or the <b>'Not shown on automap'</b> flag is set (light gray)."
\ No newline at end of file
+"Hold <b>Ctrl</b> to toggle the display of the lines that are not drawn, either because there was no height change (gray) or the <b>'Not shown on automap'</b> flag is set (light gray)."
+"Hold <b>Shift</b> to highlight and edit sectors, rather than lines. Clicking on sectors will toggle <b>'Not shown on textured automap'</b> flag. This action is only available for UDMF maps."
\ No newline at end of file
diff --git a/Source/Plugins/AutomapMode/Resources/ShowTextures.png b/Source/Plugins/AutomapMode/Resources/ShowTextures.png
new file mode 100644
index 0000000000000000000000000000000000000000..d3ae3a9a4742b968c0e9db9f9d6f816314c83f85
GIT binary patch
literal 541
zcmV+&0^<FNP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00007bV*G`2j>I~
z1PC(-!`mPL000SaNLh0L01EH`01EH{Laa2H00004XF*Lt006O%3;baP00053Nkl<Z
zc-o~>T~6X)6g{^TiwvzDL<!oWL}n&q%p}AIUuFR;VKy)eU?psa74T~2g&{E{`T$1p
zXWGyHP};fDM#dt>VCFo0fBEjY_naKyKSA-*>2&x#MeTMQ-EMbB2yrQ=A6G%E)mpgA
z>B~uDgnV%WdS(yW)-HMyAY2z!%Yp3n5taTf5iSsv^&&pi8z>$f^A!=kyNvLD3<`Qs
zqY5%^9^y&1@B2xOv_PjAD48`}kwioL7Pz}4<^B|ftVK{v6v~Imx5;FJ>2$hGAa7Rj
zTUiI3kPRz981#89??4h|*0&FEQ8AVzED#7}W||%FpIefxU(jgQSvIj*`$A#C#I@(V
z?ZLzga5yszG~l%j4<ssF+^^v*r?F?>pe`c#ZxKYohU5(KA@@KmRr%xRuQbgY?Av4d
z@$Ki!=A$@A{|I7Zvf%)vsSMA6uI=%8R>jyFvS}xV5%Y82h-le^T<AiHc1b%pqF}pD
zp&ya{z!bTCN*B%d<Qy-nM!DH+BAy~9P*wFg%CE&Zmb40z31)1S`9qwrc}QNt=;Z{o
fN|zMUQj^+8$?CHMHS;t*00000NkvXXu0mjfq#5Z_

literal 0
HcmV?d00001

-- 
GitLab