From 25b3bf2287b81063a69440825fa41304afc30646 Mon Sep 17 00:00:00 2001
From: MaxED <j.maxed@gmail.com>
Date: Wed, 16 Sep 2015 12:10:43 +0000
Subject: [PATCH] Added, Texture Browser: added "Show textures in
 subdirectories" checkbox (enabled by default). When enabled, textures from
 current PK3/PK7/Directory resource directory and it's subdirectories will be
 shown. Otherwise, only textures from current directory will be shown.
 Removed, Texture Browser: removed "Show image sizes" checkbox. "Show texture
 and flat sizes in browsers" preferences setting is now used instead. Fixed,
 Things mode: event line between pre-last and the last PatrolPoint was not
 drawn. Fixed, Things mode: highlight range for sizeless things (things with
 "fixedsize" game configuration property) was calculated incorrectly. Fixed:
 fixed a crash when opening Script Editor after using "Open map in current
 wad" command to switch to UDMF map with SCRIPTS lump when current script
 configuration was not saved in the wad's .dbs file. Fixed: map closing events
 were not triggered when using "Open map in current wad" command, which could
 potentially result in plugin crashes/incorrect behavior. Fixed: Sector
 Drawing overrides panel could trigger an exception when closing the map
 during resource loading. Internal: added "Debug + Profiler" solution
 configuration, added 2 profiling methods to DebugConsole. Internal: rewrote
 MainForm.DisplayStatus() / StatusInfo to handle selection info in a more
 structured way. Fixed, internal: some destructors could potentially be
 executed more than once potentially leading to exceptions. Other destructors
 were not called at all. Updated ZDoom_DECORATE.cfg.

---
 Build/Scripting/ZDoom_DECORATE.cfg            |  1 +
 Builder.sln                                   | 23 +++++++++
 MakeSVNRelease.bat                            |  2 +-
 Source/Core/Builder.csproj                    | 13 +++++
 Source/Core/Compilers/NodesCompiler.cs        |  2 +-
 Source/Core/Config/ConfigurationInfo.cs       |  6 +++
 Source/Core/Config/GameConfiguration.cs       |  1 +
 Source/Core/Config/IFilledTextureSet.cs       |  1 +
 Source/Core/Config/ProgramConfiguration.cs    |  6 +--
 Source/Core/Config/TextureSet.cs              |  2 +
 Source/Core/Controls/DebugConsole.cs          | 43 ++++++++++++++++
 .../Controls/ImageBrowserControl.Designer.cs  | 28 +++++------
 Source/Core/Controls/ImageBrowserControl.cs   | 23 +++++----
 Source/Core/Controls/ImageBrowserItem.cs      |  2 +-
 Source/Core/Controls/ImageSelectorControl.cs  |  6 +++
 Source/Core/Data/DataManager.cs               | 17 +++----
 Source/Core/Data/DynamicBitmapImage.cs        | 11 +++-
 Source/Core/Data/FileImage.cs                 |  3 +-
 Source/Core/Data/HighResImage.cs              |  3 +-
 Source/Core/Data/ImageData.cs                 |  4 +-
 Source/Core/Data/PK3FileImage.cs              |  1 +
 Source/Core/Editing/CustomThingsFilter.cs     |  4 +-
 Source/Core/Editing/EditModeInfo.cs           | 50 +++++++++++--------
 Source/Core/Editing/EditingManager.cs         |  1 +
 Source/Core/Editing/ThingsFilter.cs           |  7 +--
 Source/Core/GZBuilder/Data/LinksCollector.cs  | 10 ++--
 Source/Core/GZBuilder/Data/ModelData.cs       | 19 +++++--
 Source/Core/General/FileLockChecker.cs        |  1 +
 Source/Core/General/General.cs                | 19 +++----
 Source/Core/IO/DoomFlatReader.cs              |  2 +-
 Source/Core/Map/MapElement.cs                 | 15 +++---
 Source/Core/Map/MapSet.cs                     | 10 ++--
 Source/Core/Map/SelectableElement.cs          | 14 ++++--
 Source/Core/Windows/ChangeMapForm.cs          |  1 +
 Source/Core/Windows/MainForm.cs               | 43 ++--------------
 Source/Core/Windows/PreferencesForm.cs        |  4 +-
 Source/Core/Windows/StatusInfo.cs             | 41 +++++++++++++--
 Source/Core/Windows/TextureBrowserForm.cs     | 34 ++++++-------
 .../BuilderEffects/BuilderEffects.csproj      |  8 +++
 .../Plugins/BuilderModes/BuilderModes.csproj  |  9 ++++
 .../ClassicModes/DrawCurveMode.cs             | 11 +++-
 .../ClassicModes/DrawRectangleMode.cs         | 10 +++-
 .../BuilderModes/General/BuilderPlug.cs       | 10 ++--
 .../Interface/SectorDrawingOptionsPanel.cs    |  9 ++++
 .../VisualModes/BaseVisualThing.cs            |  4 +-
 Source/Plugins/ColorPicker/ColorPicker.csproj |  8 +++
 .../CommentsPanel/CommentsPanel.csproj        |  9 ++++
 Source/Plugins/NodesViewer/NodesViewer.csproj | 10 ++++
 .../SoundPropagation.csproj                   | 25 +++-------
 .../StairSectorBuilder.csproj                 |  8 +++
 Source/Plugins/TagExplorer/TagExplorer.csproj |  8 +++
 Source/Plugins/TagRange/TagRange.csproj       |  8 +++
 .../VisplaneExplorer/VisplaneExplorer.csproj  | 10 ++++
 53 files changed, 426 insertions(+), 194 deletions(-)

diff --git a/Build/Scripting/ZDoom_DECORATE.cfg b/Build/Scripting/ZDoom_DECORATE.cfg
index 26e924cbd..ade38d94a 100644
--- a/Build/Scripting/ZDoom_DECORATE.cfg
+++ b/Build/Scripting/ZDoom_DECORATE.cfg
@@ -1017,6 +1017,7 @@ constants
 	DMSS_EITHER;
 	FPF_AIMATANGLE;
 	FPF_TRANSFERTRANSLATION;
+	FPF_NOAUTOAIM;
 	FTF_CLAMP;
 	FTF_REMOVE;
 	GFF_NOEXTCHANGE;
diff --git a/Builder.sln b/Builder.sln
index 1409f3f2e..50d7921ab 100644
--- a/Builder.sln
+++ b/Builder.sln
@@ -25,50 +25,73 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StairSectorBuilder", "Sourc
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug + Profiler|x86 = Debug + Profiler|x86
 		Debug|x86 = Debug|x86
 		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug + Profiler|x86.ActiveCfg = Debug + Profiler|x86
+		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug + Profiler|x86.Build.0 = Debug + Profiler|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|x86.ActiveCfg = Debug|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Debug|x86.Build.0 = Debug|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.ActiveCfg = Release|x86
 		{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}.Release|x86.Build.0 = Release|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug + Profiler|x86.ActiveCfg = Debug + Profiler|x86
+		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug + Profiler|x86.Build.0 = Debug + Profiler|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|x86.ActiveCfg = Debug|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Debug|x86.Build.0 = Debug|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|x86.ActiveCfg = Release|x86
 		{B42D5AA0-F9A6-4234-9C4B-A05B11A64851}.Release|x86.Build.0 = Release|x86
+		{B859BE0F-A992-476D-A642-FA8EFE94AAA5}.Debug + Profiler|x86.ActiveCfg = Debug + Profiler|x86
+		{B859BE0F-A992-476D-A642-FA8EFE94AAA5}.Debug + Profiler|x86.Build.0 = Debug + Profiler|x86
 		{B859BE0F-A992-476D-A642-FA8EFE94AAA5}.Debug|x86.ActiveCfg = Debug|x86
 		{B859BE0F-A992-476D-A642-FA8EFE94AAA5}.Debug|x86.Build.0 = Debug|x86
 		{B859BE0F-A992-476D-A642-FA8EFE94AAA5}.Release|x86.ActiveCfg = Release|x86
 		{B859BE0F-A992-476D-A642-FA8EFE94AAA5}.Release|x86.Build.0 = Release|x86
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug + Profiler|x86.ActiveCfg = Debug + Profiler|x86
+		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug + Profiler|x86.Build.0 = Debug + Profiler|x86
 		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|x86.ActiveCfg = Debug|x86
 		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Debug|x86.Build.0 = Debug|x86
 		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.ActiveCfg = Release|x86
 		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.Build.0 = Release|x86
+		{BE7917F3-E6FE-4D5B-8FA9-B8E7668AC731}.Debug + Profiler|x86.ActiveCfg = Debug + Profiler|x86
+		{BE7917F3-E6FE-4D5B-8FA9-B8E7668AC731}.Debug + Profiler|x86.Build.0 = Debug + Profiler|x86
 		{BE7917F3-E6FE-4D5B-8FA9-B8E7668AC731}.Debug|x86.ActiveCfg = Debug|x86
 		{BE7917F3-E6FE-4D5B-8FA9-B8E7668AC731}.Debug|x86.Build.0 = Debug|x86
 		{BE7917F3-E6FE-4D5B-8FA9-B8E7668AC731}.Release|x86.ActiveCfg = Release|x86
 		{BE7917F3-E6FE-4D5B-8FA9-B8E7668AC731}.Release|x86.Build.0 = Release|x86
+		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug + Profiler|x86.ActiveCfg = Debug + Profiler|x86
+		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug + Profiler|x86.Build.0 = Debug + Profiler|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug|x86.ActiveCfg = Debug|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Debug|x86.Build.0 = Debug|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Release|x86.ActiveCfg = Release|x86
 		{58BD8A5B-1B48-435D-8473-A92F27D06C49}.Release|x86.Build.0 = Release|x86
+		{9F244231-6A0C-42A6-87C5-ED9620DEE096}.Debug + Profiler|x86.ActiveCfg = Debug + Profiler|x86
+		{9F244231-6A0C-42A6-87C5-ED9620DEE096}.Debug + Profiler|x86.Build.0 = Debug + Profiler|x86
 		{9F244231-6A0C-42A6-87C5-ED9620DEE096}.Debug|x86.ActiveCfg = Debug|x86
 		{9F244231-6A0C-42A6-87C5-ED9620DEE096}.Debug|x86.Build.0 = Debug|x86
 		{9F244231-6A0C-42A6-87C5-ED9620DEE096}.Release|x86.ActiveCfg = Release|x86
 		{9F244231-6A0C-42A6-87C5-ED9620DEE096}.Release|x86.Build.0 = Release|x86
+		{F49EFF6D-51CB-4E49-8223-AAE653C5B62F}.Debug + Profiler|x86.ActiveCfg = Debug + Profiler|x86
+		{F49EFF6D-51CB-4E49-8223-AAE653C5B62F}.Debug + Profiler|x86.Build.0 = Debug + Profiler|x86
 		{F49EFF6D-51CB-4E49-8223-AAE653C5B62F}.Debug|x86.ActiveCfg = Debug|x86
 		{F49EFF6D-51CB-4E49-8223-AAE653C5B62F}.Debug|x86.Build.0 = Debug|x86
 		{F49EFF6D-51CB-4E49-8223-AAE653C5B62F}.Release|x86.ActiveCfg = Release|x86
 		{F49EFF6D-51CB-4E49-8223-AAE653C5B62F}.Release|x86.Build.0 = Release|x86
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug + Profiler|x86.ActiveCfg = Debug + Profiler|x86
+		{CF670175-7099-4090-A330-EE25C7230139}.Debug + Profiler|x86.Build.0 = Debug + Profiler|x86
 		{CF670175-7099-4090-A330-EE25C7230139}.Debug|x86.ActiveCfg = Debug|x86
 		{CF670175-7099-4090-A330-EE25C7230139}.Debug|x86.Build.0 = Debug|x86
 		{CF670175-7099-4090-A330-EE25C7230139}.Release|x86.ActiveCfg = Release|x86
 		{CF670175-7099-4090-A330-EE25C7230139}.Release|x86.Build.0 = Release|x86
+		{F59B344C-DD50-4DB7-ADDD-56AAD66450AF}.Debug + Profiler|x86.ActiveCfg = Debug + Profiler|x86
+		{F59B344C-DD50-4DB7-ADDD-56AAD66450AF}.Debug + Profiler|x86.Build.0 = Debug + Profiler|x86
 		{F59B344C-DD50-4DB7-ADDD-56AAD66450AF}.Debug|x86.ActiveCfg = Debug|x86
 		{F59B344C-DD50-4DB7-ADDD-56AAD66450AF}.Debug|x86.Build.0 = Debug|x86
 		{F59B344C-DD50-4DB7-ADDD-56AAD66450AF}.Release|x86.ActiveCfg = Release|x86
 		{F59B344C-DD50-4DB7-ADDD-56AAD66450AF}.Release|x86.Build.0 = Release|x86
+		{3F365121-906B-409D-BB1E-37E0A78056C2}.Debug + Profiler|x86.ActiveCfg = Debug + Profiler|x86
+		{3F365121-906B-409D-BB1E-37E0A78056C2}.Debug + Profiler|x86.Build.0 = Debug + Profiler|x86
 		{3F365121-906B-409D-BB1E-37E0A78056C2}.Debug|x86.ActiveCfg = Debug|x86
 		{3F365121-906B-409D-BB1E-37E0A78056C2}.Debug|x86.Build.0 = Debug|x86
 		{3F365121-906B-409D-BB1E-37E0A78056C2}.Release|x86.ActiveCfg = Release|x86
diff --git a/MakeSVNRelease.bat b/MakeSVNRelease.bat
index 23a5b0945..002aea9fe 100644
--- a/MakeSVNRelease.bat
+++ b/MakeSVNRelease.bat
@@ -166,7 +166,7 @@ ECHO.
 ECHO Packing release...
 ECHO.
 IF EXIST "SVN_Build\*.7z" DEL /F /Q "SVN_Build\*.7z" > NUL
-"%SEVENZIPDIR%\7z" a .\SVN_Build\gzdb.7z .\Build\* -xr!*.pdb -xr!*.xml -x!Setup
+"%SEVENZIPDIR%\7z" a .\SVN_Build\gzdb.7z .\Build\* -xr!*.pdb -xr!*.xml -xr!JetBrains.Profiler.Core.Api.dll -x!Setup
 IF %ERRORLEVEL% NEQ 0 GOTO PACKFAIL
 IF NOT EXIST .\SVN_Build\gzdb.7z GOTO FILEFAIL
 
diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj
index 1e0772ffa..1f675192d 100644
--- a/Source/Core/Builder.csproj
+++ b/Source/Core/Builder.csproj
@@ -48,6 +48,18 @@
     </DefineConstants>
     <WarningLevel>3</WarningLevel>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\Build\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;PROFILE</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DocumentationFile>..\..\Build\Builder.xml</DocumentationFile>
+    <WarningLevel>3</WarningLevel>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
@@ -506,6 +518,7 @@
     <Compile Include="Rendering\WorldVertex.cs" />
   </ItemGroup>
   <ItemGroup>
+    <Reference Include="JetBrains.Profiler.Core.Api, Version=1.3.1661.20096, Culture=neutral, PublicKeyToken=1010a0d8d6380325" Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' " />
     <Reference Include="SharpCompress.3.5, Version=0.11.1.0, Culture=neutral, processorArchitecture=x86" />
     <Reference Include="SlimDX, Version=2.0.13.43, Culture=neutral, PublicKeyToken=b1b0c32fd1ffe4f9, processorArchitecture=x86" />
     <Reference Include="System" />
diff --git a/Source/Core/Compilers/NodesCompiler.cs b/Source/Core/Compilers/NodesCompiler.cs
index 56f237191..049ffa74c 100644
--- a/Source/Core/Compilers/NodesCompiler.cs
+++ b/Source/Core/Compilers/NodesCompiler.cs
@@ -125,7 +125,7 @@ namespace CodeImp.DoomBuilder.Compilers
 			bool errorsInErrorOutput = (outErr.Length > 0 && outErr.ToLowerInvariant().IndexOf("error") != -1);
 
 			deltatime = TimeSpan.FromTicks(process.ExitTime.Ticks - process.StartTime.Ticks);
-			General.WriteLogLine("Compiler process has finished " + (errorsInNormalOurput || errorsInErrorOutput ? "with errors." : ".")); //mxd
+			General.WriteLogLine("Compiler process has finished" + (errorsInNormalOurput || errorsInErrorOutput ? " with errors." : ".")); //mxd
 			General.WriteLogLine("Compile time: " + deltatime.TotalSeconds.ToString("########0.00") + " seconds");
 
 			//mxd
diff --git a/Source/Core/Config/ConfigurationInfo.cs b/Source/Core/Config/ConfigurationInfo.cs
index c1afddbfe..748cd7719 100644
--- a/Source/Core/Config/ConfigurationInfo.cs
+++ b/Source/Core/Config/ConfigurationInfo.cs
@@ -225,6 +225,12 @@ namespace CodeImp.DoomBuilder.Config
 		private ConfigurationInfo()
 		{
 		}
+
+		//mxd. Destructor
+		~ConfigurationInfo()
+		{
+			foreach(ThingsFilter tf in thingsfilters) tf.Dispose();
+		}
 		
 		#endregion
 
diff --git a/Source/Core/Config/GameConfiguration.cs b/Source/Core/Config/GameConfiguration.cs
index 0bb08b1ce..10899016a 100644
--- a/Source/Core/Config/GameConfiguration.cs
+++ b/Source/Core/Config/GameConfiguration.cs
@@ -405,6 +405,7 @@ namespace CodeImp.DoomBuilder.Config
 		{
 			foreach(ThingCategory tc in thingcategories) tc.Dispose();
 			foreach(LinedefActionCategory ac in actioncategories) ac.Dispose();
+			foreach(ThingsFilter tf in thingfilters) tf.Dispose(); //mxd
 		}
 		
 		#endregion
diff --git a/Source/Core/Config/IFilledTextureSet.cs b/Source/Core/Config/IFilledTextureSet.cs
index bf9453f44..2c1c63538 100644
--- a/Source/Core/Config/IFilledTextureSet.cs
+++ b/Source/Core/Config/IFilledTextureSet.cs
@@ -27,6 +27,7 @@ namespace CodeImp.DoomBuilder.Config
 	{
 		// Properties
 		string Name { get; }
+		int Level { get; } //mxd
 		ICollection<ImageData> Textures { get; }
 		ICollection<ImageData> Flats { get; }
 	}
diff --git a/Source/Core/Config/ProgramConfiguration.cs b/Source/Core/Config/ProgramConfiguration.cs
index d891c14ef..64cd743dc 100644
--- a/Source/Core/Config/ProgramConfiguration.cs
+++ b/Source/Core/Config/ProgramConfiguration.cs
@@ -426,15 +426,13 @@ namespace CodeImp.DoomBuilder.Config
 			cfg.WriteSetting("defaultbrightness", defaultbrightness);
 			
 			// Save settings configuration
-			General.WriteLogLine("Saving program configuration...");
+			General.WriteLogLine("Saving program configuration to '" + filepathname + "'...");
 			cfg.SaveConfiguration(filepathname);
 		}
 		
 		// This reads the configuration
 		private bool Read(string cfgfilepathname, string defaultfilepathname)
 		{
-			DialogResult result;
-
 			// Check if no config for this user exists yet
 			if(!File.Exists(cfgfilepathname))
 			{
@@ -450,7 +448,7 @@ namespace CodeImp.DoomBuilder.Config
 			{
 				// Error in configuration
 				// Ask user for a new copy
-				result = General.ShowErrorMessage("Error in program configuration near line " + cfg.ErrorLine + ": " + cfg.ErrorDescription + "\n\nWould you like to overwrite your settings with a new configuration to restore the default settings?", MessageBoxButtons.YesNoCancel);
+				DialogResult result = General.ShowErrorMessage("Error in program configuration near line " + cfg.ErrorLine + ": " + cfg.ErrorDescription + "\n\nWould you like to overwrite your settings with a new configuration to restore the default settings?", MessageBoxButtons.YesNoCancel);
 				if(result == DialogResult.Yes)
 				{
 					// Remove old configuration and make a new copy
diff --git a/Source/Core/Config/TextureSet.cs b/Source/Core/Config/TextureSet.cs
index 1df5a46b4..e6f527829 100644
--- a/Source/Core/Config/TextureSet.cs
+++ b/Source/Core/Config/TextureSet.cs
@@ -28,6 +28,7 @@ namespace CodeImp.DoomBuilder.Config
 		#region ================== Variables
 
 		protected string name;
+		private int level; //mxd. Folder depth of this item
 		protected List<string> filters;
 		
 		#endregion
@@ -35,6 +36,7 @@ namespace CodeImp.DoomBuilder.Config
 		#region ================== Properties
 		
 		public string Name { get { return name; } set { name = value; } }
+		public int Level { get { return level; } set { level = value; } }
 		internal List<string> Filters { get { return filters; } }
 		
 		#endregion
diff --git a/Source/Core/Controls/DebugConsole.cs b/Source/Core/Controls/DebugConsole.cs
index ca81ee1d3..7a875b713 100644
--- a/Source/Core/Controls/DebugConsole.cs
+++ b/Source/Core/Controls/DebugConsole.cs
@@ -6,6 +6,10 @@ using System.Drawing;
 using System.Globalization;
 using System.Windows.Forms;
 
+#if PROFILE
+using JetBrains.Profiler.Core.Api;
+#endif
+
 #endregion
 
 namespace CodeImp.DoomBuilder
@@ -155,6 +159,45 @@ namespace CodeImp.DoomBuilder
 			starttime = -1;
 		}
 
+		public static void StartProfiler()
+		{
+#if PROFILE
+			if(PerformanceProfiler.IsActive)
+			{
+				WriteLine(DebugMessageType.SPECIAL, "Starting the Profiler...");
+				PerformanceProfiler.Begin();
+				PerformanceProfiler.Start();
+			}
+			else
+			{
+				WriteLine(DebugMessageType.SPECIAL, "Unable to start the Profiler...");
+			}
+#else
+			WriteLine(DebugMessageType.SPECIAL, "Unable to start the Profiler: incorrect build configuration selected!");
+#endif
+		}
+
+		public static void StopProfiler() { StopProfiler(true); }
+		public static void StopProfiler(bool savesnapshot)
+		{
+#if PROFILE
+			if(PerformanceProfiler.IsActive)
+			{
+				PerformanceProfiler.Stop();
+				if(savesnapshot) PerformanceProfiler.EndSave();
+				else PerformanceProfiler.EndDrop();
+
+				WriteLine(DebugMessageType.SPECIAL, "Profiler Stopped...");
+			}
+			else
+			{
+				WriteLine(DebugMessageType.SPECIAL, "Unable to stop the Profiler...");
+			}
+#else
+			WriteLine(DebugMessageType.SPECIAL, "Unable to stop the Profiler: incorrect build configuration selected!");
+#endif
+		}
+
 		private void AddMessage(DebugMessageType type, string text, bool scroll)
 		{
 			text = textheaders[type] + text;
diff --git a/Source/Core/Controls/ImageBrowserControl.Designer.cs b/Source/Core/Controls/ImageBrowserControl.Designer.cs
index 445cce49b..29afc0a23 100644
--- a/Source/Core/Controls/ImageBrowserControl.Designer.cs
+++ b/Source/Core/Controls/ImageBrowserControl.Designer.cs
@@ -34,7 +34,7 @@ namespace CodeImp.DoomBuilder.Controls
 			this.label = new System.Windows.Forms.Label();
 			this.splitter = new System.Windows.Forms.SplitContainer();
 			this.list = new CodeImp.DoomBuilder.Controls.OptimizedListView();
-			this.showtexturesize = new System.Windows.Forms.CheckBox();
+			this.showsubdirtextures = new System.Windows.Forms.CheckBox();
 			this.longtexturenames = new System.Windows.Forms.CheckBox();
 			this.filterheightlabel = new System.Windows.Forms.Label();
 			this.filterHeight = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
@@ -81,7 +81,7 @@ namespace CodeImp.DoomBuilder.Controls
 			// 
 			// splitter.Panel2
 			// 
-			this.splitter.Panel2.Controls.Add(this.showtexturesize);
+			this.splitter.Panel2.Controls.Add(this.showsubdirtextures);
 			this.splitter.Panel2.Controls.Add(this.longtexturenames);
 			this.splitter.Panel2.Controls.Add(this.filterheightlabel);
 			this.splitter.Panel2.Controls.Add(this.filterHeight);
@@ -116,22 +116,22 @@ namespace CodeImp.DoomBuilder.Controls
 			this.list.DoubleClick += new System.EventHandler(this.list_DoubleClick);
 			this.list.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.list_ItemSelectionChanged);
 			// 
-			// showtexturesize
+			// showsubdirtextures
 			// 
-			this.showtexturesize.AutoSize = true;
-			this.showtexturesize.Location = new System.Drawing.Point(470, 9);
-			this.showtexturesize.Name = "showtexturesize";
-			this.showtexturesize.Size = new System.Drawing.Size(105, 17);
-			this.showtexturesize.TabIndex = 0;
-			this.showtexturesize.TabStop = false;
-			this.showtexturesize.Text = "Show image size";
-			this.showtexturesize.UseVisualStyleBackColor = true;
-			this.showtexturesize.CheckedChanged += new System.EventHandler(this.showtexturesize_CheckedChanged);
+			this.showsubdirtextures.AutoSize = true;
+			this.showsubdirtextures.Location = new System.Drawing.Point(595, 9);
+			this.showsubdirtextures.Name = "showsubdirtextures";
+			this.showsubdirtextures.Size = new System.Drawing.Size(172, 17);
+			this.showsubdirtextures.TabIndex = 0;
+			this.showsubdirtextures.TabStop = false;
+			this.showsubdirtextures.Text = "Show textures in subdirectories";
+			this.showsubdirtextures.UseVisualStyleBackColor = true;
+			this.showsubdirtextures.CheckedChanged += new System.EventHandler(this.showsubdirtextures_CheckedChanged);
 			// 
 			// longtexturenames
 			// 
 			this.longtexturenames.AutoSize = true;
-			this.longtexturenames.Location = new System.Drawing.Point(585, 9);
+			this.longtexturenames.Location = new System.Drawing.Point(470, 9);
 			this.longtexturenames.Name = "longtexturenames";
 			this.longtexturenames.Size = new System.Drawing.Size(119, 17);
 			this.longtexturenames.TabIndex = 0;
@@ -259,7 +259,7 @@ namespace CodeImp.DoomBuilder.Controls
 		private ButtonsNumericTextbox filterHeight;
 		private System.Windows.Forms.Label filterwidthlabel;
 		private System.Windows.Forms.CheckBox longtexturenames;
-		private System.Windows.Forms.CheckBox showtexturesize;
+		private System.Windows.Forms.CheckBox showsubdirtextures;
 
 	}
 }
diff --git a/Source/Core/Controls/ImageBrowserControl.cs b/Source/Core/Controls/ImageBrowserControl.cs
index 3491f77f7..68df45679 100644
--- a/Source/Core/Controls/ImageBrowserControl.cs
+++ b/Source/Core/Controls/ImageBrowserControl.cs
@@ -53,7 +53,8 @@ namespace CodeImp.DoomBuilder.Controls
 		private int keepselected;
 		private bool browseFlats; //mxd
 		private static bool uselongtexturenames; //mxd
-		private static bool showtexturesizes; //mxd
+		private static bool showtexturesfromsubdirs; //mxd
+		private int currentlevel; //mxd
 		
 		// All items
 		private readonly List<ImageBrowserItem> items;
@@ -71,7 +72,7 @@ namespace CodeImp.DoomBuilder.Controls
 		public bool PreventSelection { get { return preventselection; } set { preventselection = value; } }
 		public bool HideInputBox { get { return splitter.Panel2Collapsed; } set { splitter.Panel2Collapsed = value; } }
 		public bool BrowseFlats { get { return browseFlats; } set { browseFlats = value; } } //mxd
-		public static bool ShowTextureSizes { get { return showtexturesizes; } internal set { showtexturesizes = value; } } //mxd
+		public static bool ShowTexturesFromSubDirectories { get { return showtexturesfromsubdirs; } internal set { showtexturesfromsubdirs = value; } } //mxd
 		public static bool UseLongTextureNames { get { return uselongtexturenames; } internal set { uselongtexturenames = value; } } //mxd
 		public ListViewItem SelectedItem { get { if(list.SelectedItems.Count > 0) return list.SelectedItems[0]; else return null; } }
 		
@@ -132,7 +133,7 @@ namespace CodeImp.DoomBuilder.Controls
 					filterwidthlabel.Left -= offset;
 					filterHeight.Left -= offset;
 					filterheightlabel.Left -= offset;
-					showtexturesize.Left -= offset;
+					showsubdirtextures.Left -= offset;
 					longtexturenames.Left -= offset;
 					
 					mixMode = 0;
@@ -152,8 +153,8 @@ namespace CodeImp.DoomBuilder.Controls
 			if(!General.Settings.CapitalizeTextureNames)
 				objectname.CharacterCasing = CharacterCasing.Normal;
 
-			//mxd. Show texture sizes?
-			showtexturesize.Checked = showtexturesizes;
+			//mxd. Show textures in subfolders?
+			showsubdirtextures.Checked = showtexturesfromsubdirs;
 		}
 
 		// This cleans everything up
@@ -284,10 +285,10 @@ namespace CodeImp.DoomBuilder.Controls
 		}
 
 		//mxd
-		private void showtexturesize_CheckedChanged(object sender, EventArgs e)
+		private void showsubdirtextures_CheckedChanged(object sender, EventArgs e)
 		{
-			showtexturesizes = showtexturesize.Checked;
-			list.Invalidate();
+			showtexturesfromsubdirs = showsubdirtextures.Checked;
+			RefillList(false);
 		}
 		
 		#endregion
@@ -438,12 +439,15 @@ namespace CodeImp.DoomBuilder.Controls
 		}
 		
 		// This begins adding items
-		public void BeginAdding(bool keepselectedindex)
+		public void BeginAdding(bool keepselectedindex) { BeginAdding(0, keepselectedindex); } //mxd
+		public void BeginAdding(int selectedlevel, bool keepselectedindex)
 		{
 			if(keepselectedindex && (list.SelectedItems.Count > 0))
 				keepselected = list.SelectedIndices[0];
 			else
 				keepselected = -1;
+
+			currentlevel = selectedlevel;
 			
 			// Clean list
 			items.Clear();
@@ -559,6 +563,7 @@ namespace CodeImp.DoomBuilder.Controls
 				if(mixMode == 1 && item.Icon.IsFlat) return false;
 				if(mixMode == 2 && !item.Icon.IsFlat) return false;
 				if(mixMode == 3 && (browseFlats != item.Icon.IsFlat)) return false;
+				if(!showtexturesfromsubdirs && currentlevel > 0 && item.Icon.Level > currentlevel) return false;
 			}
 
 			return item.Text.ToUpperInvariant().Contains(objectname.Text.ToUpperInvariant());
diff --git a/Source/Core/Controls/ImageBrowserItem.cs b/Source/Core/Controls/ImageBrowserItem.cs
index 67c2b0222..5bbb35810 100644
--- a/Source/Core/Controls/ImageBrowserItem.cs
+++ b/Source/Core/Controls/ImageBrowserItem.cs
@@ -131,7 +131,7 @@ namespace CodeImp.DoomBuilder.Controls
 			forecolor.Dispose();
 
 			//mxd. Draw size label?
-			if(ImageBrowserControl.ShowTextureSizes && !string.IsNullOrEmpty(imagesize))
+			if(General.Settings.ShowTextureSizes && !string.IsNullOrEmpty(imagesize))
 			{
 				// Setup
 				Font sizefont = new Font(this.ListView.Font.FontFamily, this.ListView.Font.SizeInPoints - 1);
diff --git a/Source/Core/Controls/ImageSelectorControl.cs b/Source/Core/Controls/ImageSelectorControl.cs
index 374409dbb..65470cdaa 100644
--- a/Source/Core/Controls/ImageSelectorControl.cs
+++ b/Source/Core/Controls/ImageSelectorControl.cs
@@ -172,6 +172,12 @@ namespace CodeImp.DoomBuilder.Controls
 			ShowPreview(FindImage(name.Text));
 			base.Refresh();
 		}
+
+		//mxd
+		public void StopUpdate()
+		{
+			timer.Stop();
+		}
 		
 		// This redraws the image preview
 		private void ShowPreview(Image image)
diff --git a/Source/Core/Data/DataManager.cs b/Source/Core/Data/DataManager.cs
index 3e2ee9bd9..2ae70038a 100644
--- a/Source/Core/Data/DataManager.cs
+++ b/Source/Core/Data/DataManager.cs
@@ -226,9 +226,8 @@ namespace CodeImp.DoomBuilder.Data
 				whitetexture = null;
 				unknownimage.Dispose(); //mxd
 				unknownimage = null; //mxd
-				foreach (ImageData data in commenttextures) data.Dispose(); //mxd
-				modeldefentries = null;//mxd
-				mapinfo = null;
+				foreach(ImageData i in commenttextures) i.Dispose(); //mxd
+				commenttextures = null;
 				
 				// Done
 				isdisposed = true;
@@ -505,13 +504,9 @@ namespace CodeImp.DoomBuilder.Data
 			foreach(KeyValuePair<long, ImageData> i in sprites) i.Value.Dispose();
 			palette = null;
 
-			//mxd
-			if (modeldefentries != null) 
-			{
-				foreach (KeyValuePair<int, ModelData> group in modeldefentries) 
-					group.Value.Dispose();
-			}
-			
+			//mxd. Dispose models
+			foreach(KeyValuePair<int, ModelData> i in modeldefentries) i.Value.Dispose();
+		
 			// Dispose containers
 			foreach(DataReader c in containers) c.Dispose();
 			containers.Clear();
@@ -522,10 +517,12 @@ namespace CodeImp.DoomBuilder.Data
 			textures = null;
 			flats = null;
 			sprites = null;
+			modeldefentries = null;//mxd
 			texturenames = null;
 			flatnames = null;
 			imageque = null;
 			internalsprites = null;
+			mapinfo = null; //mxd
 		}
 		
 		#endregion
diff --git a/Source/Core/Data/DynamicBitmapImage.cs b/Source/Core/Data/DynamicBitmapImage.cs
index 33db85f22..5cb9c2880 100644
--- a/Source/Core/Data/DynamicBitmapImage.cs
+++ b/Source/Core/Data/DynamicBitmapImage.cs
@@ -45,8 +45,15 @@ namespace CodeImp.DoomBuilder.Data
 		// Disposer
 		public override void Dispose()
 		{
-			General.Map.Graphics.UnregisterResource(this);
-			base.Dispose();
+			// Not already disposed?
+			if(!isdisposed)
+			{
+				// Clean up
+				General.Map.Graphics.UnregisterResource(this);
+
+				// Done
+				base.Dispose();
+			}
 		}
 
 		#endregion
diff --git a/Source/Core/Data/FileImage.cs b/Source/Core/Data/FileImage.cs
index 1c551fc80..5f10bc36f 100644
--- a/Source/Core/Data/FileImage.cs
+++ b/Source/Core/Data/FileImage.cs
@@ -127,8 +127,9 @@ namespace CodeImp.DoomBuilder.Data
 				hasLongName = true;
 			}
 
-			this.longname = Lump.MakeLongName(this.name, uselongtexturenames); //mxd
+			this.longname = Lump.MakeLongName(this.name, uselongtexturenames);
 			this.fullname = filepathname;
+			this.level = virtualname.Split(new[] { Path.AltDirectorySeparatorChar }).Length - 1;
 
 			if(General.Settings.CapitalizeTextureNames && !string.IsNullOrEmpty(this.displayname))
 			{
diff --git a/Source/Core/Data/HighResImage.cs b/Source/Core/Data/HighResImage.cs
index bcdf9f44e..830078c98 100644
--- a/Source/Core/Data/HighResImage.cs
+++ b/Source/Core/Data/HighResImage.cs
@@ -52,7 +52,8 @@ namespace CodeImp.DoomBuilder.Data
 
 			//mxd
 			SetName(name);
-			this.virtualname = "[TEXTURES]/" + (!string.IsNullOrEmpty(virtualpath) ? virtualpath + "/" : "") + this.name;
+			this.virtualname = "[TEXTURES]" + Path.AltDirectorySeparatorChar + (!string.IsNullOrEmpty(virtualpath) ? virtualpath + Path.AltDirectorySeparatorChar : "") + this.name;
+			this.level = virtualname.Split(new[] { Path.AltDirectorySeparatorChar }).Length - 1;
 			this.isFlat = isflat;
 			
 			// We have no destructor
diff --git a/Source/Core/Data/ImageData.cs b/Source/Core/Data/ImageData.cs
index 87c024d9d..6a34bea12 100644
--- a/Source/Core/Data/ImageData.cs
+++ b/Source/Core/Data/ImageData.cs
@@ -56,6 +56,7 @@ namespace CodeImp.DoomBuilder.Data
 		protected bool isFlat; //mxd. if false, it's a texture
 		protected bool hasLongName; //mxd. Texture name is longer than DataManager.CLASIC_IMAGE_NAME_LENGTH
 		protected bool hasPatchWithSameName; //mxd
+		protected int level; //mxd. Folder depth of this item
 		
 		// Loading
 		private volatile ImageLoadState previewstate;
@@ -111,7 +112,8 @@ namespace CodeImp.DoomBuilder.Data
 		public float ScaledHeight { get { return height * scale.y; } }
 		public Vector2D Scale { get { return scale; } }
 		public bool WorldPanning { get { return worldpanning; } }
-		
+		public int Level { get { return level; } } //mxd
+
 		#endregion
 
 		#region ================== Constructor / Disposer
diff --git a/Source/Core/Data/PK3FileImage.cs b/Source/Core/Data/PK3FileImage.cs
index 33718df3c..50bea90f4 100644
--- a/Source/Core/Data/PK3FileImage.cs
+++ b/Source/Core/Data/PK3FileImage.cs
@@ -93,6 +93,7 @@ namespace CodeImp.DoomBuilder.Data
 			this.longname = Lump.MakeLongName(this.name);
 			this.virtualname = filepathname.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
 			this.fullname = filepathname;
+			this.level = virtualname.Split(new[] { Path.AltDirectorySeparatorChar }).Length - 1;
 
 			if(General.Settings.CapitalizeTextureNames && !string.IsNullOrEmpty(this.displayname)) 
 			{
diff --git a/Source/Core/Editing/CustomThingsFilter.cs b/Source/Core/Editing/CustomThingsFilter.cs
index c3eb273ec..28d19bb5c 100644
--- a/Source/Core/Editing/CustomThingsFilter.cs
+++ b/Source/Core/Editing/CustomThingsFilter.cs
@@ -14,7 +14,7 @@
 
 #endregion
 
-#region ================== Namespaces
+/*#region ================== Namespaces
 
 using System;
 using System.Collections.Generic;
@@ -67,4 +67,4 @@ namespace CodeImp.DoomBuilder.Editing
 
 		#endregion
 	}
-}
+}*/
diff --git a/Source/Core/Editing/EditModeInfo.cs b/Source/Core/Editing/EditModeInfo.cs
index fbd4b5d65..07a0e0219 100644
--- a/Source/Core/Editing/EditModeInfo.cs
+++ b/Source/Core/Editing/EditModeInfo.cs
@@ -17,10 +17,10 @@
 #region ================== Namespaces
 
 using System;
+using System.Drawing;
 using System.IO;
 using CodeImp.DoomBuilder.Actions;
 using CodeImp.DoomBuilder.Plugins;
-using System.Drawing;
 using CodeImp.DoomBuilder.VisualModes;
 
 #endregion
@@ -37,18 +37,20 @@ namespace CodeImp.DoomBuilder.Editing
 
 		// Mode type
 		private Plugin plugin;
-		private Type type;
-		private EditModeAttribute attribs;
+		private readonly Type type;
+		private readonly EditModeAttribute attribs;
 		
 		// Mode switching
-		private BeginActionAttribute switchactionattr;
+		private readonly BeginActionAttribute switchactionattr;
 		private ActionDelegate switchactiondel;
 
 		// Mode button
-		private Stream buttonimagestream;
-		private Image buttonimage;
-		private string buttondesc;
-		private int buttonorder = int.MaxValue;
+		private readonly Image buttonimage;
+		private readonly string buttondesc;
+		private readonly int buttonorder = int.MaxValue;
+
+		//mxd. Disposing
+		private bool isdisposed;
 		
 		#endregion
 
@@ -79,14 +81,16 @@ namespace CodeImp.DoomBuilder.Editing
 				switchactionattr = new BeginActionAttribute(attribs.SwitchAction);
 			
 			// Make button info
-			if(attr.ButtonImage != null)
+			if(!string.IsNullOrEmpty(attr.ButtonImage))
 			{
-				buttonimagestream = plugin.GetResourceStream(attr.ButtonImage);
-				if(buttonimagestream != null)
+				using(Stream stream = plugin.GetResourceStream(attr.ButtonImage))
 				{
-					buttonimage = Image.FromStream(buttonimagestream);
-					buttondesc = attr.DisplayName;
-					buttonorder = attr.ButtonOrder;
+					if(stream != null)
+					{
+						buttonimage = Image.FromStream(stream);
+						buttondesc = attr.DisplayName;
+						buttonorder = attr.ButtonOrder;
+					}
 				}
 			}
 			
@@ -97,13 +101,19 @@ namespace CodeImp.DoomBuilder.Editing
 		// Disposer
 		public void Dispose()
 		{
-			// Dispose
-			UnbindSwitchAction();
-			buttonimage.Dispose();
-			buttonimagestream.Dispose();
+			// Not already disposed?
+			if(!isdisposed)
+			{
+				// Dispose
+				UnbindSwitchAction();
+				if(buttonimage != null) buttonimage.Dispose();
+
+				// Clean up
+				plugin = null;
 
-			// Clean up
-			plugin = null;
+				// Done
+				isdisposed = true;
+			}
 		}
 		
 		#endregion
diff --git a/Source/Core/Editing/EditingManager.cs b/Source/Core/Editing/EditingManager.cs
index bd1b7df68..4b7e3b58c 100644
--- a/Source/Core/Editing/EditingManager.cs
+++ b/Source/Core/Editing/EditingManager.cs
@@ -126,6 +126,7 @@ namespace CodeImp.DoomBuilder.Editing
 				General.Actions.UnbindMethods(this);
 				
 				// Clean up
+				foreach(EditModeInfo i in allmodes) i.Dispose(); //mxd
 				
 				// Done
 				isdisposed = true;
diff --git a/Source/Core/Editing/ThingsFilter.cs b/Source/Core/Editing/ThingsFilter.cs
index c1c7b141b..75926524c 100644
--- a/Source/Core/Editing/ThingsFilter.cs
+++ b/Source/Core/Editing/ThingsFilter.cs
@@ -127,13 +127,14 @@ namespace CodeImp.DoomBuilder.Editing
 			forbiddenfields = new List<string>(f.forbiddenfields);
 			
 			AdjustForMapFormat();
+			
+			// We have no destructor
+			GC.SuppressFinalize(this);
 		}
 		
 		// Constructor for filter from configuration
 		internal ThingsFilter(Configuration cfg, string path)
 		{
-			IDictionary fields;
-			
 			// Initialize
 			requiredfields = new List<string>();
 			forbiddenfields = new List<string>();
@@ -156,7 +157,7 @@ namespace CodeImp.DoomBuilder.Editing
 			// Read flags
 			// key is string, value must be boolean which indicates if
 			// its a required field (true) or forbidden field (false).
-			fields = cfg.ReadSetting(path + ".fields", new Hashtable());
+			IDictionary fields = cfg.ReadSetting(path + ".fields", new Hashtable());
 			foreach(DictionaryEntry de in fields)
 			{
 				// Add to the corresponding list
diff --git a/Source/Core/GZBuilder/Data/LinksCollector.cs b/Source/Core/GZBuilder/Data/LinksCollector.cs
index 68975788f..c49cf9dc6 100644
--- a/Source/Core/GZBuilder/Data/LinksCollector.cs
+++ b/Source/Core/GZBuilder/Data/LinksCollector.cs
@@ -89,13 +89,14 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
 			SpecialThings result = new SpecialThings();
 
 			// Process oh so special things
-			foreach (Thing t in things)
+			foreach(Thing t in things)
 			{
-				ThingTypeInfo info = General.Map.Data.GetThingInfo(t.Type);
+				ThingTypeInfo info = General.Map.Data.GetThingInfoEx(t.Type);
+				if(info == null) continue;
 				switch (info.ClassName.ToLowerInvariant())
 				{
 					case "patrolpoint":
-						if(t.Args[0] != 0)
+						if(t.Tag != 0 || t.Args[0] != 0)
 						{
 							if(!result.PatrolPoints.ContainsKey(t.Tag)) result.PatrolPoints.Add(t.Tag, new List<Thing>());
 							result.PatrolPoints[t.Tag].Add(t);
@@ -129,7 +130,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
 			// We may need all of these actors...
 			foreach (Thing t in General.Map.Map.Things)
 			{
-				ThingTypeInfo info = General.Map.Data.GetThingInfo(t.Type);
+				ThingTypeInfo info = General.Map.Data.GetThingInfoEx(t.Type);
+				if(info == null) continue;
 				switch (info.ClassName.ToLowerInvariant())
 				{
 					case "interpolationpoint":
diff --git a/Source/Core/GZBuilder/Data/ModelData.cs b/Source/Core/GZBuilder/Data/ModelData.cs
index e09c3e75b..729609d04 100644
--- a/Source/Core/GZBuilder/Data/ModelData.cs
+++ b/Source/Core/GZBuilder/Data/ModelData.cs
@@ -36,6 +36,9 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
 
 		internal bool IsVoxel;
 
+		// Disposing
+		private bool isdisposed;
+
 		public ModelLoadState LoadState { get { return loadstate; } internal set { loadstate = value; } }
 
 		#endregion
@@ -52,11 +55,19 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
 
 		internal void Dispose() 
 		{
-			if (Model != null) 
+			// Not already disposed?
+			if(!isdisposed) 
 			{
-				foreach (Mesh mesh in Model.Meshes) mesh.Dispose();
-				foreach (Texture t in Model.Textures) t.Dispose();
-				loadstate = ModelLoadState.None;
+				// Clean up
+				if(Model != null)
+				{
+					foreach (Mesh mesh in Model.Meshes) mesh.Dispose();
+					foreach (Texture t in Model.Textures) t.Dispose();
+					loadstate = ModelLoadState.None;
+				}
+
+				// Done
+				isdisposed = true;
 			}
 		}
 
diff --git a/Source/Core/General/FileLockChecker.cs b/Source/Core/General/FileLockChecker.cs
index a4f4d6e62..1e6c6268e 100644
--- a/Source/Core/General/FileLockChecker.cs
+++ b/Source/Core/General/FileLockChecker.cs
@@ -117,6 +117,7 @@ namespace CodeImp.DoomBuilder
 			int res = RmStartSession(out handle, 0, key);
 			if(res != 0)
 			{
+				RmEndSession(handle); //mxd
 				result.Error = errorstart + "Error " + res + ". Could not begin restart session. Unable to determine file locker."; //mxd
 				return result;
 			}
diff --git a/Source/Core/General/General.cs b/Source/Core/General/General.cs
index 403c79cfb..13e1854fe 100644
--- a/Source/Core/General/General.cs
+++ b/Source/Core/General/General.cs
@@ -1025,18 +1025,15 @@ namespace CodeImp.DoomBuilder
 				
 				// Save settings configuration
 				if(!General.NoSettings)
-				{
-					General.WriteLogLine("Saving program configuration...");
 					settings.Save(Path.Combine(settingspath, SETTINGS_FILE));
-				}
 				
 				// Clean up
-				if(map != null) map.Dispose(); map = null;
-				if(editing != null) editing.Dispose(); editing = null;
-				if(mainwindow != null) mainwindow.Dispose();
-				if(actions != null) actions.Dispose();
-				if(plugins != null) plugins.Dispose();
-				if(types != null) types.Dispose();
+				if(map != null) { map.Dispose(); map = null; }
+				if(editing != null) { editing.Dispose(); editing = null; }
+				if(mainwindow != null) { mainwindow.Dispose(); mainwindow = null; }
+				if(actions != null) { actions.Dispose(); actions = null; }
+				if(plugins != null) { plugins.Dispose(); plugins = null; }
+				if(types != null) { types.Dispose(); types = null; }
 				try { D3DDevice.Terminate(); } catch(Exception) { }
 
 				// Application ends here and now
@@ -1266,6 +1263,9 @@ namespace CodeImp.DoomBuilder
 			
 			Cursor.Current = Cursors.WaitCursor;
 
+			// Let the plugins know
+			plugins.OnMapCloseBegin();
+
 			// Clear the display
 			mainwindow.ClearDisplay();
 			mainwindow.RemoveHintsDocker(); //mxd
@@ -1274,6 +1274,7 @@ namespace CodeImp.DoomBuilder
 			map.CloseScriptEditor(false);
 
 			// Let the plugins know
+			plugins.OnMapCloseEnd();
 			plugins.OnMapOpenBegin();
 
 			// Clear old errors
diff --git a/Source/Core/IO/DoomFlatReader.cs b/Source/Core/IO/DoomFlatReader.cs
index 41f8f8f7e..30dbc41cd 100644
--- a/Source/Core/IO/DoomFlatReader.cs
+++ b/Source/Core/IO/DoomFlatReader.cs
@@ -164,7 +164,7 @@ namespace CodeImp.DoomBuilder.IO
 		// Returns null on failure
 		private PixelColorBlock ReadAsPixelData(Stream stream, out int width, out int height)
 		{
-			new BinaryReader(stream);
+			//new BinaryReader(stream);
 			PixelColorBlock pixeldata;
 			float sqrlength;
 			byte[] bytes;
diff --git a/Source/Core/Map/MapElement.cs b/Source/Core/Map/MapElement.cs
index c5259c49f..43fd3a593 100644
--- a/Source/Core/Map/MapElement.cs
+++ b/Source/Core/Map/MapElement.cs
@@ -72,12 +72,15 @@ namespace CodeImp.DoomBuilder.Map
 		// Disposer
 		public virtual void Dispose()
 		{
-			// Clean up
-			fields.Owner = null;
-			fields = null;
-			
-			// Done
-			isdisposed = true;
+			if(!isdisposed)
+			{
+				// Clean up
+				fields.Owner = null;
+				fields = null;
+
+				// Done
+				isdisposed = true;
+			}
 		}
 
 		#endregion
diff --git a/Source/Core/Map/MapSet.cs b/Source/Core/Map/MapSet.cs
index 57a7363be..776f163e7 100644
--- a/Source/Core/Map/MapSet.cs
+++ b/Source/Core/Map/MapSet.cs
@@ -2746,26 +2746,26 @@ namespace CodeImp.DoomBuilder.Map
 			Thing closest = null;
 			float distance = float.MaxValue;
 			float size = float.MaxValue; //mxd
-			float d, px, py, s;
+			float d, px, py, ts;
 
 			// Go for all things in selection
 			foreach(Thing t in selection)
 			{
 				px = t.Position.x;
 				py = t.Position.y;
+				ts = ((t.FixedSize && General.Map.Renderer2D.Scale > 1.0f) ? t.Size / General.Map.Renderer2D.Scale : t.Size); //mxd
 
 				//mxd. Within range?
-				if(px < range.Left - t.Size || px > range.Right + t.Size || py < range.Top - t.Size || py > range.Bottom + t.Size) continue;
+				if(px < range.Left - ts || px > range.Right + ts || py < range.Top - ts || py > range.Bottom + ts) continue;
 
 				// Closer than previous find? mxd. Or smaller when distance is the same?
 				d = Math.Abs(px - pos.x) + Math.Abs(py - pos.y);
-				s = ((t.FixedSize && General.Map.Renderer2D.Scale > 1.0f) ? t.Size / General.Map.Renderer2D.Scale : t.Size); //mxd
-				if(d < distance || (d == distance && s < size))
+				if(d < distance || (d == distance && ts < size))
 				{
 					// This one is closer
 					closest = t;
 					distance = d;
-					size = s; //mxd
+					size = ts; //mxd
 				}
 			}
 
diff --git a/Source/Core/Map/SelectableElement.cs b/Source/Core/Map/SelectableElement.cs
index 7f6aaa1b2..74f54a97b 100644
--- a/Source/Core/Map/SelectableElement.cs
+++ b/Source/Core/Map/SelectableElement.cs
@@ -47,11 +47,15 @@ namespace CodeImp.DoomBuilder.Map
 		// Disposer
 		public override void Dispose()
 		{
-			// Remove from selection
-			if(selected) Selected = false;
-			
-			// Done
-			base.Dispose();
+			// Not already disposed?
+			if(!isdisposed)
+			{
+				// Remove from selection
+				if(selected) Selected = false;
+
+				// Done
+				base.Dispose();
+			}
 		}
 		
 		#endregion
diff --git a/Source/Core/Windows/ChangeMapForm.cs b/Source/Core/Windows/ChangeMapForm.cs
index 26a53b4a9..b6d601800 100644
--- a/Source/Core/Windows/ChangeMapForm.cs
+++ b/Source/Core/Windows/ChangeMapForm.cs
@@ -200,6 +200,7 @@ namespace CodeImp.DoomBuilder.Windows
 			//TODO: are there other settings which should stay unchanged?..
 			MapOptions newoptions = new MapOptions(mapsettings, mapslist.SelectedItems[0].Text, options.UseLongTextureNames);
 			newoptions.ConfigFile = options.ConfigFile;
+			newoptions.ScriptCompiler = options.ScriptCompiler;
 			options = newoptions;
 			
 			// Hide window
diff --git a/Source/Core/Windows/MainForm.cs b/Source/Core/Windows/MainForm.cs
index ef6998beb..41ed94de1 100644
--- a/Source/Core/Windows/MainForm.cs
+++ b/Source/Core/Windows/MainForm.cs
@@ -53,14 +53,8 @@ namespace CodeImp.DoomBuilder.Windows
 		
 		// Recent files
 		private const int MAX_RECENT_FILES_PIXELS = 250;
-
-		// Dockers
-		//private const int DOCKER_TAB_WIDTH = 20;
 		
 		// Status bar
-		private const string STATUS_READY_TEXT = "Ready.";
-		private const string STATUS_NO_SELECTION_TEXT = "Nothing selected."; //mxd
-		private const string STATUS_LOADING_TEXT = "Loading resources...";
 		private const int WARNING_FLASH_COUNT = 10;
 		private const int WARNING_FLASH_INTERVAL = 100;
 		private const int WARNING_RESET_DELAY = 5000;
@@ -160,7 +154,6 @@ namespace CodeImp.DoomBuilder.Windows
 		private StatusInfo status;
 		private int statusflashcount;
 		private bool statusflashicon;
-		private string selectioninfo = STATUS_NO_SELECTION_TEXT; //mxd
 		
 		// Properties
 		private IntPtr windowptr;
@@ -798,11 +791,8 @@ namespace CodeImp.DoomBuilder.Windows
 		public void DisplayStatus(StatusType type, string message) { DisplayStatus(new StatusInfo(type, message)); }
 		public void DisplayStatus(StatusInfo newstatus)
 		{
-			//mxd. New message is the same as the one being displayed?
-			if(newstatus.type != StatusType.Ready && status.displayed && newstatus.type == status.type && newstatus.message == status.message) return;
-			
 			// Stop timers
-			if(newstatus.type != StatusType.Selection && !newstatus.displayed) //mxd
+			if(!newstatus.displayed)
 			{
 				statusresetter.Stop();
 				statusflasher.Stop();
@@ -812,35 +802,12 @@ namespace CodeImp.DoomBuilder.Windows
 			// Determine what to do specifically for this status type
 			switch(newstatus.type)
 			{
-				// When no particular information is to be displayed.
-				// The messages displayed depends on running background processes.
-				case StatusType.Ready:
-					if((General.Map != null) && (General.Map.Data != null)) 
-					{
-						newstatus.message = General.Map.Data.IsLoading ? STATUS_LOADING_TEXT : selectioninfo;
-					} 
-					else 
-					{
-						newstatus.message = STATUS_READY_TEXT;
-					}
-					break;
-
-				case StatusType.Selection: //mxd
-					if(statusresetter.Enabled) //don't change the message right now if info or warning is displayed
-					{ 
-						selectioninfo = (string.IsNullOrEmpty(newstatus.message) ? STATUS_NO_SELECTION_TEXT : newstatus.message);
-						return;
-					}
-					if(string.IsNullOrEmpty(newstatus.message)) newstatus.message = STATUS_NO_SELECTION_TEXT;
-					if(selectioninfo == newstatus.message) return; // Selection info didn't change
-					selectioninfo = newstatus.message;
-					break;
-
 				// Shows information without flashing the icon.
+				case StatusType.Ready: //mxd
+				case StatusType.Selection: //mxd
 				case StatusType.Info:
 					if(!newstatus.displayed)
 					{
-						newstatus.message = selectioninfo + " " + newstatus.message; //mxd
 						statusresetter.Interval = INFO_RESET_DELAY;
 						statusresetter.Start();
 					}
@@ -850,7 +817,6 @@ namespace CodeImp.DoomBuilder.Windows
 				case StatusType.Action:
 					if(!newstatus.displayed)
 					{
-						newstatus.message = selectioninfo + " " + newstatus.message; //mxd
 						statusflashicon = true;
 						statusflasher.Interval = ACTION_FLASH_INTERVAL;
 						statusflashcount = ACTION_FLASH_COUNT;
@@ -864,7 +830,6 @@ namespace CodeImp.DoomBuilder.Windows
 				case StatusType.Warning:
 					if(!newstatus.displayed)
 					{
-						newstatus.message = selectioninfo + " " + newstatus.message; //mxd
 						MessageBeep(MessageBeepType.Warning);
 						statusflasher.Interval = WARNING_FLASH_INTERVAL;
 						statusflashcount = WARNING_FLASH_COUNT;
@@ -878,7 +843,7 @@ namespace CodeImp.DoomBuilder.Windows
 			// Update status description
 			status = newstatus;
 			status.displayed = true;
-			statuslabel.Text = status.message;
+			statuslabel.Text = status.ToString(); //mxd. message -> ToString()
 			
 			// Update icon as well
 			UpdateStatusIcon();
diff --git a/Source/Core/Windows/PreferencesForm.cs b/Source/Core/Windows/PreferencesForm.cs
index 23b9f1e65..da66d6dd5 100644
--- a/Source/Core/Windows/PreferencesForm.cs
+++ b/Source/Core/Windows/PreferencesForm.cs
@@ -269,8 +269,8 @@ namespace CodeImp.DoomBuilder.Windows
 			General.Settings.ScreenshotsPath = screenshotsfolderpath.Text.Trim(); //mxd
 			
 			// Script font size
-			int fontsize = 8;
-			int.TryParse(scriptfontsize.Text, out fontsize);
+			int fontsize;
+			if(!int.TryParse(scriptfontsize.Text, out fontsize)) fontsize = 10;
 			General.Settings.ScriptFontSize = fontsize;
 			
 			// Apply control keys to actions
diff --git a/Source/Core/Windows/StatusInfo.cs b/Source/Core/Windows/StatusInfo.cs
index 776edfa69..ae69ba78a 100644
--- a/Source/Core/Windows/StatusInfo.cs
+++ b/Source/Core/Windows/StatusInfo.cs
@@ -22,19 +22,52 @@ namespace CodeImp.DoomBuilder.Windows
 {
 	public struct StatusInfo
 	{
-		public StatusType type;
-		public string message;
+		public const string NO_SELECTION = "Nothing selected."; //mxd
+		public const string LOADING_TEXT = "Loading resources...";
+		public const string READY_TEXT = "Ready.";
+		
+		public readonly StatusType type;
+		public readonly string message;
+		public readonly string selectioninfo; //mxd
 		internal bool displayed;
 		
 		internal StatusInfo(StatusType type, string message)
 		{
 			this.type = type;
-			this.message = message;
+
+			switch(type)
+			{
+				case StatusType.Selection:
+					this.selectioninfo = (string.IsNullOrEmpty(message) ? NO_SELECTION : message);
+					this.message = General.MainWindow.Status.message;
+					break;
+
+				case StatusType.Ready:
+					bool mapopened = (General.Map != null) && (General.Map.Data != null);
+					bool mapisloading = mapopened && General.Map.Data.IsLoading;
+					this.selectioninfo = ((string.IsNullOrEmpty(message) && mapopened) ? NO_SELECTION : message);
+					this.message = (mapisloading ? LOADING_TEXT : (mapopened ? string.Empty : READY_TEXT));
+					break;
+
+				default:
+					this.selectioninfo = (string.IsNullOrEmpty(message) ? NO_SELECTION : General.MainWindow.Status.selectioninfo);
+					this.message = message;
+					break;
+			}
+
 			this.displayed = false;
 		}
+
+		//mxd
+		public override string ToString()
+		{
+			if(string.IsNullOrEmpty(selectioninfo)) return message;
+			if(string.IsNullOrEmpty(message)) return selectioninfo;
+			return selectioninfo + " " + message;
+		}
 	}
 	
-	public enum StatusType : int
+	public enum StatusType
 	{
 		/// <summary>
 		/// When no particular information is to be displayed. The messages displayed depends on running background processes.
diff --git a/Source/Core/Windows/TextureBrowserForm.cs b/Source/Core/Windows/TextureBrowserForm.cs
index 22ae48c4b..ea090e253 100644
--- a/Source/Core/Windows/TextureBrowserForm.cs
+++ b/Source/Core/Windows/TextureBrowserForm.cs
@@ -66,7 +66,7 @@ namespace CodeImp.DoomBuilder.Windows
 			this.Text = "Browse " + imagetype;
 
 			// Setup texture browser
-			ImageBrowserControl.ShowTextureSizes = General.Settings.ReadSetting("browserwindow.showtexturesizes", General.Settings.ShowTextureSizes);
+			ImageBrowserControl.ShowTexturesFromSubDirectories = General.Settings.ReadSetting("browserwindow.showtexturesfromsubdirs", true);
 			ImageBrowserControl.UseLongTextureNames = General.Map.Options.UseLongTextureNames;
 			browser.BrowseFlats = browseflats;
 			browser.ApplySettings();
@@ -245,16 +245,8 @@ namespace CodeImp.DoomBuilder.Windows
 			//then - in current node
 			IFilledTextureSet set = (node.Tag as IFilledTextureSet);
 
-			if (browseflats)
-			{
-				foreach(ImageData img in set.Flats)
-					if(img.LongName == longname) return node;
-			}
-			else 
-			{
-				foreach(ImageData img in set.Textures)
-					if(img.LongName == longname) return node;
-			}
+			foreach(ImageData img in (browseflats ? set.Flats : set.Textures))
+				if(img.LongName == longname) return node;
 
 			return null;
 		}
@@ -306,9 +298,11 @@ namespace CodeImp.DoomBuilder.Windows
 				if (parts.Length == 1) continue;
 				int localindex = (parts[0] == "[TEXTURES]" ? 8 : imageIndex);
 
-				for (int i = 0; i < parts.Length - 1; i++) 
+				string category = set.Name;
+				for(int i = 0; i < parts.Length - 1; i++) 
 				{
-					string category = parts[i];
+					//string category = parts[i];
+					category += (Path.DirectorySeparatorChar + parts[i]);
 					
 					//already got such category?
 					if (curNode.Nodes.Count > 0 && curNode.Nodes.ContainsKey(category)) 
@@ -316,18 +310,19 @@ namespace CodeImp.DoomBuilder.Windows
 						curNode = curNode.Nodes[category];
 					} 
 					else //create a new one
-					{ 
-						TreeNode n = new TreeNode(category) { Name = category, ImageIndex = localindex, SelectedImageIndex = localindex };
+					{
+						TreeNode n = new TreeNode(parts[i]) { Name = category, ImageIndex = localindex, SelectedImageIndex = localindex };
 
 						curNode.Nodes.Add(n);
 						curNode = n;
 
 						ResourceTextureSet ts = new ResourceTextureSet(category, set.Location);
+						ts.Level = i + 1;
 						curNode.Tag = ts;
 					}
 
 					//add to current and parent nodes
-					if (i == parts.Length - 2) 
+					if(i == parts.Length - 2) 
 					{
 						TreeNode cn = curNode;
 						while (cn != root) 
@@ -343,12 +338,13 @@ namespace CodeImp.DoomBuilder.Windows
 				}
 			}
 
-			if (root.Nodes.Count == 1 && root.Nodes[0].Nodes.Count > 0) 
+			if(root.Nodes.Count == 1 && root.Nodes[0].Nodes.Count > 0) 
 			{
 				TreeNode[] children = new TreeNode[root.Nodes[0].Nodes.Count];
 				root.Nodes[0].Nodes.CopyTo(children, 0);
 				root.Nodes.Clear();
 				root.Nodes.AddRange(children);
+				((ResourceTextureSet)root.Tag).Level++;
 			}
 
 			foreach (TreeNode n in root.Nodes) SetItemsCount(n);
@@ -476,7 +472,7 @@ namespace CodeImp.DoomBuilder.Windows
 				General.Settings.WriteSetting("browserwindow.textureset", tvTextureSets.SelectedNodes[0].Name);
 
 			//mxd. Save ImageBrowserControl settings
-			General.Settings.WriteSetting("browserwindow.showtexturesizes", ImageBrowserControl.ShowTextureSizes);
+			General.Settings.WriteSetting("browserwindow.showtexturesfromsubdirs", ImageBrowserControl.ShowTexturesFromSubDirectories);
 			if(General.Map.Config.UseLongTextureNames) General.Map.Options.UseLongTextureNames = ImageBrowserControl.UseLongTextureNames;
 			
 			// Clean up
@@ -507,7 +503,7 @@ namespace CodeImp.DoomBuilder.Windows
 			IFilledTextureSet set = (selectedset.Tag as IFilledTextureSet);
 
 			// Start adding
-			browser.BeginAdding(false);
+			browser.BeginAdding(set.Level, false); //mxd. Pass current folder level
 
 			if (browseflats) 
 			{
diff --git a/Source/Plugins/BuilderEffects/BuilderEffects.csproj b/Source/Plugins/BuilderEffects/BuilderEffects.csproj
index 823ac1720..12ad1d6a3 100644
--- a/Source/Plugins/BuilderEffects/BuilderEffects.csproj
+++ b/Source/Plugins/BuilderEffects/BuilderEffects.csproj
@@ -33,6 +33,14 @@
     <WarningLevel>4</WarningLevel>
     <PlatformTarget>x86</PlatformTarget>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;PROFILE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core">
diff --git a/Source/Plugins/BuilderModes/BuilderModes.csproj b/Source/Plugins/BuilderModes/BuilderModes.csproj
index 8c67545df..fbd5436e0 100644
--- a/Source/Plugins/BuilderModes/BuilderModes.csproj
+++ b/Source/Plugins/BuilderModes/BuilderModes.csproj
@@ -34,6 +34,15 @@
     <PlatformTarget>x86</PlatformTarget>
     <ErrorReport>prompt</ErrorReport>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;PROFILE</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core">
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs
index 946d5f48b..0a5375947 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs
@@ -54,8 +54,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		public override void Dispose() 
 		{
-			if(!isdisposed && hintlabel != null) hintlabel.Dispose();
-			base.Dispose();
+			// Not already disposed?
+			if(!isdisposed)
+			{
+				// Clean up
+				if(hintlabel != null) hintlabel.Dispose();
+
+				// Done
+				base.Dispose();
+			}
 		}
 
 		#endregion
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
index 0c1b075c3..7d21e7be9 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
@@ -61,9 +61,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 		public override void Dispose() 
 		{
-			if (!isdisposed && hintlabel != null) hintlabel.Dispose();
+			// Not already disposed?
+			if(!isdisposed)
+			{
+				// Clean up
+				if(hintlabel != null) hintlabel.Dispose();
 
-			base.Dispose();
+				// Done
+				base.Dispose();
+			}
 		}
 
 		#endregion
diff --git a/Source/Plugins/BuilderModes/General/BuilderPlug.cs b/Source/Plugins/BuilderModes/General/BuilderPlug.cs
index 9021796b9..5d8bf0dfb 100644
--- a/Source/Plugins/BuilderModes/General/BuilderPlug.cs
+++ b/Source/Plugins/BuilderModes/General/BuilderPlug.cs
@@ -439,6 +439,13 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			drawingOverridesPanel.Setup();
 			General.Map.Renderer2D.UpdateExtraFloorFlag(); //mxd
 		}
+
+		//mxd
+		public override void OnMapCloseBegin()
+		{
+			drawingOverridesPanel.Terminate();
+			General.Interface.RemoveDocker(drawingOverridesDocker);
+		}
 		
 		// Map closed
 		public override void OnMapCloseEnd()
@@ -446,9 +453,6 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			base.OnMapCloseEnd();
 			undoredopanel.UpdateList();
 
-			//mxd
-			General.Interface.RemoveDocker(drawingOverridesDocker);
-
 			//mxd. Save settings
 			SaveUISettings();
 		}
diff --git a/Source/Plugins/BuilderModes/Interface/SectorDrawingOptionsPanel.cs b/Source/Plugins/BuilderModes/Interface/SectorDrawingOptionsPanel.cs
index 3207c5e2e..2a8bda0a2 100644
--- a/Source/Plugins/BuilderModes/Interface/SectorDrawingOptionsPanel.cs
+++ b/Source/Plugins/BuilderModes/Interface/SectorDrawingOptionsPanel.cs
@@ -54,6 +54,15 @@ namespace CodeImp.DoomBuilder.BuilderModes.Interface
 			brightness.Enabled = cbBrightness.Checked;
 		}
 
+		internal void Terminate()
+		{
+			ceiling.StopUpdate();
+			floor.StopUpdate();
+			top.StopUpdate();
+			middle.StopUpdate();
+			bottom.StopUpdate();
+		}
+
 		#endregion
 
 		#region ================== Checkbox Events
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
index 439cd9498..30c64a9ea 100644
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualThing.cs
@@ -335,9 +335,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 					sprite.RemoveReference();
 					sprite = null;
 				}
+
+				base.Dispose();
 			}
-			
-			base.Dispose();
 		}
 		
 		#endregion
diff --git a/Source/Plugins/ColorPicker/ColorPicker.csproj b/Source/Plugins/ColorPicker/ColorPicker.csproj
index cadfbb265..8c81aaced 100644
--- a/Source/Plugins/ColorPicker/ColorPicker.csproj
+++ b/Source/Plugins/ColorPicker/ColorPicker.csproj
@@ -34,6 +34,14 @@
     <PlatformTarget>x86</PlatformTarget>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;PROFILE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core">
diff --git a/Source/Plugins/CommentsPanel/CommentsPanel.csproj b/Source/Plugins/CommentsPanel/CommentsPanel.csproj
index 5b5e360e0..7fed6ff94 100644
--- a/Source/Plugins/CommentsPanel/CommentsPanel.csproj
+++ b/Source/Plugins/CommentsPanel/CommentsPanel.csproj
@@ -48,6 +48,15 @@
     <PlatformTarget>x86</PlatformTarget>
     <ErrorReport>prompt</ErrorReport>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;PROFILE</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core">
diff --git a/Source/Plugins/NodesViewer/NodesViewer.csproj b/Source/Plugins/NodesViewer/NodesViewer.csproj
index 8b4dca737..3f4bb6c7e 100644
--- a/Source/Plugins/NodesViewer/NodesViewer.csproj
+++ b/Source/Plugins/NodesViewer/NodesViewer.csproj
@@ -38,6 +38,16 @@
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <PlatformTarget>x86</PlatformTarget>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;PROFILE</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
   <ItemGroup>
     <Compile Include="BuilderPlug.cs" />
     <Compile Include="Node.cs" />
diff --git a/Source/Plugins/SoundPropagationMode/SoundPropagation.csproj b/Source/Plugins/SoundPropagationMode/SoundPropagation.csproj
index b73e5a8f8..14308a784 100644
--- a/Source/Plugins/SoundPropagationMode/SoundPropagation.csproj
+++ b/Source/Plugins/SoundPropagationMode/SoundPropagation.csproj
@@ -13,23 +13,6 @@
     <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-  </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
     <DebugSymbols>true</DebugSymbols>
     <OutputPath>..\..\..\Build\Plugins\</OutputPath>
@@ -46,6 +29,14 @@
     <PlatformTarget>x86</PlatformTarget>
     <ErrorReport>prompt</ErrorReport>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;PROFILE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core">
diff --git a/Source/Plugins/StairSectorBuilder/StairSectorBuilder.csproj b/Source/Plugins/StairSectorBuilder/StairSectorBuilder.csproj
index 498df6864..5f89217c5 100644
--- a/Source/Plugins/StairSectorBuilder/StairSectorBuilder.csproj
+++ b/Source/Plugins/StairSectorBuilder/StairSectorBuilder.csproj
@@ -32,6 +32,14 @@
     <PlatformTarget>x86</PlatformTarget>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;PROFILE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="Builder, Version=1.14.0.2201, Culture=neutral, processorArchitecture=x86">
       <SpecificVersion>False</SpecificVersion>
diff --git a/Source/Plugins/TagExplorer/TagExplorer.csproj b/Source/Plugins/TagExplorer/TagExplorer.csproj
index 8f2d7244d..0f1a9dc5b 100644
--- a/Source/Plugins/TagExplorer/TagExplorer.csproj
+++ b/Source/Plugins/TagExplorer/TagExplorer.csproj
@@ -32,6 +32,14 @@
     <PlatformTarget>x86</PlatformTarget>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;PROFILE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core">
diff --git a/Source/Plugins/TagRange/TagRange.csproj b/Source/Plugins/TagRange/TagRange.csproj
index be58a5586..451ba6d0c 100644
--- a/Source/Plugins/TagRange/TagRange.csproj
+++ b/Source/Plugins/TagRange/TagRange.csproj
@@ -33,6 +33,14 @@
     <PlatformTarget>x86</PlatformTarget>
     <ErrorReport>prompt</ErrorReport>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;PROFILE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core">
diff --git a/Source/Plugins/VisplaneExplorer/VisplaneExplorer.csproj b/Source/Plugins/VisplaneExplorer/VisplaneExplorer.csproj
index f196816a7..01a2bf059 100644
--- a/Source/Plugins/VisplaneExplorer/VisplaneExplorer.csproj
+++ b/Source/Plugins/VisplaneExplorer/VisplaneExplorer.csproj
@@ -37,6 +37,16 @@
     <UseVSHostingProcess>false</UseVSHostingProcess>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug + Profiler|x86' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>..\..\..\Build\Plugins\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;PROFILE</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core">
-- 
GitLab