From 59c4a75b114ed90dcec3373e92cfe5b8dd4a1781 Mon Sep 17 00:00:00 2001
From: MaxED <j.maxed@gmail.com>
Date: Wed, 15 Jun 2016 22:02:51 +0000
Subject: [PATCH] Added "Split Joined Sectors" Edit menu item and toolbar
 button. When enabled, joined sectors adjacent to drawn lines will be split.
 Added "doomthingrotationangles" Game Configuration property. When enabled,
 editor actions related to changing thing angle will snap the resulting angle
 to 45 degree increments. This property is set to true for vanilla game
 configurations. Fixed a crash when changing game configuration from one
 without Thing actions support to one with them while in Things mode. Fixed,
 cosmetic, DB2 bug: current editing mode button was deselected after reloading
 resources. Updated documentation ("Game Configuration - Basic Settings"
 page).

---
 Build/Configurations/Hexen_HexenHexen.cfg     |   3 ++
 Build/Configurations/Includes/Doom_common.cfg |   3 ++
 Help/gc_basicsettings.html                    |   6 ++-
 Source/Core/Builder.csproj                    |   1 +
 Source/Core/Config/GameConfiguration.cs       |   3 ++
 Source/Core/Config/ProgramConfiguration.cs    |   6 ++-
 Source/Core/Controls/AngleControlEx.cs        |   5 ++-
 Source/Core/General/MapManager.cs             |   8 +++-
 Source/Core/Properties/Resources.Designer.cs  |   9 ++++-
 Source/Core/Properties/Resources.resx         |   3 ++
 Source/Core/Resources/Actions.cfg             |  11 ++++++
 Source/Core/Resources/SplitSectors.png        | Bin 0 -> 1678 bytes
 Source/Core/Windows/MainForm.Designer.cs      |  30 +++++++++++++++
 Source/Core/Windows/MainForm.cs               |  13 +++++++
 Source/Core/Windows/ThingEditForm.cs          |  10 ++++-
 Source/Core/Windows/ThingEditFormUDMF.cs      |  10 ++++-
 .../Interface/JitterThingsForm.cs             |   8 +++-
 .../ClassicModes/DrawCurveMode.cs             |   2 +-
 .../ClassicModes/DrawGeometryMode.cs          |   2 +-
 .../BuilderModes/ClassicModes/DrawGridMode.cs |   2 +-
 .../ClassicModes/DrawRectangleMode.cs         |   2 +-
 .../ClassicModes/EditSelectionMode.cs         |  11 ++++--
 .../BuilderModes/ClassicModes/ThingsMode.cs   |  36 +++++++++++++-----
 .../VisualModes/BaseVisualMode.cs             |  15 +++++---
 24 files changed, 168 insertions(+), 31 deletions(-)
 create mode 100644 Source/Core/Resources/SplitSectors.png

diff --git a/Build/Configurations/Hexen_HexenHexen.cfg b/Build/Configurations/Hexen_HexenHexen.cfg
index 297acefb7..ac59c055b 100644
--- a/Build/Configurations/Hexen_HexenHexen.cfg
+++ b/Build/Configurations/Hexen_HexenHexen.cfg
@@ -32,6 +32,9 @@ include("Includes\\Game_Hexen.cfg");
 //mxd. No DECORATE support in vanilla
 decorategames = "";
 
+//mxd. Don't do vanilla-style thing rotation angle clamping
+doomthingrotationangles = false;
+
 // Default thing filters
 // (these are not required, just useful for new users)
 thingsfilters
diff --git a/Build/Configurations/Includes/Doom_common.cfg b/Build/Configurations/Includes/Doom_common.cfg
index b895513cf..b3f1d0cb4 100644
--- a/Build/Configurations/Includes/Doom_common.cfg
+++ b/Build/Configurations/Includes/Doom_common.cfg
@@ -17,6 +17,9 @@ common
   defaultflatscale = 1.0f;
   scaledtextureoffsets = true;
 
+  //mxd. Do vanilla-style thing rotation angle clamping
+  doomthingrotationangles = true;
+
   // Texture sources
   textures
   {
diff --git a/Help/gc_basicsettings.html b/Help/gc_basicsettings.html
index 8a9de024c..2474fcd28 100644
--- a/Help/gc_basicsettings.html
+++ b/Help/gc_basicsettings.html
@@ -145,9 +145,13 @@ damagetypes = "None BFGSplash Drowning Slime";
 	Arguments for the linedef action number to put on the lines when making a door.<br />
 	<br />
 	<b class="fat">doomlightlevels</b> (boolean)<br />
-	Set this to <b>false</b> to use linear lighting in Doom Builder. Normally Doom Builder uses a simulation of Doom's light levels. <br />
+	Set this to <b>false</b> to use linear lighting in Doom Builder. Normally Doom Builder uses a simulation of Doom's light levels.<br />
 	Default value is <b>true</b>.<br />
 	<br />
+	<b class="fat">doomthingrotationangles</b> (boolean) - <span class="red">GZDB only</span>.<br />
+	When set  to <b>true</b>, editor actions related to changing thing angle will snap the resulting angle to 45 degree increments.<br />
+	Default value is <b>false</b>.<br />
+	<br />
 	<b class="fat">start3dmode</b> (integer)<br />
 	Thing type number that Doom Builder will use to keep your Visual Mode camera position stored in the map. Doom Builder will place a single thing of this type in your map and move it along as you move in Visual Mode.<br />
 	<br />
diff --git a/Source/Core/Builder.csproj b/Source/Core/Builder.csproj
index 9087bcad3..9135c2ac7 100644
--- a/Source/Core/Builder.csproj
+++ b/Source/Core/Builder.csproj
@@ -1179,6 +1179,7 @@
     <None Include="Resources\ModelDisabled.png" />
     <None Include="Resources\ModelFiltered.png" />
     <Content Include="Resources\Model_selected.png" />
+    <None Include="Resources\SplitSectors.png" />
     <None Include="Resources\ScriptProperty.png" />
     <None Include="Resources\TextWhitespace.png" />
     <None Include="Resources\TextIndent.png" />
diff --git a/Source/Core/Config/GameConfiguration.cs b/Source/Core/Config/GameConfiguration.cs
index 7fb6807ae..28188dd15 100644
--- a/Source/Core/Config/GameConfiguration.cs
+++ b/Source/Core/Config/GameConfiguration.cs
@@ -85,6 +85,7 @@ namespace CodeImp.DoomBuilder.Config
 		private readonly int bottomboundary;
 		private readonly int safeboundary; //mxd
 		private readonly bool doomlightlevels;
+		private readonly bool doomthingrotationangles; //mxd
 		private readonly string actionspecialhelp; //mxd
 		private readonly string thingclasshelp; //mxd
 		private readonly bool sidedefcompressionignoresaction; //mxd
@@ -208,6 +209,7 @@ namespace CodeImp.DoomBuilder.Config
 		public int BottomBoundary { get { return bottomboundary; } }
 		public int SafeBoundary { get { return safeboundary; } } //mxd
 		public bool DoomLightLevels { get { return doomlightlevels; } }
+		public bool DoomThingRotationAngles { get { return doomthingrotationangles; } } //mxd. When set to true, thing rotation angles will be clamped to the nearest 45 deg increment
 		public string ActionSpecialHelp { get { return actionspecialhelp; } } //mxd
 		public string ThingClassHelp { get { return thingclasshelp; } } //mxd
 		internal bool SidedefCompressionIgnoresAction { get { return sidedefcompressionignoresaction; } } //mxd
@@ -360,6 +362,7 @@ namespace CodeImp.DoomBuilder.Config
 			bottomboundary = cfg.ReadSetting("bottomboundary", -32768);
 			safeboundary = cfg.ReadSetting("safeboundary", 32767); //mxd
 			doomlightlevels = cfg.ReadSetting("doomlightlevels", true);
+			doomthingrotationangles = cfg.ReadSetting("doomthingrotationangles", false); //mxd
 			actionspecialhelp = cfg.ReadSetting("actionspecialhelp", string.Empty); //mxd
 			thingclasshelp = cfg.ReadSetting("thingclasshelp", string.Empty); //mxd
 			sidedefcompressionignoresaction = cfg.ReadSetting("sidedefcompressionignoresaction", false); //mxd
diff --git a/Source/Core/Config/ProgramConfiguration.cs b/Source/Core/Config/ProgramConfiguration.cs
index 541e8b93b..1c1e9fd78 100644
--- a/Source/Core/Config/ProgramConfiguration.cs
+++ b/Source/Core/Config/ProgramConfiguration.cs
@@ -92,6 +92,7 @@ namespace CodeImp.DoomBuilder.Config
 		private bool keeptexturefilterfocused; //mxd
 		private SplitLineBehavior splitlinebehavior; //mxd
 		private MergeGeometryMode mergegeomode; //mxd
+		private bool splitjoinedsectors; //mxd
 		private bool usehighlight; //mxd
 		private bool switchviewmodes; //mxd
 
@@ -207,7 +208,8 @@ namespace CodeImp.DoomBuilder.Config
 		public bool KeepTextureFilterFocused { get { return keeptexturefilterfocused; } internal set { keeptexturefilterfocused = value; } } //mxd
 		public SplitLineBehavior SplitLineBehavior { get { return splitlinebehavior; } set { splitlinebehavior = value; } } //mxd
 		public MergeGeometryMode MergeGeometryMode { get { return mergegeomode; } internal set { mergegeomode = value; } } //mxd
-		
+		public bool SplitJoinedSectors { get { return splitjoinedsectors; } internal set { splitjoinedsectors = value; } } //mxd
+
 		//mxd. Highlight mode
 		public bool UseHighlight
 		{ 
@@ -356,6 +358,7 @@ namespace CodeImp.DoomBuilder.Config
 				keeptexturefilterfocused = cfg.ReadSetting("keeptexturefilterfocused", true); //mxd
 				splitlinebehavior = (SplitLineBehavior)General.Clamp(cfg.ReadSetting("splitlinebehavior", 0), 0, Enum.GetValues(typeof(SplitLineBehavior)).Length - 1); //mxd
 				mergegeomode = (MergeGeometryMode)General.Clamp(cfg.ReadSetting("mergegeometrymode", (int)MergeGeometryMode.REPLACE), 0, Enum.GetValues(typeof(MergeGeometryMode)).Length - 1); //mxd
+				splitjoinedsectors = cfg.ReadSetting("splitjoinedsectors", true); //mxd
 				usehighlight = cfg.ReadSetting("usehighlight", true); //mxd
 				switchviewmodes = cfg.ReadSetting("switchviewmodes", false); //mxd
 
@@ -474,6 +477,7 @@ namespace CodeImp.DoomBuilder.Config
 			cfg.WriteSetting("keeptexturefilterfocused", keeptexturefilterfocused); //mxd
 			cfg.WriteSetting("splitlinebehavior", (int)splitlinebehavior); //mxd
 			cfg.WriteSetting("mergegeometrymode", (int)mergegeomode); //mxd
+			cfg.WriteSetting("splitjoinedsectors", splitjoinedsectors); //mxd
 			cfg.WriteSetting("usehighlight", usehighlight); //mxd
 			cfg.WriteSetting("switchviewmodes", switchviewmodes); //mxd
 
diff --git a/Source/Core/Controls/AngleControlEx.cs b/Source/Core/Controls/AngleControlEx.cs
index 1cf2dd87a..3cb9889fc 100644
--- a/Source/Core/Controls/AngleControlEx.cs
+++ b/Source/Core/Controls/AngleControlEx.cs
@@ -26,6 +26,8 @@ namespace CodeImp.DoomBuilder.Controls
 		private const int markScaler = 5;
 		private Point origin;
 
+		private bool doomangleclamping;
+
 		//UI colors
 		private readonly Color fillColor = SystemColors.Window;
 		private readonly Color fillInactiveColor = SystemColors.Control;
@@ -44,6 +46,7 @@ namespace CodeImp.DoomBuilder.Controls
 
 		public int Angle { get { return (angle == NO_ANGLE ? NO_ANGLE : angle - angleoffset); } set { angle = (value == NO_ANGLE ? NO_ANGLE : value + angleoffset); this.Refresh(); } }
 		public int AngleOffset { get { return angleoffset; } set { angleoffset = value; this.Refresh(); } }
+		public bool DoomAngleClamping { get { return doomangleclamping; } set { doomangleclamping = value; } }
 		public const int NO_ANGLE = int.MinValue;
 
 		#endregion
@@ -189,7 +192,7 @@ namespace CodeImp.DoomBuilder.Controls
 			{
 				int thisAngle = XYToDegrees(new Point(e.X, e.Y), origin);
 
-				if(e.Button == MouseButtons.Left) 
+				if(e.Button == MouseButtons.Left || doomangleclamping) 
 				{
 					thisAngle = (int)Math.Round(thisAngle / 45f) * 45;
 					if(thisAngle == 360) thisAngle = 0;
diff --git a/Source/Core/General/MapManager.cs b/Source/Core/General/MapManager.cs
index 05a23000b..901320dea 100644
--- a/Source/Core/General/MapManager.cs
+++ b/Source/Core/General/MapManager.cs
@@ -2258,7 +2258,13 @@ namespace CodeImp.DoomBuilder
 			General.Plugins.ReloadResources();
 
 			// Inform editing mode that the resources are reloaded
-			if(General.Editing.Mode != null) General.Editing.Mode.OnReloadResources();
+			if(General.Editing.Mode != null)
+			{
+				General.Editing.Mode.OnReloadResources();
+
+				//mxd. Also Check appropriate button on interface
+				General.MainWindow.CheckEditModeButton(General.Editing.Mode.EditModeButtonName); 
+			}
 
 			// Reset status
 			General.MainWindow.DisplayStatus(oldstatus);
diff --git a/Source/Core/Properties/Resources.Designer.cs b/Source/Core/Properties/Resources.Designer.cs
index 086ad5f23..1c089b0e4 100644
--- a/Source/Core/Properties/Resources.Designer.cs
+++ b/Source/Core/Properties/Resources.Designer.cs
@@ -1,7 +1,7 @@
 //------------------------------------------------------------------------------
 // <auto-generated>
 //     This code was generated by a tool.
-//     Runtime Version:2.0.50727.5466
+//     Runtime Version:2.0.50727.5485
 //
 //     Changes to this file may cause incorrect behavior and will be lost if
 //     the code is regenerated.
@@ -963,6 +963,13 @@ namespace CodeImp.DoomBuilder.Properties {
             }
         }
         
+        internal static System.Drawing.Bitmap SplitSectors {
+            get {
+                object obj = ResourceManager.GetObject("SplitSectors", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
         internal static System.Drawing.Bitmap Status0 {
             get {
                 object obj = ResourceManager.GetObject("Status0", resourceCulture);
diff --git a/Source/Core/Properties/Resources.resx b/Source/Core/Properties/Resources.resx
index a114545da..afdf57b68 100644
--- a/Source/Core/Properties/Resources.resx
+++ b/Source/Core/Properties/Resources.resx
@@ -595,4 +595,7 @@
   <data name="MergeGeoRemoveLines" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\MergeGeoRemoveLines.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
+  <data name="SplitSectors" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\SplitSectors.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/Core/Resources/Actions.cfg b/Source/Core/Resources/Actions.cfg
index ff40bfa7a..ffb6cd7c7 100644
--- a/Source/Core/Resources/Actions.cfg
+++ b/Source/Core/Resources/Actions.cfg
@@ -507,6 +507,17 @@ toggleautomerge
 	allowscroll = true;
 }
 
+//mxd
+togglejoinedsectorssplitting
+{
+	title = "Split Joined Sectors";
+	category = "edit";
+	description = "When enabled, joined sectors adjacent to drawn lines will be split.";
+	allowkeys = true;
+	allowmouse = true;
+	allowscroll = true;
+}
+
 //mxd
 toggleautoclearsidetextures
 {
diff --git a/Source/Core/Resources/SplitSectors.png b/Source/Core/Resources/SplitSectors.png
new file mode 100644
index 0000000000000000000000000000000000000000..a259ed0498495e843c041c89af4f3bd2ceacd169
GIT binary patch
literal 1678
zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk?
zp1FzXsX?iUDV2pMQ*9U+nAI{vB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+*
zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn
zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxOgGuU%v{0TQqR!T
z+}y-mN5ROz&{W^RSl`${*T~q)#K6kLNC66zfVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj
z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5
zFD<cE0=g99h1>$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;Np<V
zf>iyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr7I$IMft0!ZY(y
z^2>`g!FqgstvvIJOA_;vQ$1a5m4K$`WoD*W85%em8=III1A&{Np{tpti<6s$i@B+>
zxuLU(iJK8juS<S%X>Mv>2~2MaLN7=&cD<nFkXrz>*(J3ovn(~mttdZN0qkw7Ox$iU
z#AzN>ZwhX=7~#~b4|I$^C~}b^8zuxyK_DhP=>j?M#Gjf6Oz}m)q<vqy`#J*y(?3ra
z$B>F!J%OG+!igev#;K<a?!Hx<?WU~c!SK4z&`{1I<Z<hZg95fvYrT8KEh3UT*o7W9
zMf>=~2=LBw=t+9i75KPGNN7n|WV5JKbk^;e+w6_!&b*&Fxvfd2=H&0~@9XdXzE{n1
zOoF4SVanWW%j`?9zp4v5h4;zWm@)lNOv&Q3)i}B~On9B{i{Fn|tgza5)6S;maMF><
zx!NCPpV~H`zaPBO#p__~ZKXGRl9=W93iC|W>tJ(N{Be-CY^%IZmFSb8BTYBYR@deE
zXnU|O_nG~JN$|gbgwAQknR5*uO<(XigCXTl{)gc3gl#Qnj=KDE{7~Ac(YYa|RM+RR
zkVf_fM*R~F&nKo#Iu|%$TI)T>f<5eC*o;L&t~u^67j}7M)X~+GGl^AnNm;WM<Gs(h
z6FdqwY$@RmdB48BotLrWSV~1v#kY7h&55SRcqPkb-%ZQdS@W?c`RuK)fqGmYBa)uo
zy1M%M?f2X5!xHp%Pnol(*#DWp2X>BcUsq@475=j_b#i&XxNqgVKEHgfpc<dTB|A*w
z8Do?@vsPXWa*aOA*X6!$&ZkeCZoH58jJ0sG?K~R4LSnDF43};7xuf^^nLiYB<V~F>
z@<jcS?-q@B0Z#*@m`=}HsZzh${ek83uzCmg=Yc|wTtP;XoTom$eHXLq=bZ-vv-2KR
zE}e2z=k+;J)#oKLbLDv4?>ekXWBXL{`0T?U;{3;$n>5aD`Sa=So79`{oMzcQ5%?kO
zwZhPM!<n?$+3kg~Ezk9@Y>c_CF|E`ya@xMue*s))T2dFq&s<=ld9p5C<IlCzMe*SV
zXZGc?)%wn2@J^cQGO0vfzhc{}5L0c*wD&9rPNX+}*C_ZS?4+;Ea`K&-<o0OMt@j0g
ztxA=6ylT;*t}h}iJ;x_WOj^BFs=U)Jct*%dA^n{Zll#S+#JZ3EV^VxywsqIejzquM
zxS*Il9gA9aXt=2_&M~-q<l3V}F;PO&SF=k08i-2=Th+bqRp8OM<8`QHdwoR7trv2U
s_qJY4u}Qg{^_g8DEBA|U%^&Rp3@2+EnEi!+{Q=bwp00i_>zopr0ARg>z5oCK

literal 0
HcmV?d00001

diff --git a/Source/Core/Windows/MainForm.Designer.cs b/Source/Core/Windows/MainForm.Designer.cs
index c0c5841b7..29a84ee2c 100644
--- a/Source/Core/Windows/MainForm.Designer.cs
+++ b/Source/Core/Windows/MainForm.Designer.cs
@@ -75,6 +75,7 @@ namespace CodeImp.DoomBuilder.Windows
 			this.itempastespecial = new System.Windows.Forms.ToolStripMenuItem();
 			this.itemsnaptogrid = new System.Windows.Forms.ToolStripMenuItem();
 			this.itemautomerge = new System.Windows.Forms.ToolStripMenuItem();
+			this.itemsplitjoinedsectors = new System.Windows.Forms.ToolStripMenuItem();
 			this.itemautoclearsidetextures = new System.Windows.Forms.ToolStripMenuItem();
 			this.seperatoreditgeometry = new System.Windows.Forms.ToolStripSeparator();
 			this.itemgridinc = new System.Windows.Forms.ToolStripMenuItem();
@@ -193,6 +194,7 @@ namespace CodeImp.DoomBuilder.Windows
 			this.buttontogglefixedthingsscale = new System.Windows.Forms.ToolStripButton();
 			this.buttonsnaptogrid = new System.Windows.Forms.ToolStripButton();
 			this.buttonautomerge = new System.Windows.Forms.ToolStripButton();
+			this.buttonsplitjoinedsectors = new System.Windows.Forms.ToolStripButton();
 			this.buttonautoclearsidetextures = new System.Windows.Forms.ToolStripButton();
 			this.seperatorgeometry = new System.Windows.Forms.ToolStripSeparator();
 			this.buttontogglefx = new System.Windows.Forms.ToolStripButton();
@@ -533,6 +535,7 @@ namespace CodeImp.DoomBuilder.Windows
             this.itemsnaptogrid,
             this.itemdynamicgridsize,
             this.itemautomerge,
+			this.itemsplitjoinedsectors,
             this.itemautoclearsidetextures,
             this.seperatoreditgeometry,
             this.itemgridinc,
@@ -634,6 +637,17 @@ namespace CodeImp.DoomBuilder.Windows
 			this.itemautomerge.Text = "Snap to &Geometry";
 			this.itemautomerge.Click += new System.EventHandler(this.InvokeTaggedAction);
 			// 
+			// itemsplitjoinedsectors
+			// 
+			this.itemsplitjoinedsectors.Checked = true;
+			this.itemsplitjoinedsectors.CheckState = System.Windows.Forms.CheckState.Checked;
+			this.itemsplitjoinedsectors.Image = global::CodeImp.DoomBuilder.Properties.Resources.SplitSectors;
+			this.itemsplitjoinedsectors.Name = "itemsplitjoinedsectors";
+			this.itemsplitjoinedsectors.Size = new System.Drawing.Size(219, 22);
+			this.itemsplitjoinedsectors.Tag = "builder_togglejoinedsectorssplitting";
+			this.itemsplitjoinedsectors.Text = "Split &Joined Sectors when Drawing Lines";
+			this.itemsplitjoinedsectors.Click += new System.EventHandler(this.InvokeTaggedAction);
+			// 
 			// itemautoclearsidetextures
 			// 
 			this.itemautoclearsidetextures.Checked = true;
@@ -1306,6 +1320,7 @@ namespace CodeImp.DoomBuilder.Windows
             this.buttonsnaptogrid,
             this.buttontoggledynamicgrid,
             this.buttonautomerge,
+			this.buttonsplitjoinedsectors,
             this.buttonautoclearsidetextures,
             this.seperatorgeometry,
             this.buttontogglefx,
@@ -1793,6 +1808,19 @@ namespace CodeImp.DoomBuilder.Windows
 			this.buttonautomerge.Text = "Snap to Geometry";
 			this.buttonautomerge.Click += new System.EventHandler(this.InvokeTaggedAction);
 			// 
+			// buttonsplitjoinedsectors
+			// 
+			this.buttonsplitjoinedsectors.Checked = true;
+			this.buttonsplitjoinedsectors.CheckState = System.Windows.Forms.CheckState.Checked;
+			this.buttonsplitjoinedsectors.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+			this.buttonsplitjoinedsectors.Image = global::CodeImp.DoomBuilder.Properties.Resources.SplitSectors;
+			this.buttonsplitjoinedsectors.ImageTransparentColor = System.Drawing.Color.Magenta;
+			this.buttonsplitjoinedsectors.Name = "buttonsplitjoinedsectors";
+			this.buttonsplitjoinedsectors.Size = new System.Drawing.Size(23, 22);
+			this.buttonsplitjoinedsectors.Tag = "builder_togglejoinedsectorssplitting";
+			this.buttonsplitjoinedsectors.Text = "Split Joined Sectors when Drawing Lines";
+			this.buttonsplitjoinedsectors.Click += new System.EventHandler(this.InvokeTaggedAction);
+			// 
 			// buttonautoclearsidetextures
 			// 
 			this.buttonautoclearsidetextures.Checked = true;
@@ -2680,6 +2708,8 @@ namespace CodeImp.DoomBuilder.Windows
 		private System.Windows.Forms.ToolStripMenuItem itemsnaptogrid;
 		private System.Windows.Forms.ToolStripButton buttonautomerge;
 		private System.Windows.Forms.ToolStripMenuItem itemautomerge;
+		private System.Windows.Forms.ToolStripButton buttonsplitjoinedsectors;
+		private System.Windows.Forms.ToolStripMenuItem itemsplitjoinedsectors;
 		private System.Windows.Forms.Timer processor;
 		private System.Windows.Forms.ToolStripSeparator separatorgzmodes;
 		private System.Windows.Forms.ToolStripSeparator seperatorfilesave;
diff --git a/Source/Core/Windows/MainForm.cs b/Source/Core/Windows/MainForm.cs
index 2e6e2b2be..78da88641 100644
--- a/Source/Core/Windows/MainForm.cs
+++ b/Source/Core/Windows/MainForm.cs
@@ -2114,6 +2114,8 @@ namespace CodeImp.DoomBuilder.Windows
 			buttontoggledynamicgrid.Visible = General.Settings.ToolbarGeometry && maploaded; //mxd
 			buttontoggledynamicgrid.Checked = General.Settings.DynamicGridSize; //mxd
 			buttonautomerge.Visible = General.Settings.ToolbarGeometry && maploaded;
+			buttonsplitjoinedsectors.Visible = General.Settings.ToolbarGeometry && maploaded; //mxd
+			buttonsplitjoinedsectors.Checked = General.Settings.SplitJoinedSectors; //mxd
 			buttonautoclearsidetextures.Visible = General.Settings.ToolbarGeometry && maploaded; //mxd
 			buttontest.Visible = General.Settings.ToolbarTesting && maploaded;
 
@@ -2762,6 +2764,7 @@ namespace CodeImp.DoomBuilder.Windows
 			itemcopy.Enabled = (General.Map != null) && (General.Editing.Mode != null) && General.Editing.Mode.Attributes.AllowCopyPaste;
 			itempaste.Enabled = (General.Map != null) && (General.Editing.Mode != null) && General.Editing.Mode.Attributes.AllowCopyPaste;
 			itempastespecial.Enabled = (General.Map != null) && (General.Editing.Mode != null) && General.Editing.Mode.Attributes.AllowCopyPaste;
+			itemsplitjoinedsectors.Checked = General.Settings.SplitJoinedSectors; //mxd
 			itemautoclearsidetextures.Checked = General.Settings.AutoClearSidedefTextures; //mxd
 			itemdynamicgridsize.Enabled = (General.Map != null); //mxd
 			itemdynamicgridsize.Checked = General.Settings.DynamicGridSize; //mxd
@@ -2894,6 +2897,16 @@ namespace CodeImp.DoomBuilder.Windows
 			DisplayStatus(StatusType.Action, "Snap to geometry is " + (buttonautomerge.Checked ? "ENABLED" : "DISABLED"));
 		}
 
+		//mxd
+		[BeginAction("togglejoinedsectorssplitting")]
+		internal void ToggleJoinedSectorsSplitting()
+		{
+			buttonsplitjoinedsectors.Checked = !buttonsplitjoinedsectors.Checked;
+			itemsplitjoinedsectors.Checked = buttonsplitjoinedsectors.Checked;
+			General.Settings.SplitJoinedSectors = buttonsplitjoinedsectors.Checked;
+			DisplayStatus(StatusType.Action, "Joined sectors splitting is " + (General.Settings.SplitJoinedSectors ? "ENABLED" : "DISABLED"));
+		}
+
 		//mxd
 		[BeginAction("togglebrightness")]
 		internal void ToggleBrightness() 
diff --git a/Source/Core/Windows/ThingEditForm.cs b/Source/Core/Windows/ThingEditForm.cs
index 0d33ded8d..76dc045fc 100644
--- a/Source/Core/Windows/ThingEditForm.cs
+++ b/Source/Core/Windows/ThingEditForm.cs
@@ -114,6 +114,9 @@ namespace CodeImp.DoomBuilder.Windows
 				posZ.AllowDecimal = true;
 			}
 
+			//mxd. Use doom angle clamping?
+			anglecontrol.DoomAngleClamping = General.Map.Config.DoomThingRotationAngles;
+
 			//mxd. Arrange inteface
 			int targetheight;
 			if(General.Map.FormatInterface.HasThingAction)
@@ -364,7 +367,12 @@ namespace CodeImp.DoomBuilder.Windows
 			foreach(Thing t in things)
 			{
 				// Coordination
-				if(cbRandomAngle.Checked) t.Rotate(General.Random(0, 359)); //mxd
+				if(cbRandomAngle.Checked) //mxd
+				{
+					int newangle = General.Random(0, 359);
+					if(General.Map.Config.DoomThingRotationAngles) newangle = newangle / 45 * 45;
+					t.Rotate(newangle);
+				}
 
 				//mxd. Check position
 				float px = General.Clamp(t.Position.x, General.Map.Config.LeftBoundary, General.Map.Config.RightBoundary);
diff --git a/Source/Core/Windows/ThingEditFormUDMF.cs b/Source/Core/Windows/ThingEditFormUDMF.cs
index 68198a1c4..8f3350aa9 100644
--- a/Source/Core/Windows/ThingEditFormUDMF.cs
+++ b/Source/Core/Windows/ThingEditFormUDMF.cs
@@ -148,6 +148,9 @@ namespace CodeImp.DoomBuilder.Windows
 				posZ.AllowDecimal = true;
 			}
 
+			//mxd. Use doom angle clamping?
+			anglecontrol.DoomAngleClamping = General.Map.Config.DoomThingRotationAngles;
+
 			// Value linking
 			scale.LinkValues = linkscale;
 
@@ -462,7 +465,12 @@ namespace CodeImp.DoomBuilder.Windows
 			{
 				// Coordination
 				//mxd. Randomize rotations?
-				if(cbrandomangle.Checked) t.Rotate(General.Random(0, 359));
+				if(cbrandomangle.Checked)
+				{
+					int newangle = General.Random(0, 359);
+					if(General.Map.Config.DoomThingRotationAngles) newangle = newangle / 45 * 45;
+					t.Rotate(newangle);
+				}
 				if(cbrandompitch.Checked) t.SetPitch(General.Random(0, 359));
 				if(cbrandomroll.Checked) t.SetRoll(General.Random(0, 359));
 
diff --git a/Source/Plugins/BuilderEffects/Interface/JitterThingsForm.cs b/Source/Plugins/BuilderEffects/Interface/JitterThingsForm.cs
index 886282cdb..8db130425 100644
--- a/Source/Plugins/BuilderEffects/Interface/JitterThingsForm.cs
+++ b/Source/Plugins/BuilderEffects/Interface/JitterThingsForm.cs
@@ -201,9 +201,13 @@ namespace CodeImp.DoomBuilder.BuilderEffects
 		private void ApplyRotation(int ammount) 
 		{
 			for(int i = 0; i < selection.Count; i++)
-				selection[i].Rotate((int)((thingData[i].Angle + ammount * thingData[i].JitterRotation) % 360));
+			{
+				int newangle = (int)Math.Round(thingData[i].Angle + ammount * thingData[i].JitterRotation);
+				if(General.Map.Config.DoomThingRotationAngles) newangle = newangle / 45 * 45;
+				selection[i].Rotate(newangle % 360);
+			}
 
-			//update view
+			// Update view
 			if(editingModeName == "ThingsMode") General.Interface.RedrawDisplay();
 		}
 
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs
index 81c77308e..e3c91078e 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs
@@ -249,7 +249,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 					General.Map.Map.Update();
 
 					//mxd. Outer sectors may require some splittin...
-					Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true));
+					if(General.Settings.SplitJoinedSectors) Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true));
 
 					// Edit new sectors?
 					List<Sector> newsectors = General.Map.Map.GetMarkedSectors(true);
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs
index 21f77f343..d90164e34 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs
@@ -780,7 +780,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 					General.Map.Map.Update();
 
 					//mxd. Outer sectors may require some splittin...
-					Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true));
+					if(General.Settings.SplitJoinedSectors) Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true));
 
 					// Edit new sectors?
 					List<Sector> newsectors = General.Map.Map.GetMarkedSectors(true);
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs
index ba91d7467..3fc76b695 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs
@@ -115,7 +115,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 						General.Map.Map.ClearAllSelected();
 
 						//mxd. Outer sectors may require some splittin...
-						Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true));
+						if(General.Settings.SplitJoinedSectors) Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true));
 
 						// Edit new sectors?
 						if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0))
diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
index 0f07350c7..d3a016c3e 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs
@@ -386,7 +386,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 					General.Map.Map.Update();
 
 					//mxd. Outer sectors may require some splittin...
-					Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true));
+					if(General.Settings.SplitJoinedSectors) Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true));
 
 					// Edit new sectors?
 					List<Sector> newsectors = General.Map.Map.GetMarkedSectors(true);
diff --git a/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs b/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs
index 17bc3b9f2..64c6ebfed 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs
@@ -18,7 +18,6 @@
 
 using System;
 using System.Collections.Generic;
-using System.Collections.ObjectModel;
 using System.Drawing;
 using System.Windows.Forms;
 using CodeImp.DoomBuilder.Actions;
@@ -848,8 +847,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			index = 0;
 			foreach(Thing t in selectedthings)
 			{
-				if(!fixedrotationthingtypes.Contains(t.Type)) //mxd. Polyobject Anchors, I hate you!
-					t.Rotate(Angle2D.Normalized(newthingangle[index]));
+				//mxd. Added special Polyobj Anchor handling and Doom angle clamping
+				if(!fixedrotationthingtypes.Contains(t.Type))
+				{
+					int newangle = Angle2D.RealToDoom(Angle2D.Normalized(newthingangle[index]));
+					if(General.Map.Config.DoomThingRotationAngles) newangle = newangle / 45 * 45;
+					t.Rotate(newangle);
+				}
+				
 				index++;
 			}
 			
diff --git a/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs
index b6937b37f..f48e3829f 100644
--- a/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs
+++ b/Source/Plugins/BuilderModes/ClassicModes/ThingsMode.cs
@@ -265,6 +265,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				//mxd. Render sector tag labels
 				if(BuilderPlug.Me.ViewSelectionEffects && General.Map.FormatInterface.HasThingAction)
 				{
+					//mxd. sectorlabels will be null after switching map configuration from one 
+					// without ThingAction to one with it while in Things mode
+					if(sectorlabels == null) SetupSectorLabels(); 
+					
 					List<ITextLabel> torender = new List<ITextLabel>(sectorlabels.Count);
 					foreach(KeyValuePair<Sector, string[]> group in sectortexts)
 					{
@@ -1494,25 +1498,33 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				General.Interface.DisplayStatus(StatusType.Action, "Rotated a thing.");
 			}
 
-			//change angle
-			if(General.Interface.CtrlState) //point away
+			// Change angle
+			if(General.Interface.CtrlState) // Point away
 			{ 
 				foreach(Thing t in selected) 
 				{
 					ThingTypeInfo info = General.Map.Data.GetThingInfo(t.Type);
 					if(info == null || info.Category == null || info.Category.Arrow == 0)
 						continue;
-					t.Rotate(Vector2D.GetAngle(mousemappos, t.Position) + Angle2D.PI);
+
+					int newangle = Angle2D.RealToDoom(Vector2D.GetAngle(mousemappos, t.Position) + Angle2D.PI);
+					if(General.Map.Config.DoomThingRotationAngles) newangle = (newangle + 22) / 45 * 45;
+
+					t.Rotate(newangle);
 				}
 			} 
-			else //point at
+			else // Point at cursor
 			{ 
 				foreach(Thing t in selected) 
 				{
 					ThingTypeInfo info = General.Map.Data.GetThingInfo(t.Type);
 					if(info == null || info.Category == null || info.Category.Arrow == 0)
 						continue;
-					t.Rotate(Vector2D.GetAngle(mousemappos, t.Position));
+
+					int newangle = Angle2D.RealToDoom(Vector2D.GetAngle(mousemappos, t.Position));
+					if(General.Map.Config.DoomThingRotationAngles) newangle = (newangle + 22) / 45 * 45;
+
+					t.Rotate(newangle);
 				}
 			}
 
@@ -1524,14 +1536,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		[BeginAction("rotateclockwise")]
 		public void RotateCW() 
 		{
-			RotateThings(-5);
+			RotateThings(General.Map.Config.DoomThingRotationAngles ? -45 : -5);
 		}
 
 		//mxd. rotate counterclockwise
 		[BeginAction("rotatecounterclockwise")]
 		public void RotateCCW() 
 		{
-			RotateThings(5);
+			RotateThings(General.Map.Config.DoomThingRotationAngles ? 45 : 5);
 		}
 
 		//mxd
@@ -1560,8 +1572,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				General.Interface.DisplayStatus(StatusType.Action, "Rotated a thing.");
 			}
 
-			//change angle
-			foreach(Thing t in selected) t.Rotate(General.ClampAngle(t.AngleDoom + increment));
+			// Change angle
+			foreach(Thing t in selected)
+			{
+				int newangle = t.AngleDoom + increment;
+				if(General.Map.Config.DoomThingRotationAngles) newangle = (newangle + 22) / 45 * 45;
+
+				t.Rotate(General.ClampAngle(newangle));
+			}
 
 			// Redraw screen
 			General.Interface.RedrawDisplay();
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
index 0fa83bb09..9512836a2 100644
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
@@ -3204,18 +3204,18 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		[BeginAction("rotateclockwise")]
 		public void RotateCW() 
 		{
-			RotateThingsAndTextures(5);
+			RotateThingsAndTextures(General.Map.Config.DoomThingRotationAngles ? 45 : 5, 5);
 		}
 
 		//mxd. Rotate counterclockwise
 		[BeginAction("rotatecounterclockwise")]
 		public void RotateCCW() 
 		{
-			RotateThingsAndTextures(-5);
+			RotateThingsAndTextures(General.Map.Config.DoomThingRotationAngles ? -45 : -5, - 5);
 		}
 
 		//mxd
-		private void RotateThingsAndTextures(int increment) 
+		private void RotateThingsAndTextures(int thingangleincrement, int textureangleincrement) 
 		{
 			PreAction(UndoGroup.ThingAngleChange);
 
@@ -3227,7 +3227,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				if(obj is BaseVisualThing) 
 				{
 					BaseVisualThing t = (BaseVisualThing)obj;
-					t.SetAngle(General.ClampAngle(t.Thing.AngleDoom + increment));
+
+					int newangle = t.Thing.AngleDoom + thingangleincrement;
+					if(General.Map.Config.DoomThingRotationAngles) newangle = newangle / 45 * 45;
+					t.SetAngle(General.ClampAngle(newangle));
 
 					// Visual sectors may be affected by this thing...
 					if(thingdata.ContainsKey(t.Thing))
@@ -3247,12 +3250,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				else if(obj is VisualFloor) 
 				{
 					VisualFloor vf = (VisualFloor)obj;
-					vf.OnChangeTextureRotation(General.ClampAngle(vf.GetControlSector().Fields.GetValue("rotationfloor", 0.0f) + increment));
+					vf.OnChangeTextureRotation(General.ClampAngle(vf.GetControlSector().Fields.GetValue("rotationfloor", 0.0f) + textureangleincrement));
 				} 
 				else if(obj is VisualCeiling) 
 				{
 					VisualCeiling vc = (VisualCeiling)obj;
-					vc.OnChangeTextureRotation(General.ClampAngle(vc.GetControlSector().Fields.GetValue("rotationceiling", 0.0f) + increment));
+					vc.OnChangeTextureRotation(General.ClampAngle(vc.GetControlSector().Fields.GetValue("rotationceiling", 0.0f) + textureangleincrement));
 				}
 			}
 
-- 
GitLab