From af4f40389fb05fc96408a63d154f5a3289f52059 Mon Sep 17 00:00:00 2001
From: MaxED <j.maxed@gmail.com>
Date: Sat, 18 Jun 2016 00:10:35 +0000
Subject: [PATCH] Added, Automap mode: added "Show hidden lines" top menu
 button. Added, Automap mode: added "Show secrets" top menu button. Added,
 Automap mode: added "Color preset" top menu drop-down.

---
 Source/Core/Builder.csproj                    |   1 +
 Source/Core/Config/GameConfiguration.cs       |  10 +-
 Source/Core/Config/SectorEffectData.cs        |  15 ++
 Source/Core/General/MapManager.cs             |   3 +-
 Source/Plugins/AutomapMode/AutomapMode.cs     | 225 +++++++++++++++---
 Source/Plugins/AutomapMode/AutomapMode.csproj |  27 +++
 Source/Plugins/AutomapMode/BuilderPlug.cs     |  14 +-
 .../Interface/MenusForm.Designer.cs           | 120 ++++++++++
 .../AutomapMode/Interface/MenusForm.cs        |  54 +++++
 .../AutomapMode/Interface/MenusForm.resx      | 123 ++++++++++
 .../Properties/Resources.Designer.cs          |  77 ++++++
 .../AutomapMode/Properties/Resources.resx     | 127 ++++++++++
 .../Plugins/AutomapMode/Resources/Hints.cfg   |   2 +-
 .../AutomapMode/Resources/ShowHiddenLines.png | Bin 0 -> 1227 bytes
 .../AutomapMode/Resources/ShowSecrets.png     | Bin 0 -> 1209 bytes
 .../BuilderModes/General/CopyStructures.cs    |   8 +-
 16 files changed, 760 insertions(+), 46 deletions(-)
 create mode 100644 Source/Core/Config/SectorEffectData.cs
 create mode 100644 Source/Plugins/AutomapMode/Interface/MenusForm.Designer.cs
 create mode 100644 Source/Plugins/AutomapMode/Interface/MenusForm.cs
 create mode 100644 Source/Plugins/AutomapMode/Interface/MenusForm.resx
 create mode 100644 Source/Plugins/AutomapMode/Properties/Resources.Designer.cs
 create mode 100644 Source/Plugins/AutomapMode/Properties/Resources.resx
 create mode 100644 Source/Plugins/AutomapMode/Resources/ShowHiddenLines.png
 create mode 100644 Source/Plugins/AutomapMode/Resources/ShowSecrets.png

diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj
index 9135c2ac7..088f296da 100644
--- a/Source/Core/Builder.csproj
+++ b/Source/Core/Builder.csproj
@@ -708,6 +708,7 @@
     <Compile Include="Config\ModelAndLightRenderModes.cs" />
     <Compile Include="Config\PasteOptions.cs" />
     <Compile Include="Config\ScriptDocumentSettings.cs" />
+    <Compile Include="Config\SectorEffectData.cs" />
     <Compile Include="Config\ThingsFlagsCompare.cs" />
     <Compile Include="Controls\ActionSpecialHelpButton.cs">
       <SubType>UserControl</SubType>
diff --git a/Source/Core/Config/GameConfiguration.cs b/Source/Core/Config/GameConfiguration.cs
index 28188dd15..91ec92b65 100644
--- a/Source/Core/Config/GameConfiguration.cs
+++ b/Source/Core/Config/GameConfiguration.cs
@@ -1068,10 +1068,10 @@ namespace CodeImp.DoomBuilder.Config
 		}
 
 		//mxd
-		public static HashSet<int> GetGeneralizedSectorEffectBits(int effect) { return GetGeneralizedSectorEffectBits(effect, General.Map.Config.GenEffectOptions); }
-		public static HashSet<int> GetGeneralizedSectorEffectBits(int effect, List<GeneralizedOption> options)
+		public SectorEffectData GetSectorEffectData(int effect) { return GetSectorEffectData(effect, General.Map.Config.GenEffectOptions); }
+		public SectorEffectData GetSectorEffectData(int effect, List<GeneralizedOption> options)
 		{
-			HashSet<int> result = new HashSet<int>();
+			SectorEffectData result = new SectorEffectData();
 			if(effect > 0)
 			{
 				int cureffect = effect;
@@ -1083,12 +1083,12 @@ namespace CodeImp.DoomBuilder.Config
 						if(bit.Index > 0 && (cureffect & bit.Index) == bit.Index)
 						{
 							cureffect -= bit.Index;
-							result.Add(bit.Index);
+							result.GeneralizedBits.Add(bit.Index);
 						}
 					}
 				}
 
-				if(cureffect > 0) result.Add(cureffect);
+				if(cureffect > 0) result.Effect = cureffect;
 			}
 
 			return result;
diff --git a/Source/Core/Config/SectorEffectData.cs b/Source/Core/Config/SectorEffectData.cs
new file mode 100644
index 000000000..1a2bb96b3
--- /dev/null
+++ b/Source/Core/Config/SectorEffectData.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+
+namespace CodeImp.DoomBuilder.Config
+{
+	public class SectorEffectData
+	{
+		public int Effect;
+		public HashSet<int> GeneralizedBits;
+
+		public SectorEffectData()
+		{
+			GeneralizedBits = new HashSet<int>();
+		}
+	}
+}
diff --git a/Source/Core/General/MapManager.cs b/Source/Core/General/MapManager.cs
index 996a4f012..cabdfc05b 100644
--- a/Source/Core/General/MapManager.cs
+++ b/Source/Core/General/MapManager.cs
@@ -672,7 +672,8 @@ namespace CodeImp.DoomBuilder
 					// Problem! Can't save the map like this!
 					General.ShowErrorMessage("Unable to save the map: there are too many unique sidedefs!" + Environment.NewLine + Environment.NewLine
 						+ "Sidedefs before compresion: " + initialsidescount + Environment.NewLine
-						+ "Sidedefs after compresion: " + outputset.Sidedefs.Count, MessageBoxButtons.OK);
+						+ "Sidedefs after compresion: " + outputset.Sidedefs.Count
+						+ " (" + (outputset.Sidedefs.Count - io.MaxSidedefs) + " sidedefs above the limit)", MessageBoxButtons.OK);
 					General.MainWindow.DisplayStatus(oldstatus);
 					return false;
 				}
diff --git a/Source/Plugins/AutomapMode/AutomapMode.cs b/Source/Plugins/AutomapMode/AutomapMode.cs
index e22964cfa..74472c384 100644
--- a/Source/Plugins/AutomapMode/AutomapMode.cs
+++ b/Source/Plugins/AutomapMode/AutomapMode.cs
@@ -18,7 +18,9 @@
 
 using System;
 using System.Collections.Generic;
+using System.Drawing;
 using System.Windows.Forms;
+using CodeImp.DoomBuilder.Config;
 using CodeImp.DoomBuilder.Map;
 using CodeImp.DoomBuilder.Rendering;
 using CodeImp.DoomBuilder.Editing;
@@ -32,11 +34,21 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			  ButtonImage = "automap.png",	// Image resource name for the button
 			  ButtonOrder = int.MinValue + 503,	// Position of the button (lower is more to the bottom)
 			  ButtonGroup = "000_editing",
-			  UseByDefault = true,
-			  SafeStartMode = true)]
+			  UseByDefault = true)]
 
-	public class AutomapMode : ClassicMode
-	{
+	public class AutomapMode : ClassicMode
+	{
+		#region ================== Enums
+
+		internal enum ColorPreset
+		{
+			DOOM,
+			HEXEN,
+			STRIFE,
+		}
+
+		#endregion
+
 		#region ================== Constants
 
 		private const float LINE_LENGTH_SCALER = 0.001f; //mxd
@@ -46,10 +58,24 @@ namespace CodeImp.DoomBuilder.AutomapMode
 		#region ================== Variables
 
 		private CustomPresentation automappresentation;
-		private List<Linedef> validlinedefs;
+		private List<Linedef> validlinedefs;
+		private HashSet<Sector> secretsectors; //mxd
 
 		// Highlighted item
-		private Linedef highlighted;
+		private Linedef highlighted;
+
+		//mxd. UI
+		private MenusForm menusform;
+
+		//mxd. Colors
+		private PixelColor ColorSingleSided;
+		private PixelColor ColorSecret;
+		private PixelColor ColorFloorDiff;
+		private PixelColor ColorCeilDiff;
+		private PixelColor ColorMatchingHeight;
+		private PixelColor ColorHiddenFlag;
+		private PixelColor ColorInvisible;
+		private PixelColor ColorBackground;
 		
 		#endregion
 
@@ -61,6 +87,37 @@ namespace CodeImp.DoomBuilder.AutomapMode
 
 		#region ================== Constructor / Disposer
 
+		//mxd
+		public AutomapMode()
+		{
+			// Create and setup menu
+			menusform = new MenusForm();
+			menusform.ShowHiddenLines = General.Settings.ReadPluginSetting("automapmode.showhiddenlines", false);
+			menusform.ShowSecretSectors = General.Settings.ReadPluginSetting("automapmode.showsecretsectors", false);
+			menusform.ColorPreset = (ColorPreset)General.Settings.ReadPluginSetting("automapmode.colorpreset", (int)ColorPreset.DOOM);
+
+			// Handle events
+			menusform.OnShowHiddenLinesChanged += delegate
+			{
+				UpdateValidLinedefs();
+				General.Interface.RedrawDisplay();
+			};
+
+			menusform.OnShowSecretSectorsChanged += delegate
+			{
+				General.Interface.RedrawDisplay();
+			};
+
+			menusform.OnColorPresetChanged += delegate
+			{
+				ApplyColorPreset(menusform.ColorPreset);
+				General.Interface.RedrawDisplay();
+			};
+
+			// Apply color preset
+			ApplyColorPreset(menusform.ColorPreset);
+		}
+
 		#endregion
 
 		#region ================== Methods
@@ -74,7 +131,7 @@ namespace CodeImp.DoomBuilder.AutomapMode
 				// Undraw previous highlight
 				if((highlighted != null) && !highlighted.IsDisposed)
 				{
-					PixelColor c = LinedefIsValid(highlighted) ? DetermineLinedefColor(highlighted) : new PixelColor(255, 0, 0, 0);
+					PixelColor c = LinedefIsValid(highlighted) ? DetermineLinedefColor(highlighted) : PixelColor.Transparent;
 					renderer.PlotLine(highlighted.Start.Position, highlighted.End.Position, c, LINE_LENGTH_SCALER);
 				}
 
@@ -105,34 +162,39 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			validlinedefs = new List<Linedef>();
 			foreach(Linedef ld in General.Map.Map.Linedefs)
 				if(LinedefIsValid(ld)) validlinedefs.Add(ld);
+		}
+
+		//mxd
+		internal void UpdateSecretSectors()
+		{
+			secretsectors = new HashSet<Sector>();
+			foreach(Sector s in General.Map.Map.Sectors)
+				if(SectorIsSecret(s)) secretsectors.Add(s);
 		}
 
-		private static PixelColor DetermineLinedefColor(Linedef ld)
-		{
-			if(ld.IsFlagSet(BuilderPlug.Me.HiddenFlag))
-				return new PixelColor(255, 192, 192, 192);
-
-			if(ld.Back == null || ld.IsFlagSet(BuilderPlug.Me.SecretFlag))
-				return new PixelColor(255, 252, 0, 0);
-
-			if(ld.Front.Sector.FloorHeight != ld.Back.Sector.FloorHeight)
-				return new PixelColor(255, 188, 120, 72);
-
-			if(ld.Front.Sector.CeilHeight != ld.Back.Sector.CeilHeight)
-				return new PixelColor(255, 252, 252, 0);
-
-			if(ld.Front.Sector.CeilHeight == ld.Back.Sector.CeilHeight && ld.Front.Sector.FloorHeight == ld.Back.Sector.FloorHeight)
-				return new PixelColor(255, 128, 128, 128);
-
-			if(General.Interface.CtrlState)
-				return new PixelColor(255, 192, 192, 192);
+		private PixelColor DetermineLinedefColor(Linedef ld)
+		{
+			//mxd
+			if(menusform.ShowSecretSectors &&
+			   (ld.Front != null && secretsectors.Contains(ld.Front.Sector) || ld.Back != null && secretsectors.Contains(ld.Back.Sector)))
+				return ColorSecret;
+
+			if(ld.IsFlagSet(BuilderPlug.Me.HiddenFlag)) return ColorHiddenFlag;
+			if(ld.Back == null || ld.IsFlagSet(BuilderPlug.Me.SecretFlag)) return ColorSingleSided;
+			if(ld.Front.Sector.FloorHeight != ld.Back.Sector.FloorHeight) return ColorFloorDiff;
+			if(ld.Front.Sector.CeilHeight != ld.Back.Sector.CeilHeight) return ColorCeilDiff;
+
+			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; 
 
 			return new PixelColor(255, 255, 255, 255);
 		}
 
-		private static bool LinedefIsValid(Linedef ld)
+		private bool LinedefIsValid(Linedef ld)
 		{
-			if(General.Interface.CtrlState) return true;
+			if(menusform.ShowHiddenLines ^ General.Interface.CtrlState) return true;
 			if(ld.IsFlagSet(BuilderPlug.Me.HiddenFlag)) return false;
 			if(ld.Back == null || ld.IsFlagSet(BuilderPlug.Me.SecretFlag)) return true;
 			if(ld.Back != null && (ld.Front.Sector.FloorHeight != ld.Back.Sector.FloorHeight || ld.Front.Sector.CeilHeight != ld.Back.Sector.CeilHeight)) return true;
@@ -140,6 +202,65 @@ namespace CodeImp.DoomBuilder.AutomapMode
 			return false;
 		}
 
+		//mxd
+		private static bool SectorIsSecret(Sector s)
+		{
+			SectorEffectData data = General.Map.Config.GetSectorEffectData(s.Effect);
+
+			if(General.Map.DOOM)
+			{
+				// Sector is secret when it's Special is 9 or it has generalized flag 128
+				if(data.Effect == 9 || data.GeneralizedBits.Contains(128)) return true;
+			}
+			else
+			{
+				//Hexen/UDMF: sector is secret when it has generalized flag 1024
+				if(data.GeneralizedBits.Contains(1024)) return true;
+			}
+
+			return false;
+		}
+
+		//mxd
+		private void ApplyColorPreset(ColorPreset preset)
+		{
+			switch(preset)
+			{
+				case ColorPreset.DOOM:
+					ColorSingleSided = new PixelColor(255, 252, 0, 0);
+					ColorSecret = new PixelColor(255, 255, 0, 255);
+					ColorFloorDiff = new PixelColor(255, 188, 120, 72);
+					ColorCeilDiff = new PixelColor(255, 252, 252, 0);
+					ColorHiddenFlag = new PixelColor(255, 192, 192, 192);
+					ColorInvisible = new PixelColor(255, 192, 192, 192);
+					ColorMatchingHeight = new PixelColor(255, 108, 108, 108);
+					ColorBackground = new PixelColor(255, 0, 0, 0);
+					break;
+
+				case ColorPreset.HEXEN:
+					ColorSingleSided = new PixelColor(255, 89, 64, 27);
+					ColorSecret = new PixelColor(255, 255, 0, 255);
+					ColorFloorDiff = new PixelColor(255, 208, 176, 133);
+					ColorCeilDiff = new PixelColor(255, 103, 59, 31);
+					ColorHiddenFlag = new PixelColor(255, 192, 192, 192);
+					ColorInvisible = new PixelColor(255, 108, 108, 108);
+					ColorMatchingHeight = new PixelColor(255, 108, 108, 108);
+					ColorBackground = new PixelColor(255, 163, 129, 84);
+					break;
+
+				case ColorPreset.STRIFE:
+					ColorSingleSided = new PixelColor(255, 199, 195, 195);
+					ColorSecret = new PixelColor(255, 255, 0, 255);
+					ColorFloorDiff = new PixelColor(255, 55, 59, 91);
+					ColorCeilDiff = new PixelColor(255, 108, 108, 108);
+					ColorHiddenFlag = new PixelColor(255, 0, 87, 130);
+					ColorInvisible = new PixelColor(255, 192, 192, 192);
+					ColorMatchingHeight = new PixelColor(255, 112, 112, 160);
+					ColorBackground = new PixelColor(255, 0, 0, 0);
+					break;
+			}
+		}
+
 		#endregion
 		
 		#region ================== Events
@@ -166,23 +287,53 @@ namespace CodeImp.DoomBuilder.AutomapMode
 
 			// Automap presentation without the surfaces
 			automappresentation = new CustomPresentation();
-			automappresentation.AddLayer(new PresentLayer(RendererLayer.Background, BlendingMode.Mask, General.Settings.BackgroundAlpha));
+			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));
 			renderer.SetPresentation(automappresentation);
 
 			UpdateValidLinedefs();
+			UpdateSecretSectors(); //mxd
+
+			//mxd. Show UI
+			menusform.Register();
 		}
 		
 		// Mode disengages
 		public override void OnDisengage()
 		{
 			base.OnDisengage();
+
+			//mxd. Store settings
+			General.Settings.WritePluginSetting("automapmode.showhiddenlines", menusform.ShowHiddenLines);
+			General.Settings.WritePluginSetting("automapmode.showsecretsectors", menusform.ShowSecretSectors);
+			General.Settings.WritePluginSetting("automapmode.colorpreset", (int)menusform.ColorPreset);
+
+			//mxd. Hide UI
+			menusform.Unregister();
 
 			// Hide highlight info
 			General.Interface.HideInfo();
 		}
 
+		//mxd
+		public override void OnUndoEnd()
+		{
+			UpdateValidLinedefs();
+			UpdateSecretSectors();
+
+			base.OnUndoEnd();
+		}
+
+		//mxd
+		public override void OnRedoEnd()
+		{
+			UpdateValidLinedefs();
+			UpdateSecretSectors();
+
+			base.OnRedoEnd();
+		}
+
 		// This redraws the display
 		public override void OnRedrawDisplay()
 		{
@@ -205,6 +356,14 @@ namespace CodeImp.DoomBuilder.AutomapMode
 				renderer.Finish();
 			}
 
+			//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);
+				renderer.Finish();
+			}
+
 			renderer.Present();
 		}
 
@@ -212,8 +371,8 @@ namespace CodeImp.DoomBuilder.AutomapMode
 		{
 			// Item highlighted?
 			if((highlighted != null) && !highlighted.IsDisposed)
-			{
-				General.Map.UndoRedo.CreateUndo("Toggle linedef show as 1-sided on automap flag");
+			{
+				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));
@@ -227,8 +386,8 @@ namespace CodeImp.DoomBuilder.AutomapMode
 		{
 			// Item highlighted?
 			if((highlighted != null) && !highlighted.IsDisposed)
-			{
-				General.Map.UndoRedo.CreateUndo("Toggle linedef not shown on automap flag");
+			{
+				General.Map.UndoRedo.CreateUndo("Toggle \"Not shown on automap\" linedef flag");
 
 				// Toggle flag
 				highlighted.SetFlag(BuilderPlug.Me.HiddenFlag, !highlighted.IsFlagSet(BuilderPlug.Me.HiddenFlag));
diff --git a/Source/Plugins/AutomapMode/AutomapMode.csproj b/Source/Plugins/AutomapMode/AutomapMode.csproj
index 8431646ba..5b4bcf188 100644
--- a/Source/Plugins/AutomapMode/AutomapMode.csproj
+++ b/Source/Plugins/AutomapMode/AutomapMode.csproj
@@ -42,7 +42,18 @@
   <ItemGroup>
     <Compile Include="BuilderPlug.cs" />
     <Compile Include="AutomapMode.cs" />
+    <Compile Include="Interface\MenusForm.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Interface\MenusForm.Designer.cs">
+      <DependentUpon>MenusForm.cs</DependentUpon>
+    </Compile>
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\Core\Builder.csproj">
@@ -56,7 +67,10 @@
     <Reference Include="System.Core">
       <RequiredTargetFramework>3.5</RequiredTargetFramework>
     </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
     <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
     <EmbeddedResource Include="Resources\automap.png" />
@@ -65,6 +79,19 @@
     <EmbeddedResource Include="Resources\Actions.cfg" />
   </ItemGroup>
   <ItemGroup>
+    <EmbeddedResource Include="Interface\MenusForm.resx">
+      <DependentUpon>MenusForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
     <EmbeddedResource Include="Resources\Hints.cfg" />
   </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\ShowHiddenLines.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\ShowSecrets.png" />
+  </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/Source/Plugins/AutomapMode/BuilderPlug.cs b/Source/Plugins/AutomapMode/BuilderPlug.cs
index 5c74205b8..844232c9c 100644
--- a/Source/Plugins/AutomapMode/BuilderPlug.cs
+++ b/Source/Plugins/AutomapMode/BuilderPlug.cs
@@ -40,7 +40,7 @@ namespace CodeImp.DoomBuilder.AutomapMode
 		// Static instance. We can't use a real static class, because BuilderPlug must
 		// be instantiated by the core, so we keep a static reference. (this technique
 		// should be familiar to object-oriented programmers)
-		private static BuilderPlug me;
+		private static BuilderPlug me;
 
 		#endregion
 
@@ -85,7 +85,11 @@ namespace CodeImp.DoomBuilder.AutomapMode
 		public override void OnMapOpenEnd()
 		{
 			AutomapMode mode = General.Editing.Mode as AutomapMode;
-			if(mode != null) mode.UpdateValidLinedefs();
+			if(mode != null)
+			{
+				mode.UpdateValidLinedefs();
+				mode.UpdateSecretSectors();
+			}
 			
 			base.OnMapOpenEnd();
 		}
@@ -94,7 +98,11 @@ namespace CodeImp.DoomBuilder.AutomapMode
 		public override void OnMapNewEnd()
 		{
 			AutomapMode mode = General.Editing.Mode as AutomapMode;
-			if(mode != null) mode.UpdateValidLinedefs();
+			if(mode != null)
+			{
+				mode.UpdateValidLinedefs();
+				mode.UpdateSecretSectors();
+			}
 			
 			base.OnMapNewEnd();
 		}
diff --git a/Source/Plugins/AutomapMode/Interface/MenusForm.Designer.cs b/Source/Plugins/AutomapMode/Interface/MenusForm.Designer.cs
new file mode 100644
index 000000000..5e7e03dd1
--- /dev/null
+++ b/Source/Plugins/AutomapMode/Interface/MenusForm.Designer.cs
@@ -0,0 +1,120 @@
+namespace CodeImp.DoomBuilder.AutomapMode
+{
+	partial class MenusForm
+	{
+		/// <summary> 
+		/// Required designer variable.
+		/// </summary>
+		private System.ComponentModel.IContainer components = null;
+
+		/// <summary> 
+		/// Clean up any resources being used.
+		/// </summary>
+		/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+		protected override void Dispose(bool disposing)
+		{
+			if(disposing && (components != null))
+			{
+				components.Dispose();
+			}
+			base.Dispose(disposing);
+		}
+
+		#region Component Designer generated code
+
+		/// <summary> 
+		/// Required method for Designer support - do not modify 
+		/// the contents of this method with the code editor.
+		/// </summary>
+		private void InitializeComponent()
+		{
+			this.toolStrip1 = new System.Windows.Forms.ToolStrip();
+			this.showhiddenlines = new System.Windows.Forms.ToolStripButton();
+			this.showsecretsectors = 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.toolStrip1.SuspendLayout();
+			this.SuspendLayout();
+			// 
+			// toolStrip1
+			// 
+			this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.showhiddenlines,
+            this.showsecretsectors,
+            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";
+			// 
+			// 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.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);
+			// 
+			// 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(121, 25);
+			this.colorpreset.SelectedIndexChanged += new System.EventHandler(this.colorpreset_SelectedIndexChanged);
+			// 
+			// 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();
+
+		}
+
+		#endregion
+
+		private System.Windows.Forms.ToolStrip toolStrip1;
+		private System.Windows.Forms.ToolStripButton showhiddenlines;
+		private System.Windows.Forms.ToolStripButton showsecretsectors;
+		private System.Windows.Forms.ToolStripSeparator colorpresetseparator;
+		private System.Windows.Forms.ToolStripLabel colorpresetlabel;
+		private System.Windows.Forms.ToolStripComboBox colorpreset;
+	}
+}
diff --git a/Source/Plugins/AutomapMode/Interface/MenusForm.cs b/Source/Plugins/AutomapMode/Interface/MenusForm.cs
new file mode 100644
index 000000000..859f5290a
--- /dev/null
+++ b/Source/Plugins/AutomapMode/Interface/MenusForm.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Windows.Forms;
+
+namespace CodeImp.DoomBuilder.AutomapMode
+{
+	public partial class MenusForm : UserControl
+	{
+		public event EventHandler OnShowHiddenLinesChanged;
+		public event EventHandler OnShowSecretSectorsChanged;
+		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; } }
+		internal AutomapMode.ColorPreset ColorPreset { get { return (AutomapMode.ColorPreset)colorpreset.SelectedIndex; } set { colorpreset.SelectedIndex = (int)value; } }
+		
+		public MenusForm()
+		{
+			InitializeComponent();
+		}
+
+		public void Register()
+		{
+			General.Interface.AddButton(showhiddenlines);
+			General.Interface.AddButton(showsecretsectors);
+			General.Interface.AddButton(colorpresetseparator);
+			General.Interface.AddButton(colorpresetlabel);
+			General.Interface.AddButton(colorpreset);
+		}
+
+		public void Unregister()
+		{
+			General.Interface.RemoveButton(colorpreset);
+			General.Interface.RemoveButton(colorpresetlabel);
+			General.Interface.RemoveButton(colorpresetseparator);
+			General.Interface.RemoveButton(showsecretsectors);
+			General.Interface.RemoveButton(showhiddenlines);
+		}
+
+		private void showhiddenlines_CheckedChanged(object sender, EventArgs e)
+		{
+			if(OnShowHiddenLinesChanged != null) OnShowHiddenLinesChanged(showhiddenlines.Checked, EventArgs.Empty);
+		}
+
+		private void showsecretsectors_CheckedChanged(object sender, EventArgs e)
+		{
+			if(OnShowSecretSectorsChanged != null) OnShowSecretSectorsChanged(showsecretsectors.Checked, EventArgs.Empty);
+		}
+
+		private void colorpreset_SelectedIndexChanged(object sender, EventArgs e)
+		{
+			if(OnColorPresetChanged != null) OnColorPresetChanged(colorpreset.SelectedIndex, EventArgs.Empty);
+		}
+	}
+}
diff --git a/Source/Plugins/AutomapMode/Interface/MenusForm.resx b/Source/Plugins/AutomapMode/Interface/MenusForm.resx
new file mode 100644
index 000000000..36f2967b5
--- /dev/null
+++ b/Source/Plugins/AutomapMode/Interface/MenusForm.resx
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/AutomapMode/Properties/Resources.Designer.cs b/Source/Plugins/AutomapMode/Properties/Resources.Designer.cs
new file mode 100644
index 000000000..493c26216
--- /dev/null
+++ b/Source/Plugins/AutomapMode/Properties/Resources.Designer.cs
@@ -0,0 +1,77 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:2.0.50727.5485
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace CodeImp.DoomBuilder.AutomapMode.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeImp.DoomBuilder.AutomapMode.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        internal static System.Drawing.Bitmap ShowHiddenLines {
+            get {
+                object obj = ResourceManager.GetObject("ShowHiddenLines", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap ShowSecrets {
+            get {
+                object obj = ResourceManager.GetObject("ShowSecrets", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+    }
+}
diff --git a/Source/Plugins/AutomapMode/Properties/Resources.resx b/Source/Plugins/AutomapMode/Properties/Resources.resx
new file mode 100644
index 000000000..4fa11f4c7
--- /dev/null
+++ b/Source/Plugins/AutomapMode/Properties/Resources.resx
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="ShowHiddenLines" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\ShowHiddenLines.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="ShowSecrets" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\ShowSecrets.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 f2d3e1b64..f004af3eb 100644
--- a/Source/Plugins/AutomapMode/Resources/Hints.cfg
+++ b/Source/Plugins/AutomapMode/Resources/Hints.cfg
@@ -8,4 +8,4 @@ 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 show 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)."
\ No newline at end of file
diff --git a/Source/Plugins/AutomapMode/Resources/ShowHiddenLines.png b/Source/Plugins/AutomapMode/Resources/ShowHiddenLines.png
new file mode 100644
index 0000000000000000000000000000000000000000..b298ab1123c82c413177d11f685bda7af8f69797
GIT binary patch
literal 1227
zcmbVMUuYaf7+(`@Yak^>C^fdaY!DRPoBemUx7$0@yW5L7$z8(bplQJ3-tJs(Np@$u
zJIQShsxdxj9)v_fwctZVe6XT<NfB&qf<>`VC>Yv8sI`g|QAqKj7>$avmt6EA^udMQ
z`DW(#`~H7BGf;TGy{)s2qNw&<uT~^$NBHh(A>Y}#YK$z8;_MI}L={}qJxHZYREBiU
z)<<9w>gME$%P>JvtrJ#h2oL4^R0G)&J;X!;+a+v@N^}RVZj3@qm*I%zB$>PCml)bI
zlg!a*p3A!#ShafV9vrL}N=ALuP)w%#IXV%jM1c*lP6zgw<EufEY3Nmn93BIPZb0y8
zlG$`>C_g}FkO%2#B*q$COr~We!bfFUlAomoj*kLP1R}=@qAGE!B+y$AL#%mbMJ;MQ
zTeiq9$y70RRRC(WTBIgMkT(K&MNt4J06}00g7qgItOu;)cQrL=&^J8G#TIhtP@`T(
z<2cC>Pd7ub-F$vqvEy$gilht#x(oOS2W&fxtAX}$5&rAOj%dF$=|WJ1J{tE7Qjbbk
zlT31Ve?uXVc%$}v7AcB8rXge8h7QhYNrv1+Ov_Xi0ZQ?hV6uGK;Mg)J$*f{<6;`jv
zl2BGmT^6HFJv;HUu~<rzQ=BMi3eRU_@hC6E`5sXdQZY@*YE5p=@v-h0uxZ;Owl}#-
z&waUS#)CRWUJ0SGW)}=p5k`I$xpXGes5<@BQOhw=&3`&9(`M8f^sEVJ_ISvq8+lf(
z9em*VxGYGz&Q?TGVMSR|*fMVtiRYs6IOKFu=9n$M`G4~Vh*KbJmj5(Q^N4h0C~l7e
z*=!FJbjSpGWK_O;<)PonnEjH|Ql(&ZzWDjxY3@KG_jczC(}gR4vrgZIxvRHZ*R_kU
zJp#_G^`+B~ou9pZF2ARB#<kWCfAQ^&^wPEc@s=N#)~WteEkC{fqz2%^yz%p|&n#8<
zzxP{vK)v;b@!|Zn)y~Z0t1I<;yZ3#6dhPJ+mnTj^c<j#P@qO<vPxabU$%7k*zL7ql
z2m4>nE#7Jc@jDag2cI}ySI?ZhyX<$IySVtyq2;tT11|qLb@s)F6T5%d*tK{4k0Uq6
zuMf8g_wbRG;jWt<C-W-<vl)-!ZeG~<>#MKNe)eu*<m1}GH|G`(e3ZTP>9BgM`+;55
X!lmj||EpIP!{19TThKm9zcl?1V=$nl

literal 0
HcmV?d00001

diff --git a/Source/Plugins/AutomapMode/Resources/ShowSecrets.png b/Source/Plugins/AutomapMode/Resources/ShowSecrets.png
new file mode 100644
index 0000000000000000000000000000000000000000..f5d2dac259bf23126a7d98f97c324d359441b6ea
GIT binary patch
literal 1209
zcmbVMTWHi+7!F#n7OEl&UKR~0ip9<3GM6-=v$NC5%sSYq<2c|vtd~r3(g|&HVshF^
z3%*qA<w0~+7S|Sa#id;ZA6(gobyr&{;(`>mFKgG^%Cb-u^hNN=%gMA;eJCOZl5<Y-
zf8YQ8w;ay4eN$hzs*WIt`t&9_hu0<kT{{myk9}8);AJIB7SJ}Rqq5=vBCf$AAk(JO
z4st-zdiMMYnh9clw~;TPLZ($xp&3won}BE97)=n(G0#@i4uHraXg91V_2SwMiZrw+
zwLP3+Gj;-$j7_}`*w)*YS9?2DQKMpCk<Ffj2~2<#(la|PSMs7%g;&CR|20FA6%*7E
zrKUv{GFdVK9YBTy5n5#<0x5_AE-VNk;Y*TdxiG^9nIKE^K`F#aA)cJMDD2JAbSWpN
zW_;mOlqw-)OAJ#kmjmTs06OgqCyFA&@(j<@*n)O@ETnj}<u+6qWZ<ffVIu=tq|c}n
zVHb*0Sm|^Krk%;m5?k&}qHxL>Pq7&;z%r)k$5pX*Q4YM9F{ibg@38@s11{`xR9p|e
zp$f*i`?w?D5UY{4I0i0?(kVl=%LEom%TWq{3225Ui9853MR<+oiYiMN*^oesDy!3q
zE`<1^s3}4)T;-VyA4xTFO~I5949OzLB_l0DoJ;T`FK}|WCBimUv1!Xiilu_8Zv*?D
z!A3rcl@bn65Oneoc2>I}TY?C>C1{h0M5XHFhV6!>!Lr-vmuWg`88}8a&{7UG$x5Cj
zV-5|U7XLI}``r97SQO(o%LmO<eT6&H-_DK#KFkgiu<!&qcvQZSv?qAXCev~}@BMS~
zI9GS`>m|vvin(7~w`L?|o@kr!`Ub~tZmwN3(lB|byRma@{Q~w_&BU!eNp5w&cItKT
z&iLB9ld)4H^J?yOAG|brAenvpYB-$yLx1t_-QR0h!XFMyJ-&AQ#L$H?J$L`~RciQW
zdU5T^XZwy0#PzLL2kQs+%S(+1zx-VapB_E@*V6IWL;AsjMUR#by*&H4f5)B1)(umw
z=Z3^H3wM_LI==r;-?8xGZ=-`x7sr1!)?Ez6vTsV`|KEN-@YA<@m-W*}^1F{*FHB5r
gydK}x6RTN4P^-6|Up9Q@NB?J%PPWOHTXy%o1O3vNr2qf`

literal 0
HcmV?d00001

diff --git a/Source/Plugins/BuilderModes/General/CopyStructures.cs b/Source/Plugins/BuilderModes/General/CopyStructures.cs
index ceae71a0c..60a55bd28 100644
--- a/Source/Plugins/BuilderModes/General/CopyStructures.cs
+++ b/Source/Plugins/BuilderModes/General/CopyStructures.cs
@@ -810,11 +810,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				if(!General.Map.Config.GeneralizedEffects || source.Effect == 0 || target.Effect == 0) return false;
 
 				// Get effect bits...
-				HashSet<int> sourcebits = GameConfiguration.GetGeneralizedSectorEffectBits(source.Effect);
-				HashSet<int> targetbits = GameConfiguration.GetGeneralizedSectorEffectBits(target.Effect);
+				SectorEffectData sourcedata = General.Map.Config.GetSectorEffectData(source.Effect);
+				SectorEffectData targetdata = General.Map.Config.GetSectorEffectData(target.Effect);
 				
 				// No bits match when at least one effect is not generalized, or when bits don't overlap 
-				if(sourcebits.Count == 0 || targetbits.Count == 0 || !sourcebits.Overlaps(targetbits)) return false;
+				if(sourcedata.Effect != targetdata.Effect 
+					|| sourcedata.GeneralizedBits.Count != targetdata.GeneralizedBits.Count 
+					|| !sourcedata.GeneralizedBits.Overlaps(targetdata.GeneralizedBits)) return false;
 			}
 
 			if(!General.Map.UDMF) return true;
-- 
GitLab