diff --git a/Help/Contents.hhc b/Help/Contents.hhc
index f7c2bb685371fcf367d266c933f971f6e1f6b51c..dce1671f6be614c5367ca24c8008a6a0058e97ab 100644
--- a/Help/Contents.hhc
+++ b/Help/Contents.hhc
@@ -243,15 +243,19 @@
               <UL>
 			        <LI> <OBJECT type="text/sitemap">
 				      <param name="Name" value="Draw Rectangle mode">
-				      <param name="Local" value="gz_drawrect.html">
+				      <param name="Local" value="gz_mode_drawrect.html">
 				      </OBJECT>
 				      <LI> <OBJECT type="text/sitemap">
 				      <param name="Name" value="Draw Ellipse mode">
-				      <param name="Local" value="gz_drawellipse.html">
+				      <param name="Local" value="gz_mode_drawellipse.html">
 				      </OBJECT>
 				      <LI> <OBJECT type="text/sitemap">
 				      <param name="Name" value="Bridge mode">
-				      <param name="Local" value="gz_drawbridge.html">
+				      <param name="Local" value="gz_mode_drawbridge.html">
+				      </OBJECT>
+				      <LI> <OBJECT type="text/sitemap">
+				      <param name="Name" value="Snap selected vertices to grid mode">
+				      <param name="Local" value="gz_mode_snapverts.html">
 				      </OBJECT>
 				      </UL>
 				<LI> <OBJECT type="text/sitemap">
@@ -275,6 +279,10 @@
 				      <param name="Name" value="Color Picker plugin">
 				      <param name="Local" value="gz_plug_colorpicker.html">
 				      </OBJECT>
+				      <LI> <OBJECT type="text/sitemap">
+				      <param name="Name" value="UDMF Controls plugin">
+				      <param name="Local" value="gz_plug_udmfcontrols.html">
+				      </OBJECT>
 				      </UL>
 				<LI> <OBJECT type="text/sitemap">
 				<param name="Name" value="Frequently asked questions">
diff --git a/Help/gz_actions.html b/Help/gz_actions.html
index 4c375c508dad81e2fd44772379d4471763a3ccae..75527d06dd066b881fe2dc83c760730acdd4d76d 100644
--- a/Help/gz_actions.html
+++ b/Help/gz_actions.html
@@ -23,17 +23,17 @@
       <td><strong>Description:</strong></td>
     </tr>
     <tr>
-      <td><a href="gz_drawrect.html">Start Rectangle Drawing</a></td>
+      <td><a href="gz_mode_drawrect.html">Start Rectangle Drawing</a></td>
       <td><div align="center">Ctrl-Shift-D</div></td>
       <td>Starts drawing rectangle. Increase / Decrease Sudivision Level and Increase / Decrease Corners Bevel actions are avaliable in this mode.</td>
     </tr>
     <tr>
-      <td><a href="gz_drawrect.html">Start Ellipse Drawing</a></td>
+      <td><a href="gz_mode_drawellipse.html">Start Ellipse Drawing</a></td>
       <td><div align="center">Ctrl-Alt-D</div></td>
       <td>Starts drawing ellipse. Increase / Decrease Sudivision Level and Increase / Decrease Corners Bevel actions are avaliable in this mode.</td>
     </tr>
     <tr>
-      <td><a href="gz_drawrect.html">Bridge Mode</a></td>
+      <td><a href="gz_mode_drawbridge.html">Bridge Mode</a></td>
       <td><div align="center">Ctrl-B</div></td>
       <td>Select two lines or two series of lines, then activate this tool to draw a bezier path between them. Increase / Decrease Sudivision Level actions are avaliable in this mode.</td>
     </tr>
@@ -59,6 +59,22 @@
     </tr>
   </table>
   <br />
+  
+  <h2><strong>Edit:</strong></h2>
+  <table border="0" cellspacing="3" cellpadding="3">
+    <tr>
+      <td width="130"><strong>Name:</strong></td>
+      <td width="130"><div align="center"><strong>Default shortcut:</strong></div></td>
+      <td><strong>Description:</strong></td>
+    </tr>
+    <tr>
+      <td><a href="gz_mode_snapverts.html">Snap Selected Vertices to Grid</a></td>
+      <td><div align="center">-</div></td>
+      <td>Snaps selected vertices to grid.</td>
+    </tr>
+  </table>
+  <br />
+
   <h2><strong>GZDoom Builder:</strong></h2>
   <table border="0" cellspacing="3" cellpadding="3">
     <tr>
@@ -125,6 +141,13 @@
       <td><div align="center">K</div></td>
       <td>Select dynamic light thing(s) or sector(s), then use this panel to set light properties quickly.</td>
     </tr>
+    
+    <tr>
+      <td>Open <a href="gz_plug_udmfcontrols.html">UDMF Controls</a></td>
+      <td><div align="center">Ctrl-T</div></td>
+      <td>Select surface(s) in Visual Modes, then use this panel to edit sector and texture properties quickly.</td>
+    </tr>
+
     <tr>
       <td><a id="newtestmap"></a>Test map from current position</td>
       <td><div align="center">Ctrl-F9</div></td>
diff --git a/Help/gz_editmodes.html b/Help/gz_editmodes.html
index 69e5b6c615a5fd8639fe23a9af62b3312aca2042..e49f3353eccfcc7eb6a867791e1a31ef8fd39127 100644
--- a/Help/gz_editmodes.html
+++ b/Help/gz_editmodes.html
@@ -17,9 +17,10 @@
 	
 	<div id="contents">
 	<p>To help you create things faster, GZDoom Builder adds several new editing modes:</br></br>
-	<a href="gz_drawrect.html">Draw Rectangle Mode</a></br>
-	<a href="gz_drawellipse.html">Draw Ellipse Mode</a></br>
-  <a href="gz_drawbridge.html">Bridge Mode</a>
+	<a href="gz_mode_drawrect.html">Draw Rectangle Mode</a></br>
+	<a href="gz_mode_drawellipse.html">Draw Ellipse Mode</a></br>
+  <a href="gz_mode_drawbridge.html">Bridge Mode</a></br>
+  <a href="gz_mode_snapverts.html">Snap selected vertices to grid mode</a>
   </p>
 	</div>
 </body>
diff --git a/Help/gz_drawbridge.html b/Help/gz_mode_drawbridge.html
similarity index 100%
rename from Help/gz_drawbridge.html
rename to Help/gz_mode_drawbridge.html
diff --git a/Help/gz_drawellipse.html b/Help/gz_mode_drawellipse.html
similarity index 100%
rename from Help/gz_drawellipse.html
rename to Help/gz_mode_drawellipse.html
diff --git a/Help/gz_drawrect.html b/Help/gz_mode_drawrect.html
similarity index 100%
rename from Help/gz_drawrect.html
rename to Help/gz_mode_drawrect.html
diff --git a/Help/gz_mode_snapverts.html b/Help/gz_mode_snapverts.html
new file mode 100644
index 0000000000000000000000000000000000000000..4d9d3972bd9bede1deef885b1f07d1842eddf753
--- /dev/null
+++ b/Help/gz_mode_snapverts.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+	
+	<title>Draw Ellipse mode</title>
+	
+	<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
+	<link rel="stylesheet" type="text/css" href="default.css" media="screen" title="Default" />
+</head>
+<body>
+
+	<object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
+	<param name="keyword" value="Template">
+	</object>
+	
+	<div id="gz_title"><h1>Snap selected vertices to grid mode</h1></div>
+	
+	<div id="contents">
+	<p>
+Activate this mode to snap selected vertices to grid.<br>
+<b>Menu:</b> Edit -> Snap selected vertices to grid.<br>
+<b>Found in:</b> Preferences -> Controls -> Drawing.<br>
+<b>Default key:</b> none.<br>
+	</div>
+</body>
diff --git a/Help/gz_plug_udmfcontrols.html b/Help/gz_plug_udmfcontrols.html
new file mode 100644
index 0000000000000000000000000000000000000000..847187dd44b97730ebc3120f8b1504220ff08edd
--- /dev/null
+++ b/Help/gz_plug_udmfcontrols.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+	
+	<title>GZDoom Builder features</title>
+	
+	<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
+	<link rel="stylesheet" type="text/css" href="default.css" media="screen" title="Default" />
+</head>
+<body>
+	
+	<object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
+	<param name="keyword" value="Template">
+	</object>
+	
+	<div id="gz_title"><h1>UDMF Controls plugin</h1></div>
+	
+	<div id="contents">
+	<p>UDMF Controls plugin lets you edit surface properties and linedef/sector UDMF flags quickly.<br />
+	  <strong>Default key:</strong> Ctrl-T.<br />
+    <strong>Found in:</strong> Preferences -> Controls -> Tools -> Open UDMF Controls.<br /><br />
+    <img style="float:left; margin-right:10px" src="gz_udmfcontrols.jpg"/>
+    <strong>Usage:</strong> select some surfaces in Visual Modes, then open UDMF Controls panel to edit surface properties and linedef/sector UDMF flags. If no surfaces are selected, currently hilighted surface will be used.<br /><br />
+When <strong>Relative mode</strong> is active, scale, position and rotation are changed relatively to their initial values.<br /><br />
+You can press <strong>Shift</strong>, then click inside Rotation control's dial to snap angle to 45-degrees increment.
+    </p>
+</div>
+</body>
diff --git a/Help/gz_plugins.html b/Help/gz_plugins.html
index 9a259fa76f8c248c5ddab3c4c987b7abbe9005ad..d75b094d01c62f2b54f7a6ecf09757c000a9af0c 100644
--- a/Help/gz_plugins.html
+++ b/Help/gz_plugins.html
@@ -18,7 +18,9 @@
 	<div id="contents">
 	<p>
 	<h2>List of plugins made for GZDoom Builder:</h2>
-</br><a href="gz_plug_colorpicker.html">Color Picker plugin.</a></br>
+</br>
+<a href="gz_plug_colorpicker.html">Color Picker plugin.</a></br>
+<a href="gz_plug_udmfcontrols.html">UDMF Controls plugin.</a></br>
 	</p>
 	</div>
 </body>
diff --git a/Help/gz_udmfcontrols.jpg b/Help/gz_udmfcontrols.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..cb6a3b877e53b0e4bcc91e8572083e34c3d88258
Binary files /dev/null and b/Help/gz_udmfcontrols.jpg differ
diff --git a/Source/Core/Builder.sln b/Source/Core/Builder.sln
index e1b362101c5ddb271f7792316ac5ef22ee35e44e..e199765ed966fe3ec55a1ffae9e371208d1a360a 100644
--- a/Source/Core/Builder.sln
+++ b/Source/Core/Builder.sln
@@ -7,6 +7,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BuilderModes", "..\Plugins\
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorPicker", "..\Plugins\ColorPicker\ColorPicker.csproj", "{A4761900-0EA3-4FE4-A919-847FD5080EFC}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GZDoomEditing", "..\Plugins\GZDoomEditing\GZDoomEditing.csproj", "{760A9BC7-CB73-4C36-858B-994C14996FCD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UDMFControls", "..\Plugins\UMDFControls\UDMFControls.csproj", "{2D11C828-295C-463A-8545-CA1AD6D51518}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -47,6 +51,26 @@ Global
 		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|Mixed Platforms.Build.0 = Release|x86
 		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.ActiveCfg = Release|x86
 		{A4761900-0EA3-4FE4-A919-847FD5080EFC}.Release|x86.Build.0 = Release|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Any CPU.ActiveCfg = Debug|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|Mixed Platforms.Build.0 = Debug|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|x86.ActiveCfg = Debug|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Debug|x86.Build.0 = Debug|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Any CPU.ActiveCfg = Release|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Mixed Platforms.ActiveCfg = Release|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|Mixed Platforms.Build.0 = Release|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.ActiveCfg = Release|x86
+		{760A9BC7-CB73-4C36-858B-994C14996FCD}.Release|x86.Build.0 = Release|x86
+		{2D11C828-295C-463A-8545-CA1AD6D51518}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{2D11C828-295C-463A-8545-CA1AD6D51518}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2D11C828-295C-463A-8545-CA1AD6D51518}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{2D11C828-295C-463A-8545-CA1AD6D51518}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{2D11C828-295C-463A-8545-CA1AD6D51518}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{2D11C828-295C-463A-8545-CA1AD6D51518}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{2D11C828-295C-463A-8545-CA1AD6D51518}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2D11C828-295C-463A-8545-CA1AD6D51518}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{2D11C828-295C-463A-8545-CA1AD6D51518}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{2D11C828-295C-463A-8545-CA1AD6D51518}.Release|x86.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
diff --git a/Source/Core/GZBuilder/GZGeneral.cs b/Source/Core/GZBuilder/GZGeneral.cs
index b5be3453fc0b5e5f6902cabbef35313e77f20244..cdf66d7379d7bd5e10239fb3ba8f50b3c511ffb4 100644
--- a/Source/Core/GZBuilder/GZGeneral.cs
+++ b/Source/Core/GZBuilder/GZGeneral.cs
@@ -30,7 +30,7 @@ namespace CodeImp.DoomBuilder.GZBuilder
         public static bool UDMF;
 
         //version
-        public const float Version = 1.08f;
+        public const float Version = 1.09f;
 
         //debug console
 #if DEBUG
@@ -100,7 +100,7 @@ namespace CodeImp.DoomBuilder.GZBuilder
         [BeginAction("gztogglemodels")]
         private static void toggleModels() {
             General.Settings.GZDrawModels = !General.Settings.GZDrawModels;
-            General.MainWindow.DisplayStatus(StatusType.Action, "MD3 models rendering is " + (General.Settings.GZDrawModels ? "ENABLED" : "DISABLED"));
+            General.MainWindow.DisplayStatus(StatusType.Action, "Models rendering is " + (General.Settings.GZDrawModels ? "ENABLED" : "DISABLED"));
             General.MainWindow.RedrawDisplay();
             General.MainWindow.UpdateGZDoomPannel();
         }
diff --git a/Source/Core/General/General.cs b/Source/Core/General/General.cs
index 49e29fcca5d64b188391bf6dc6ee3bec55d007e6..7f62e08ffe6199655bc4310cb3f0cdc84f873fa0 100644
--- a/Source/Core/General/General.cs
+++ b/Source/Core/General/General.cs
@@ -1539,10 +1539,12 @@ namespace CodeImp.DoomBuilder
 
         //mxd. This clamps angle between 0 and 359
         public static int ClampAngle(int angle) {
-            if (angle > -1 && angle < 360) return angle;
-            int n = angle / 360;
-            if (angle > 0) return angle - n * 360;
-            return 360 - Math.Abs(angle) + Math.Abs(n) * 360;
+            return (angle + 360) % 360;
+        }
+
+        //mxd. This clamps angle between 0 and 359
+        public static float ClampAngle(float angle) {
+            return (angle + 360) % 360;
         }
 		
 		// This returns an element from a collection by index
diff --git a/Source/Core/Resources/Splash3_trans.png b/Source/Core/Resources/Splash3_trans.png
index ecac1cf357a2fc8dfffa350844a084d1dbbb23e7..d06c49c1cb06d44d45d58ca068ccb5735252ec57 100644
Binary files a/Source/Core/Resources/Splash3_trans.png and b/Source/Core/Resources/Splash3_trans.png differ
diff --git a/Source/Core/VisualModes/VisualGeometry.cs b/Source/Core/VisualModes/VisualGeometry.cs
index 25d0e0d1982cedc255a25ad1660d1a5b644e513a..8cea2cb8a3cdcb4fc77561d5ebcfb52a1642c95b 100644
--- a/Source/Core/VisualModes/VisualGeometry.cs
+++ b/Source/Core/VisualModes/VisualGeometry.cs
@@ -84,6 +84,7 @@ namespace CodeImp.DoomBuilder.VisualModes
 
         //mxd
         private Vector3[] boundingBox;
+        protected VisualGeometryType geoType;
 		
 		#endregion
 
@@ -98,6 +99,7 @@ namespace CodeImp.DoomBuilder.VisualModes
 
         //mxd
         internal Vector3[] BoundingBox { get { return boundingBox; } }
+        public VisualGeometryType GeometryType { get { return geoType; } }
 
 		/// <summary>
 		/// Render pass in which this geometry must be rendered. Default is Solid.
@@ -140,6 +142,8 @@ namespace CodeImp.DoomBuilder.VisualModes
 		{
 			this.sector = vs;
 			this.ModulateColor = new PixelColor(255, 255, 255, 255);
+            //mxd
+            geoType = VisualGeometryType.UNKNOWN;
 		}
 
 		/// <summary>
@@ -151,6 +155,8 @@ namespace CodeImp.DoomBuilder.VisualModes
 			this.sector = vs;
 			this.sidedef = sd;
 			this.ModulateColor = new PixelColor(255, 255, 255, 255);
+            //mxd
+            geoType = VisualGeometryType.UNKNOWN;
 		}
 
 		#endregion
@@ -239,4 +245,13 @@ namespace CodeImp.DoomBuilder.VisualModes
 
 		#endregion
 	}
+
+    public enum VisualGeometryType:int{
+        FLOOR = 0,
+        CEILING = 1,
+        WALL_UPPER = 2,
+        WALL_MIDDLE = 3,
+        WALL_BOTTOM = 4,
+        UNKNOWN = 5,
+    }
 }
diff --git a/Source/Core/VisualModes/VisualMode.cs b/Source/Core/VisualModes/VisualMode.cs
index b9c2ef061da2b7c08d81383c95033d26b7819c49..fec4176f00df3a3610e9a0c1446004a6f3221924 100644
--- a/Source/Core/VisualModes/VisualMode.cs
+++ b/Source/Core/VisualModes/VisualMode.cs
@@ -73,6 +73,7 @@ namespace CodeImp.DoomBuilder.VisualModes
         //mxd
         private List<VisualThing> selectedVisualThings;
         private List<VisualSector> selectedVisualSectors;
+        private List<VisualGeometry> selectedSurfaces;
         //used in "Play From Here" Action
         private Thing playerStart;
         private Vector3D playerStartPosition;
@@ -169,6 +170,7 @@ namespace CodeImp.DoomBuilder.VisualModes
                 //mxd
                 selectedVisualSectors = null;
                 selectedVisualThings = null;
+                selectedSurfaces = null;
 				
 				// Done
 				base.Dispose();
@@ -215,6 +217,10 @@ namespace CodeImp.DoomBuilder.VisualModes
 			
 			// Do not leave the sector on the camera
 			General.Map.VisualCamera.Sector = null;
+
+            //mxd
+            selectedVisualSectors = null;
+            selectedVisualThings = null;
 			
 			// Stop special input mode
 			General.Interface.DisableProcessing();
@@ -414,10 +420,6 @@ namespace CodeImp.DoomBuilder.VisualModes
 			visiblegeometry = new List<VisualGeometry>(visiblegeometry.Capacity);
 			visiblethings = new List<VisualThing>(visiblethings.Capacity);
 
-            //mxd
-            //visibleThingsUpdated = true;
-            //visibleGeometryUpdated = true;
-
 			// Get the blocks within view range
 			visibleblocks = blockmap.GetFrustumRange(renderer.Frustum2D);
 			
@@ -883,18 +885,18 @@ namespace CodeImp.DoomBuilder.VisualModes
                     if (group.Value != null && group.Value.Selected)
                         selectedVisualThings.Add(group.Value);
                 }
-            }
 
-            //if nothing is selected - try to get thing from hilighted object
-            if (selectedVisualThings.Count == 0) {
-                Vector3D start = General.Map.VisualCamera.Position;
-                Vector3D delta = General.Map.VisualCamera.Target - General.Map.VisualCamera.Position;
-                delta = delta.GetFixedLength(General.Settings.ViewDistance * 0.98f);
-                VisualPickResult target = PickObject(start, start + delta);
+                //if nothing is selected - try to get thing from hilighted object
+                if (selectedVisualThings.Count == 0) {
+                    Vector3D start = General.Map.VisualCamera.Position;
+                    Vector3D delta = General.Map.VisualCamera.Target - General.Map.VisualCamera.Position;
+                    delta = delta.GetFixedLength(General.Settings.ViewDistance * 0.98f);
+                    VisualPickResult target = PickObject(start, start + delta);
 
-                //not appropriate way to do this, but...
-                if (target.picked != null && target.picked.GetType().Name.IndexOf("Thing") != -1)
-                    return new List<VisualThing>() { (VisualThing)target.picked };
+                    //not appropriate way to do this, but...
+                    if (target.picked != null && target.picked.GetType().Name.IndexOf("Thing") != -1)
+                        selectedVisualThings.Add((VisualThing)target.picked);
+                }
             }
 
             return selectedVisualThings;
@@ -914,24 +916,52 @@ namespace CodeImp.DoomBuilder.VisualModes
                         }
                     }
                 }
+
+                //if nothing is selected - try to get sector from hilighted object
+                if (selectedVisualSectors.Count == 0) {
+                    VisualGeometry vg = getHilightedSurface();
+                    if (vg != null) selectedVisualSectors.Add(vg.Sector);
+                }
             }
+            return selectedVisualSectors;
+        }
+
+        /// <summary>
+        /// mxd. This returns list of selected sectors based on surfaces selected in visual mode
+        /// </summary>
+        public List<VisualGeometry> GetSelectedSurfaces(bool refreshSelection) {
+            if (refreshSelection || selectedSurfaces == null) {
+                selectedSurfaces = new List<VisualGeometry>();
+                foreach (KeyValuePair<Sector, VisualSector> group in allsectors) {
+                    foreach (VisualGeometry vg in group.Value.AllGeometry) {
+                        if (vg.Selected)
+                            selectedSurfaces.Add(vg);
+                    }
+                }
 
-            //if nothing is selected - try to get sector from hilighted object
-            if (selectedVisualSectors.Count == 0) {
-                Vector3D start = General.Map.VisualCamera.Position;
-                Vector3D delta = General.Map.VisualCamera.Target - General.Map.VisualCamera.Position;
-                delta = delta.GetFixedLength(General.Settings.ViewDistance * 0.98f);
-                VisualPickResult target = PickObject(start, start + delta);
-
-                //not appropriate way to do this, but...
-                if (target.picked != null && target.picked.GetType().Name.IndexOf("Thing") == -1) {
-                    VisualGeometry vg = (VisualGeometry)target.picked;
-                    if(vg.Sector != null)
-                        return new List<VisualSector>() { vg.Sector };
+                //if nothing is selected - try to get hilighted surface
+                if (selectedSurfaces.Count == 0) {
+                    VisualGeometry vg = getHilightedSurface();
+                    if(vg != null) selectedSurfaces.Add(vg);
                 }
             }
+            return selectedSurfaces;
+        }
 
-            return selectedVisualSectors;
+        //mxd
+        private VisualGeometry getHilightedSurface() {
+            Vector3D start = General.Map.VisualCamera.Position;
+            Vector3D delta = General.Map.VisualCamera.Target - General.Map.VisualCamera.Position;
+            delta = delta.GetFixedLength(General.Settings.ViewDistance * 0.98f);
+            VisualPickResult target = PickObject(start, start + delta);
+
+            //not appropriate way to do this, but...
+            if (target.picked != null && target.picked.GetType().Name.IndexOf("Thing") == -1) {
+                VisualGeometry vg = (VisualGeometry)target.picked;
+                if (vg.Sector != null)
+                    return vg;
+            }
+            return null;
         }
 
 		/// <summary>
diff --git a/Source/Core/Windows/LinedefEditForm.Designer.cs b/Source/Core/Windows/LinedefEditForm.Designer.cs
index efb9d9561166e49f273597d499f286258c8ce246..9df7f386d89dee3e257cdf28d9977bb4da776641 100644
--- a/Source/Core/Windows/LinedefEditForm.Designer.cs
+++ b/Source/Core/Windows/LinedefEditForm.Designer.cs
@@ -28,881 +28,881 @@ namespace CodeImp.DoomBuilder.Windows
 		/// </summary>
 		private void InitializeComponent()
 		{
-			System.Windows.Forms.Label label2;
-			System.Windows.Forms.Label taglabel;
-			System.Windows.Forms.Label label3;
-			System.Windows.Forms.Label label4;
-			System.Windows.Forms.Label label5;
-			System.Windows.Forms.Label label6;
-			System.Windows.Forms.Label label7;
-			System.Windows.Forms.Label label8;
-			System.Windows.Forms.Label label9;
-			System.Windows.Forms.Label label10;
-			System.Windows.Forms.Label label11;
-			System.Windows.Forms.Label label12;
-			System.Windows.Forms.Label activationlabel;
-			this.cancel = new System.Windows.Forms.Button();
-			this.apply = new System.Windows.Forms.Button();
-			this.actiongroup = new System.Windows.Forms.GroupBox();
-			this.argspanel = new System.Windows.Forms.Panel();
-			this.arg2 = new CodeImp.DoomBuilder.Controls.ArgumentBox();
-			this.arg1 = new CodeImp.DoomBuilder.Controls.ArgumentBox();
-			this.arg0 = new CodeImp.DoomBuilder.Controls.ArgumentBox();
-			this.arg3 = new CodeImp.DoomBuilder.Controls.ArgumentBox();
-			this.arg4 = new CodeImp.DoomBuilder.Controls.ArgumentBox();
-			this.arg1label = new System.Windows.Forms.Label();
-			this.arg0label = new System.Windows.Forms.Label();
-			this.arg3label = new System.Windows.Forms.Label();
-			this.arg2label = new System.Windows.Forms.Label();
-			this.arg4label = new System.Windows.Forms.Label();
-			this.hexenpanel = new System.Windows.Forms.Panel();
-			this.activation = new System.Windows.Forms.ComboBox();
-			this.action = new CodeImp.DoomBuilder.Controls.ActionSelectorControl();
-			this.browseaction = new System.Windows.Forms.Button();
-			this.udmfpanel = new System.Windows.Forms.Panel();
-			this.udmfactivates = new CodeImp.DoomBuilder.Controls.CheckboxArrayControl();
-			this.newtag = new System.Windows.Forms.Button();
-			this.settingsgroup = new System.Windows.Forms.GroupBox();
-			this.flags = new CodeImp.DoomBuilder.Controls.CheckboxArrayControl();
-			this.checkBox1 = new System.Windows.Forms.CheckBox();
-			this.tabs = new System.Windows.Forms.TabControl();
-			this.tabproperties = new System.Windows.Forms.TabPage();
-			this.idgroup = new System.Windows.Forms.GroupBox();
-			this.tag = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
-			this.tabsidedefs = new System.Windows.Forms.TabPage();
-			this.splitter = new System.Windows.Forms.SplitContainer();
-			this.frontside = new System.Windows.Forms.CheckBox();
-			this.frontgroup = new System.Windows.Forms.GroupBox();
-			this.frontoffsety = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
-			this.frontoffsetx = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
-			this.frontsector = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
-			this.customfrontbutton = new System.Windows.Forms.Button();
-			this.frontlow = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
-			this.frontmid = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
-			this.fronthigh = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
-			this.backside = new System.Windows.Forms.CheckBox();
-			this.backgroup = new System.Windows.Forms.GroupBox();
-			this.backoffsety = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
-			this.backoffsetx = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
-			this.backsector = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
-			this.custombackbutton = new System.Windows.Forms.Button();
-			this.backlow = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
-			this.backmid = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
-			this.backhigh = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
-			this.tabcustom = new System.Windows.Forms.TabPage();
-			this.fieldslist = new CodeImp.DoomBuilder.Controls.FieldsEditorControl();
-			this.heightpanel1 = new System.Windows.Forms.Panel();
-			this.heightpanel2 = new System.Windows.Forms.Panel();
-			label2 = new System.Windows.Forms.Label();
-			taglabel = new System.Windows.Forms.Label();
-			label3 = new System.Windows.Forms.Label();
-			label4 = new System.Windows.Forms.Label();
-			label5 = new System.Windows.Forms.Label();
-			label6 = new System.Windows.Forms.Label();
-			label7 = new System.Windows.Forms.Label();
-			label8 = new System.Windows.Forms.Label();
-			label9 = new System.Windows.Forms.Label();
-			label10 = new System.Windows.Forms.Label();
-			label11 = new System.Windows.Forms.Label();
-			label12 = new System.Windows.Forms.Label();
-			activationlabel = new System.Windows.Forms.Label();
-			this.actiongroup.SuspendLayout();
-			this.argspanel.SuspendLayout();
-			this.hexenpanel.SuspendLayout();
-			this.udmfpanel.SuspendLayout();
-			this.settingsgroup.SuspendLayout();
-			this.tabs.SuspendLayout();
-			this.tabproperties.SuspendLayout();
-			this.idgroup.SuspendLayout();
-			this.tabsidedefs.SuspendLayout();
-			this.splitter.Panel1.SuspendLayout();
-			this.splitter.Panel2.SuspendLayout();
-			this.splitter.SuspendLayout();
-			this.frontgroup.SuspendLayout();
-			this.backgroup.SuspendLayout();
-			this.tabcustom.SuspendLayout();
-			this.SuspendLayout();
-			// 
-			// label2
-			// 
-			label2.AutoSize = true;
-			label2.Location = new System.Drawing.Point(15, 30);
-			label2.Name = "label2";
-			label2.Size = new System.Drawing.Size(41, 14);
-			label2.TabIndex = 9;
-			label2.Text = "Action:";
-			// 
-			// taglabel
-			// 
-			taglabel.AutoSize = true;
-			taglabel.Location = new System.Drawing.Point(28, 31);
-			taglabel.Name = "taglabel";
-			taglabel.Size = new System.Drawing.Size(28, 14);
-			taglabel.TabIndex = 6;
-			taglabel.Text = "Tag:";
-			// 
-			// label3
-			// 
-			label3.Location = new System.Drawing.Point(252, 18);
-			label3.Name = "label3";
-			label3.Size = new System.Drawing.Size(83, 16);
-			label3.TabIndex = 3;
-			label3.Text = "Upper";
-			label3.TextAlign = System.Drawing.ContentAlignment.TopCenter;
-			// 
-			// label4
-			// 
-			label4.Location = new System.Drawing.Point(343, 18);
-			label4.Name = "label4";
-			label4.Size = new System.Drawing.Size(83, 16);
-			label4.TabIndex = 4;
-			label4.Text = "Middle";
-			label4.TextAlign = System.Drawing.ContentAlignment.TopCenter;
-			// 
-			// label5
-			// 
-			label5.Location = new System.Drawing.Point(434, 18);
-			label5.Name = "label5";
-			label5.Size = new System.Drawing.Size(83, 16);
-			label5.TabIndex = 5;
-			label5.Text = "Lower";
-			label5.TextAlign = System.Drawing.ContentAlignment.TopCenter;
-			// 
-			// label6
-			// 
-			label6.AutoSize = true;
-			label6.Location = new System.Drawing.Point(16, 79);
-			label6.Name = "label6";
-			label6.Size = new System.Drawing.Size(81, 14);
-			label6.TabIndex = 7;
-			label6.Text = "Texture Offset:";
-			// 
-			// label7
-			// 
-			label7.AutoSize = true;
-			label7.Location = new System.Drawing.Point(16, 79);
-			label7.Name = "label7";
-			label7.Size = new System.Drawing.Size(81, 14);
-			label7.TabIndex = 7;
-			label7.Text = "Texture Offset:";
-			// 
-			// label8
-			// 
-			label8.Location = new System.Drawing.Point(437, 18);
-			label8.Name = "label8";
-			label8.Size = new System.Drawing.Size(83, 16);
-			label8.TabIndex = 5;
-			label8.Text = "Lower";
-			label8.TextAlign = System.Drawing.ContentAlignment.TopCenter;
-			// 
-			// label9
-			// 
-			label9.Location = new System.Drawing.Point(346, 18);
-			label9.Name = "label9";
-			label9.Size = new System.Drawing.Size(83, 16);
-			label9.TabIndex = 4;
-			label9.Text = "Middle";
-			label9.TextAlign = System.Drawing.ContentAlignment.TopCenter;
-			// 
-			// label10
-			// 
-			label10.Location = new System.Drawing.Point(255, 18);
-			label10.Name = "label10";
-			label10.Size = new System.Drawing.Size(83, 16);
-			label10.TabIndex = 3;
-			label10.Text = "Upper";
-			label10.TextAlign = System.Drawing.ContentAlignment.TopCenter;
-			// 
-			// label11
-			// 
-			label11.AutoSize = true;
-			label11.Location = new System.Drawing.Point(26, 40);
-			label11.Name = "label11";
-			label11.Size = new System.Drawing.Size(71, 14);
-			label11.TabIndex = 13;
-			label11.Text = "Sector Index:";
-			// 
-			// label12
-			// 
-			label12.AutoSize = true;
-			label12.Location = new System.Drawing.Point(26, 40);
-			label12.Name = "label12";
-			label12.Size = new System.Drawing.Size(71, 14);
-			label12.TabIndex = 16;
-			label12.Text = "Sector Index:";
-			// 
-			// activationlabel
-			// 
-			activationlabel.AutoSize = true;
-			activationlabel.Location = new System.Drawing.Point(6, 17);
-			activationlabel.Name = "activationlabel";
-			activationlabel.Size = new System.Drawing.Size(44, 14);
-			activationlabel.TabIndex = 10;
-			activationlabel.Text = "Trigger:";
-			// 
-			// cancel
-			// 
-			this.cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
-			this.cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
-			this.cancel.Location = new System.Drawing.Point(455, 592);
-			this.cancel.Name = "cancel";
-			this.cancel.Size = new System.Drawing.Size(112, 25);
-			this.cancel.TabIndex = 2;
-			this.cancel.Text = "Cancel";
-			this.cancel.UseVisualStyleBackColor = true;
-			this.cancel.Click += new System.EventHandler(this.cancel_Click);
-			// 
-			// apply
-			// 
-			this.apply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
-			this.apply.Location = new System.Drawing.Point(336, 592);
-			this.apply.Name = "apply";
-			this.apply.Size = new System.Drawing.Size(112, 25);
-			this.apply.TabIndex = 1;
-			this.apply.Text = "OK";
-			this.apply.UseVisualStyleBackColor = true;
-			this.apply.Click += new System.EventHandler(this.apply_Click);
-			// 
-			// actiongroup
-			// 
-			this.actiongroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-						| System.Windows.Forms.AnchorStyles.Right)));
-			this.actiongroup.Controls.Add(this.argspanel);
-			this.actiongroup.Controls.Add(this.hexenpanel);
-			this.actiongroup.Controls.Add(label2);
-			this.actiongroup.Controls.Add(this.action);
-			this.actiongroup.Controls.Add(this.browseaction);
-			this.actiongroup.Controls.Add(this.udmfpanel);
-			this.actiongroup.Location = new System.Drawing.Point(8, 177);
-			this.actiongroup.Name = "actiongroup";
-			this.actiongroup.Size = new System.Drawing.Size(533, 281);
-			this.actiongroup.TabIndex = 1;
-			this.actiongroup.TabStop = false;
-			this.actiongroup.Text = " Action ";
-			// 
-			// argspanel
-			// 
-			this.argspanel.Controls.Add(this.arg2);
-			this.argspanel.Controls.Add(this.arg1);
-			this.argspanel.Controls.Add(this.arg0);
-			this.argspanel.Controls.Add(this.arg3);
-			this.argspanel.Controls.Add(this.arg4);
-			this.argspanel.Controls.Add(this.arg1label);
-			this.argspanel.Controls.Add(this.arg0label);
-			this.argspanel.Controls.Add(this.arg3label);
-			this.argspanel.Controls.Add(this.arg2label);
-			this.argspanel.Controls.Add(this.arg4label);
-			this.argspanel.Location = new System.Drawing.Point(6, 54);
-			this.argspanel.Name = "argspanel";
-			this.argspanel.Size = new System.Drawing.Size(521, 83);
-			this.argspanel.TabIndex = 2;
-			this.argspanel.Visible = false;
-			// 
-			// arg2
-			// 
-			this.arg2.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-			this.arg2.Location = new System.Drawing.Point(123, 55);
-			this.arg2.Name = "arg2";
-			this.arg2.Size = new System.Drawing.Size(93, 24);
-			this.arg2.TabIndex = 2;
-			// 
-			// arg1
-			// 
-			this.arg1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-			this.arg1.Location = new System.Drawing.Point(123, 29);
-			this.arg1.Name = "arg1";
-			this.arg1.Size = new System.Drawing.Size(93, 24);
-			this.arg1.TabIndex = 1;
-			// 
-			// arg0
-			// 
-			this.arg0.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-			this.arg0.Location = new System.Drawing.Point(123, 3);
-			this.arg0.Name = "arg0";
-			this.arg0.Size = new System.Drawing.Size(93, 24);
-			this.arg0.TabIndex = 0;
-			// 
-			// arg3
-			// 
-			this.arg3.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-			this.arg3.Location = new System.Drawing.Point(364, 3);
-			this.arg3.Name = "arg3";
-			this.arg3.Size = new System.Drawing.Size(93, 24);
-			this.arg3.TabIndex = 3;
-			// 
-			// arg4
-			// 
-			this.arg4.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-			this.arg4.Location = new System.Drawing.Point(364, 29);
-			this.arg4.Name = "arg4";
-			this.arg4.Size = new System.Drawing.Size(93, 24);
-			this.arg4.TabIndex = 4;
-			// 
-			// arg1label
-			// 
-			this.arg1label.Location = new System.Drawing.Point(-62, 34);
-			this.arg1label.Name = "arg1label";
-			this.arg1label.Size = new System.Drawing.Size(179, 14);
-			this.arg1label.TabIndex = 33;
-			this.arg1label.Text = "Argument 2:";
-			this.arg1label.TextAlign = System.Drawing.ContentAlignment.TopRight;
-			this.arg1label.UseMnemonic = false;
-			// 
-			// arg0label
-			// 
-			this.arg0label.Location = new System.Drawing.Point(-62, 8);
-			this.arg0label.Name = "arg0label";
-			this.arg0label.Size = new System.Drawing.Size(179, 14);
-			this.arg0label.TabIndex = 32;
-			this.arg0label.Text = "Argument 1:";
-			this.arg0label.TextAlign = System.Drawing.ContentAlignment.TopRight;
-			this.arg0label.UseMnemonic = false;
-			// 
-			// arg3label
-			// 
-			this.arg3label.Location = new System.Drawing.Point(179, 8);
-			this.arg3label.Name = "arg3label";
-			this.arg3label.Size = new System.Drawing.Size(179, 14);
-			this.arg3label.TabIndex = 36;
-			this.arg3label.Text = "Argument 4:";
-			this.arg3label.TextAlign = System.Drawing.ContentAlignment.TopRight;
-			this.arg3label.UseMnemonic = false;
-			// 
-			// arg2label
-			// 
-			this.arg2label.Location = new System.Drawing.Point(-62, 60);
-			this.arg2label.Name = "arg2label";
-			this.arg2label.Size = new System.Drawing.Size(179, 14);
-			this.arg2label.TabIndex = 35;
-			this.arg2label.Text = "Argument 3:";
-			this.arg2label.TextAlign = System.Drawing.ContentAlignment.TopRight;
-			this.arg2label.UseMnemonic = false;
-			// 
-			// arg4label
-			// 
-			this.arg4label.Location = new System.Drawing.Point(179, 34);
-			this.arg4label.Name = "arg4label";
-			this.arg4label.Size = new System.Drawing.Size(179, 14);
-			this.arg4label.TabIndex = 34;
-			this.arg4label.Text = "Argument 5:";
-			this.arg4label.TextAlign = System.Drawing.ContentAlignment.TopRight;
-			this.arg4label.UseMnemonic = false;
-			// 
-			// hexenpanel
-			// 
-			this.hexenpanel.Controls.Add(this.activation);
-			this.hexenpanel.Controls.Add(activationlabel);
-			this.hexenpanel.Location = new System.Drawing.Point(6, 139);
-			this.hexenpanel.Name = "hexenpanel";
-			this.hexenpanel.Size = new System.Drawing.Size(521, 49);
-			this.hexenpanel.TabIndex = 3;
-			this.hexenpanel.Visible = false;
-			// 
-			// activation
-			// 
-			this.activation.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-			this.activation.FormattingEnabled = true;
-			this.activation.Location = new System.Drawing.Point(56, 13);
-			this.activation.Name = "activation";
-			this.activation.Size = new System.Drawing.Size(437, 22);
-			this.activation.TabIndex = 0;
-			// 
-			// action
-			// 
-			this.action.BackColor = System.Drawing.Color.Transparent;
-			this.action.Cursor = System.Windows.Forms.Cursors.Default;
-			this.action.Empty = false;
-			this.action.GeneralizedCategories = null;
-			this.action.Location = new System.Drawing.Point(62, 27);
-			this.action.Name = "action";
-			this.action.Size = new System.Drawing.Size(401, 21);
-			this.action.TabIndex = 0;
-			this.action.Value = 402;
-			this.action.ValueChanges += new System.EventHandler(this.action_ValueChanges);
-			// 
-			// browseaction
-			// 
-			this.browseaction.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-			this.browseaction.Image = global::CodeImp.DoomBuilder.Properties.Resources.List;
-			this.browseaction.Location = new System.Drawing.Point(469, 25);
-			this.browseaction.Name = "browseaction";
-			this.browseaction.Padding = new System.Windows.Forms.Padding(0, 0, 1, 3);
-			this.browseaction.Size = new System.Drawing.Size(28, 25);
-			this.browseaction.TabIndex = 1;
-			this.browseaction.Text = " ";
-			this.browseaction.UseVisualStyleBackColor = true;
-			this.browseaction.Click += new System.EventHandler(this.browseaction_Click);
-			// 
-			// udmfpanel
-			// 
-			this.udmfpanel.Controls.Add(this.udmfactivates);
-			this.udmfpanel.Location = new System.Drawing.Point(6, 143);
-			this.udmfpanel.Name = "udmfpanel";
-			this.udmfpanel.Size = new System.Drawing.Size(505, 132);
-			this.udmfpanel.TabIndex = 4;
-			this.udmfpanel.Visible = false;
-			// 
-			// udmfactivates
-			// 
-			this.udmfactivates.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-						| System.Windows.Forms.AnchorStyles.Left)
-						| System.Windows.Forms.AnchorStyles.Right)));
-			this.udmfactivates.AutoScroll = true;
-			this.udmfactivates.Columns = 2;
-			this.udmfactivates.Location = new System.Drawing.Point(56, 5);
-			this.udmfactivates.Name = "udmfactivates";
-			this.udmfactivates.Size = new System.Drawing.Size(437, 123);
-			this.udmfactivates.TabIndex = 0;
-			// 
-			// newtag
-			// 
-			this.newtag.Location = new System.Drawing.Point(149, 27);
-			this.newtag.Name = "newtag";
-			this.newtag.Size = new System.Drawing.Size(76, 23);
-			this.newtag.TabIndex = 1;
-			this.newtag.Text = "New Tag";
-			this.newtag.UseVisualStyleBackColor = true;
-			this.newtag.Click += new System.EventHandler(this.newtag_Click);
-			// 
-			// settingsgroup
-			// 
-			this.settingsgroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-						| System.Windows.Forms.AnchorStyles.Right)));
-			this.settingsgroup.Controls.Add(this.flags);
-			this.settingsgroup.Location = new System.Drawing.Point(8, 8);
-			this.settingsgroup.Name = "settingsgroup";
-			this.settingsgroup.Size = new System.Drawing.Size(533, 163);
-			this.settingsgroup.TabIndex = 0;
-			this.settingsgroup.TabStop = false;
-			this.settingsgroup.Text = " Settings ";
-			// 
-			// flags
-			// 
-			this.flags.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-						| System.Windows.Forms.AnchorStyles.Left)
-						| System.Windows.Forms.AnchorStyles.Right)));
-			this.flags.AutoScroll = true;
-			this.flags.Columns = 3;
-			this.flags.Location = new System.Drawing.Point(18, 26);
-			this.flags.Name = "flags";
-			this.flags.Size = new System.Drawing.Size(509, 125);
-			this.flags.TabIndex = 0;
-			// 
-			// checkBox1
-			// 
-			this.checkBox1.Location = new System.Drawing.Point(0, 0);
-			this.checkBox1.Name = "checkBox1";
-			this.checkBox1.Size = new System.Drawing.Size(104, 24);
-			this.checkBox1.TabIndex = 0;
-			this.checkBox1.Text = "checkBox1";
-			this.checkBox1.UseVisualStyleBackColor = true;
-			// 
-			// tabs
-			// 
-			this.tabs.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-						| System.Windows.Forms.AnchorStyles.Left)
-						| System.Windows.Forms.AnchorStyles.Right)));
-			this.tabs.Controls.Add(this.tabproperties);
-			this.tabs.Controls.Add(this.tabsidedefs);
-			this.tabs.Controls.Add(this.tabcustom);
-			this.tabs.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-			this.tabs.Location = new System.Drawing.Point(10, 10);
-			this.tabs.Margin = new System.Windows.Forms.Padding(1);
-			this.tabs.Name = "tabs";
-			this.tabs.SelectedIndex = 0;
-			this.tabs.Size = new System.Drawing.Size(557, 565);
-			this.tabs.SizeMode = System.Windows.Forms.TabSizeMode.Fixed;
-			this.tabs.TabIndex = 0;
-			// 
-			// tabproperties
-			// 
-			this.tabproperties.Controls.Add(this.idgroup);
-			this.tabproperties.Controls.Add(this.settingsgroup);
-			this.tabproperties.Controls.Add(this.actiongroup);
-			this.tabproperties.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-			this.tabproperties.Location = new System.Drawing.Point(4, 23);
-			this.tabproperties.Name = "tabproperties";
-			this.tabproperties.Padding = new System.Windows.Forms.Padding(5);
-			this.tabproperties.Size = new System.Drawing.Size(549, 538);
-			this.tabproperties.TabIndex = 0;
-			this.tabproperties.Text = "Properties";
-			this.tabproperties.UseVisualStyleBackColor = true;
-			// 
-			// idgroup
-			// 
-			this.idgroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-						| System.Windows.Forms.AnchorStyles.Right)));
-			this.idgroup.Controls.Add(this.tag);
-			this.idgroup.Controls.Add(taglabel);
-			this.idgroup.Controls.Add(this.newtag);
-			this.idgroup.Location = new System.Drawing.Point(8, 464);
-			this.idgroup.Name = "idgroup";
-			this.idgroup.Size = new System.Drawing.Size(533, 66);
-			this.idgroup.TabIndex = 2;
-			this.idgroup.TabStop = false;
-			this.idgroup.Text = " Identification ";
-			// 
-			// tag
-			// 
-			this.tag.AllowDecimal = false;
-			this.tag.AllowNegative = false;
-			this.tag.AllowRelative = true;
-			this.tag.ButtonStep = 1;
-			this.tag.Location = new System.Drawing.Point(62, 26);
-			this.tag.Name = "tag";
-			this.tag.Size = new System.Drawing.Size(75, 24);
-			this.tag.StepValues = null;
-			this.tag.TabIndex = 7;
-			// 
-			// tabsidedefs
-			// 
-			this.tabsidedefs.Controls.Add(this.splitter);
-			this.tabsidedefs.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-			this.tabsidedefs.Location = new System.Drawing.Point(4, 23);
-			this.tabsidedefs.Name = "tabsidedefs";
-			this.tabsidedefs.Padding = new System.Windows.Forms.Padding(5);
-			this.tabsidedefs.Size = new System.Drawing.Size(549, 538);
-			this.tabsidedefs.TabIndex = 1;
-			this.tabsidedefs.Text = "Sidedefs";
-			this.tabsidedefs.UseVisualStyleBackColor = true;
-			// 
-			// splitter
-			// 
-			this.splitter.Dock = System.Windows.Forms.DockStyle.Fill;
-			this.splitter.IsSplitterFixed = true;
-			this.splitter.Location = new System.Drawing.Point(5, 5);
-			this.splitter.Name = "splitter";
-			this.splitter.Orientation = System.Windows.Forms.Orientation.Horizontal;
-			// 
-			// splitter.Panel1
-			// 
-			this.splitter.Panel1.Controls.Add(this.frontside);
-			this.splitter.Panel1.Controls.Add(this.frontgroup);
-			// 
-			// splitter.Panel2
-			// 
-			this.splitter.Panel2.Controls.Add(this.backside);
-			this.splitter.Panel2.Controls.Add(this.backgroup);
-			this.splitter.Size = new System.Drawing.Size(539, 528);
-			this.splitter.SplitterDistance = 256;
-			this.splitter.TabIndex = 3;
-			// 
-			// frontside
-			// 
-			this.frontside.AutoSize = true;
-			this.frontside.Location = new System.Drawing.Point(15, 1);
-			this.frontside.Name = "frontside";
-			this.frontside.Size = new System.Drawing.Size(75, 18);
-			this.frontside.TabIndex = 0;
-			this.frontside.Text = "Front Side";
-			this.frontside.UseVisualStyleBackColor = true;
-			this.frontside.CheckStateChanged += new System.EventHandler(this.frontside_CheckStateChanged);
-			// 
-			// frontgroup
-			// 
-			this.frontgroup.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-						| System.Windows.Forms.AnchorStyles.Left)
-						| System.Windows.Forms.AnchorStyles.Right)));
-			this.frontgroup.Controls.Add(this.frontoffsety);
-			this.frontgroup.Controls.Add(this.frontoffsetx);
-			this.frontgroup.Controls.Add(this.frontsector);
-			this.frontgroup.Controls.Add(this.customfrontbutton);
-			this.frontgroup.Controls.Add(label11);
-			this.frontgroup.Controls.Add(this.frontlow);
-			this.frontgroup.Controls.Add(this.frontmid);
-			this.frontgroup.Controls.Add(this.fronthigh);
-			this.frontgroup.Controls.Add(label6);
-			this.frontgroup.Controls.Add(label5);
-			this.frontgroup.Controls.Add(label4);
-			this.frontgroup.Controls.Add(label3);
-			this.frontgroup.Enabled = false;
-			this.frontgroup.Location = new System.Drawing.Point(3, 3);
-			this.frontgroup.Name = "frontgroup";
-			this.frontgroup.Size = new System.Drawing.Size(533, 250);
-			this.frontgroup.TabIndex = 1;
-			this.frontgroup.TabStop = false;
-			this.frontgroup.Text = "     ";
-			// 
-			// frontoffsety
-			// 
-			this.frontoffsety.AllowDecimal = false;
-			this.frontoffsety.AllowNegative = true;
-			this.frontoffsety.AllowRelative = true;
-			this.frontoffsety.ButtonStep = 1;
-			this.frontoffsety.Location = new System.Drawing.Point(171, 74);
-			this.frontoffsety.Name = "frontoffsety";
-			this.frontoffsety.Size = new System.Drawing.Size(62, 24);
-			this.frontoffsety.StepValues = null;
-			this.frontoffsety.TabIndex = 16;
-			// 
-			// frontoffsetx
-			// 
-			this.frontoffsetx.AllowDecimal = false;
-			this.frontoffsetx.AllowNegative = true;
-			this.frontoffsetx.AllowRelative = true;
-			this.frontoffsetx.ButtonStep = 1;
-			this.frontoffsetx.Location = new System.Drawing.Point(103, 74);
-			this.frontoffsetx.Name = "frontoffsetx";
-			this.frontoffsetx.Size = new System.Drawing.Size(62, 24);
-			this.frontoffsetx.StepValues = null;
-			this.frontoffsetx.TabIndex = 15;
-			// 
-			// frontsector
-			// 
-			this.frontsector.AllowDecimal = false;
-			this.frontsector.AllowNegative = false;
-			this.frontsector.AllowRelative = false;
-			this.frontsector.ButtonStep = 1;
-			this.frontsector.Location = new System.Drawing.Point(103, 35);
-			this.frontsector.Name = "frontsector";
-			this.frontsector.Size = new System.Drawing.Size(130, 24);
-			this.frontsector.StepValues = null;
-			this.frontsector.TabIndex = 14;
-			// 
-			// customfrontbutton
-			// 
-			this.customfrontbutton.Location = new System.Drawing.Point(103, 124);
-			this.customfrontbutton.Name = "customfrontbutton";
-			this.customfrontbutton.Size = new System.Drawing.Size(115, 25);
-			this.customfrontbutton.TabIndex = 3;
-			this.customfrontbutton.Text = "Custom fields...";
-			this.customfrontbutton.UseVisualStyleBackColor = true;
-			this.customfrontbutton.Visible = false;
-			this.customfrontbutton.Click += new System.EventHandler(this.customfrontbutton_Click);
-			// 
-			// frontlow
-			// 
-			this.frontlow.Location = new System.Drawing.Point(434, 37);
-			this.frontlow.Name = "frontlow";
-			this.frontlow.Required = false;
-			this.frontlow.Size = new System.Drawing.Size(83, 112);
-			this.frontlow.TabIndex = 6;
-			this.frontlow.TextureName = "";
-			// 
-			// frontmid
-			// 
-			this.frontmid.Location = new System.Drawing.Point(343, 37);
-			this.frontmid.Name = "frontmid";
-			this.frontmid.Required = false;
-			this.frontmid.Size = new System.Drawing.Size(83, 112);
-			this.frontmid.TabIndex = 5;
-			this.frontmid.TextureName = "";
-			// 
-			// fronthigh
-			// 
-			this.fronthigh.Location = new System.Drawing.Point(252, 37);
-			this.fronthigh.Name = "fronthigh";
-			this.fronthigh.Required = false;
-			this.fronthigh.Size = new System.Drawing.Size(83, 112);
-			this.fronthigh.TabIndex = 4;
-			this.fronthigh.TextureName = "";
-			// 
-			// backside
-			// 
-			this.backside.AutoSize = true;
-			this.backside.Location = new System.Drawing.Point(15, 1);
-			this.backside.Name = "backside";
-			this.backside.Size = new System.Drawing.Size(74, 18);
-			this.backside.TabIndex = 0;
-			this.backside.Text = "Back Side";
-			this.backside.UseVisualStyleBackColor = true;
-			this.backside.CheckStateChanged += new System.EventHandler(this.backside_CheckStateChanged);
-			// 
-			// backgroup
-			// 
-			this.backgroup.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-						| System.Windows.Forms.AnchorStyles.Left)
-						| System.Windows.Forms.AnchorStyles.Right)));
-			this.backgroup.Controls.Add(this.backoffsety);
-			this.backgroup.Controls.Add(this.backoffsetx);
-			this.backgroup.Controls.Add(this.backsector);
-			this.backgroup.Controls.Add(this.custombackbutton);
-			this.backgroup.Controls.Add(label12);
-			this.backgroup.Controls.Add(this.backlow);
-			this.backgroup.Controls.Add(this.backmid);
-			this.backgroup.Controls.Add(this.backhigh);
-			this.backgroup.Controls.Add(label7);
-			this.backgroup.Controls.Add(label8);
-			this.backgroup.Controls.Add(label9);
-			this.backgroup.Controls.Add(label10);
-			this.backgroup.Enabled = false;
-			this.backgroup.Location = new System.Drawing.Point(3, 3);
-			this.backgroup.Name = "backgroup";
-			this.backgroup.Size = new System.Drawing.Size(535, 262);
-			this.backgroup.TabIndex = 1;
-			this.backgroup.TabStop = false;
-			this.backgroup.Text = "     ";
-			// 
-			// backoffsety
-			// 
-			this.backoffsety.AllowDecimal = false;
-			this.backoffsety.AllowNegative = true;
-			this.backoffsety.AllowRelative = true;
-			this.backoffsety.ButtonStep = 1;
-			this.backoffsety.Location = new System.Drawing.Point(171, 74);
-			this.backoffsety.Name = "backoffsety";
-			this.backoffsety.Size = new System.Drawing.Size(62, 24);
-			this.backoffsety.StepValues = null;
-			this.backoffsety.TabIndex = 19;
-			// 
-			// backoffsetx
-			// 
-			this.backoffsetx.AllowDecimal = false;
-			this.backoffsetx.AllowNegative = true;
-			this.backoffsetx.AllowRelative = true;
-			this.backoffsetx.ButtonStep = 1;
-			this.backoffsetx.Location = new System.Drawing.Point(103, 74);
-			this.backoffsetx.Name = "backoffsetx";
-			this.backoffsetx.Size = new System.Drawing.Size(62, 24);
-			this.backoffsetx.StepValues = null;
-			this.backoffsetx.TabIndex = 18;
-			// 
-			// backsector
-			// 
-			this.backsector.AllowDecimal = false;
-			this.backsector.AllowNegative = false;
-			this.backsector.AllowRelative = false;
-			this.backsector.ButtonStep = 1;
-			this.backsector.Location = new System.Drawing.Point(103, 35);
-			this.backsector.Name = "backsector";
-			this.backsector.Size = new System.Drawing.Size(130, 24);
-			this.backsector.StepValues = null;
-			this.backsector.TabIndex = 17;
-			// 
-			// custombackbutton
-			// 
-			this.custombackbutton.Location = new System.Drawing.Point(103, 124);
-			this.custombackbutton.Name = "custombackbutton";
-			this.custombackbutton.Size = new System.Drawing.Size(115, 25);
-			this.custombackbutton.TabIndex = 3;
-			this.custombackbutton.Text = "Custom fields...";
-			this.custombackbutton.UseVisualStyleBackColor = true;
-			this.custombackbutton.Visible = false;
-			this.custombackbutton.Click += new System.EventHandler(this.custombackbutton_Click);
-			// 
-			// backlow
-			// 
-			this.backlow.Location = new System.Drawing.Point(437, 37);
-			this.backlow.Name = "backlow";
-			this.backlow.Required = false;
-			this.backlow.Size = new System.Drawing.Size(83, 112);
-			this.backlow.TabIndex = 6;
-			this.backlow.TextureName = "";
-			// 
-			// backmid
-			// 
-			this.backmid.Location = new System.Drawing.Point(346, 37);
-			this.backmid.Name = "backmid";
-			this.backmid.Required = false;
-			this.backmid.Size = new System.Drawing.Size(83, 112);
-			this.backmid.TabIndex = 5;
-			this.backmid.TextureName = "";
-			// 
-			// backhigh
-			// 
-			this.backhigh.Location = new System.Drawing.Point(255, 37);
-			this.backhigh.Name = "backhigh";
-			this.backhigh.Required = false;
-			this.backhigh.Size = new System.Drawing.Size(83, 112);
-			this.backhigh.TabIndex = 4;
-			this.backhigh.TextureName = "";
-			// 
-			// tabcustom
-			// 
-			this.tabcustom.Controls.Add(this.fieldslist);
-			this.tabcustom.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-			this.tabcustom.Location = new System.Drawing.Point(4, 23);
-			this.tabcustom.Name = "tabcustom";
-			this.tabcustom.Padding = new System.Windows.Forms.Padding(3);
-			this.tabcustom.Size = new System.Drawing.Size(549, 538);
-			this.tabcustom.TabIndex = 2;
-			this.tabcustom.Text = "Custom";
-			this.tabcustom.UseVisualStyleBackColor = true;
-			// 
-			// fieldslist
-			// 
-			this.fieldslist.AllowInsert = true;
-			this.fieldslist.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-						| System.Windows.Forms.AnchorStyles.Left)
-						| System.Windows.Forms.AnchorStyles.Right)));
-			this.fieldslist.AutoInsertUserPrefix = true;
-			this.fieldslist.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
-			this.fieldslist.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-			this.fieldslist.Location = new System.Drawing.Point(11, 11);
-			this.fieldslist.Margin = new System.Windows.Forms.Padding(8);
-			this.fieldslist.Name = "fieldslist";
-			this.fieldslist.PropertyColumnVisible = true;
-			this.fieldslist.PropertyColumnWidth = 150;
-			this.fieldslist.Size = new System.Drawing.Size(511, 516);
-			this.fieldslist.TabIndex = 0;
-			this.fieldslist.TypeColumnVisible = true;
-			this.fieldslist.TypeColumnWidth = 100;
-			this.fieldslist.ValueColumnVisible = true;
-			// 
-			// heightpanel1
-			// 
-			this.heightpanel1.BackColor = System.Drawing.Color.Navy;
-			this.heightpanel1.Location = new System.Drawing.Point(0, -19);
-			this.heightpanel1.Name = "heightpanel1";
-			this.heightpanel1.Size = new System.Drawing.Size(78, 510);
-			this.heightpanel1.TabIndex = 3;
-			this.heightpanel1.Visible = false;
-			// 
-			// heightpanel2
-			// 
-			this.heightpanel2.BackColor = System.Drawing.Color.Navy;
-			this.heightpanel2.Location = new System.Drawing.Point(473, -19);
-			this.heightpanel2.Name = "heightpanel2";
-			this.heightpanel2.Size = new System.Drawing.Size(88, 470);
-			this.heightpanel2.TabIndex = 4;
-			this.heightpanel2.Visible = false;
-			// 
-			// LinedefEditForm
-			// 
-			this.AcceptButton = this.apply;
-			this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
-			this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
-			this.CancelButton = this.cancel;
-			this.ClientSize = new System.Drawing.Size(577, 627);
-			this.Controls.Add(this.tabs);
-			this.Controls.Add(this.cancel);
-			this.Controls.Add(this.apply);
-			this.Controls.Add(this.heightpanel1);
-			this.Controls.Add(this.heightpanel2);
-			this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
-			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
-			this.MaximizeBox = false;
-			this.MinimizeBox = false;
-			this.Name = "LinedefEditForm";
-			this.Opacity = 0;
-			this.ShowIcon = false;
-			this.ShowInTaskbar = false;
-			this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
-			this.Text = "Edit Linedef";
-			this.HelpRequested += new System.Windows.Forms.HelpEventHandler(this.LinedefEditForm_HelpRequested);
-			this.actiongroup.ResumeLayout(false);
-			this.actiongroup.PerformLayout();
-			this.argspanel.ResumeLayout(false);
-			this.hexenpanel.ResumeLayout(false);
-			this.hexenpanel.PerformLayout();
-			this.udmfpanel.ResumeLayout(false);
-			this.settingsgroup.ResumeLayout(false);
-			this.tabs.ResumeLayout(false);
-			this.tabproperties.ResumeLayout(false);
-			this.idgroup.ResumeLayout(false);
-			this.idgroup.PerformLayout();
-			this.tabsidedefs.ResumeLayout(false);
-			this.splitter.Panel1.ResumeLayout(false);
-			this.splitter.Panel1.PerformLayout();
-			this.splitter.Panel2.ResumeLayout(false);
-			this.splitter.Panel2.PerformLayout();
-			this.splitter.ResumeLayout(false);
-			this.frontgroup.ResumeLayout(false);
-			this.frontgroup.PerformLayout();
-			this.backgroup.ResumeLayout(false);
-			this.backgroup.PerformLayout();
-			this.tabcustom.ResumeLayout(false);
-			this.ResumeLayout(false);
+            System.Windows.Forms.Label label2;
+            System.Windows.Forms.Label taglabel;
+            System.Windows.Forms.Label label3;
+            System.Windows.Forms.Label label4;
+            System.Windows.Forms.Label label5;
+            System.Windows.Forms.Label label6;
+            System.Windows.Forms.Label label7;
+            System.Windows.Forms.Label label8;
+            System.Windows.Forms.Label label9;
+            System.Windows.Forms.Label label10;
+            System.Windows.Forms.Label label11;
+            System.Windows.Forms.Label label12;
+            System.Windows.Forms.Label activationlabel;
+            this.cancel = new System.Windows.Forms.Button();
+            this.apply = new System.Windows.Forms.Button();
+            this.actiongroup = new System.Windows.Forms.GroupBox();
+            this.argspanel = new System.Windows.Forms.Panel();
+            this.arg2 = new CodeImp.DoomBuilder.Controls.ArgumentBox();
+            this.arg1 = new CodeImp.DoomBuilder.Controls.ArgumentBox();
+            this.arg0 = new CodeImp.DoomBuilder.Controls.ArgumentBox();
+            this.arg3 = new CodeImp.DoomBuilder.Controls.ArgumentBox();
+            this.arg4 = new CodeImp.DoomBuilder.Controls.ArgumentBox();
+            this.arg1label = new System.Windows.Forms.Label();
+            this.arg0label = new System.Windows.Forms.Label();
+            this.arg3label = new System.Windows.Forms.Label();
+            this.arg2label = new System.Windows.Forms.Label();
+            this.arg4label = new System.Windows.Forms.Label();
+            this.hexenpanel = new System.Windows.Forms.Panel();
+            this.activation = new System.Windows.Forms.ComboBox();
+            this.action = new CodeImp.DoomBuilder.Controls.ActionSelectorControl();
+            this.browseaction = new System.Windows.Forms.Button();
+            this.udmfpanel = new System.Windows.Forms.Panel();
+            this.udmfactivates = new CodeImp.DoomBuilder.Controls.CheckboxArrayControl();
+            this.newtag = new System.Windows.Forms.Button();
+            this.settingsgroup = new System.Windows.Forms.GroupBox();
+            this.flags = new CodeImp.DoomBuilder.Controls.CheckboxArrayControl();
+            this.checkBox1 = new System.Windows.Forms.CheckBox();
+            this.tabs = new System.Windows.Forms.TabControl();
+            this.tabproperties = new System.Windows.Forms.TabPage();
+            this.idgroup = new System.Windows.Forms.GroupBox();
+            this.tag = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+            this.tabsidedefs = new System.Windows.Forms.TabPage();
+            this.splitter = new System.Windows.Forms.SplitContainer();
+            this.frontside = new System.Windows.Forms.CheckBox();
+            this.frontgroup = new System.Windows.Forms.GroupBox();
+            this.frontoffsety = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+            this.frontoffsetx = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+            this.frontsector = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+            this.customfrontbutton = new System.Windows.Forms.Button();
+            this.frontlow = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
+            this.frontmid = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
+            this.fronthigh = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
+            this.backside = new System.Windows.Forms.CheckBox();
+            this.backgroup = new System.Windows.Forms.GroupBox();
+            this.backoffsety = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+            this.backoffsetx = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+            this.backsector = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox();
+            this.custombackbutton = new System.Windows.Forms.Button();
+            this.backlow = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
+            this.backmid = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
+            this.backhigh = new CodeImp.DoomBuilder.Controls.TextureSelectorControl();
+            this.tabcustom = new System.Windows.Forms.TabPage();
+            this.fieldslist = new CodeImp.DoomBuilder.Controls.FieldsEditorControl();
+            this.heightpanel1 = new System.Windows.Forms.Panel();
+            this.heightpanel2 = new System.Windows.Forms.Panel();
+            label2 = new System.Windows.Forms.Label();
+            taglabel = new System.Windows.Forms.Label();
+            label3 = new System.Windows.Forms.Label();
+            label4 = new System.Windows.Forms.Label();
+            label5 = new System.Windows.Forms.Label();
+            label6 = new System.Windows.Forms.Label();
+            label7 = new System.Windows.Forms.Label();
+            label8 = new System.Windows.Forms.Label();
+            label9 = new System.Windows.Forms.Label();
+            label10 = new System.Windows.Forms.Label();
+            label11 = new System.Windows.Forms.Label();
+            label12 = new System.Windows.Forms.Label();
+            activationlabel = new System.Windows.Forms.Label();
+            this.actiongroup.SuspendLayout();
+            this.argspanel.SuspendLayout();
+            this.hexenpanel.SuspendLayout();
+            this.udmfpanel.SuspendLayout();
+            this.settingsgroup.SuspendLayout();
+            this.tabs.SuspendLayout();
+            this.tabproperties.SuspendLayout();
+            this.idgroup.SuspendLayout();
+            this.tabsidedefs.SuspendLayout();
+            this.splitter.Panel1.SuspendLayout();
+            this.splitter.Panel2.SuspendLayout();
+            this.splitter.SuspendLayout();
+            this.frontgroup.SuspendLayout();
+            this.backgroup.SuspendLayout();
+            this.tabcustom.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // label2
+            // 
+            label2.AutoSize = true;
+            label2.Location = new System.Drawing.Point(15, 30);
+            label2.Name = "label2";
+            label2.Size = new System.Drawing.Size(41, 14);
+            label2.TabIndex = 9;
+            label2.Text = "Action:";
+            // 
+            // taglabel
+            // 
+            taglabel.AutoSize = true;
+            taglabel.Location = new System.Drawing.Point(28, 31);
+            taglabel.Name = "taglabel";
+            taglabel.Size = new System.Drawing.Size(28, 14);
+            taglabel.TabIndex = 6;
+            taglabel.Text = "Tag:";
+            // 
+            // label3
+            // 
+            label3.Location = new System.Drawing.Point(252, 18);
+            label3.Name = "label3";
+            label3.Size = new System.Drawing.Size(83, 16);
+            label3.TabIndex = 3;
+            label3.Text = "Upper";
+            label3.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // label4
+            // 
+            label4.Location = new System.Drawing.Point(343, 18);
+            label4.Name = "label4";
+            label4.Size = new System.Drawing.Size(83, 16);
+            label4.TabIndex = 4;
+            label4.Text = "Middle";
+            label4.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // label5
+            // 
+            label5.Location = new System.Drawing.Point(434, 18);
+            label5.Name = "label5";
+            label5.Size = new System.Drawing.Size(83, 16);
+            label5.TabIndex = 5;
+            label5.Text = "Lower";
+            label5.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // label6
+            // 
+            label6.AutoSize = true;
+            label6.Location = new System.Drawing.Point(16, 79);
+            label6.Name = "label6";
+            label6.Size = new System.Drawing.Size(81, 14);
+            label6.TabIndex = 7;
+            label6.Text = "Texture Offset:";
+            // 
+            // label7
+            // 
+            label7.AutoSize = true;
+            label7.Location = new System.Drawing.Point(16, 79);
+            label7.Name = "label7";
+            label7.Size = new System.Drawing.Size(81, 14);
+            label7.TabIndex = 7;
+            label7.Text = "Texture Offset:";
+            // 
+            // label8
+            // 
+            label8.Location = new System.Drawing.Point(437, 18);
+            label8.Name = "label8";
+            label8.Size = new System.Drawing.Size(83, 16);
+            label8.TabIndex = 5;
+            label8.Text = "Lower";
+            label8.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // label9
+            // 
+            label9.Location = new System.Drawing.Point(346, 18);
+            label9.Name = "label9";
+            label9.Size = new System.Drawing.Size(83, 16);
+            label9.TabIndex = 4;
+            label9.Text = "Middle";
+            label9.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // label10
+            // 
+            label10.Location = new System.Drawing.Point(255, 18);
+            label10.Name = "label10";
+            label10.Size = new System.Drawing.Size(83, 16);
+            label10.TabIndex = 3;
+            label10.Text = "Upper";
+            label10.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+            // 
+            // label11
+            // 
+            label11.AutoSize = true;
+            label11.Location = new System.Drawing.Point(26, 40);
+            label11.Name = "label11";
+            label11.Size = new System.Drawing.Size(71, 14);
+            label11.TabIndex = 13;
+            label11.Text = "Sector Index:";
+            // 
+            // label12
+            // 
+            label12.AutoSize = true;
+            label12.Location = new System.Drawing.Point(26, 40);
+            label12.Name = "label12";
+            label12.Size = new System.Drawing.Size(71, 14);
+            label12.TabIndex = 16;
+            label12.Text = "Sector Index:";
+            // 
+            // activationlabel
+            // 
+            activationlabel.AutoSize = true;
+            activationlabel.Location = new System.Drawing.Point(6, 17);
+            activationlabel.Name = "activationlabel";
+            activationlabel.Size = new System.Drawing.Size(44, 14);
+            activationlabel.TabIndex = 10;
+            activationlabel.Text = "Trigger:";
+            // 
+            // cancel
+            // 
+            this.cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            this.cancel.Location = new System.Drawing.Point(455, 592);
+            this.cancel.Name = "cancel";
+            this.cancel.Size = new System.Drawing.Size(112, 25);
+            this.cancel.TabIndex = 2;
+            this.cancel.Text = "Cancel";
+            this.cancel.UseVisualStyleBackColor = true;
+            this.cancel.Click += new System.EventHandler(this.cancel_Click);
+            // 
+            // apply
+            // 
+            this.apply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+            this.apply.Location = new System.Drawing.Point(336, 592);
+            this.apply.Name = "apply";
+            this.apply.Size = new System.Drawing.Size(112, 25);
+            this.apply.TabIndex = 1;
+            this.apply.Text = "OK";
+            this.apply.UseVisualStyleBackColor = true;
+            this.apply.Click += new System.EventHandler(this.apply_Click);
+            // 
+            // actiongroup
+            // 
+            this.actiongroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.actiongroup.Controls.Add(this.argspanel);
+            this.actiongroup.Controls.Add(this.hexenpanel);
+            this.actiongroup.Controls.Add(label2);
+            this.actiongroup.Controls.Add(this.action);
+            this.actiongroup.Controls.Add(this.browseaction);
+            this.actiongroup.Controls.Add(this.udmfpanel);
+            this.actiongroup.Location = new System.Drawing.Point(8, 181);
+            this.actiongroup.Name = "actiongroup";
+            this.actiongroup.Size = new System.Drawing.Size(533, 291);
+            this.actiongroup.TabIndex = 1;
+            this.actiongroup.TabStop = false;
+            this.actiongroup.Text = " Action ";
+            // 
+            // argspanel
+            // 
+            this.argspanel.Controls.Add(this.arg2);
+            this.argspanel.Controls.Add(this.arg1);
+            this.argspanel.Controls.Add(this.arg0);
+            this.argspanel.Controls.Add(this.arg3);
+            this.argspanel.Controls.Add(this.arg4);
+            this.argspanel.Controls.Add(this.arg1label);
+            this.argspanel.Controls.Add(this.arg0label);
+            this.argspanel.Controls.Add(this.arg3label);
+            this.argspanel.Controls.Add(this.arg2label);
+            this.argspanel.Controls.Add(this.arg4label);
+            this.argspanel.Location = new System.Drawing.Point(6, 54);
+            this.argspanel.Name = "argspanel";
+            this.argspanel.Size = new System.Drawing.Size(521, 83);
+            this.argspanel.TabIndex = 2;
+            this.argspanel.Visible = false;
+            // 
+            // arg2
+            // 
+            this.arg2.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.arg2.Location = new System.Drawing.Point(123, 55);
+            this.arg2.Name = "arg2";
+            this.arg2.Size = new System.Drawing.Size(93, 24);
+            this.arg2.TabIndex = 2;
+            // 
+            // arg1
+            // 
+            this.arg1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.arg1.Location = new System.Drawing.Point(123, 29);
+            this.arg1.Name = "arg1";
+            this.arg1.Size = new System.Drawing.Size(93, 24);
+            this.arg1.TabIndex = 1;
+            // 
+            // arg0
+            // 
+            this.arg0.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.arg0.Location = new System.Drawing.Point(123, 3);
+            this.arg0.Name = "arg0";
+            this.arg0.Size = new System.Drawing.Size(93, 24);
+            this.arg0.TabIndex = 0;
+            // 
+            // arg3
+            // 
+            this.arg3.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.arg3.Location = new System.Drawing.Point(364, 3);
+            this.arg3.Name = "arg3";
+            this.arg3.Size = new System.Drawing.Size(93, 24);
+            this.arg3.TabIndex = 3;
+            // 
+            // arg4
+            // 
+            this.arg4.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.arg4.Location = new System.Drawing.Point(364, 29);
+            this.arg4.Name = "arg4";
+            this.arg4.Size = new System.Drawing.Size(93, 24);
+            this.arg4.TabIndex = 4;
+            // 
+            // arg1label
+            // 
+            this.arg1label.Location = new System.Drawing.Point(-62, 34);
+            this.arg1label.Name = "arg1label";
+            this.arg1label.Size = new System.Drawing.Size(179, 14);
+            this.arg1label.TabIndex = 33;
+            this.arg1label.Text = "Argument 2:";
+            this.arg1label.TextAlign = System.Drawing.ContentAlignment.TopRight;
+            this.arg1label.UseMnemonic = false;
+            // 
+            // arg0label
+            // 
+            this.arg0label.Location = new System.Drawing.Point(-62, 8);
+            this.arg0label.Name = "arg0label";
+            this.arg0label.Size = new System.Drawing.Size(179, 14);
+            this.arg0label.TabIndex = 32;
+            this.arg0label.Text = "Argument 1:";
+            this.arg0label.TextAlign = System.Drawing.ContentAlignment.TopRight;
+            this.arg0label.UseMnemonic = false;
+            // 
+            // arg3label
+            // 
+            this.arg3label.Location = new System.Drawing.Point(179, 8);
+            this.arg3label.Name = "arg3label";
+            this.arg3label.Size = new System.Drawing.Size(179, 14);
+            this.arg3label.TabIndex = 36;
+            this.arg3label.Text = "Argument 4:";
+            this.arg3label.TextAlign = System.Drawing.ContentAlignment.TopRight;
+            this.arg3label.UseMnemonic = false;
+            // 
+            // arg2label
+            // 
+            this.arg2label.Location = new System.Drawing.Point(-62, 60);
+            this.arg2label.Name = "arg2label";
+            this.arg2label.Size = new System.Drawing.Size(179, 14);
+            this.arg2label.TabIndex = 35;
+            this.arg2label.Text = "Argument 3:";
+            this.arg2label.TextAlign = System.Drawing.ContentAlignment.TopRight;
+            this.arg2label.UseMnemonic = false;
+            // 
+            // arg4label
+            // 
+            this.arg4label.Location = new System.Drawing.Point(179, 34);
+            this.arg4label.Name = "arg4label";
+            this.arg4label.Size = new System.Drawing.Size(179, 14);
+            this.arg4label.TabIndex = 34;
+            this.arg4label.Text = "Argument 5:";
+            this.arg4label.TextAlign = System.Drawing.ContentAlignment.TopRight;
+            this.arg4label.UseMnemonic = false;
+            // 
+            // hexenpanel
+            // 
+            this.hexenpanel.Controls.Add(this.activation);
+            this.hexenpanel.Controls.Add(activationlabel);
+            this.hexenpanel.Location = new System.Drawing.Point(6, 139);
+            this.hexenpanel.Name = "hexenpanel";
+            this.hexenpanel.Size = new System.Drawing.Size(521, 49);
+            this.hexenpanel.TabIndex = 3;
+            this.hexenpanel.Visible = false;
+            // 
+            // activation
+            // 
+            this.activation.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+            this.activation.FormattingEnabled = true;
+            this.activation.Location = new System.Drawing.Point(56, 13);
+            this.activation.Name = "activation";
+            this.activation.Size = new System.Drawing.Size(437, 22);
+            this.activation.TabIndex = 0;
+            // 
+            // action
+            // 
+            this.action.BackColor = System.Drawing.Color.Transparent;
+            this.action.Cursor = System.Windows.Forms.Cursors.Default;
+            this.action.Empty = false;
+            this.action.GeneralizedCategories = null;
+            this.action.Location = new System.Drawing.Point(62, 27);
+            this.action.Name = "action";
+            this.action.Size = new System.Drawing.Size(401, 21);
+            this.action.TabIndex = 0;
+            this.action.Value = 402;
+            this.action.ValueChanges += new System.EventHandler(this.action_ValueChanges);
+            // 
+            // browseaction
+            // 
+            this.browseaction.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.browseaction.Image = global::CodeImp.DoomBuilder.Properties.Resources.List;
+            this.browseaction.Location = new System.Drawing.Point(469, 25);
+            this.browseaction.Name = "browseaction";
+            this.browseaction.Padding = new System.Windows.Forms.Padding(0, 0, 1, 3);
+            this.browseaction.Size = new System.Drawing.Size(28, 25);
+            this.browseaction.TabIndex = 1;
+            this.browseaction.Text = " ";
+            this.browseaction.UseVisualStyleBackColor = true;
+            this.browseaction.Click += new System.EventHandler(this.browseaction_Click);
+            // 
+            // udmfpanel
+            // 
+            this.udmfpanel.Controls.Add(this.udmfactivates);
+            this.udmfpanel.Location = new System.Drawing.Point(6, 143);
+            this.udmfpanel.Name = "udmfpanel";
+            this.udmfpanel.Size = new System.Drawing.Size(505, 142);
+            this.udmfpanel.TabIndex = 4;
+            this.udmfpanel.Visible = false;
+            // 
+            // udmfactivates
+            // 
+            this.udmfactivates.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                        | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.udmfactivates.AutoScroll = true;
+            this.udmfactivates.Columns = 2;
+            this.udmfactivates.Location = new System.Drawing.Point(56, 5);
+            this.udmfactivates.Name = "udmfactivates";
+            this.udmfactivates.Size = new System.Drawing.Size(437, 133);
+            this.udmfactivates.TabIndex = 0;
+            // 
+            // newtag
+            // 
+            this.newtag.Location = new System.Drawing.Point(149, 27);
+            this.newtag.Name = "newtag";
+            this.newtag.Size = new System.Drawing.Size(76, 23);
+            this.newtag.TabIndex = 1;
+            this.newtag.Text = "New Tag";
+            this.newtag.UseVisualStyleBackColor = true;
+            this.newtag.Click += new System.EventHandler(this.newtag_Click);
+            // 
+            // settingsgroup
+            // 
+            this.settingsgroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.settingsgroup.Controls.Add(this.flags);
+            this.settingsgroup.Location = new System.Drawing.Point(8, 3);
+            this.settingsgroup.Name = "settingsgroup";
+            this.settingsgroup.Size = new System.Drawing.Size(533, 172);
+            this.settingsgroup.TabIndex = 0;
+            this.settingsgroup.TabStop = false;
+            this.settingsgroup.Text = " Settings ";
+            // 
+            // flags
+            // 
+            this.flags.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                        | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.flags.AutoScroll = true;
+            this.flags.Columns = 3;
+            this.flags.Location = new System.Drawing.Point(18, 19);
+            this.flags.Name = "flags";
+            this.flags.Size = new System.Drawing.Size(509, 147);
+            this.flags.TabIndex = 0;
+            // 
+            // checkBox1
+            // 
+            this.checkBox1.Location = new System.Drawing.Point(0, 0);
+            this.checkBox1.Name = "checkBox1";
+            this.checkBox1.Size = new System.Drawing.Size(104, 24);
+            this.checkBox1.TabIndex = 0;
+            this.checkBox1.Text = "checkBox1";
+            this.checkBox1.UseVisualStyleBackColor = true;
+            // 
+            // tabs
+            // 
+            this.tabs.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                        | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.tabs.Controls.Add(this.tabproperties);
+            this.tabs.Controls.Add(this.tabsidedefs);
+            this.tabs.Controls.Add(this.tabcustom);
+            this.tabs.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.tabs.Location = new System.Drawing.Point(10, 10);
+            this.tabs.Margin = new System.Windows.Forms.Padding(1);
+            this.tabs.Name = "tabs";
+            this.tabs.SelectedIndex = 0;
+            this.tabs.Size = new System.Drawing.Size(557, 578);
+            this.tabs.SizeMode = System.Windows.Forms.TabSizeMode.Fixed;
+            this.tabs.TabIndex = 0;
+            // 
+            // tabproperties
+            // 
+            this.tabproperties.Controls.Add(this.idgroup);
+            this.tabproperties.Controls.Add(this.settingsgroup);
+            this.tabproperties.Controls.Add(this.actiongroup);
+            this.tabproperties.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.tabproperties.Location = new System.Drawing.Point(4, 23);
+            this.tabproperties.Name = "tabproperties";
+            this.tabproperties.Padding = new System.Windows.Forms.Padding(5);
+            this.tabproperties.Size = new System.Drawing.Size(549, 551);
+            this.tabproperties.TabIndex = 0;
+            this.tabproperties.Text = "Properties";
+            this.tabproperties.UseVisualStyleBackColor = true;
+            // 
+            // idgroup
+            // 
+            this.idgroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.idgroup.Controls.Add(this.tag);
+            this.idgroup.Controls.Add(taglabel);
+            this.idgroup.Controls.Add(this.newtag);
+            this.idgroup.Location = new System.Drawing.Point(8, 478);
+            this.idgroup.Name = "idgroup";
+            this.idgroup.Size = new System.Drawing.Size(533, 66);
+            this.idgroup.TabIndex = 2;
+            this.idgroup.TabStop = false;
+            this.idgroup.Text = " Identification ";
+            // 
+            // tag
+            // 
+            this.tag.AllowDecimal = false;
+            this.tag.AllowNegative = false;
+            this.tag.AllowRelative = true;
+            this.tag.ButtonStep = 1;
+            this.tag.Location = new System.Drawing.Point(62, 26);
+            this.tag.Name = "tag";
+            this.tag.Size = new System.Drawing.Size(75, 24);
+            this.tag.StepValues = null;
+            this.tag.TabIndex = 7;
+            // 
+            // tabsidedefs
+            // 
+            this.tabsidedefs.Controls.Add(this.splitter);
+            this.tabsidedefs.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.tabsidedefs.Location = new System.Drawing.Point(4, 23);
+            this.tabsidedefs.Name = "tabsidedefs";
+            this.tabsidedefs.Padding = new System.Windows.Forms.Padding(5);
+            this.tabsidedefs.Size = new System.Drawing.Size(549, 551);
+            this.tabsidedefs.TabIndex = 1;
+            this.tabsidedefs.Text = "Sidedefs";
+            this.tabsidedefs.UseVisualStyleBackColor = true;
+            // 
+            // splitter
+            // 
+            this.splitter.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.splitter.IsSplitterFixed = true;
+            this.splitter.Location = new System.Drawing.Point(5, 5);
+            this.splitter.Name = "splitter";
+            this.splitter.Orientation = System.Windows.Forms.Orientation.Horizontal;
+            // 
+            // splitter.Panel1
+            // 
+            this.splitter.Panel1.Controls.Add(this.frontside);
+            this.splitter.Panel1.Controls.Add(this.frontgroup);
+            // 
+            // splitter.Panel2
+            // 
+            this.splitter.Panel2.Controls.Add(this.backside);
+            this.splitter.Panel2.Controls.Add(this.backgroup);
+            this.splitter.Size = new System.Drawing.Size(539, 541);
+            this.splitter.SplitterDistance = 262;
+            this.splitter.TabIndex = 3;
+            // 
+            // frontside
+            // 
+            this.frontside.AutoSize = true;
+            this.frontside.Location = new System.Drawing.Point(15, 1);
+            this.frontside.Name = "frontside";
+            this.frontside.Size = new System.Drawing.Size(75, 18);
+            this.frontside.TabIndex = 0;
+            this.frontside.Text = "Front Side";
+            this.frontside.UseVisualStyleBackColor = true;
+            this.frontside.CheckStateChanged += new System.EventHandler(this.frontside_CheckStateChanged);
+            // 
+            // frontgroup
+            // 
+            this.frontgroup.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                        | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.frontgroup.Controls.Add(this.frontoffsety);
+            this.frontgroup.Controls.Add(this.frontoffsetx);
+            this.frontgroup.Controls.Add(this.frontsector);
+            this.frontgroup.Controls.Add(this.customfrontbutton);
+            this.frontgroup.Controls.Add(label11);
+            this.frontgroup.Controls.Add(this.frontlow);
+            this.frontgroup.Controls.Add(this.frontmid);
+            this.frontgroup.Controls.Add(this.fronthigh);
+            this.frontgroup.Controls.Add(label6);
+            this.frontgroup.Controls.Add(label5);
+            this.frontgroup.Controls.Add(label4);
+            this.frontgroup.Controls.Add(label3);
+            this.frontgroup.Enabled = false;
+            this.frontgroup.Location = new System.Drawing.Point(3, 3);
+            this.frontgroup.Name = "frontgroup";
+            this.frontgroup.Size = new System.Drawing.Size(533, 256);
+            this.frontgroup.TabIndex = 1;
+            this.frontgroup.TabStop = false;
+            this.frontgroup.Text = "     ";
+            // 
+            // frontoffsety
+            // 
+            this.frontoffsety.AllowDecimal = false;
+            this.frontoffsety.AllowNegative = true;
+            this.frontoffsety.AllowRelative = true;
+            this.frontoffsety.ButtonStep = 1;
+            this.frontoffsety.Location = new System.Drawing.Point(171, 74);
+            this.frontoffsety.Name = "frontoffsety";
+            this.frontoffsety.Size = new System.Drawing.Size(62, 24);
+            this.frontoffsety.StepValues = null;
+            this.frontoffsety.TabIndex = 16;
+            // 
+            // frontoffsetx
+            // 
+            this.frontoffsetx.AllowDecimal = false;
+            this.frontoffsetx.AllowNegative = true;
+            this.frontoffsetx.AllowRelative = true;
+            this.frontoffsetx.ButtonStep = 1;
+            this.frontoffsetx.Location = new System.Drawing.Point(103, 74);
+            this.frontoffsetx.Name = "frontoffsetx";
+            this.frontoffsetx.Size = new System.Drawing.Size(62, 24);
+            this.frontoffsetx.StepValues = null;
+            this.frontoffsetx.TabIndex = 15;
+            // 
+            // frontsector
+            // 
+            this.frontsector.AllowDecimal = false;
+            this.frontsector.AllowNegative = false;
+            this.frontsector.AllowRelative = false;
+            this.frontsector.ButtonStep = 1;
+            this.frontsector.Location = new System.Drawing.Point(103, 35);
+            this.frontsector.Name = "frontsector";
+            this.frontsector.Size = new System.Drawing.Size(130, 24);
+            this.frontsector.StepValues = null;
+            this.frontsector.TabIndex = 14;
+            // 
+            // customfrontbutton
+            // 
+            this.customfrontbutton.Location = new System.Drawing.Point(103, 124);
+            this.customfrontbutton.Name = "customfrontbutton";
+            this.customfrontbutton.Size = new System.Drawing.Size(115, 25);
+            this.customfrontbutton.TabIndex = 3;
+            this.customfrontbutton.Text = "Custom fields...";
+            this.customfrontbutton.UseVisualStyleBackColor = true;
+            this.customfrontbutton.Visible = false;
+            this.customfrontbutton.Click += new System.EventHandler(this.customfrontbutton_Click);
+            // 
+            // frontlow
+            // 
+            this.frontlow.Location = new System.Drawing.Point(434, 37);
+            this.frontlow.Name = "frontlow";
+            this.frontlow.Required = false;
+            this.frontlow.Size = new System.Drawing.Size(83, 112);
+            this.frontlow.TabIndex = 6;
+            this.frontlow.TextureName = "";
+            // 
+            // frontmid
+            // 
+            this.frontmid.Location = new System.Drawing.Point(343, 37);
+            this.frontmid.Name = "frontmid";
+            this.frontmid.Required = false;
+            this.frontmid.Size = new System.Drawing.Size(83, 112);
+            this.frontmid.TabIndex = 5;
+            this.frontmid.TextureName = "";
+            // 
+            // fronthigh
+            // 
+            this.fronthigh.Location = new System.Drawing.Point(252, 37);
+            this.fronthigh.Name = "fronthigh";
+            this.fronthigh.Required = false;
+            this.fronthigh.Size = new System.Drawing.Size(83, 112);
+            this.fronthigh.TabIndex = 4;
+            this.fronthigh.TextureName = "";
+            // 
+            // backside
+            // 
+            this.backside.AutoSize = true;
+            this.backside.Location = new System.Drawing.Point(15, 1);
+            this.backside.Name = "backside";
+            this.backside.Size = new System.Drawing.Size(74, 18);
+            this.backside.TabIndex = 0;
+            this.backside.Text = "Back Side";
+            this.backside.UseVisualStyleBackColor = true;
+            this.backside.CheckStateChanged += new System.EventHandler(this.backside_CheckStateChanged);
+            // 
+            // backgroup
+            // 
+            this.backgroup.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                        | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.backgroup.Controls.Add(this.backoffsety);
+            this.backgroup.Controls.Add(this.backoffsetx);
+            this.backgroup.Controls.Add(this.backsector);
+            this.backgroup.Controls.Add(this.custombackbutton);
+            this.backgroup.Controls.Add(label12);
+            this.backgroup.Controls.Add(this.backlow);
+            this.backgroup.Controls.Add(this.backmid);
+            this.backgroup.Controls.Add(this.backhigh);
+            this.backgroup.Controls.Add(label7);
+            this.backgroup.Controls.Add(label8);
+            this.backgroup.Controls.Add(label9);
+            this.backgroup.Controls.Add(label10);
+            this.backgroup.Enabled = false;
+            this.backgroup.Location = new System.Drawing.Point(3, 3);
+            this.backgroup.Name = "backgroup";
+            this.backgroup.Size = new System.Drawing.Size(535, 269);
+            this.backgroup.TabIndex = 1;
+            this.backgroup.TabStop = false;
+            this.backgroup.Text = "     ";
+            // 
+            // backoffsety
+            // 
+            this.backoffsety.AllowDecimal = false;
+            this.backoffsety.AllowNegative = true;
+            this.backoffsety.AllowRelative = true;
+            this.backoffsety.ButtonStep = 1;
+            this.backoffsety.Location = new System.Drawing.Point(171, 74);
+            this.backoffsety.Name = "backoffsety";
+            this.backoffsety.Size = new System.Drawing.Size(62, 24);
+            this.backoffsety.StepValues = null;
+            this.backoffsety.TabIndex = 19;
+            // 
+            // backoffsetx
+            // 
+            this.backoffsetx.AllowDecimal = false;
+            this.backoffsetx.AllowNegative = true;
+            this.backoffsetx.AllowRelative = true;
+            this.backoffsetx.ButtonStep = 1;
+            this.backoffsetx.Location = new System.Drawing.Point(103, 74);
+            this.backoffsetx.Name = "backoffsetx";
+            this.backoffsetx.Size = new System.Drawing.Size(62, 24);
+            this.backoffsetx.StepValues = null;
+            this.backoffsetx.TabIndex = 18;
+            // 
+            // backsector
+            // 
+            this.backsector.AllowDecimal = false;
+            this.backsector.AllowNegative = false;
+            this.backsector.AllowRelative = false;
+            this.backsector.ButtonStep = 1;
+            this.backsector.Location = new System.Drawing.Point(103, 35);
+            this.backsector.Name = "backsector";
+            this.backsector.Size = new System.Drawing.Size(130, 24);
+            this.backsector.StepValues = null;
+            this.backsector.TabIndex = 17;
+            // 
+            // custombackbutton
+            // 
+            this.custombackbutton.Location = new System.Drawing.Point(103, 124);
+            this.custombackbutton.Name = "custombackbutton";
+            this.custombackbutton.Size = new System.Drawing.Size(115, 25);
+            this.custombackbutton.TabIndex = 3;
+            this.custombackbutton.Text = "Custom fields...";
+            this.custombackbutton.UseVisualStyleBackColor = true;
+            this.custombackbutton.Visible = false;
+            this.custombackbutton.Click += new System.EventHandler(this.custombackbutton_Click);
+            // 
+            // backlow
+            // 
+            this.backlow.Location = new System.Drawing.Point(437, 37);
+            this.backlow.Name = "backlow";
+            this.backlow.Required = false;
+            this.backlow.Size = new System.Drawing.Size(83, 112);
+            this.backlow.TabIndex = 6;
+            this.backlow.TextureName = "";
+            // 
+            // backmid
+            // 
+            this.backmid.Location = new System.Drawing.Point(346, 37);
+            this.backmid.Name = "backmid";
+            this.backmid.Required = false;
+            this.backmid.Size = new System.Drawing.Size(83, 112);
+            this.backmid.TabIndex = 5;
+            this.backmid.TextureName = "";
+            // 
+            // backhigh
+            // 
+            this.backhigh.Location = new System.Drawing.Point(255, 37);
+            this.backhigh.Name = "backhigh";
+            this.backhigh.Required = false;
+            this.backhigh.Size = new System.Drawing.Size(83, 112);
+            this.backhigh.TabIndex = 4;
+            this.backhigh.TextureName = "";
+            // 
+            // tabcustom
+            // 
+            this.tabcustom.Controls.Add(this.fieldslist);
+            this.tabcustom.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.tabcustom.Location = new System.Drawing.Point(4, 23);
+            this.tabcustom.Name = "tabcustom";
+            this.tabcustom.Padding = new System.Windows.Forms.Padding(3);
+            this.tabcustom.Size = new System.Drawing.Size(549, 551);
+            this.tabcustom.TabIndex = 2;
+            this.tabcustom.Text = "Custom";
+            this.tabcustom.UseVisualStyleBackColor = true;
+            // 
+            // fieldslist
+            // 
+            this.fieldslist.AllowInsert = true;
+            this.fieldslist.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+                        | System.Windows.Forms.AnchorStyles.Left)
+                        | System.Windows.Forms.AnchorStyles.Right)));
+            this.fieldslist.AutoInsertUserPrefix = true;
+            this.fieldslist.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
+            this.fieldslist.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.fieldslist.Location = new System.Drawing.Point(11, 11);
+            this.fieldslist.Margin = new System.Windows.Forms.Padding(8);
+            this.fieldslist.Name = "fieldslist";
+            this.fieldslist.PropertyColumnVisible = true;
+            this.fieldslist.PropertyColumnWidth = 150;
+            this.fieldslist.Size = new System.Drawing.Size(511, 529);
+            this.fieldslist.TabIndex = 0;
+            this.fieldslist.TypeColumnVisible = true;
+            this.fieldslist.TypeColumnWidth = 100;
+            this.fieldslist.ValueColumnVisible = true;
+            // 
+            // heightpanel1
+            // 
+            this.heightpanel1.BackColor = System.Drawing.Color.Navy;
+            this.heightpanel1.Location = new System.Drawing.Point(0, -19);
+            this.heightpanel1.Name = "heightpanel1";
+            this.heightpanel1.Size = new System.Drawing.Size(78, 480);
+            this.heightpanel1.TabIndex = 3;
+            this.heightpanel1.Visible = false;
+            // 
+            // heightpanel2
+            // 
+            this.heightpanel2.BackColor = System.Drawing.Color.Navy;
+            this.heightpanel2.Location = new System.Drawing.Point(473, -19);
+            this.heightpanel2.Name = "heightpanel2";
+            this.heightpanel2.Size = new System.Drawing.Size(88, 470);
+            this.heightpanel2.TabIndex = 4;
+            this.heightpanel2.Visible = false;
+            // 
+            // LinedefEditForm
+            // 
+            this.AcceptButton = this.apply;
+            this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+            this.CancelButton = this.cancel;
+            this.ClientSize = new System.Drawing.Size(577, 627);
+            this.Controls.Add(this.tabs);
+            this.Controls.Add(this.cancel);
+            this.Controls.Add(this.apply);
+            this.Controls.Add(this.heightpanel1);
+            this.Controls.Add(this.heightpanel2);
+            this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+            this.MaximizeBox = false;
+            this.MinimizeBox = false;
+            this.Name = "LinedefEditForm";
+            this.Opacity = 0;
+            this.ShowIcon = false;
+            this.ShowInTaskbar = false;
+            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+            this.Text = "Edit Linedef";
+            this.HelpRequested += new System.Windows.Forms.HelpEventHandler(this.LinedefEditForm_HelpRequested);
+            this.actiongroup.ResumeLayout(false);
+            this.actiongroup.PerformLayout();
+            this.argspanel.ResumeLayout(false);
+            this.hexenpanel.ResumeLayout(false);
+            this.hexenpanel.PerformLayout();
+            this.udmfpanel.ResumeLayout(false);
+            this.settingsgroup.ResumeLayout(false);
+            this.tabs.ResumeLayout(false);
+            this.tabproperties.ResumeLayout(false);
+            this.idgroup.ResumeLayout(false);
+            this.idgroup.PerformLayout();
+            this.tabsidedefs.ResumeLayout(false);
+            this.splitter.Panel1.ResumeLayout(false);
+            this.splitter.Panel1.PerformLayout();
+            this.splitter.Panel2.ResumeLayout(false);
+            this.splitter.Panel2.PerformLayout();
+            this.splitter.ResumeLayout(false);
+            this.frontgroup.ResumeLayout(false);
+            this.frontgroup.PerformLayout();
+            this.backgroup.ResumeLayout(false);
+            this.backgroup.PerformLayout();
+            this.tabcustom.ResumeLayout(false);
+            this.ResumeLayout(false);
 
 		}
 
diff --git a/Source/Core/Windows/LinedefEditForm.cs b/Source/Core/Windows/LinedefEditForm.cs
index 2d6c0161e15b52dd2ba2ce77539740faf94a6a17..86d327ae2e02f3c7dc20d5178483773e61a9033e 100644
--- a/Source/Core/Windows/LinedefEditForm.cs
+++ b/Source/Core/Windows/LinedefEditForm.cs
@@ -91,7 +91,9 @@ namespace CodeImp.DoomBuilder.Windows
 			// Arrange panels
 			if(General.Map.FormatInterface.HasPresetActivations)
 			{
-				actiongroup.Height = hexenpanel.Bottom + action.Top + (actiongroup.Width - actiongroup.ClientRectangle.Width);
+				//mxd
+                //actiongroup.Height = hexenpanel.Bottom + action.Top + (actiongroup.Width - actiongroup.ClientRectangle.Width);
+                actiongroup.Height = hexenpanel.Location.Y + hexenpanel.Height;
 				this.Height = heightpanel1.Height;
 			}
 			else if(!General.Map.FormatInterface.HasMixedActivations &&
diff --git a/Source/Core/Windows/LinedefEditForm.resx b/Source/Core/Windows/LinedefEditForm.resx
index 5b456d1cd24f41961592dfefe69b5464943988f0..d853157aeb2d12c50a75fc89bb3a6f33dd293247 100644
--- a/Source/Core/Windows/LinedefEditForm.resx
+++ b/Source/Core/Windows/LinedefEditForm.resx
@@ -201,9 +201,6 @@
   <metadata name="apply.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="actiongroup.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-    <value>True</value>
-  </metadata>
   <metadata name="argspanel.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
@@ -252,30 +249,18 @@
   <metadata name="udmfpanel.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="udmfactivates.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-    <value>True</value>
-  </metadata>
   <metadata name="newtag.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="settingsgroup.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-    <value>True</value>
-  </metadata>
   <metadata name="flags.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
   <metadata name="checkBox1.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="tabs.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-    <value>True</value>
-  </metadata>
   <metadata name="tabproperties.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
-  <metadata name="idgroup.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-    <value>True</value>
-  </metadata>
   <metadata name="tag.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
diff --git a/Source/Plugins/BuilderModes/BuilderModes.csproj b/Source/Plugins/BuilderModes/BuilderModes.csproj
index 14952c35464182038050d38d62b14f93f8d61923..902a664250bdbbde4fd63c06c30da7acc70f47b1 100644
--- a/Source/Plugins/BuilderModes/BuilderModes.csproj
+++ b/Source/Plugins/BuilderModes/BuilderModes.csproj
@@ -241,6 +241,7 @@
     <Compile Include="ClassicModes\BridgeMode.cs" />
     <Compile Include="ClassicModes\DrawEllipseMode.cs" />
     <Compile Include="ClassicModes\DrawRectangleMode.cs" />
+    <Compile Include="ClassicModes\SnapVerticesMode.cs" />
     <Compile Include="ErrorChecks\CheckMissingTextures.cs" />
     <Compile Include="ErrorChecks\CheckUnknownFlats.cs" />
     <Compile Include="ErrorChecks\CheckUnknownTextures.cs" />
@@ -332,6 +333,9 @@
   <ItemGroup>
     <EmbeddedResource Include="Resources\BridgeMode.png" />
   </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Resources\SnapVerts.png" />
+  </ItemGroup>
   <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.
diff --git a/Source/Plugins/BuilderModes/ClassicModes/SnapVerticesMode.cs b/Source/Plugins/BuilderModes/ClassicModes/SnapVerticesMode.cs
new file mode 100644
index 0000000000000000000000000000000000000000..c3f7159cafd68630600a64f5c1cd9f4b607ac70b
--- /dev/null
+++ b/Source/Plugins/BuilderModes/ClassicModes/SnapVerticesMode.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Windows.Forms;
+
+using CodeImp.DoomBuilder.Editing;
+using CodeImp.DoomBuilder.Geometry;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.Windows;
+
+namespace CodeImp.DoomBuilder.BuilderModes.ClassicModes
+{
+    [EditMode(DisplayName = "Snap Vertices to Grid",
+              SwitchAction = "snapvertstogrid",
+              AllowCopyPaste = false,
+              Optional = false,
+              Volatile = true)]
+    public class SnapVerticesMode : BaseClassicMode
+    {
+        public SnapVerticesMode() {
+            // We have no destructor
+            GC.SuppressFinalize(this);
+        }
+        
+        // Mode engages
+        public override void OnEngage() {
+            base.OnEngage();
+
+            //get selection
+            General.Map.Map.MarkAllSelectedGeometry(true, false, true, false, false);
+            List<Vertex> verts = General.Map.Map.GetMarkedVertices(true);
+
+            //nothing selected?
+            if (verts.Count == 0) {
+                General.Interface.DisplayStatus(StatusType.Warning, "Select some vertices first!");
+                base.OnCancel();
+                General.Editing.ChangeMode(General.Editing.PreviousStableMode.Name);
+                return;
+            }
+
+            // Make undo for the snapping
+            General.Map.UndoRedo.CreateUndo("Snap vertices");
+
+            int snappedCount = 0;
+
+            //snap them all!
+            foreach (Vertex v in verts) {
+                Vector2D pos = v.Position;
+                v.SnapToGrid();
+
+                if (v.Position.x != pos.x || v.Position.y != pos.y)
+                    snappedCount++;
+            }
+
+            //done
+            General.Interface.DisplayStatus(StatusType.Info, "Snapped " + snappedCount + " vertices.");
+            base.OnAccept();
+            General.Editing.ChangeMode(General.Editing.PreviousStableMode.Name);
+        }
+
+        // Disenagaging
+        public override void OnDisengage() {
+            base.OnDisengage();
+            Cursor.Current = Cursors.AppStarting;
+
+            if (!cancelled) {
+                // Update cached values
+                General.Map.Map.Update();
+                // Map is changed
+                General.Map.IsChanged = true;
+            }
+
+            // Done
+            Cursor.Current = Cursors.Default;
+        }
+    }
+}
diff --git a/Source/Plugins/BuilderModes/General/BuilderPlug.cs b/Source/Plugins/BuilderModes/General/BuilderPlug.cs
index 5b3a162d5661a287959d09cb90bc091dc4b06864..26530fddb0aa9abed71144f6b3043254d0878f14 100644
--- a/Source/Plugins/BuilderModes/General/BuilderPlug.cs
+++ b/Source/Plugins/BuilderModes/General/BuilderPlug.cs
@@ -74,6 +74,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// Dockers
 		private UndoRedoPanel undoredopanel;
 		private Docker undoredodocker;
+
+        //mxd
+        private ToolStripMenuItem snapModeMenuItem;
 		
 		// Settings
 		private int showvisualthings;			// 0 = none, 1 = sprite only, 2 = sprite caged
@@ -178,6 +181,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			undoredopanel = new UndoRedoPanel();
 			undoredodocker = new Docker("undoredo", "Undo / Redo", undoredopanel);
 			General.Interface.AddDocker(undoredodocker);
+
+            //mxd. add "Snap Vertices" menu button
+            snapModeMenuItem = new ToolStripMenuItem("Snap selected vertices to grid");
+            snapModeMenuItem.Tag = "snapvertstogrid";
+            snapModeMenuItem.Click += new EventHandler(InvokeTaggedAction);
+            snapModeMenuItem.Image = CodeImp.DoomBuilder.BuilderModes.Properties.Resources.SnapVerts;
+            snapModeMenuItem.Enabled = false;
+            General.Interface.AddMenu(snapModeMenuItem, MenuSection.EditGeometry);
 		}
 		
 		// Disposer
@@ -307,6 +318,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			base.OnMapNewEnd();
 			undoredopanel.SetBeginDescription("New Map");
 			undoredopanel.UpdateList();
+
+            //mxd
+            snapModeMenuItem.Enabled = true;
 		}
 		
 		// Map opened
@@ -315,6 +329,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			base.OnMapOpenEnd();
 			undoredopanel.SetBeginDescription("Opened Map");
 			undoredopanel.UpdateList();
+
+            //mxd
+            snapModeMenuItem.Enabled = true;
 		}
 		
 		// Map closed
@@ -322,6 +339,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		{
 			base.OnMapCloseEnd();
 			undoredopanel.UpdateList();
+
+            //mxd
+            snapModeMenuItem.Enabled = false;
 		}
 		
 		// Redo performed
@@ -351,6 +371,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			base.OnUndoWithdrawn();
 			undoredopanel.UpdateList();
 		}
+
+        //mxd
+        private void InvokeTaggedAction(object sender, EventArgs e) {
+            General.Interface.InvokeTaggedAction(sender, e);
+        }
 		
 		#endregion
 		
diff --git a/Source/Plugins/BuilderModes/Interface/BridgeModeForm.cs b/Source/Plugins/BuilderModes/Interface/BridgeModeForm.cs
index cf7ed3464ae03259314f2861416e3318f635a1a0..1e333fd7341456c39a7b99c89b5e1040a275a420 100644
--- a/Source/Plugins/BuilderModes/Interface/BridgeModeForm.cs
+++ b/Source/Plugins/BuilderModes/Interface/BridgeModeForm.cs
@@ -67,22 +67,22 @@ namespace CodeImp.DoomBuilder.BuilderModes.Interface {
 //events
         private void BezierPathForm_FormClosed(object sender, FormClosedEventArgs e) {
             if (OnCancelClick != null)
-                OnCancelClick(this, new EventArgs());
+                OnCancelClick(this, EventArgs.Empty);
         }
 
         private void buttonCancel_Click(object sender, EventArgs e) {
             if (OnCancelClick != null)
-                OnCancelClick(this, new EventArgs());
+                OnCancelClick(this, EventArgs.Empty);
         }
 
         private void buttonOK_Click(object sender, EventArgs e) {
             if (OnOkClick != null)
-                OnOkClick(this, new EventArgs());
+                OnOkClick(this, EventArgs.Empty);
         }
 
         private void nudSubdivisions_ValueChanged(object sender, EventArgs e) {
             if (OnSubdivisionChanged != null)
-                OnSubdivisionChanged(this, new EventArgs());
+                OnSubdivisionChanged(this, EventArgs.Empty);
         }
 
         private void BezierPathForm_MouseEnter(object sender, EventArgs e) {
@@ -95,7 +95,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Interface {
 
         private void buttonFlip_Click(object sender, EventArgs e) {
             if (OnFlipClick != null)
-                OnFlipClick(this, new EventArgs());
+                OnFlipClick(this, EventArgs.Empty);
         }
 
         private void cbCopy_CheckedChanged(object sender, EventArgs e) {
diff --git a/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs b/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs
index cfeb1379c1b6773ecce1eb93a7ab7f5ee6715d61..59eca161e23e0f88291181e7ebea486ed46c90f5 100644
--- a/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs
+++ b/Source/Plugins/BuilderModes/Properties/Resources.Designer.cs
@@ -1,10 +1,10 @@
 //------------------------------------------------------------------------------
 // <auto-generated>
-//     This code was generated by a tool.
-//     Runtime Version:4.0.30319.269
+//     Этот код создан программой.
+//     Исполняемая версия:2.0.50727.5420
 //
-//     Changes to this file may cause incorrect behavior and will be lost if
-//     the code is regenerated.
+//     Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
+//     повторной генерации кода.
 // </auto-generated>
 //------------------------------------------------------------------------------
 
@@ -13,13 +13,13 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties {
     
     
     /// <summary>
-    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    ///   Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
     /// </summary>
-    // This class was auto-generated by the StronglyTypedResourceBuilder
-    // class via a tool like ResGen or Visual Studio.
-    // To add or remove a member, edit your .ResX file then rerun ResGen
-    // with the /str option, or rebuild your VS project.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    // Этот класс создан автоматически классом StronglyTypedResourceBuilder
+    // с помощью такого средства, как ResGen или Visual Studio.
+    // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
+    // с параметром /str или перестройте свой проект VS.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
     internal class Resources {
@@ -33,7 +33,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties {
         }
         
         /// <summary>
-        ///   Returns the cached ResourceManager instance used by this class.
+        ///   Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
         /// </summary>
         [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
         internal static global::System.Resources.ResourceManager ResourceManager {
@@ -47,8 +47,8 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties {
         }
         
         /// <summary>
-        ///   Overrides the current thread's CurrentUICulture property for all
-        ///   resource lookups using this strongly typed resource class.
+        ///   Перезаписывает свойство CurrentUICulture текущего потока для всех
+        ///   обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
         /// </summary>
         [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
         internal static global::System.Globalization.CultureInfo Culture {
@@ -144,6 +144,13 @@ namespace CodeImp.DoomBuilder.BuilderModes.Properties {
             }
         }
         
+        internal static System.Drawing.Bitmap SnapVerts {
+            get {
+                object obj = ResourceManager.GetObject("SnapVerts", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
         internal static System.Drawing.Bitmap Text {
             get {
                 object obj = ResourceManager.GetObject("Text", resourceCulture);
diff --git a/Source/Plugins/BuilderModes/Properties/Resources.resx b/Source/Plugins/BuilderModes/Properties/Resources.resx
index 5b7db7cdd4c58aa6702ad2f1f974fa379b8da20a..00b32dc872f5df2c37456db86c7bfac5d1c2ecd7 100644
--- a/Source/Plugins/BuilderModes/Properties/Resources.resx
+++ b/Source/Plugins/BuilderModes/Properties/Resources.resx
@@ -163,4 +163,7 @@
   <data name="Text" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>..\Resources\Text.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
+  <data name="SnapVerts" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\SnapVerts.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
 </root>
\ No newline at end of file
diff --git a/Source/Plugins/BuilderModes/Resources/Actions.cfg b/Source/Plugins/BuilderModes/Resources/Actions.cfg
index c5152257acc88db19607cf6589139abe3e840fdc..a2050ac9f25464a389aca01cdb1d440004e529ad 100644
--- a/Source/Plugins/BuilderModes/Resources/Actions.cfg
+++ b/Source/Plugins/BuilderModes/Resources/Actions.cfg
@@ -183,6 +183,16 @@ bridgemode
 	default = 131138;
 }
 
+//mxd
+snapvertstogrid
+{
+  title = "Snap Selected Vertices to Grid";
+	category = "edit";
+	description = "Snaps selected vertices to grid.";
+	allowkeys = true;
+	allowmouse = false;
+	allowscroll = false;
+}
 
 drawpoint
 {
diff --git a/Source/Plugins/BuilderModes/Resources/SnapVerts.png b/Source/Plugins/BuilderModes/Resources/SnapVerts.png
new file mode 100644
index 0000000000000000000000000000000000000000..7ce008b3cc3473010d872d4caffb72d583a0a022
Binary files /dev/null and b/Source/Plugins/BuilderModes/Resources/SnapVerts.png differ
diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs b/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs
index 1dc5747a904bac72a8eed5b2488de49eab1ff48a..ddbc2289f3619585ccafe23ded13b690f64336c3 100644
--- a/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/VisualCeiling.cs
@@ -59,7 +59,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// Constructor
 		public VisualCeiling(BaseVisualMode mode, VisualSector vs) : base(mode, vs)
 		{
-			// We have no destructor
+            //mxd
+            geoType = VisualGeometryType.CEILING;
+            
+            // We have no destructor
 			GC.SuppressFinalize(this);
 		}
 
diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs b/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs
index f1f8f259d99620edb76137456368101fbedfc160..66240773609c3b9aafefb61d73b88df8d5b187e0 100644
--- a/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/VisualFloor.cs
@@ -59,7 +59,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// Constructor
 		public VisualFloor(BaseVisualMode mode, VisualSector vs) : base(mode, vs)
 		{
-			// We have no destructor
+			//mxd
+            geoType = VisualGeometryType.FLOOR;
+            
+            // We have no destructor
 			GC.SuppressFinalize(this);
 		}
 
diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualLower.cs b/Source/Plugins/BuilderModes/VisualModes/VisualLower.cs
index 16ad6e045102ce9995961d2ef975de7032b8facb..0cc718234ce4f0bb7e7c4957eecd6cc688edb363 100644
--- a/Source/Plugins/BuilderModes/VisualModes/VisualLower.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/VisualLower.cs
@@ -58,7 +58,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// Constructor
 		public VisualLower(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s)
 		{
-			// We have no destructor
+            //mxd
+            geoType = VisualGeometryType.WALL_BOTTOM;
+            
+            // We have no destructor
 			GC.SuppressFinalize(this);
 		}
 
diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs
index 222841d6305df6fc28111472d7461e167ed4a4a0..8491876f268d35b430e907c7e31ecd2bcc5a406b 100644
--- a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleDouble.cs
@@ -58,7 +58,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// Constructor
 		public VisualMiddleDouble(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s)
 		{
-			// Set render pass
+            //mxd
+            geoType = VisualGeometryType.WALL_MIDDLE;
+            
+            // Set render pass
 			this.RenderPass = RenderPass.Mask;
 			
 			// We have no destructor
diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleSingle.cs b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleSingle.cs
index ca66d7c6190f41adc07b07776a83e5764154fc43..79b98efb321655f4b45ad81a4b63185f6dd442a4 100644
--- a/Source/Plugins/BuilderModes/VisualModes/VisualMiddleSingle.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/VisualMiddleSingle.cs
@@ -58,7 +58,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// Constructor
 		public VisualMiddleSingle(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s)
 		{
-			// We have no destructor
+            //mxd
+            geoType = VisualGeometryType.WALL_MIDDLE;
+            
+            // We have no destructor
 			GC.SuppressFinalize(this);
 		}
 
diff --git a/Source/Plugins/BuilderModes/VisualModes/VisualUpper.cs b/Source/Plugins/BuilderModes/VisualModes/VisualUpper.cs
index 8e01847de6ab9da61a4eaee911f7a2b827a1e9b3..3abb1db4b4d7ffa611b74a6ffb4b43600cfb82b4 100644
--- a/Source/Plugins/BuilderModes/VisualModes/VisualUpper.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/VisualUpper.cs
@@ -58,7 +58,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		// Constructor
 		public VisualUpper(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s)
 		{
-			// We have no destructor
+            //mxd
+            geoType = VisualGeometryType.WALL_UPPER;
+            
+            // We have no destructor
 			GC.SuppressFinalize(this);
 		}
 
diff --git a/Source/Plugins/ColorPicker/BuilderPlug.cs b/Source/Plugins/ColorPicker/BuilderPlug.cs
index 82b815ac2f09d165ec39140959af8d9721a32438..a30d79724027084e677ad9f04f702df415515fd6 100644
--- a/Source/Plugins/ColorPicker/BuilderPlug.cs
+++ b/Source/Plugins/ColorPicker/BuilderPlug.cs
@@ -26,9 +26,7 @@ namespace CodeImp.DoomBuilder.ColorPicker
         private IColorPicker form;
         private ToolsForm toolsform;
 
-        private string currentModeName = "";
-
-        private Point formLocation; //used to keep forms location constant
+        private Point formLocation; //used to keep form's location constant
 
         public override void OnInitialize() {
             if (GZBuilder.GZGeneral.Version < 1.06f) {
@@ -67,7 +65,7 @@ namespace CodeImp.DoomBuilder.ColorPicker
             if (General.Editing.Mode == null)
                 return;
 
-            currentModeName = General.Editing.Mode.GetType().Name;
+            string currentModeName = General.Editing.Mode.GetType().Name;
 
             //display one of colorPickers or tell the user why we can't do that
             if (currentModeName == "ThingsMode") {
@@ -97,7 +95,7 @@ namespace CodeImp.DoomBuilder.ColorPicker
                     if (GZBuilder.GZGeneral.UDMF && (selectedSectorsCount > 0 || General.Map.Map.SelectedSectorsCount > 0)) {
                         form = new SectorColorPicker();
                     } else {
-                        General.Interface.DisplayStatus(StatusType.Warning, "Select some lights " + (GZBuilder.GZGeneral.UDMF ? "or sectors " : "") + "first!");
+                        General.Interface.DisplayStatus(StatusType.Warning, "Select some lights " + (GZBuilder.GZGeneral.UDMF ? ", sectors or surfaces " : "") + "first!");
                         return;
                     }
                 } else {
diff --git a/Source/Plugins/ColorPicker/ColorPicker.csproj b/Source/Plugins/ColorPicker/ColorPicker.csproj
index cb0dee549db1ff9328dc617df6e85906fb93925f..f3518a8ac7280e62fab96f764850124d28f34c16 100644
--- a/Source/Plugins/ColorPicker/ColorPicker.csproj
+++ b/Source/Plugins/ColorPicker/ColorPicker.csproj
@@ -40,6 +40,7 @@
     <Reference Include="System.Drawing" />
     <Reference Include="System.Data" />
     <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
     <Reference Include="Trackbar, Version=1.0.2486.37933, Culture=neutral, PublicKeyToken=503bf28f63ad27b4">
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\..\..\Build\Trackbar.dll</HintPath>
diff --git a/Source/Plugins/ColorPicker/Controls/ColorPickerControl.cs b/Source/Plugins/ColorPicker/Controls/ColorPickerControl.cs
index 5d16ef53ce5378f046cbc9953cb71a1b6f35c37d..6f5138f83a94b1705978e325addf214282aee230 100644
--- a/Source/Plugins/ColorPicker/Controls/ColorPickerControl.cs
+++ b/Source/Plugins/ColorPicker/Controls/ColorPickerControl.cs
@@ -21,13 +21,7 @@ namespace CodeImp.DoomBuilder.ColorPicker.Controls {
         private ColorWheel colorWheel;
         private ColorHandler.RGB RGB;
 
-        public ColorHandler.RGB CurrentColor { 
-            get 
-            {
-                //GZBuilder.GZGeneral.Trace("get CurrentColor: " + RGB.Red + "," + RGB.Green + "," + RGB.Blue);
-                return RGB; 
-            } 
-        }
+        public ColorHandler.RGB CurrentColor { get { return RGB; } }
 
         private bool isInUpdate = false;
         private Color startColor;
@@ -146,8 +140,7 @@ namespace CodeImp.DoomBuilder.ColorPicker.Controls {
         }
 
         private void onPaint(object sender, System.Windows.Forms.PaintEventArgs e) {
-            // Depending on the circumstances, force a repaint
-            // of the color wheel passing different information.
+            // Depending on the circumstances, force a repaint of the color wheel passing different information.
             switch (changeType) {
                 case ChangeStyle.MouseMove:
                 case ChangeStyle.None:
diff --git a/Source/Plugins/ColorPicker/Windows/LightColorPicker.Designer.cs b/Source/Plugins/ColorPicker/Windows/LightColorPicker.Designer.cs
index fc5aaad7f841247d46d303d0190946b6d6c40c5a..9f11eede1efd29807836218cdefa6030dcf2aeb9 100644
--- a/Source/Plugins/ColorPicker/Windows/LightColorPicker.Designer.cs
+++ b/Source/Plugins/ColorPicker/Windows/LightColorPicker.Designer.cs
@@ -54,6 +54,7 @@
             this.colorPickerSlider1.ShowLimits = true;
             this.colorPickerSlider1.Size = new System.Drawing.Size(311, 45);
             this.colorPickerSlider1.TabIndex = 6;
+            this.colorPickerSlider1.Value = 0;
             // 
             // colorPickerSlider2
             // 
@@ -62,6 +63,7 @@
             this.colorPickerSlider2.ShowLimits = false;
             this.colorPickerSlider2.Size = new System.Drawing.Size(311, 48);
             this.colorPickerSlider2.TabIndex = 7;
+            this.colorPickerSlider2.Value = 0;
             // 
             // colorPickerSlider3
             // 
@@ -70,6 +72,7 @@
             this.colorPickerSlider3.ShowLimits = true;
             this.colorPickerSlider3.Size = new System.Drawing.Size(311, 48);
             this.colorPickerSlider3.TabIndex = 8;
+            this.colorPickerSlider3.Value = 0;
             // 
             // LightColorPicker
             // 
diff --git a/Source/Plugins/GZDoomEditing/VisualModes/VisualCeiling.cs b/Source/Plugins/GZDoomEditing/VisualModes/VisualCeiling.cs
index 05a98794790c12877c1974070087a3a8875fbe2b..d6688928de07d1908d1d073fc29116e9387a1450 100644
--- a/Source/Plugins/GZDoomEditing/VisualModes/VisualCeiling.cs
+++ b/Source/Plugins/GZDoomEditing/VisualModes/VisualCeiling.cs
@@ -61,7 +61,10 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
 		// Constructor
 		public VisualCeiling(BaseVisualMode mode, VisualSector vs) : base(mode, vs)
 		{
-			// We have no destructor
+            //mxd
+            geoType = VisualGeometryType.CEILING;
+            
+            // We have no destructor
 			GC.SuppressFinalize(this);
 		}
 
diff --git a/Source/Plugins/GZDoomEditing/VisualModes/VisualFloor.cs b/Source/Plugins/GZDoomEditing/VisualModes/VisualFloor.cs
index a811a979649569bb4d4c8f674e97a2289cd7412d..ad2fb5583263cba361ae31cb876992f15f3d5b40 100644
--- a/Source/Plugins/GZDoomEditing/VisualModes/VisualFloor.cs
+++ b/Source/Plugins/GZDoomEditing/VisualModes/VisualFloor.cs
@@ -61,7 +61,10 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
 		// Constructor
 		public VisualFloor(BaseVisualMode mode, VisualSector vs) : base(mode, vs)
 		{
-			// We have no destructor
+            //mxd
+            geoType = VisualGeometryType.FLOOR;
+            
+            // We have no destructor
 			GC.SuppressFinalize(this);
 		}
 
diff --git a/Source/Plugins/GZDoomEditing/VisualModes/VisualLower.cs b/Source/Plugins/GZDoomEditing/VisualModes/VisualLower.cs
index ac9aaf4596ed86817be378f78af959163f9369f6..c646ec9f71c16eb7ee76fce0fa04fb61e2fe468f 100644
--- a/Source/Plugins/GZDoomEditing/VisualModes/VisualLower.cs
+++ b/Source/Plugins/GZDoomEditing/VisualModes/VisualLower.cs
@@ -59,7 +59,10 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
 		// Constructor
 		public VisualLower(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s)
 		{
-			// We have no destructor
+            //mxd
+            geoType = VisualGeometryType.WALL_BOTTOM;
+            
+            // We have no destructor
 			GC.SuppressFinalize(this);
 		}
 		
diff --git a/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddle3D.cs b/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddle3D.cs
index c93cf53044b37015eba0614132aeb1b6f22e734f..f52fd525c26a799f1a08e23d775abd73e120086d 100644
--- a/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddle3D.cs
+++ b/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddle3D.cs
@@ -61,7 +61,10 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
 		// Constructor
 		public VisualMiddle3D(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s)
 		{
-			// We have no destructor
+            //mxd
+            geoType = VisualGeometryType.WALL_MIDDLE;
+            
+            // We have no destructor
 			GC.SuppressFinalize(this);
 		}
 		
diff --git a/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleDouble.cs b/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleDouble.cs
index 1afbddc9c4909caa4cbc126beae6ed0acfb438c2..5a70f69b2f09bf318a1bd5829585320837d08825 100644
--- a/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleDouble.cs
+++ b/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleDouble.cs
@@ -63,7 +63,10 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
 		// Constructor
 		public VisualMiddleDouble(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s)
 		{
-			// Set render pass
+            //mxd
+            geoType = VisualGeometryType.WALL_MIDDLE;
+            
+            // Set render pass
 			this.RenderPass = RenderPass.Mask;
 			
 			// We have no destructor
diff --git a/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleSingle.cs b/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleSingle.cs
index a599cb9fa6d413c2e3a92b8b194ef1356a7323af..9d8d94b5714d535049ee8beeef6eea25c4fb0819 100644
--- a/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleSingle.cs
+++ b/Source/Plugins/GZDoomEditing/VisualModes/VisualMiddleSingle.cs
@@ -59,7 +59,10 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
 		// Constructor
 		public VisualMiddleSingle(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s)
 		{
-			// We have no destructor
+            //mxd
+            geoType = VisualGeometryType.WALL_MIDDLE;
+            
+            // We have no destructor
 			GC.SuppressFinalize(this);
 		}
 		
diff --git a/Source/Plugins/GZDoomEditing/VisualModes/VisualUpper.cs b/Source/Plugins/GZDoomEditing/VisualModes/VisualUpper.cs
index 0f4180818235916a764993e8aa19497c3a4f8e0f..b19aff1d1747700831c7fd4d5bab7476ecb24dad 100644
--- a/Source/Plugins/GZDoomEditing/VisualModes/VisualUpper.cs
+++ b/Source/Plugins/GZDoomEditing/VisualModes/VisualUpper.cs
@@ -60,7 +60,10 @@ namespace CodeImp.DoomBuilder.GZDoomEditing
 		// Constructor
 		public VisualUpper(BaseVisualMode mode, VisualSector vs, Sidedef s) : base(mode, vs, s)
 		{
-			// We have no destructor
+            //mxd
+            geoType = VisualGeometryType.WALL_UPPER;
+            
+            // We have no destructor
 			GC.SuppressFinalize(this);
 		}
 
diff --git a/Source/Plugins/UMDFControls/BuilderPlug.cs b/Source/Plugins/UMDFControls/BuilderPlug.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8d22535b8b478cc6048007571db6a3906faf0a8b
--- /dev/null
+++ b/Source/Plugins/UMDFControls/BuilderPlug.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+
+using CodeImp.DoomBuilder.Plugins;
+using CodeImp.DoomBuilder.Actions;
+using CodeImp.DoomBuilder.Windows;
+using CodeImp.DoomBuilder.VisualModes;
+
+namespace CodeImp.DoomBuilder.UDMFControls
+{
+    public class BuilderPlug: Plug {
+        private static BuilderPlug me;
+        public static BuilderPlug Me { get { return me; } }
+
+        public override string Name { get { return "UDMF Controls"; } }
+
+        private UDMFControlsForm form;
+
+        private Point formLocation; //used to keep form's location constant
+
+        public override void OnInitialize() {
+            if (GZBuilder.GZGeneral.Version < 1.09f) {
+                General.ErrorLogger.Add(ErrorType.Error, "UDMFControls plugin: GZDoomBuilder 1.09 or later required!");
+                return;
+            }
+
+            base.OnInitialize();
+            me = this;
+
+            General.Actions.BindMethods(this);
+        }
+
+        /*public override void OnEditKeyDown(KeyEventArgs e) {
+            //dbg
+            GZBuilder.GZGeneral.Trace("OnEditKeyDown");
+            
+            base.OnEditKeyDown(e);
+            if(form != null){
+                form.FineMovement = General.Interface.ShiftState;
+                form.FastMovement = General.Interface.CtrlState;
+            }
+        }
+
+        public override void OnEditKeyUp(KeyEventArgs e) {
+            base.OnEditKeyUp(e);
+            if (form != null) {
+                form.FineMovement = General.Interface.ShiftState;
+                form.FastMovement = General.Interface.CtrlState;
+            }
+        }*/
+
+        public override void Dispose() {
+            base.Dispose();
+            General.Actions.UnbindMethods(this);
+
+            if (form != null) form.Close();
+            form = null;
+        }
+
+        [BeginAction("openudmfcontrols")]
+        private void openControls() {
+            if (General.Editing.Mode == null)
+                return;
+
+            if (!GZBuilder.GZGeneral.UDMF) {
+                General.Interface.DisplayStatus(StatusType.Warning, "Map in UDMF format required!");
+                return;
+            }
+
+            if (General.Editing.Mode.GetType().Name == "BaseVisualMode") {
+                if (((VisualMode)General.Editing.Mode).GetSelectedSurfaces(true).Count == 0) {
+                    General.Interface.DisplayStatus(StatusType.Warning, "Select some surfaces first!");
+                    return;
+                }
+            } else {//wrong mode
+                General.Interface.DisplayStatus(StatusType.Warning, "Switch to Visual Mode first!");
+                return;
+            }
+
+            //show form
+            form = new UDMFControlsForm();
+            if (formLocation.X == 0 && formLocation.Y == 0) {
+                Size displaySize = Plug.DisplaySize;
+                Point displayLocation = Plug.DisplayLocationAbs;
+                formLocation = new Point(displayLocation.X + displaySize.Width - form.Width - 16, displayLocation.Y + 32);
+            }
+            form.Location = formLocation;
+            form.FormClosed += new FormClosedEventHandler(form_FormClosed);
+            form.ShowDialog(Form.ActiveForm);
+        }
+
+        private void form_FormClosed(object sender, FormClosedEventArgs e) {
+            formLocation = form.Location;
+            form.Dispose();
+            form = null;
+        }
+    }
+}
diff --git a/Source/Plugins/UMDFControls/Controls/AngleControl.cs b/Source/Plugins/UMDFControls/Controls/AngleControl.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b8cdb29b05d52683f377e77f08457c3c50cb3479
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/AngleControl.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+
+namespace CodeImp.DoomBuilder.UDMFControls
+{
+    public partial class AngleControl : UserControl
+    {
+        private const float RADIANS_PER_DEGREE = (float)Math.PI / 180.0f;
+        private const float DEGREES_PER_RADIAN = 180.0f / (float)Math.PI;
+
+        private bool blockEvents;
+
+        //draw related
+        private Pen penRed;
+        private Point center;
+        private int needleLength;
+
+        //events
+        public event EventHandler OnAngleChanged;
+
+        private float angle;
+        public float Value {
+            get {
+                return (float)nudAngle.Value;
+            }
+            set {
+                prevAngle = (float)nudAngle.Value;
+                angle = General.ClampAngle(359 - value);
+                blockEvents = true;
+                nudAngle.Value = (decimal)General.ClampAngle(value);
+                blockEvents = false;
+                panelAngleControl.Invalidate();
+            }
+        }
+
+        private float prevAngle;
+        public float Delta { get { return (float)nudAngle.Value - prevAngle; } }
+
+        public bool SnapAngle;
+
+        public AngleControl() {
+            InitializeComponent();
+
+            penRed = new Pen(Color.Red, 2.0f);
+            center = new Point(panelAngleControl.Width / 2, panelAngleControl.Height / 2);
+            needleLength = center.X - 4;
+            angle = 0;
+
+            //events
+            panelAngleControl.MouseDown += new MouseEventHandler(panelAngleControl_MouseDown);
+            panelAngleControl.MouseUp += new MouseEventHandler(panelAngleControl_MouseUp);
+        }
+
+        private void update() {
+            //redraw
+            panelAngleControl.Invalidate();
+
+            //dispatch event
+            if (OnAngleChanged != null) OnAngleChanged(this, EventArgs.Empty);
+        }
+
+        private int calcDegrees(Point pt) {
+            int degrees;
+
+            if (pt.X == 0) {
+                // The point is on the y-axis. Determine whether it's above or below the x-axis, and return the 
+                // corresponding angle. Note that the orientation of the y-coordinate is backwards. That is, 
+                // A positive Y value indicates a point BELOW the x-axis.
+                if (pt.Y > 0) degrees = 270;
+                else degrees = 90;
+            } else {
+                // This value needs to be multiplied by -1 because the y-coordinate is opposite from the normal direction here.
+                // That is, a y-coordinate that's "higher" on the form has a lower y-value, in this coordinate
+                // system. So everything's off by a factor of -1 when performing the ratio calculations.
+                degrees = (int)(-Math.Atan((double)pt.Y / pt.X) * DEGREES_PER_RADIAN);
+
+                // If the x-coordinate of the selected point is to the left of the center of the circle, you 
+                // need to add 180 degrees to the angle. ArcTan only gives you a value on the right-hand side 
+                // of the circle.
+                if (pt.X < 0) degrees += 180;
+
+                // Ensure that the return value is between 0 and 360.
+                degrees = General.ClampAngle(degrees);
+            }
+            return degrees;
+        }
+
+        //events
+        private void nudAngle_ValueChanged(object sender, EventArgs e) {
+            if (!blockEvents) {
+                prevAngle = angle;
+                angle = (int)((NumericUpDown)sender).Value;
+                update();
+            }
+        }
+
+        private void panelAngleControl_Paint(object sender, PaintEventArgs e) {
+            //angle line
+            float angleDeg = (float)((angle + 450) % 360) * RADIANS_PER_DEGREE;
+            int px = center.X + (int)(Math.Sin(angleDeg) * (float)needleLength);
+            int py = center.Y + (int)(Math.Cos(angleDeg) * (float)needleLength);
+
+            e.Graphics.DrawLine(penRed, center, new Point(px, py));
+        }
+
+        //mouse events
+        private void panelAngleControl_MouseDown(object sender, MouseEventArgs e) {
+            Point delta = new Point(e.X - center.X, e.Y - center.Y);
+            int distance = (int)(Math.Sqrt(delta.X * delta.X + delta.Y * delta.Y) / center.X); //center.X == dial radius
+
+            if (distance < center.X)  //clicked inside dial
+                panelAngleControl.MouseMove += new MouseEventHandler(panelAngleControl_MouseMove);
+        }
+
+        private void panelAngleControl_MouseUp(object sender, MouseEventArgs e) {
+            panelAngleControl.MouseMove -= panelAngleControl_MouseMove;
+
+            prevAngle = (float)nudAngle.Value;
+            if (SnapAngle)
+                angle = (((int)(Math.Round((float)calcDegrees(new Point(e.X - center.X, e.Y - center.Y)) / 45f)) * 45) + 359) % 360;
+            else
+                angle = calcDegrees(new Point(e.X - center.X, e.Y - center.Y));
+
+            blockEvents = true;
+            nudAngle.Value = (decimal)(359f - angle);
+            blockEvents = false;
+            update();
+
+            //reset snap state
+            SnapAngle = false;
+        }
+
+        private void panelAngleControl_MouseMove(object sender, MouseEventArgs e) {
+            prevAngle = (float)nudAngle.Value;
+            angle = calcDegrees(new Point(e.X - center.X, e.Y - center.Y));
+            blockEvents = true;
+            nudAngle.Value = (decimal)(359f - angle);
+            blockEvents = false;
+            update();
+        }
+    }
+}
diff --git a/Source/Plugins/UMDFControls/Controls/AngleControl.designer.cs b/Source/Plugins/UMDFControls/Controls/AngleControl.designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..145030c153813590a4140f371e3bf92090e398d0
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/AngleControl.designer.cs
@@ -0,0 +1,105 @@
+namespace CodeImp.DoomBuilder.UDMFControls
+{
+    partial class AngleControl {
+        /// <summary> 
+        /// Требуется переменная конструктора.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Освободить все используемые ресурсы.
+        /// </summary>
+        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
+        protected override void Dispose(bool disposing) {
+            if (disposing && (components != null)) {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Код, автоматически созданный конструктором компонентов
+
+        /// <summary> 
+        /// Обязательный метод для поддержки конструктора - не изменяйте 
+        /// содержимое данного метода при помощи редактора кода.
+        /// </summary>
+        private void InitializeComponent() {
+            this.components = new System.ComponentModel.Container();
+            this.panelAngleControl = new System.Windows.Forms.Panel();
+            this.nudAngle = new System.Windows.Forms.NumericUpDown();
+            this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
+            this.label1 = new System.Windows.Forms.Label();
+            ((System.ComponentModel.ISupportInitialize)(this.nudAngle)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // panelAngleControl
+            // 
+            this.panelAngleControl.BackgroundImage = global::CodeImp.DoomBuilder.UDMFControls.Properties.Resources.dial;
+            this.panelAngleControl.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
+            this.panelAngleControl.Location = new System.Drawing.Point(3, 3);
+            this.panelAngleControl.Margin = new System.Windows.Forms.Padding(0);
+            this.panelAngleControl.Name = "panelAngleControl";
+            this.panelAngleControl.Size = new System.Drawing.Size(96, 96);
+            this.panelAngleControl.TabIndex = 0;
+            this.toolTip1.SetToolTip(this.panelAngleControl, "Click to set angle\r\nShift-click to set angle snapped to 45-degrees increment");
+            this.panelAngleControl.Paint += new System.Windows.Forms.PaintEventHandler(this.panelAngleControl_Paint);
+            // 
+            // nudAngle
+            // 
+            this.nudAngle.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.nudAngle.Increment = new decimal(new int[] {
+            15,
+            0,
+            0,
+            0});
+            this.nudAngle.Location = new System.Drawing.Point(45, 102);
+            this.nudAngle.Maximum = new decimal(new int[] {
+            9000,
+            0,
+            0,
+            0});
+            this.nudAngle.Minimum = new decimal(new int[] {
+            9000,
+            0,
+            0,
+            -2147483648});
+            this.nudAngle.Name = "nudAngle";
+            this.nudAngle.Size = new System.Drawing.Size(54, 20);
+            this.nudAngle.TabIndex = 1;
+            this.nudAngle.ValueChanged += new System.EventHandler(this.nudAngle_ValueChanged);
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.label1.Location = new System.Drawing.Point(4, 104);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(38, 14);
+            this.label1.TabIndex = 2;
+            this.label1.Text = "Angle:";
+            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // AngleControl
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+            this.Controls.Add(this.label1);
+            this.Controls.Add(this.nudAngle);
+            this.Controls.Add(this.panelAngleControl);
+            this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.Name = "AngleControl";
+            this.Size = new System.Drawing.Size(104, 127);
+            ((System.ComponentModel.ISupportInitialize)(this.nudAngle)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Panel panelAngleControl;
+        private System.Windows.Forms.NumericUpDown nudAngle;
+        private System.Windows.Forms.ToolTip toolTip1;
+        private System.Windows.Forms.Label label1;
+    }
+}
diff --git a/Source/Plugins/UMDFControls/Controls/AngleControl.resx b/Source/Plugins/UMDFControls/Controls/AngleControl.resx
new file mode 100644
index 0000000000000000000000000000000000000000..7ce03af83e40e77b68ba82339823f058013a8955
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/AngleControl.resx
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/UMDFControls/Controls/FloatSlider.cs b/Source/Plugins/UMDFControls/Controls/FloatSlider.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3e3e459d31e5aa761e988c191d77cddcf89ab98d
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/FloatSlider.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace CodeImp.DoomBuilder.UDMFControls
+{
+    public partial class FloatSlider : UserControl
+    {
+        private bool blockEvents;
+        public event EventHandler OnValueChanged;
+
+        public float Value {
+            get {
+                return (float)trackBar1.Value / 10f;
+            }
+            set {
+                blockEvents = true;
+                numericUpDown1.Value = (decimal)General.Clamp(value, (float)numericUpDown1.Minimum, (float)numericUpDown1.Maximum);
+                blockEvents = false;
+            }
+        }
+
+        private int previousValue;
+        private int delta;
+        public float Delta { get { return (float)delta / 10f; } }
+
+        private bool showLabels = true;
+        public bool ShowLabels {
+            get {
+                return showLabels;
+            }
+            set {
+                showLabels = value;
+                labelMin.Visible = showLabels;
+                labelMax.Visible = showLabels;
+            }
+        }
+        
+        public FloatSlider() {
+            InitializeComponent();
+            ShowLabels = showLabels;
+            numericUpDown1.DecimalPlaces = 1;
+        }
+
+        public void SetLimits(float min, float max, bool doubledLimits) {
+            blockEvents = true;
+
+            trackBar1.Value = General.Clamp(trackBar1.Value, (int)(min * 10), (int)(max * 10));
+            trackBar1.Minimum = (int)(min * 10);
+            trackBar1.Maximum = (int)(max * 10);
+
+            labelMin.Text = min.ToString();
+            labelMax.Text = max.ToString();
+
+            numericUpDown1.Value = (decimal)General.Clamp((float)numericUpDown1.Value, min, max);
+
+            if (doubledLimits) {
+                numericUpDown1.Minimum = (decimal)(min * 2);
+                numericUpDown1.Maximum = (decimal)(max * 2);
+            } else {
+                numericUpDown1.Minimum = (decimal)min;
+                numericUpDown1.Maximum = (decimal)max;
+            }
+
+            blockEvents = false;
+        }
+
+        //events
+        private void trackBar1_ValueChanged(object sender, EventArgs e) {
+             int value = ((TrackBar)sender).Value;
+             delta = value - previousValue;
+             previousValue = value;
+
+             numericUpDown1.Value = Math.Round((decimal)(value / 10.0), 1);
+        }
+
+        private void numericUpDown1_ValueChanged(object sender, EventArgs e) {
+            float val = (float)((NumericUpDown)sender).Value;
+
+            if (!blockEvents && OnValueChanged != null)
+                OnValueChanged(this, EventArgs.Empty);
+
+            blockEvents = true;
+            trackBar1.Value = General.Clamp((int)(val * 10), trackBar1.Minimum, trackBar1.Maximum);
+            blockEvents = false;
+        }
+    }
+}
diff --git a/Source/Plugins/UMDFControls/Controls/FloatSlider.designer.cs b/Source/Plugins/UMDFControls/Controls/FloatSlider.designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..45df2694084eb29ae1203e83747ec59e7962000d
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/FloatSlider.designer.cs
@@ -0,0 +1,102 @@
+namespace CodeImp.DoomBuilder.UDMFControls
+{
+    partial class FloatSlider
+    {
+        /// <summary> 
+        /// Требуется переменная конструктора.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Освободить все используемые ресурсы.
+        /// </summary>
+        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
+        protected override void Dispose(bool disposing) {
+            if (disposing && (components != null)) {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Код, автоматически созданный конструктором компонентов
+
+        /// <summary> 
+        /// Обязательный метод для поддержки конструктора - не изменяйте 
+        /// содержимое данного метода при помощи редактора кода.
+        /// </summary>
+        private void InitializeComponent() {
+            this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
+            this.trackBar1 = new Dotnetrix.Controls.TrackBar();
+            this.labelMin = new System.Windows.Forms.Label();
+            this.labelMax = new System.Windows.Forms.Label();
+            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // numericUpDown1
+            // 
+            this.numericUpDown1.DecimalPlaces = 1;
+            this.numericUpDown1.Increment = new decimal(new int[] {
+            1,
+            0,
+            0,
+            65536});
+            this.numericUpDown1.Location = new System.Drawing.Point(167, 16);
+            this.numericUpDown1.Name = "numericUpDown1";
+            this.numericUpDown1.Size = new System.Drawing.Size(44, 20);
+            this.numericUpDown1.TabIndex = 5;
+            this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged);
+            // 
+            // trackBar1
+            // 
+            this.trackBar1.LargeChange = 10;
+            this.trackBar1.Location = new System.Drawing.Point(24, 17);
+            this.trackBar1.Maximum = 512;
+            this.trackBar1.Name = "trackBar1";
+            this.trackBar1.Size = new System.Drawing.Size(137, 45);
+            this.trackBar1.TabIndex = 4;
+            this.trackBar1.ValueChanged += new System.EventHandler(this.trackBar1_ValueChanged);
+            // 
+            // labelMin
+            // 
+            this.labelMin.Location = new System.Drawing.Point(20, 0);
+            this.labelMin.Name = "labelMin";
+            this.labelMin.Size = new System.Drawing.Size(36, 15);
+            this.labelMin.TabIndex = 6;
+            this.labelMin.Text = "0";
+            this.labelMin.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // labelMax
+            // 
+            this.labelMax.Location = new System.Drawing.Point(134, 0);
+            this.labelMax.Name = "labelMax";
+            this.labelMax.Size = new System.Drawing.Size(36, 15);
+            this.labelMax.TabIndex = 7;
+            this.labelMax.Text = "512";
+            this.labelMax.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // FloatSlider
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.labelMax);
+            this.Controls.Add(this.labelMin);
+            this.Controls.Add(this.numericUpDown1);
+            this.Controls.Add(this.trackBar1);
+            this.Name = "FloatSlider";
+            this.Size = new System.Drawing.Size(220, 45);
+            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        protected System.Windows.Forms.NumericUpDown numericUpDown1;
+        protected Dotnetrix.Controls.TrackBar trackBar1;
+        protected System.Windows.Forms.Label labelMin;
+        protected System.Windows.Forms.Label labelMax;
+    }
+}
diff --git a/Source/Plugins/UMDFControls/Controls/FloatSlider.resx b/Source/Plugins/UMDFControls/Controls/FloatSlider.resx
new file mode 100644
index 0000000000000000000000000000000000000000..ff31a6db56e23b5a334f34387830ba5b4bd33eb8
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/FloatSlider.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/UMDFControls/Controls/IntSlider.cs b/Source/Plugins/UMDFControls/Controls/IntSlider.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f07d93f13763de60a98c8760430dffb166d70f76
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/IntSlider.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace CodeImp.DoomBuilder.UDMFControls
+{
+    public partial class IntSlider : UserControl {
+
+        private bool blockEvents;
+        public event EventHandler OnValueChanged;
+
+        private int previousValue;
+        public int Value { 
+            get
+            { 
+                return (int)numericUpDown1.Value; 
+            }
+            set
+            {
+                blockEvents = true;
+                numericUpDown1.Value = General.Clamp(value, (int)numericUpDown1.Minimum, (int)numericUpDown1.Maximum);
+                blockEvents = false;
+            }
+        }
+
+        public int Delta { get { return trackBar1.Value - previousValue; }}
+
+        private bool showLabels;
+        public bool ShowLabels {
+            get {
+                return showLabels;
+            }
+            set {
+                showLabels = value;
+                labelMin.Visible = showLabels;
+                labelMax.Visible = showLabels;
+            }
+        }
+        
+        public IntSlider() {
+            InitializeComponent();
+        }
+
+        public void SetLimits(int min, int max) {
+            //bool blockEventsStatus = blockEvents;
+            blockEvents = true;
+
+            trackBar1.Value = General.Clamp(trackBar1.Value, min, max);
+            trackBar1.Minimum = min;
+            trackBar1.Maximum = max;
+
+            labelMin.Text = min.ToString();
+            labelMax.Text = max.ToString();
+
+            numericUpDown1.Value = General.Clamp((int)numericUpDown1.Value, min, max);
+            numericUpDown1.Minimum = min;
+            numericUpDown1.Maximum = max;
+
+            //blockEvents = blockEventsStatus;
+            blockEvents = false;
+        }
+
+//events
+        private void trackBar1_ValueChanged(object sender, EventArgs e) {
+            numericUpDown1.Value = ((TrackBar)sender).Value;
+        }
+
+        private void numericUpDown1_ValueChanged(object sender, EventArgs e) {
+            int val = (int)((NumericUpDown)sender).Value;
+
+            if (!blockEvents && OnValueChanged != null)
+                OnValueChanged(this, EventArgs.Empty);
+
+            previousValue = trackBar1.Value;
+            blockEvents = true;
+            trackBar1.Value = General.Clamp(val, trackBar1.Minimum, trackBar1.Maximum); //clamp it!
+            blockEvents = false;
+        }
+    }
+}
diff --git a/Source/Plugins/UMDFControls/Controls/IntSlider.designer.cs b/Source/Plugins/UMDFControls/Controls/IntSlider.designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f049976f874355bb9f68805ebbaa4e32d00fbdf2
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/IntSlider.designer.cs
@@ -0,0 +1,97 @@
+namespace CodeImp.DoomBuilder.UDMFControls
+{
+    partial class IntSlider {
+        /// <summary> 
+        /// Требуется переменная конструктора.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Освободить все используемые ресурсы.
+        /// </summary>
+        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
+        protected override void Dispose(bool disposing) {
+            if (disposing && (components != null)) {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Код, автоматически созданный конструктором компонентов
+
+        /// <summary> 
+        /// Обязательный метод для поддержки конструктора - не изменяйте 
+        /// содержимое данного метода при помощи редактора кода.
+        /// </summary>
+        private void InitializeComponent() {
+            this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
+            this.trackBar1 = new Dotnetrix.Controls.TrackBar();
+            this.labelMin = new System.Windows.Forms.Label();
+            this.labelMax = new System.Windows.Forms.Label();
+            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // numericUpDown1
+            // 
+            this.numericUpDown1.Location = new System.Drawing.Point(167, 16);
+            this.numericUpDown1.Name = "numericUpDown1";
+            this.numericUpDown1.Size = new System.Drawing.Size(44, 20);
+            this.numericUpDown1.TabIndex = 5;
+            this.numericUpDown1.ValueChanged += new System.EventHandler(this.numericUpDown1_ValueChanged);
+            // 
+            // trackBar1
+            // 
+            this.trackBar1.LargeChange = 32;
+            this.trackBar1.Location = new System.Drawing.Point(24, 17);
+            this.trackBar1.Maximum = 512;
+            this.trackBar1.Name = "trackBar1";
+            this.trackBar1.Size = new System.Drawing.Size(137, 45);
+            this.trackBar1.SmallChange = 4;
+            this.trackBar1.TabIndex = 4;
+            this.trackBar1.TickFrequency = 16;
+            this.trackBar1.ValueChanged += new System.EventHandler(this.trackBar1_ValueChanged);
+            // 
+            // labelMin
+            // 
+            this.labelMin.Location = new System.Drawing.Point(20, 0);
+            this.labelMin.Name = "labelMin";
+            this.labelMin.Size = new System.Drawing.Size(36, 15);
+            this.labelMin.TabIndex = 6;
+            this.labelMin.Text = "0";
+            this.labelMin.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // labelMax
+            // 
+            this.labelMax.Location = new System.Drawing.Point(134, 0);
+            this.labelMax.Name = "labelMax";
+            this.labelMax.Size = new System.Drawing.Size(36, 15);
+            this.labelMax.TabIndex = 7;
+            this.labelMax.Text = "512";
+            this.labelMax.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // ColorPickerSlider
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.labelMax);
+            this.Controls.Add(this.labelMin);
+            this.Controls.Add(this.numericUpDown1);
+            this.Controls.Add(this.trackBar1);
+            this.Name = "ColorPickerSlider";
+            this.Size = new System.Drawing.Size(220, 45);
+            ((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.NumericUpDown numericUpDown1;
+        private Dotnetrix.Controls.TrackBar trackBar1;
+        private System.Windows.Forms.Label labelMin;
+        private System.Windows.Forms.Label labelMax;
+    }
+}
diff --git a/Source/Plugins/UMDFControls/Controls/IntSlider.resx b/Source/Plugins/UMDFControls/Controls/IntSlider.resx
new file mode 100644
index 0000000000000000000000000000000000000000..ff31a6db56e23b5a334f34387830ba5b4bd33eb8
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/IntSlider.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/UMDFControls/Controls/PositionControl.cs b/Source/Plugins/UMDFControls/Controls/PositionControl.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7db68406337ce3ad50a28c7f46911fd743690bef
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/PositionControl.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+
+using CodeImp.DoomBuilder.Geometry;
+
+namespace CodeImp.DoomBuilder.UDMFControls
+{
+    public partial class PositionControl : UserControl
+    {
+        private static int stepSize = 0;
+        private bool blockEvents;
+        public event EventHandler OnValueChanged;
+
+        public Vector2D Value {
+            get {
+                return new Vector2D((float)nudX.Value, (float)nudY.Value);
+            }
+            set {
+                prevX = (float)nudX.Value;
+                prevY = (float)nudY.Value;
+                
+                blockEvents = true;
+                nudX.Value = (decimal)value.x;
+                nudY.Value = (decimal)value.y;
+                blockEvents = false;
+
+                delta.x = (float)nudX.Value - prevX;
+                delta.y = (float)nudY.Value - prevY;
+            }
+        }
+
+        private float prevX, prevY;
+        private Vector2D delta;
+        public Vector2D Delta { get { return delta; } }
+
+//constructor
+        public PositionControl() {
+            delta = new Vector2D();
+            InitializeComponent();
+            trackBar1.Value = stepSize;
+            labelStepSize.Text = stepSize == 0 ? "1" : stepSize.ToString();
+        }
+//events
+        private void nudX_ValueChanged(object sender, EventArgs e) {
+            delta.x = (float)nudX.Value - prevX;
+            prevX = (float)nudX.Value;
+            
+            if (!blockEvents && OnValueChanged != null)
+                OnValueChanged(this, EventArgs.Empty);
+        }
+
+        private void nudY_ValueChanged(object sender, EventArgs e) {
+            delta.y = (float)nudY.Value - prevY;
+            prevY = (float)nudY.Value;
+
+            if (!blockEvents && OnValueChanged != null)
+                OnValueChanged(this, EventArgs.Empty);
+        }
+
+        private void trackBar1_Scroll(object sender, EventArgs e) {
+            stepSize = trackBar1.Value;
+            nudX.Increment = stepSize == 0 ? 1 : stepSize;
+            nudY.Increment = nudX.Increment;
+            labelStepSize.Text = nudX.Increment.ToString();
+        }
+    }
+}
diff --git a/Source/Plugins/UMDFControls/Controls/PositionControl.designer.cs b/Source/Plugins/UMDFControls/Controls/PositionControl.designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5afed22a71f7eb3a4daa3af61bd658d07a9b9de1
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/PositionControl.designer.cs
@@ -0,0 +1,168 @@
+namespace CodeImp.DoomBuilder.UDMFControls
+{
+    partial class PositionControl
+    {
+        /// <summary> 
+        /// Требуется переменная конструктора.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Освободить все используемые ресурсы.
+        /// </summary>
+        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
+        protected override void Dispose(bool disposing) {
+            if (disposing && (components != null)) {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Код, автоматически созданный конструктором компонентов
+
+        /// <summary> 
+        /// Обязательный метод для поддержки конструктора - не изменяйте 
+        /// содержимое данного метода при помощи редактора кода.
+        /// </summary>
+        private void InitializeComponent() {
+            this.nudY = new System.Windows.Forms.NumericUpDown();
+            this.nudX = new System.Windows.Forms.NumericUpDown();
+            this.label1 = new System.Windows.Forms.Label();
+            this.label2 = new System.Windows.Forms.Label();
+            this.trackBar1 = new Dotnetrix.Controls.TrackBar();
+            this.label3 = new System.Windows.Forms.Label();
+            this.labelStepSize = new System.Windows.Forms.Label();
+            ((System.ComponentModel.ISupportInitialize)(this.nudY)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.nudX)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // nudY
+            // 
+            this.nudY.DecimalPlaces = 1;
+            this.nudY.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.nudY.Location = new System.Drawing.Point(29, 29);
+            this.nudY.Maximum = new decimal(new int[] {
+            99999,
+            0,
+            0,
+            0});
+            this.nudY.Minimum = new decimal(new int[] {
+            99999,
+            0,
+            0,
+            -2147483648});
+            this.nudY.Name = "nudY";
+            this.nudY.Size = new System.Drawing.Size(70, 20);
+            this.nudY.TabIndex = 2;
+            this.nudY.ValueChanged += new System.EventHandler(this.nudY_ValueChanged);
+            // 
+            // nudX
+            // 
+            this.nudX.DecimalPlaces = 1;
+            this.nudX.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.nudX.Location = new System.Drawing.Point(29, 3);
+            this.nudX.Maximum = new decimal(new int[] {
+            99999,
+            0,
+            0,
+            0});
+            this.nudX.Minimum = new decimal(new int[] {
+            99999,
+            0,
+            0,
+            -2147483648});
+            this.nudX.Name = "nudX";
+            this.nudX.Size = new System.Drawing.Size(70, 20);
+            this.nudX.TabIndex = 1;
+            this.nudX.ValueChanged += new System.EventHandler(this.nudX_ValueChanged);
+            // 
+            // label1
+            // 
+            this.label1.AutoSize = true;
+            this.label1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.label1.Location = new System.Drawing.Point(10, 6);
+            this.label1.Name = "label1";
+            this.label1.Size = new System.Drawing.Size(17, 14);
+            this.label1.TabIndex = 3;
+            this.label1.Text = "X:";
+            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.label2.Location = new System.Drawing.Point(10, 32);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(17, 14);
+            this.label2.TabIndex = 4;
+            this.label2.Text = "Y:";
+            this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // trackBar1
+            // 
+            this.trackBar1.LargeChange = 8;
+            this.trackBar1.Location = new System.Drawing.Point(0, 78);
+            this.trackBar1.Maximum = 64;
+            this.trackBar1.Name = "trackBar1";
+            this.trackBar1.Size = new System.Drawing.Size(104, 45);
+            this.trackBar1.SmallChange = 4;
+            this.trackBar1.TabIndex = 5;
+            this.trackBar1.TickFrequency = 4;
+            this.trackBar1.TickStyle = System.Windows.Forms.TickStyle.TopLeft;
+            this.trackBar1.Scroll += new System.EventHandler(this.trackBar1_Scroll);
+            // 
+            // label3
+            // 
+            this.label3.AutoSize = true;
+            this.label3.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.label3.Location = new System.Drawing.Point(10, 64);
+            this.label3.Name = "label3";
+            this.label3.Size = new System.Drawing.Size(55, 14);
+            this.label3.TabIndex = 6;
+            this.label3.Text = "Step size:";
+            this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            // 
+            // labelStepSize
+            // 
+            this.labelStepSize.AutoSize = true;
+            this.labelStepSize.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.labelStepSize.Location = new System.Drawing.Point(85, 64);
+            this.labelStepSize.Name = "labelStepSize";
+            this.labelStepSize.Size = new System.Drawing.Size(19, 14);
+            this.labelStepSize.TabIndex = 8;
+            this.labelStepSize.Text = "64";
+            this.labelStepSize.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // PositionControl
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+            this.Controls.Add(this.labelStepSize);
+            this.Controls.Add(this.label3);
+            this.Controls.Add(this.trackBar1);
+            this.Controls.Add(this.label2);
+            this.Controls.Add(this.label1);
+            this.Controls.Add(this.nudX);
+            this.Controls.Add(this.nudY);
+            this.Name = "PositionControl";
+            this.Size = new System.Drawing.Size(106, 127);
+            ((System.ComponentModel.ISupportInitialize)(this.nudY)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.nudX)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.NumericUpDown nudY;
+        private System.Windows.Forms.NumericUpDown nudX;
+        private System.Windows.Forms.Label label1;
+        private System.Windows.Forms.Label label2;
+        private Dotnetrix.Controls.TrackBar trackBar1;
+        private System.Windows.Forms.Label label3;
+        private System.Windows.Forms.Label labelStepSize;
+    }
+}
diff --git a/Source/Plugins/UMDFControls/Controls/PositionControl.resx b/Source/Plugins/UMDFControls/Controls/PositionControl.resx
new file mode 100644
index 0000000000000000000000000000000000000000..ff31a6db56e23b5a334f34387830ba5b4bd33eb8
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/PositionControl.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/UMDFControls/Controls/ScaleControl.cs b/Source/Plugins/UMDFControls/Controls/ScaleControl.cs
new file mode 100644
index 0000000000000000000000000000000000000000..da8e7df46351a1c3e7d3cd34c565988e5ddafaf0
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/ScaleControl.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Windows.Forms;
+
+using CodeImp.DoomBuilder.Geometry;
+
+namespace CodeImp.DoomBuilder.UDMFControls
+{
+    public partial class ScaleControl : UserControl
+    {
+        private bool linkSliders;
+        public event EventHandler OnValueChanged;
+
+        public Vector2D Value {
+            set {
+                floatSlider1.Value = value.x;
+                floatSlider2.Value = value.y;
+            }
+            get {
+                return new Vector2D(floatSlider1.Value, floatSlider2.Value);
+            }
+        }
+
+        public Vector2D Delta { get { return new Vector2D(floatSlider1.Delta, floatSlider2.Delta); } }
+        
+        public ScaleControl() {
+            InitializeComponent();
+
+            setLinkButtonIcon(linkSliders);
+
+            floatSlider1.OnValueChanged += new EventHandler(floatSlider1_OnValueChanged);
+            floatSlider2.OnValueChanged += new EventHandler(floatSlider2_OnValueChanged);
+            button1.Click += new EventHandler(button1_Click);
+        }
+
+        private void setLinkButtonIcon(bool link){
+            button1.BackgroundImage = link ? Properties.Resources.Chain : Properties.Resources.Chain2;
+        }
+
+        public void SetLimits(float min, float max) {
+            floatSlider1.SetLimits(min, max, true);
+            floatSlider2.SetLimits(min, max, true);
+        }
+
+//events
+        private void floatSlider1_OnValueChanged(object sender, EventArgs e) {
+            if (linkSliders) floatSlider2.Value = ((FloatSlider)sender).Value;
+            if (OnValueChanged != null) OnValueChanged(this, EventArgs.Empty);
+        }
+
+        private void floatSlider2_OnValueChanged(object sender, EventArgs e) {
+            if (linkSliders) floatSlider1.Value = ((FloatSlider)sender).Value;
+            if (OnValueChanged != null) OnValueChanged(this, EventArgs.Empty);
+        }
+
+        private void button1_Click(object sender, EventArgs e) {
+            setLinkButtonIcon(linkSliders = !linkSliders);
+        }
+    }
+}
diff --git a/Source/Plugins/UMDFControls/Controls/ScaleControl.designer.cs b/Source/Plugins/UMDFControls/Controls/ScaleControl.designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..21acc0c95a779c42e0f27bf9689566b5dec8ae52
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/ScaleControl.designer.cs
@@ -0,0 +1,93 @@
+namespace CodeImp.DoomBuilder.UDMFControls
+{
+    partial class ScaleControl
+    {
+        /// <summary> 
+        /// Требуется переменная конструктора.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary> 
+        /// Освободить все используемые ресурсы.
+        /// </summary>
+        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
+        protected override void Dispose(bool disposing) {
+            if (disposing && (components != null)) {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Код, автоматически созданный конструктором компонентов
+
+        /// <summary> 
+        /// Обязательный метод для поддержки конструктора - не изменяйте 
+        /// содержимое данного метода при помощи редактора кода.
+        /// </summary>
+        private void InitializeComponent() {
+            this.button1 = new System.Windows.Forms.Button();
+            this.pictureBox1 = new System.Windows.Forms.PictureBox();
+            this.floatSlider2 = new CodeImp.DoomBuilder.UDMFControls.FloatSlider();
+            this.floatSlider1 = new CodeImp.DoomBuilder.UDMFControls.FloatSlider();
+            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // button1
+            // 
+            this.button1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
+            this.button1.Location = new System.Drawing.Point(6, 38);
+            this.button1.Name = "button1";
+            this.button1.Size = new System.Drawing.Size(18, 24);
+            this.button1.TabIndex = 2;
+            this.button1.UseVisualStyleBackColor = true;
+            // 
+            // pictureBox1
+            // 
+            this.pictureBox1.Image = global::CodeImp.DoomBuilder.UDMFControls.Properties.Resources.ScaleLink;
+            this.pictureBox1.Location = new System.Drawing.Point(15, 26);
+            this.pictureBox1.Name = "pictureBox1";
+            this.pictureBox1.Size = new System.Drawing.Size(10, 47);
+            this.pictureBox1.TabIndex = 3;
+            this.pictureBox1.TabStop = false;
+            // 
+            // floatSlider2
+            // 
+            this.floatSlider2.Location = new System.Drawing.Point(0, 45);
+            this.floatSlider2.Name = "floatSlider2";
+            this.floatSlider2.ShowLabels = false;
+            this.floatSlider2.Size = new System.Drawing.Size(220, 45);
+            this.floatSlider2.TabIndex = 1;
+            this.floatSlider2.Value = 0F;
+            // 
+            // floatSlider1
+            // 
+            this.floatSlider1.Location = new System.Drawing.Point(0, 0);
+            this.floatSlider1.Name = "floatSlider1";
+            this.floatSlider1.ShowLabels = true;
+            this.floatSlider1.Size = new System.Drawing.Size(220, 45);
+            this.floatSlider1.TabIndex = 0;
+            this.floatSlider1.Value = 0F;
+            // 
+            // ScaleControl
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.button1);
+            this.Controls.Add(this.pictureBox1);
+            this.Controls.Add(this.floatSlider1);
+            this.Controls.Add(this.floatSlider2);
+            this.Name = "ScaleControl";
+            this.Size = new System.Drawing.Size(220, 94);
+            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private FloatSlider floatSlider1;
+        private FloatSlider floatSlider2;
+        private System.Windows.Forms.Button button1;
+        private System.Windows.Forms.PictureBox pictureBox1;
+    }
+}
diff --git a/Source/Plugins/UMDFControls/Controls/ScaleControl.resx b/Source/Plugins/UMDFControls/Controls/ScaleControl.resx
new file mode 100644
index 0000000000000000000000000000000000000000..ff31a6db56e23b5a334f34387830ba5b4bd33eb8
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Controls/ScaleControl.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/UMDFControls/Properties/AssemblyInfo.cs b/Source/Plugins/UMDFControls/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a67c5d9a3119e2b37893d67d9909d9af90f556cb
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Управление общими сведениями о сборке осуществляется с помощью 
+// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения,
+// связанные со сборкой.
+[assembly: AssemblyTitle("UDMFControls")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Microsoft")]
+[assembly: AssemblyProduct("UDMFControls")]
+[assembly: AssemblyCopyright("Copyright © Microsoft 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Параметр ComVisible со значением FALSE делает типы в сборке невидимыми 
+// для COM-компонентов.  Если требуется обратиться к типу в этой сборке через 
+// COM, задайте атрибуту ComVisible значение TRUE для этого типа.
+[assembly: ComVisible(false)]
+
+// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM
+[assembly: Guid("52807f91-6f70-4eee-a2ba-5732411dabee")]
+
+// Сведения о версии сборки состоят из следующих четырех значений:
+//
+//      Основной номер версии
+//      Дополнительный номер версии 
+//      Номер построения
+//      Редакция
+//
+// Можно задать все значения или принять номер построения и номер редакции по умолчанию, 
+// используя "*", как показано ниже:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/Plugins/UMDFControls/Properties/Resources.Designer.cs b/Source/Plugins/UMDFControls/Properties/Resources.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..637d278d1d68e392c9ac8f458c09bb7f37eb14cc
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Properties/Resources.Designer.cs
@@ -0,0 +1,91 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     Этот код создан программой.
+//     Исполняемая версия:2.0.50727.5420
+//
+//     Изменения в этом файле могут привести к неправильной работе и будут потеряны в случае
+//     повторной генерации кода.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace CodeImp.DoomBuilder.UDMFControls.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   Класс ресурса со строгой типизацией для поиска локализованных строк и т.д.
+    /// </summary>
+    // Этот класс создан автоматически классом StronglyTypedResourceBuilder
+    // с помощью такого средства, как ResGen или Visual Studio.
+    // Чтобы добавить или удалить член, измените файл .ResX и снова запустите ResGen
+    // с параметром /str или перестройте свой проект VS.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Возвращает кэшированный экземпляр ResourceManager, использованный этим классом.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeImp.DoomBuilder.UDMFControls.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Перезаписывает свойство CurrentUICulture текущего потока для всех
+        ///   обращений к ресурсу с помощью этого класса ресурса со строгой типизацией.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Chain {
+            get {
+                object obj = ResourceManager.GetObject("Chain", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap Chain2 {
+            get {
+                object obj = ResourceManager.GetObject("Chain2", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap dial {
+            get {
+                object obj = ResourceManager.GetObject("dial", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        internal static System.Drawing.Bitmap ScaleLink {
+            get {
+                object obj = ResourceManager.GetObject("ScaleLink", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+    }
+}
diff --git a/Source/Plugins/UMDFControls/Properties/Resources.resx b/Source/Plugins/UMDFControls/Properties/Resources.resx
new file mode 100644
index 0000000000000000000000000000000000000000..aef4c09ad8ad988915e4dbc984315be4089afb12
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Properties/Resources.resx
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="dial" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\dial.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="Chain" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Chain.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="Chain2" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\Chain2.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="ScaleLink" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\Resources\ScaleLink.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Source/Plugins/UMDFControls/Resources/Actions.cfg b/Source/Plugins/UMDFControls/Resources/Actions.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..b4a3d24c24570b8d7b1aeb75ca70dd1e6c980f08
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Resources/Actions.cfg
@@ -0,0 +1,10 @@
+openudmfcontrols
+{
+    title = "Open UDMF Controls";
+	category = "tools";
+	description = "Select surface(s) in Visual Modes, then use this panel to edit sector and texture properties quickly.";
+	allowkeys = true;
+	allowmouse = true;
+	allowscroll = false;
+	default = 131156; //Ctrl-T
+}
\ No newline at end of file
diff --git a/Source/Plugins/UMDFControls/Resources/Chain.png b/Source/Plugins/UMDFControls/Resources/Chain.png
new file mode 100644
index 0000000000000000000000000000000000000000..9645e3d831671f9daeca19bd5935c4f5072d4342
Binary files /dev/null and b/Source/Plugins/UMDFControls/Resources/Chain.png differ
diff --git a/Source/Plugins/UMDFControls/Resources/Chain2.png b/Source/Plugins/UMDFControls/Resources/Chain2.png
new file mode 100644
index 0000000000000000000000000000000000000000..e159befecfe2a74ef506972c93a5f2369b598358
Binary files /dev/null and b/Source/Plugins/UMDFControls/Resources/Chain2.png differ
diff --git a/Source/Plugins/UMDFControls/Resources/Dial.png b/Source/Plugins/UMDFControls/Resources/Dial.png
new file mode 100644
index 0000000000000000000000000000000000000000..a03129857a4119c0dd20c94ac7ca24f1535f0569
Binary files /dev/null and b/Source/Plugins/UMDFControls/Resources/Dial.png differ
diff --git a/Source/Plugins/UMDFControls/Resources/ScaleLink.png b/Source/Plugins/UMDFControls/Resources/ScaleLink.png
new file mode 100644
index 0000000000000000000000000000000000000000..43be37a2185d83e1807099fa79a66d2bf8803c3e
Binary files /dev/null and b/Source/Plugins/UMDFControls/Resources/ScaleLink.png differ
diff --git a/Source/Plugins/UMDFControls/UDMFControls.csproj b/Source/Plugins/UMDFControls/UDMFControls.csproj
new file mode 100644
index 0000000000000000000000000000000000000000..76c8ff150bc44613799b5105427385c03d600b89
--- /dev/null
+++ b/Source/Plugins/UMDFControls/UDMFControls.csproj
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{2D11C828-295C-463A-8545-CA1AD6D51518}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>CodeImp.DoomBuilder.UDMFControls</RootNamespace>
+    <AssemblyName>UDMFControls</AssemblyName>
+    <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>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data.DataSetExtensions">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="Trackbar, Version=1.0.2486.37933, Culture=neutral, PublicKeyToken=503bf28f63ad27b4">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\..\..\Build\Trackbar.dll</HintPath>
+      <Private>False</Private>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="BuilderPlug.cs" />
+    <Compile Include="Controls\AngleControl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Controls\AngleControl.designer.cs">
+      <DependentUpon>AngleControl.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Controls\FloatSlider.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Controls\FloatSlider.designer.cs">
+      <DependentUpon>FloatSlider.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Controls\IntSlider.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Controls\IntSlider.designer.cs">
+      <DependentUpon>IntSlider.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Controls\PositionControl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Controls\PositionControl.designer.cs">
+      <DependentUpon>PositionControl.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Controls\ScaleControl.cs">
+      <SubType>UserControl</SubType>
+    </Compile>
+    <Compile Include="Controls\ScaleControl.designer.cs">
+      <DependentUpon>ScaleControl.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Compile Include="Windows\UDMFControlsForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="Windows\UDMFControlsForm.Designer.cs">
+      <DependentUpon>UDMFControlsForm.cs</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Core\Builder.csproj">
+      <Project>{818B3D10-F791-4C3F-9AF5-BB2D0079B63C}</Project>
+      <Name>Builder</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\ColorPicker\ColorPicker.csproj">
+      <Project>{A4761900-0EA3-4FE4-A919-847FD5080EFC}</Project>
+      <Name>ColorPicker</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Controls\AngleControl.resx">
+      <DependentUpon>AngleControl.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Resources\Dial.png" />
+    <EmbeddedResource Include="Windows\UDMFControlsForm.resx">
+      <DependentUpon>UDMFControlsForm.cs</DependentUpon>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Controls\FloatSlider.resx">
+      <DependentUpon>FloatSlider.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Controls\IntSlider.resx">
+      <DependentUpon>IntSlider.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Controls\PositionControl.resx">
+      <DependentUpon>PositionControl.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Controls\ScaleControl.resx">
+      <DependentUpon>ScaleControl.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Resources\Actions.cfg" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\Chain.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\Chain2.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Resources\ScaleLink.png" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\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.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Source/Plugins/UMDFControls/Windows/UDMFControlsForm.Designer.cs b/Source/Plugins/UMDFControls/Windows/UDMFControlsForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..69091ad8269c921960ea545897dfdeaacc6ed92c
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Windows/UDMFControlsForm.Designer.cs
@@ -0,0 +1,539 @@
+namespace CodeImp.DoomBuilder.UDMFControls
+{
+    partial class UDMFControlsForm {
+        /// <summary>
+        /// Требуется переменная конструктора.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Освободить все используемые ресурсы.
+        /// </summary>
+        /// <param name="disposing">истинно, если управляемый ресурс должен быть удален; иначе ложно.</param>
+        protected override void Dispose(bool disposing) {
+            if (disposing && (components != null)) {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Код, автоматически созданный конструктором форм Windows
+
+        /// <summary>
+        /// Обязательный метод для поддержки конструктора - не изменяйте
+        /// содержимое данного метода при помощи редактора кода.
+        /// </summary>
+        private void InitializeComponent() {
+            this.btnOK = new System.Windows.Forms.Button();
+            this.btnCancel = new System.Windows.Forms.Button();
+            this.gbRotation = new System.Windows.Forms.GroupBox();
+            this.angleControl1 = new CodeImp.DoomBuilder.UDMFControls.AngleControl();
+            this.gbPosition = new System.Windows.Forms.GroupBox();
+            this.positionControl1 = new CodeImp.DoomBuilder.UDMFControls.PositionControl();
+            this.gbScale = new System.Windows.Forms.GroupBox();
+            this.scaleControl = new CodeImp.DoomBuilder.UDMFControls.ScaleControl();
+            this.bgBrightness = new System.Windows.Forms.GroupBox();
+            this.cblightabsolute = new System.Windows.Forms.CheckBox();
+            this.sliderBrightness = new CodeImp.DoomBuilder.UDMFControls.IntSlider();
+            this.tabControl1 = new System.Windows.Forms.TabControl();
+            this.tabPage1 = new System.Windows.Forms.TabPage();
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.cbRelativeMode = new System.Windows.Forms.CheckBox();
+            this.gbAlpha = new System.Windows.Forms.GroupBox();
+            this.label2 = new System.Windows.Forms.Label();
+            this.cbRenderStyle = new System.Windows.Forms.ComboBox();
+            this.sliderAlpha = new CodeImp.DoomBuilder.UDMFControls.FloatSlider();
+            this.labelGravity = new System.Windows.Forms.Label();
+            this.nudGravity = new System.Windows.Forms.NumericUpDown();
+            this.gbDesaturation = new System.Windows.Forms.GroupBox();
+            this.sliderDesaturation = new CodeImp.DoomBuilder.UDMFControls.FloatSlider();
+            this.tabPage2 = new System.Windows.Forms.TabPage();
+            this.gbFlagsFloor = new System.Windows.Forms.GroupBox();
+            this.cbsilent = new System.Windows.Forms.CheckBox();
+            this.cbnorespawn = new System.Windows.Forms.CheckBox();
+            this.cbnofallingdamage = new System.Windows.Forms.CheckBox();
+            this.cbdropactors = new System.Windows.Forms.CheckBox();
+            this.gbFlagsWall = new System.Windows.Forms.GroupBox();
+            this.cbsmoothlighting = new System.Windows.Forms.CheckBox();
+            this.cbnodecals = new System.Windows.Forms.CheckBox();
+            this.cbnofakecontrast = new System.Windows.Forms.CheckBox();
+            this.cbwrapmidtex = new System.Windows.Forms.CheckBox();
+            this.cbclipmidtex = new System.Windows.Forms.CheckBox();
+            this.gbRotation.SuspendLayout();
+            this.gbPosition.SuspendLayout();
+            this.gbScale.SuspendLayout();
+            this.bgBrightness.SuspendLayout();
+            this.tabControl1.SuspendLayout();
+            this.tabPage1.SuspendLayout();
+            this.groupBox1.SuspendLayout();
+            this.gbAlpha.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.nudGravity)).BeginInit();
+            this.gbDesaturation.SuspendLayout();
+            this.tabPage2.SuspendLayout();
+            this.gbFlagsFloor.SuspendLayout();
+            this.gbFlagsWall.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // btnOK
+            // 
+            this.btnOK.Location = new System.Drawing.Point(3, 680);
+            this.btnOK.Name = "btnOK";
+            this.btnOK.Size = new System.Drawing.Size(125, 25);
+            this.btnOK.TabIndex = 0;
+            this.btnOK.Text = "OK";
+            this.btnOK.UseVisualStyleBackColor = true;
+            this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
+            // 
+            // btnCancel
+            // 
+            this.btnCancel.Location = new System.Drawing.Point(132, 680);
+            this.btnCancel.Name = "btnCancel";
+            this.btnCancel.Size = new System.Drawing.Size(125, 25);
+            this.btnCancel.TabIndex = 1;
+            this.btnCancel.Text = "Cancel";
+            this.btnCancel.UseVisualStyleBackColor = true;
+            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
+            // 
+            // gbRotation
+            // 
+            this.gbRotation.Controls.Add(this.angleControl1);
+            this.gbRotation.Location = new System.Drawing.Point(116, 19);
+            this.gbRotation.Name = "gbRotation";
+            this.gbRotation.Size = new System.Drawing.Size(114, 150);
+            this.gbRotation.TabIndex = 4;
+            this.gbRotation.TabStop = false;
+            this.gbRotation.Text = "Rotation:";
+            // 
+            // angleControl1
+            // 
+            this.angleControl1.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.angleControl1.Location = new System.Drawing.Point(6, 19);
+            this.angleControl1.Name = "angleControl1";
+            this.angleControl1.Size = new System.Drawing.Size(102, 125);
+            this.angleControl1.TabIndex = 2;
+            this.angleControl1.Tag = "rotation";
+            this.angleControl1.Value = 0F;
+            this.angleControl1.OnAngleChanged += new System.EventHandler(this.angleControl1_OnAngleChanged);
+            // 
+            // gbPosition
+            // 
+            this.gbPosition.Controls.Add(this.positionControl1);
+            this.gbPosition.Location = new System.Drawing.Point(6, 19);
+            this.gbPosition.Name = "gbPosition";
+            this.gbPosition.Size = new System.Drawing.Size(105, 150);
+            this.gbPosition.TabIndex = 1;
+            this.gbPosition.TabStop = false;
+            this.gbPosition.Text = "Position:";
+            // 
+            // positionControl1
+            // 
+            this.positionControl1.Location = new System.Drawing.Point(-2, 20);
+            this.positionControl1.Name = "positionControl1";
+            this.positionControl1.Size = new System.Drawing.Size(106, 127);
+            this.positionControl1.TabIndex = 0;
+            this.positionControl1.Tag = "offset";
+            this.positionControl1.OnValueChanged += new System.EventHandler(this.positionControl1_OnValueChanged);
+            // 
+            // gbScale
+            // 
+            this.gbScale.Controls.Add(this.scaleControl);
+            this.gbScale.Location = new System.Drawing.Point(6, 172);
+            this.gbScale.Name = "gbScale";
+            this.gbScale.Size = new System.Drawing.Size(224, 119);
+            this.gbScale.TabIndex = 5;
+            this.gbScale.TabStop = false;
+            this.gbScale.Text = "Scale:";
+            // 
+            // scaleControl
+            // 
+            this.scaleControl.Location = new System.Drawing.Point(8, 19);
+            this.scaleControl.Name = "scaleControl";
+            this.scaleControl.Size = new System.Drawing.Size(220, 94);
+            this.scaleControl.TabIndex = 0;
+            this.scaleControl.Tag = "scale";
+            this.scaleControl.OnValueChanged += new System.EventHandler(this.scaleControl_OnValueChanged);
+            // 
+            // bgBrightness
+            // 
+            this.bgBrightness.Controls.Add(this.cblightabsolute);
+            this.bgBrightness.Controls.Add(this.sliderBrightness);
+            this.bgBrightness.Location = new System.Drawing.Point(5, 337);
+            this.bgBrightness.Name = "bgBrightness";
+            this.bgBrightness.Size = new System.Drawing.Size(234, 94);
+            this.bgBrightness.TabIndex = 6;
+            this.bgBrightness.TabStop = false;
+            this.bgBrightness.Text = "Brightness:";
+            // 
+            // cblightabsolute
+            // 
+            this.cblightabsolute.AutoSize = true;
+            this.cblightabsolute.Location = new System.Drawing.Point(10, 70);
+            this.cblightabsolute.Name = "cblightabsolute";
+            this.cblightabsolute.Size = new System.Drawing.Size(109, 18);
+            this.cblightabsolute.TabIndex = 1;
+            this.cblightabsolute.Tag = "lightabsolute";
+            this.cblightabsolute.Text = "Absolute Lighting";
+            this.cblightabsolute.UseVisualStyleBackColor = true;
+            this.cblightabsolute.CheckedChanged += new System.EventHandler(this.cblightabsolute_CheckedChanged);
+            // 
+            // sliderBrightness
+            // 
+            this.sliderBrightness.Location = new System.Drawing.Point(6, 19);
+            this.sliderBrightness.Name = "sliderBrightness";
+            this.sliderBrightness.ShowLabels = true;
+            this.sliderBrightness.Size = new System.Drawing.Size(220, 45);
+            this.sliderBrightness.TabIndex = 0;
+            this.sliderBrightness.Tag = "light";
+            this.sliderBrightness.Value = 0;
+            this.sliderBrightness.OnValueChanged += new System.EventHandler(this.sliderBrightness_OnValueChanged);
+            // 
+            // tabControl1
+            // 
+            this.tabControl1.Controls.Add(this.tabPage1);
+            this.tabControl1.Controls.Add(this.tabPage2);
+            this.tabControl1.Location = new System.Drawing.Point(3, 3);
+            this.tabControl1.Name = "tabControl1";
+            this.tabControl1.SelectedIndex = 0;
+            this.tabControl1.Size = new System.Drawing.Size(254, 671);
+            this.tabControl1.TabIndex = 0;
+            // 
+            // tabPage1
+            // 
+            this.tabPage1.Controls.Add(this.groupBox1);
+            this.tabPage1.Controls.Add(this.gbAlpha);
+            this.tabPage1.Controls.Add(this.labelGravity);
+            this.tabPage1.Controls.Add(this.nudGravity);
+            this.tabPage1.Controls.Add(this.gbDesaturation);
+            this.tabPage1.Controls.Add(this.bgBrightness);
+            this.tabPage1.Location = new System.Drawing.Point(4, 23);
+            this.tabPage1.Name = "tabPage1";
+            this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
+            this.tabPage1.Size = new System.Drawing.Size(246, 644);
+            this.tabPage1.TabIndex = 0;
+            this.tabPage1.Text = "Properties";
+            this.tabPage1.UseVisualStyleBackColor = true;
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.Controls.Add(this.gbPosition);
+            this.groupBox1.Controls.Add(this.cbRelativeMode);
+            this.groupBox1.Controls.Add(this.gbRotation);
+            this.groupBox1.Controls.Add(this.gbScale);
+            this.groupBox1.Location = new System.Drawing.Point(5, 6);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(234, 325);
+            this.groupBox1.TabIndex = 13;
+            this.groupBox1.TabStop = false;
+            this.groupBox1.Text = "Transform:";
+            // 
+            // cbRelativeMode
+            // 
+            this.cbRelativeMode.AutoSize = true;
+            this.cbRelativeMode.Location = new System.Drawing.Point(6, 297);
+            this.cbRelativeMode.Name = "cbRelativeMode";
+            this.cbRelativeMode.Size = new System.Drawing.Size(93, 18);
+            this.cbRelativeMode.TabIndex = 12;
+            this.cbRelativeMode.Text = "Relative mode";
+            this.cbRelativeMode.UseVisualStyleBackColor = true;
+            this.cbRelativeMode.CheckedChanged += new System.EventHandler(this.cbRelativeMode_CheckedChanged);
+            // 
+            // gbAlpha
+            // 
+            this.gbAlpha.Controls.Add(this.label2);
+            this.gbAlpha.Controls.Add(this.cbRenderStyle);
+            this.gbAlpha.Controls.Add(this.sliderAlpha);
+            this.gbAlpha.Location = new System.Drawing.Point(5, 437);
+            this.gbAlpha.Name = "gbAlpha";
+            this.gbAlpha.Size = new System.Drawing.Size(234, 100);
+            this.gbAlpha.TabIndex = 11;
+            this.gbAlpha.TabStop = false;
+            this.gbAlpha.Text = "Transparency:";
+            // 
+            // label2
+            // 
+            this.label2.AutoSize = true;
+            this.label2.Location = new System.Drawing.Point(7, 74);
+            this.label2.Name = "label2";
+            this.label2.Size = new System.Drawing.Size(72, 14);
+            this.label2.TabIndex = 12;
+            this.label2.Text = "Render Style:";
+            // 
+            // cbRenderStyle
+            // 
+            this.cbRenderStyle.FormattingEnabled = true;
+            this.cbRenderStyle.Location = new System.Drawing.Point(85, 70);
+            this.cbRenderStyle.Name = "cbRenderStyle";
+            this.cbRenderStyle.Size = new System.Drawing.Size(141, 22);
+            this.cbRenderStyle.TabIndex = 1;
+            this.cbRenderStyle.Tag = "renderstyle";
+            this.cbRenderStyle.SelectedIndexChanged += new System.EventHandler(this.cbRenderStyle_SelectedIndexChanged);
+            // 
+            // sliderAlpha
+            // 
+            this.sliderAlpha.Location = new System.Drawing.Point(6, 19);
+            this.sliderAlpha.Name = "sliderAlpha";
+            this.sliderAlpha.ShowLabels = true;
+            this.sliderAlpha.Size = new System.Drawing.Size(220, 45);
+            this.sliderAlpha.TabIndex = 0;
+            this.sliderAlpha.Tag = "alpha";
+            this.sliderAlpha.Value = 0F;
+            this.sliderAlpha.OnValueChanged += new System.EventHandler(this.sliderAlpha_OnValueChanged);
+            // 
+            // labelGravity
+            // 
+            this.labelGravity.AutoSize = true;
+            this.labelGravity.Location = new System.Drawing.Point(12, 621);
+            this.labelGravity.Name = "labelGravity";
+            this.labelGravity.Size = new System.Drawing.Size(45, 14);
+            this.labelGravity.TabIndex = 0;
+            this.labelGravity.Text = "Gravity:";
+            // 
+            // nudGravity
+            // 
+            this.nudGravity.DecimalPlaces = 1;
+            this.nudGravity.Location = new System.Drawing.Point(63, 618);
+            this.nudGravity.Minimum = new decimal(new int[] {
+            100,
+            0,
+            0,
+            -2147483648});
+            this.nudGravity.Name = "nudGravity";
+            this.nudGravity.Size = new System.Drawing.Size(60, 20);
+            this.nudGravity.TabIndex = 8;
+            this.nudGravity.Tag = "gravity";
+            // 
+            // gbDesaturation
+            // 
+            this.gbDesaturation.Controls.Add(this.sliderDesaturation);
+            this.gbDesaturation.Location = new System.Drawing.Point(5, 543);
+            this.gbDesaturation.Name = "gbDesaturation";
+            this.gbDesaturation.Size = new System.Drawing.Size(234, 70);
+            this.gbDesaturation.TabIndex = 7;
+            this.gbDesaturation.TabStop = false;
+            this.gbDesaturation.Text = "Desaturation:";
+            // 
+            // sliderDesaturation
+            // 
+            this.sliderDesaturation.Location = new System.Drawing.Point(6, 19);
+            this.sliderDesaturation.Name = "sliderDesaturation";
+            this.sliderDesaturation.ShowLabels = true;
+            this.sliderDesaturation.Size = new System.Drawing.Size(220, 45);
+            this.sliderDesaturation.TabIndex = 0;
+            this.sliderDesaturation.Tag = "desaturation";
+            this.sliderDesaturation.Value = 0F;
+            // 
+            // tabPage2
+            // 
+            this.tabPage2.Controls.Add(this.gbFlagsFloor);
+            this.tabPage2.Controls.Add(this.gbFlagsWall);
+            this.tabPage2.Location = new System.Drawing.Point(4, 23);
+            this.tabPage2.Name = "tabPage2";
+            this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
+            this.tabPage2.Size = new System.Drawing.Size(246, 644);
+            this.tabPage2.TabIndex = 1;
+            this.tabPage2.Text = "Flags";
+            this.tabPage2.UseVisualStyleBackColor = true;
+            // 
+            // gbFlagsFloor
+            // 
+            this.gbFlagsFloor.Controls.Add(this.cbsilent);
+            this.gbFlagsFloor.Controls.Add(this.cbnorespawn);
+            this.gbFlagsFloor.Controls.Add(this.cbnofallingdamage);
+            this.gbFlagsFloor.Controls.Add(this.cbdropactors);
+            this.gbFlagsFloor.Location = new System.Drawing.Point(6, 150);
+            this.gbFlagsFloor.Name = "gbFlagsFloor";
+            this.gbFlagsFloor.Size = new System.Drawing.Size(235, 112);
+            this.gbFlagsFloor.TabIndex = 3;
+            this.gbFlagsFloor.TabStop = false;
+            this.gbFlagsFloor.Text = "Floor and Ceiling flags:";
+            // 
+            // cbsilent
+            // 
+            this.cbsilent.AutoSize = true;
+            this.cbsilent.Location = new System.Drawing.Point(6, 91);
+            this.cbsilent.Name = "cbsilent";
+            this.cbsilent.Size = new System.Drawing.Size(52, 18);
+            this.cbsilent.TabIndex = 3;
+            this.cbsilent.Tag = "silent";
+            this.cbsilent.Text = "Silent";
+            this.cbsilent.UseVisualStyleBackColor = true;
+            // 
+            // cbnorespawn
+            // 
+            this.cbnorespawn.AutoSize = true;
+            this.cbnorespawn.Location = new System.Drawing.Point(6, 67);
+            this.cbnorespawn.Name = "cbnorespawn";
+            this.cbnorespawn.Size = new System.Drawing.Size(89, 18);
+            this.cbnorespawn.TabIndex = 2;
+            this.cbnorespawn.Tag = "norespawn";
+            this.cbnorespawn.Text = "No Respawn";
+            this.cbnorespawn.UseVisualStyleBackColor = true;
+            // 
+            // cbnofallingdamage
+            // 
+            this.cbnofallingdamage.AutoSize = true;
+            this.cbnofallingdamage.Location = new System.Drawing.Point(6, 43);
+            this.cbnofallingdamage.Name = "cbnofallingdamage";
+            this.cbnofallingdamage.Size = new System.Drawing.Size(114, 18);
+            this.cbnofallingdamage.TabIndex = 1;
+            this.cbnofallingdamage.Tag = "nofallingdamage";
+            this.cbnofallingdamage.Text = "No Falling Damage";
+            this.cbnofallingdamage.UseVisualStyleBackColor = true;
+            // 
+            // cbdropactors
+            // 
+            this.cbdropactors.AutoSize = true;
+            this.cbdropactors.Location = new System.Drawing.Point(6, 19);
+            this.cbdropactors.Name = "cbdropactors";
+            this.cbdropactors.Size = new System.Drawing.Size(84, 18);
+            this.cbdropactors.TabIndex = 0;
+            this.cbdropactors.Tag = "dropactors";
+            this.cbdropactors.Text = "Drop Actors";
+            this.cbdropactors.UseVisualStyleBackColor = true;
+            // 
+            // gbFlagsWall
+            // 
+            this.gbFlagsWall.Controls.Add(this.cbsmoothlighting);
+            this.gbFlagsWall.Controls.Add(this.cbnodecals);
+            this.gbFlagsWall.Controls.Add(this.cbnofakecontrast);
+            this.gbFlagsWall.Controls.Add(this.cbwrapmidtex);
+            this.gbFlagsWall.Controls.Add(this.cbclipmidtex);
+            this.gbFlagsWall.Location = new System.Drawing.Point(6, 6);
+            this.gbFlagsWall.Name = "gbFlagsWall";
+            this.gbFlagsWall.Size = new System.Drawing.Size(235, 138);
+            this.gbFlagsWall.TabIndex = 2;
+            this.gbFlagsWall.TabStop = false;
+            this.gbFlagsWall.Text = "Wall flags:";
+            // 
+            // cbsmoothlighting
+            // 
+            this.cbsmoothlighting.AutoSize = true;
+            this.cbsmoothlighting.Location = new System.Drawing.Point(6, 115);
+            this.cbsmoothlighting.Name = "cbsmoothlighting";
+            this.cbsmoothlighting.Size = new System.Drawing.Size(102, 18);
+            this.cbsmoothlighting.TabIndex = 4;
+            this.cbsmoothlighting.Tag = "smoothlighting";
+            this.cbsmoothlighting.Text = "Smooth Lighting";
+            this.cbsmoothlighting.UseVisualStyleBackColor = true;
+            // 
+            // cbnodecals
+            // 
+            this.cbnodecals.AutoSize = true;
+            this.cbnodecals.Location = new System.Drawing.Point(6, 91);
+            this.cbnodecals.Name = "cbnodecals";
+            this.cbnodecals.Size = new System.Drawing.Size(75, 18);
+            this.cbnodecals.TabIndex = 3;
+            this.cbnodecals.Tag = "nodecals";
+            this.cbnodecals.Text = "No Decals";
+            this.cbnodecals.UseVisualStyleBackColor = true;
+            // 
+            // cbnofakecontrast
+            // 
+            this.cbnofakecontrast.AutoSize = true;
+            this.cbnofakecontrast.Location = new System.Drawing.Point(6, 67);
+            this.cbnofakecontrast.Name = "cbnofakecontrast";
+            this.cbnofakecontrast.Size = new System.Drawing.Size(109, 18);
+            this.cbnofakecontrast.TabIndex = 2;
+            this.cbnofakecontrast.Tag = "nofakecontrast";
+            this.cbnofakecontrast.Text = "No Fake Contrast";
+            this.cbnofakecontrast.UseVisualStyleBackColor = true;
+            // 
+            // cbwrapmidtex
+            // 
+            this.cbwrapmidtex.AutoSize = true;
+            this.cbwrapmidtex.Location = new System.Drawing.Point(6, 43);
+            this.cbwrapmidtex.Name = "cbwrapmidtex";
+            this.cbwrapmidtex.Size = new System.Drawing.Size(124, 18);
+            this.cbwrapmidtex.TabIndex = 1;
+            this.cbwrapmidtex.Tag = "wrapmidtex";
+            this.cbwrapmidtex.Text = "Wrap Middle Texture";
+            this.cbwrapmidtex.UseVisualStyleBackColor = true;
+            this.cbwrapmidtex.CheckedChanged += new System.EventHandler(this.cbwrapmidtex_CheckedChanged);
+            // 
+            // cbclipmidtex
+            // 
+            this.cbclipmidtex.AutoSize = true;
+            this.cbclipmidtex.Location = new System.Drawing.Point(6, 19);
+            this.cbclipmidtex.Name = "cbclipmidtex";
+            this.cbclipmidtex.Size = new System.Drawing.Size(115, 18);
+            this.cbclipmidtex.TabIndex = 0;
+            this.cbclipmidtex.Tag = "clipmidtex";
+            this.cbclipmidtex.Text = "Clip Middle Texture";
+            this.cbclipmidtex.UseVisualStyleBackColor = true;
+            // 
+            // UDMFControlsForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+            this.ClientSize = new System.Drawing.Size(259, 709);
+            this.Controls.Add(this.tabControl1);
+            this.Controls.Add(this.btnCancel);
+            this.Controls.Add(this.btnOK);
+            this.Font = new System.Drawing.Font("Arial", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(204)));
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
+            this.Name = "UDMFControlsForm";
+            this.Opacity = 0;
+            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
+            this.Text = "UDMF Controls";
+            this.gbRotation.ResumeLayout(false);
+            this.gbPosition.ResumeLayout(false);
+            this.gbScale.ResumeLayout(false);
+            this.bgBrightness.ResumeLayout(false);
+            this.bgBrightness.PerformLayout();
+            this.tabControl1.ResumeLayout(false);
+            this.tabPage1.ResumeLayout(false);
+            this.tabPage1.PerformLayout();
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
+            this.gbAlpha.ResumeLayout(false);
+            this.gbAlpha.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this.nudGravity)).EndInit();
+            this.gbDesaturation.ResumeLayout(false);
+            this.tabPage2.ResumeLayout(false);
+            this.gbFlagsFloor.ResumeLayout(false);
+            this.gbFlagsFloor.PerformLayout();
+            this.gbFlagsWall.ResumeLayout(false);
+            this.gbFlagsWall.PerformLayout();
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Button btnOK;
+        private System.Windows.Forms.Button btnCancel;
+        private AngleControl angleControl1;
+        private System.Windows.Forms.GroupBox gbRotation;
+        private System.Windows.Forms.GroupBox gbPosition;
+        private PositionControl positionControl1;
+        private System.Windows.Forms.GroupBox gbScale;
+        private ScaleControl scaleControl;
+        private System.Windows.Forms.GroupBox bgBrightness;
+        private IntSlider sliderBrightness;
+        private System.Windows.Forms.TabControl tabControl1;
+        private System.Windows.Forms.TabPage tabPage1;
+        private System.Windows.Forms.TabPage tabPage2;
+        private System.Windows.Forms.Label labelGravity;
+        private System.Windows.Forms.NumericUpDown nudGravity;
+        private System.Windows.Forms.GroupBox gbDesaturation;
+        private FloatSlider sliderDesaturation;
+        private System.Windows.Forms.GroupBox gbFlagsFloor;
+        private System.Windows.Forms.CheckBox cbsilent;
+        private System.Windows.Forms.CheckBox cbnorespawn;
+        private System.Windows.Forms.CheckBox cbnofallingdamage;
+        private System.Windows.Forms.CheckBox cbdropactors;
+        private System.Windows.Forms.GroupBox gbFlagsWall;
+        private System.Windows.Forms.CheckBox cbsmoothlighting;
+        private System.Windows.Forms.CheckBox cbnodecals;
+        private System.Windows.Forms.CheckBox cbnofakecontrast;
+        private System.Windows.Forms.CheckBox cbwrapmidtex;
+        private System.Windows.Forms.CheckBox cbclipmidtex;
+        private System.Windows.Forms.GroupBox gbAlpha;
+        private FloatSlider sliderAlpha;
+        private System.Windows.Forms.ComboBox cbRenderStyle;
+        private System.Windows.Forms.Label label2;
+        private System.Windows.Forms.CheckBox cblightabsolute;
+        private System.Windows.Forms.CheckBox cbRelativeMode;
+        private System.Windows.Forms.GroupBox groupBox1;
+    }
+}
\ No newline at end of file
diff --git a/Source/Plugins/UMDFControls/Windows/UDMFControlsForm.cs b/Source/Plugins/UMDFControls/Windows/UDMFControlsForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5b63cc74c22325547460c3f0fa1a2cda7272e03f
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Windows/UDMFControlsForm.cs
@@ -0,0 +1,663 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+
+using CodeImp.DoomBuilder.Config;
+using CodeImp.DoomBuilder.Map;
+using CodeImp.DoomBuilder.VisualModes;
+using CodeImp.DoomBuilder.Windows;
+using CodeImp.DoomBuilder.Geometry;
+using CodeImp.DoomBuilder.Types;
+
+namespace CodeImp.DoomBuilder.UDMFControls
+{
+    public partial class UDMFControlsForm : DelayedForm {
+        private List<VisualGeometry> floors;
+        private List<VisualGeometry> ceilings;
+
+        private List<VisualGeometry> wallsTop;
+        private List<VisualGeometry> wallsMid;
+        private List<VisualGeometry> wallsBottom;
+
+        private List<List<VisualGeometry>> walls;
+        private List<List<VisualGeometry>> ceilingsAndFloors;
+
+        private List<VisualSector> updateList; //list of sectors to update
+
+        private CheckBox[] wallFlags;
+        private CheckBox[] sectorFlags;
+
+        private List<string> renderStyles;
+
+        private static bool relativeMode;
+
+        public UDMFControlsForm() {
+            //capture keys
+            KeyPreview = true;
+            
+            //initialize form
+            InitializeComponent();
+            
+            //create collections
+            floors = new List<VisualGeometry>();
+            ceilings = new List<VisualGeometry>();
+            wallsTop = new List<VisualGeometry>();
+            wallsMid = new List<VisualGeometry>();
+            wallsBottom = new List<VisualGeometry>();
+
+            walls = new List<List<VisualGeometry>>() { wallsTop, wallsMid, wallsBottom };
+            ceilingsAndFloors = new List<List<VisualGeometry>>() { ceilings, floors };
+            
+            updateList = new List<VisualSector>();
+
+            wallFlags = new CheckBox[] { cbnodecals, cbnofakecontrast, cbclipmidtex, cbsmoothlighting };
+            sectorFlags = new CheckBox[] { cbsilent, cbnofallingdamage, cbdropactors, cbnorespawn };
+
+            renderStyles = new List<string>() { "translucent", "add" };
+
+            KeyDown += new KeyEventHandler(UDMFControlsForm_KeyDown);
+            KeyUp += new KeyEventHandler(UDMFControlsForm_KeyUp);
+
+            cbRelativeMode.Checked = relativeMode;
+
+            setup();
+        }
+
+        //we should be in Visual mode and should have some surfaces selected at this point
+        private void setup() {
+            VisualMode vm = (VisualMode)General.Editing.Mode;
+
+            //should contain something, otherwise we wouldn't be here
+            List<VisualGeometry> surfaces = vm.GetSelectedSurfaces(false);
+
+            //create undo
+            string rest = surfaces.Count + " surface" + (surfaces.Count > 1 ? "s" : "");
+            General.Map.UndoRedo.CreateUndo("Edit texture properties of " + rest);
+
+            //get default values
+            List<UniversalFieldInfo> defaultSidedefFields = General.Map.Config.SidedefFields;
+            List<UniversalFieldInfo> defaultLinedefFields = General.Map.Config.LinedefFields;
+            List<UniversalFieldInfo> defaultSectorFields = General.Map.Config.SectorFields;
+
+            VisualGeometry firstWall = null;
+            VisualGeometry firstFloor = null; //or ceiling!
+
+            List<int> sectorIndeces = new List<int>();
+
+            //sort things
+            foreach (VisualGeometry vg in surfaces) {
+                if (sectorIndeces.IndexOf(vg.Sector.Sector.FixedIndex) == -1) {
+                    updateList.Add(vg.Sector);
+                    sectorIndeces.Add(vg.Sector.Sector.FixedIndex);
+                }
+                
+                switch (vg.GeometryType) {
+                    case VisualGeometryType.CEILING:
+                        if (firstFloor == null) firstFloor = vg;
+                        ceilings.Add(vg);
+                        vg.Sector.Sector.Fields.BeforeFieldsChange();
+                        setDefaultUniversalProperties(vg.Sector.Sector.Fields, defaultSectorFields);
+                        break;
+
+                    case VisualGeometryType.FLOOR:
+                        if (firstFloor == null) firstFloor = vg;
+                        floors.Add(vg);
+                        vg.Sector.Sector.Fields.BeforeFieldsChange();
+                        setDefaultUniversalProperties(vg.Sector.Sector.Fields, defaultSectorFields);
+                        break;
+
+                    case VisualGeometryType.WALL_BOTTOM:
+                        if (firstWall == null) firstWall = vg;
+                        wallsBottom.Add(vg);
+                        vg.Sidedef.Fields.BeforeFieldsChange();
+                        vg.Sidedef.Line.Fields.BeforeFieldsChange();
+                        setDefaultUniversalProperties(vg.Sidedef.Fields, defaultSidedefFields);
+                        setDefaultUniversalProperties(vg.Sidedef.Line.Fields, defaultLinedefFields);
+                        break;
+
+                    case VisualGeometryType.WALL_MIDDLE:
+                        if (firstWall == null) firstWall = vg;
+                        wallsMid.Add(vg);
+                        vg.Sidedef.Fields.BeforeFieldsChange();
+                        vg.Sidedef.Line.Fields.BeforeFieldsChange();
+                        setDefaultUniversalProperties(vg.Sidedef.Fields, defaultSidedefFields);
+                        setDefaultUniversalProperties(vg.Sidedef.Line.Fields, defaultLinedefFields);
+                        break;
+
+                    case VisualGeometryType.WALL_UPPER:
+                        if (firstWall == null) firstWall = vg;
+                        wallsTop.Add(vg);
+                        vg.Sidedef.Fields.BeforeFieldsChange();
+                        vg.Sidedef.Line.Fields.BeforeFieldsChange();
+                        setDefaultUniversalProperties(vg.Sidedef.Fields, defaultSidedefFields);
+                        setDefaultUniversalProperties(vg.Sidedef.Line.Fields, defaultLinedefFields);
+                        break;
+
+                    default: //dbg
+                        GZBuilder.GZGeneral.Trace("WARNING: got unknown visual geometry type!");
+                        break;
+                }
+            }
+
+            //set sliders limits
+            sliderDesaturation.SetLimits(0f, 1f, false);
+            sliderAlpha.SetLimits(0f, 1f, false);
+            scaleControl.SetLimits(-2f, 2f);
+
+            cbRenderStyle.Items.AddRange(new object[] { "Translucent", "Add" });
+            cbRenderStyle.SelectedIndex = 0;
+
+            //set initial values to controls
+            if (firstFloor != null) {
+                //get values
+                float scaleX = (float)firstFloor.Sector.Sector.Fields[KeyNames.GetScaleX(firstFloor.GeometryType)].Value;
+                float scaleY = (float)firstFloor.Sector.Sector.Fields[KeyNames.GetScaleY(firstFloor.GeometryType)].Value;
+                float translateX = (float)firstFloor.Sector.Sector.Fields[KeyNames.GetTranslationX(firstFloor.GeometryType)].Value;
+                float translateY = (float)firstFloor.Sector.Sector.Fields[KeyNames.GetTranslationY(firstFloor.GeometryType)].Value;
+
+                //set shared and sector flags
+                cblightabsolute.Checked = (bool)firstFloor.Sector.Sector.Fields[KeyNames.GetLightAbsolute(firstFloor.GeometryType)].Value;
+                
+                foreach(CheckBox cb in sectorFlags)
+                    cb.Checked = (bool)firstFloor.Sector.Sector.Fields[(string)cb.Tag].Value;
+
+                //set values to controls
+                scaleControl.Value = new Vector2D(scaleX, scaleY);
+                positionControl1.Value = new Vector2D(translateX, translateY);
+                angleControl1.Value = (int)((float)firstFloor.Sector.Sector.Fields[KeyNames.GetRotation(firstFloor.GeometryType)].Value);
+                sliderBrightness.Value = (int)firstFloor.Sector.Sector.Fields[KeyNames.GetLight(firstFloor.GeometryType)].Value;
+                nudGravity.Value = (decimal)((float)firstFloor.Sector.Sector.Fields[(string)nudGravity.Tag].Value);
+                sliderDesaturation.Value = (float)firstFloor.Sector.Sector.Fields[(string)sliderDesaturation.Tag].Value;
+
+            } else {//disable floor/ceiling related controls
+                gbRotation.Enabled = false;
+                gbFlagsFloor.Enabled = false;
+                nudGravity.Enabled = false;
+                labelGravity.Enabled = false;
+                gbDesaturation.Enabled = false;
+            }
+
+            if (firstWall != null) {
+                if(firstFloor == null){ //get shared values from wall
+                    //get values
+                    float scaleX = (float)firstWall.Sidedef.Fields[KeyNames.GetScaleX(firstWall.GeometryType)].Value;
+                    float scaleY = (float)firstWall.Sidedef.Fields[KeyNames.GetScaleY(firstWall.GeometryType)].Value;
+                    float translateX = (float)firstWall.Sidedef.Fields[KeyNames.GetTranslationX(firstWall.GeometryType)].Value;
+                    float translateY = (float)firstWall.Sidedef.Fields[KeyNames.GetTranslationY(firstWall.GeometryType)].Value;
+
+                    //set values to controls
+                    scaleControl.Value = new Vector2D(scaleX, scaleY);
+                    positionControl1.Value = new Vector2D(translateX, translateY);
+                    sliderBrightness.Value = (int)firstWall.Sidedef.Fields[KeyNames.GetLight(firstWall.GeometryType)].Value;
+                    cblightabsolute.Checked = (bool)firstWall.Sidedef.Fields[KeyNames.GetLightAbsolute(firstWall.GeometryType)].Value;
+
+                    //set linedef values
+                    sliderAlpha.Value = (float)firstWall.Sidedef.Line.Fields[(string)sliderAlpha.Tag].Value;
+                    string renderStyle = (string)firstWall.Sidedef.Line.Fields[(string)cbRenderStyle.Tag].Value;
+                    cbRenderStyle.SelectedIndex = renderStyles.IndexOf(renderStyle);
+                }
+
+                //set wall flags
+                foreach(CheckBox cb in wallFlags)
+                    cb.Checked = (bool)firstWall.Sidedef.Fields[(string)cb.Tag].Value;
+
+            } else { //disable wall-related controls
+                gbFlagsWall.Enabled = false;
+                gbAlpha.Enabled = false;
+            }
+
+            //brightness slider
+            if(cblightabsolute.Checked)
+                sliderBrightness.SetLimits(0, 255);
+            else
+                sliderBrightness.SetLimits(-255, 255);
+
+            Text = "Editing " + rest;
+        }
+
+        private void setDefaultUniversalProperties(UniFields fields, List<UniversalFieldInfo> defaultFields) {
+            foreach (UniversalFieldInfo info in defaultFields) {
+                if (!fields.ContainsKey(info.Name))
+                    fields.Add(info.Name, new UniValue(info.Type, (UniversalType)info.Type == UniversalType.Integer ? (object)Convert.ToInt32(info.Default) : info.Default));
+            }
+        }
+
+        private void removeDefaultUniversalProperties(UniFields fields, List<UniversalFieldInfo> defaultFields) {
+            foreach (UniversalFieldInfo info in defaultFields) {
+                if (fields.ContainsKey(info.Name) && fields[info.Name].Value.Equals((UniversalType)info.Type == UniversalType.Integer ? (object)Convert.ToInt32(info.Default) : info.Default))
+                    fields.Remove(info.Name);
+            }
+        }
+
+        private void removeDefaultValues() {
+            //remove default values...
+            List<UniversalFieldInfo> defaultSidedefFields = General.Map.Config.SidedefFields;
+            List<UniversalFieldInfo> defaultLinedefFields = General.Map.Config.LinedefFields;
+            List<UniversalFieldInfo> defaultSectorFields = General.Map.Config.SectorFields;
+
+            //...from floors/ceilings...
+            foreach (List<VisualGeometry> list in ceilingsAndFloors) {
+                foreach (VisualGeometry floor in list)
+                    removeDefaultUniversalProperties(floor.Sector.Sector.Fields, defaultSectorFields);
+            }
+
+            //...and walls
+            foreach (List<VisualGeometry> list in walls) {
+                foreach (VisualGeometry wall in list) {
+                    removeDefaultUniversalProperties(wall.Sidedef.Fields, defaultSidedefFields);
+                    removeDefaultUniversalProperties(wall.Sidedef.Line.Fields, defaultLinedefFields);
+                }
+            }
+        }
+
+//update view
+        private void update() {
+            foreach (VisualSector vs in updateList)
+                vs.UpdateSectorData();
+        }
+
+//shared props
+        private void setSharedProperty(string propName, object value) {
+            setSidedefProperty(propName, value);
+            setSectorProperty(propName, value);
+        }
+
+        private void setSharedPairedProperty(string propName, Vector2D value) {
+            setPairedSectorProperty(propName, value);
+            setPairedSidedefProperty(propName, value);
+        }
+
+//linedef props
+        private void setLinedefProperty(string propName, object value) {
+            foreach (List<VisualGeometry> list in walls) {
+                foreach (VisualGeometry vg in list)
+                    vg.Sidedef.Line.Fields[propName].Value = value;
+            }
+        }
+
+//sidedef props
+        private void setSidedefProperty(string propName, object value) {
+            //special cases
+            if (propName == "scale" || propName == "offset") {
+                setPairedSidedefProperty(propName, (Vector2D)value);
+                return;
+            }
+
+            //apply value
+            foreach (List<VisualGeometry> list in walls) {
+                foreach (VisualGeometry vg in list)
+                    vg.Sidedef.Fields[propName].Value = value;
+            }
+        }
+
+        private void setPairedSidedefProperty(string propName, Vector2D value) {
+            if (propName != "scale" && propName != "offset")
+                return;
+
+            string upperNameX  = "x_top";
+            string upperNameY  = "y_top";
+            string middleNameX = "x_mid";
+            string middleNameY = "y_mid";
+            string lowerNameX  = "x_bottom";
+            string lowerNameY  = "y_bottom";
+
+            string[] props = new string[] { upperNameX, upperNameY, middleNameX, middleNameY, lowerNameX, lowerNameY };
+
+            for (int i = 0; i < props.Length; i++ )
+                props[i] = propName + props[i];
+
+            int index = 0;
+            //apply values
+
+            if (relativeMode) {
+                float val;
+                foreach (List<VisualGeometry> list in walls) { //top -> middle -> bottom
+                    foreach (VisualGeometry vg in list) {
+                        val = (float)vg.Sidedef.Fields[props[index]].Value + value.x;
+                        vg.Sidedef.Fields[props[index]].Value = val;
+
+                        val = (float)vg.Sidedef.Fields[props[index+1]].Value + value.y;
+                        vg.Sidedef.Fields[props[index + 1]].Value = val;
+                    }
+                    index += 2;
+                }
+            } else {
+                foreach (List<VisualGeometry> list in walls) { //top -> middle -> bottom
+                    foreach (VisualGeometry vg in list) {
+                        vg.Sidedef.Fields[props[index]].Value = value.x;
+                        vg.Sidedef.Fields[props[index + 1]].Value = value.y;
+                    }
+                    index += 2;
+                }
+            }
+        }
+
+//floor/ceiling props
+        private void setSectorProperty(string propName, object value) {
+            //special cases
+            if (propName == "scale" || propName == "offset") {
+                setPairedSectorProperty(propName, (Vector2D)value);
+                return;
+            } else if (propName == "light" || propName == "lightabsolute" || propName == "rotation") {
+                string propFloor;
+                string propCeiling;
+
+                if (propName == "light") {
+                    propFloor = "lightfloor";
+                    propCeiling = "lightceiling";
+                } else if (propName == "lightabsolute") {
+                    propFloor = "lightfloorabsolute";
+                    propCeiling = "lightceilingabsolute";
+                } else {
+                    propFloor = "rotationfloor";
+                    propCeiling = "rotationceiling";
+                }
+
+                if (propName == "rotation" && relativeMode) {
+                    float val;
+
+                    foreach (VisualGeometry vg in floors) {
+                        val = (float)vg.Sector.Sector.Fields[propFloor].Value + (float)value;
+                        vg.Sector.Sector.Fields[propFloor].Value = (object)val;
+                    }
+
+                    foreach (VisualGeometry vg in ceilings) {
+                        val = (float)vg.Sector.Sector.Fields[propCeiling].Value + (float)value;
+                        vg.Sector.Sector.Fields[propCeiling].Value = (object)val;
+                    }
+                } else {
+                    foreach (VisualGeometry vg in floors)
+                        vg.Sector.Sector.Fields[propFloor].Value = value;
+
+                    foreach (VisualGeometry vg in ceilings)
+                        vg.Sector.Sector.Fields[propCeiling].Value = value;
+                }
+                return;
+            }
+
+            foreach (List<VisualGeometry> list in ceilingsAndFloors) {
+                foreach (VisualGeometry vg in list)
+                    vg.Sector.Sector.Fields[propName].Value = value;
+            }
+        }
+
+        private void setPairedSectorProperty(string propName, Vector2D value) {
+            if (propName != "scale" && propName != "offset")
+                return;
+
+            string ceilingNameX, ceilingNameY, floorNameX, floorNameY;
+            string[] props;
+
+            if (propName == "scale") {
+                ceilingNameX = "xscaleceiling";
+                ceilingNameY = "yscaleceiling";
+                floorNameX = "xscalefloor";
+                floorNameY = "yscalefloor";
+            } else {
+                ceilingNameX = "xpanningceiling";
+                ceilingNameY = "ypanningceiling";
+                floorNameX = "xpanningfloor";
+                floorNameY = "ypanningfloor";
+            }
+            props = new string[] { ceilingNameX, ceilingNameY, floorNameX, floorNameY };
+
+            int index = 0;
+
+            if (relativeMode) {
+                float val;
+                foreach (List<VisualGeometry> list in ceilingsAndFloors) { //ceilings -> floors
+                    foreach (VisualGeometry vg in list) {
+                        val = (float)vg.Sector.Sector.Fields[props[index]].Value + value.x;
+                        vg.Sector.Sector.Fields[props[index]].Value = (object)val;
+
+                        val = (float)vg.Sector.Sector.Fields[props[index + 1]].Value + value.y;
+                        vg.Sector.Sector.Fields[props[index + 1]].Value = (object)val;
+                    }
+                    index += 2;
+                }
+            } else {
+                foreach (List<VisualGeometry> list in ceilingsAndFloors) { //ceilings -> floors
+                    foreach (VisualGeometry vg in list) {
+                        vg.Sector.Sector.Fields[props[index]].Value = value.x;
+                        vg.Sector.Sector.Fields[props[index + 1]].Value = value.y;
+                    }
+                    index += 2;
+                }
+            }
+        }
+        
+//EVENTS
+        private void btnOK_Click(object sender, EventArgs e) {
+            //apply flags and settings, which are not updated in real time
+            //gravity
+            setSectorProperty((string)nudGravity.Tag, (object)((float)nudGravity.Value));
+            //desaturation
+            setSectorProperty((string)sliderDesaturation.Tag, (object)sliderDesaturation.Value);
+
+            //wall flags
+            foreach (CheckBox cb in wallFlags) 
+                setSidedefProperty((string)cb.Tag, (object)cb.Checked);
+
+            //sector flags
+            foreach (CheckBox cb in sectorFlags)
+                setSectorProperty((string)cb.Tag, (object)cb.Checked);
+
+            //update sectors
+            foreach (VisualSector vs in updateList) {
+                vs.Sector.UpdateNeeded = true;
+                vs.Sector.UpdateCache();
+            }
+
+            removeDefaultValues();
+            Close();
+        }
+
+        private void btnCancel_Click(object sender, EventArgs e) {
+            //remove default values...
+            removeDefaultValues();
+
+            //restore initial values
+            General.Map.UndoRedo.PerformUndo();
+            Close();
+        }
+
+//KEYBOARD EVENTS
+        private void UDMFControlsForm_KeyDown(object sender, KeyEventArgs e) {
+            if (e.Shift) {
+                angleControl1.SnapAngle = e.Shift;
+                e.Handled = true;
+            }
+        }
+
+        private void UDMFControlsForm_KeyUp(object sender, KeyEventArgs e) {
+            if (e.Shift) {
+                angleControl1.SnapAngle = !e.Shift;
+                e.Handled = true;
+            }
+        }
+
+//INTERACTIVE CONTROLS
+//position
+        private void positionControl1_OnValueChanged(object sender, EventArgs e) {
+            setSharedPairedProperty((string)positionControl1.Tag, relativeMode ? positionControl1.Delta : positionControl1.Value);
+            update();
+        }
+
+//rotation
+        private void angleControl1_OnAngleChanged(object sender, EventArgs e) {
+            setSectorProperty((string)angleControl1.Tag, relativeMode ? (float)angleControl1.Delta : (float)angleControl1.Value);
+            update();
+        }
+
+//scale
+        private void scaleControl_OnValueChanged(object sender, EventArgs e) {
+            setSharedPairedProperty((string)scaleControl.Tag, relativeMode ? scaleControl.Delta : scaleControl.Value);
+            update();
+        }
+
+//brightness
+        private void sliderBrightness_OnValueChanged(object sender, EventArgs e) {
+            setSharedProperty((string)sliderBrightness.Tag, (object)sliderBrightness.Value);
+            update();
+        }
+
+//alpha
+        private void sliderAlpha_OnValueChanged(object sender, EventArgs e) {
+            setLinedefProperty((string)sliderAlpha.Tag, sliderAlpha.Value);
+            update();
+        }
+
+        private void cbRenderStyle_SelectedIndexChanged(object sender, EventArgs e) {
+            string val = cbRenderStyle.Text.ToLowerInvariant();
+            setLinedefProperty((string)cbRenderStyle.Tag, val);
+            update();
+        }
+
+//flags
+        private void cbwrapmidtex_CheckedChanged(object sender, EventArgs e) {
+            setSidedefProperty((string)cbwrapmidtex.Tag, (object)cbwrapmidtex.Checked);
+            update();
+        }
+
+        private void cblightabsolute_CheckedChanged(object sender, EventArgs e) {
+            if(cblightabsolute.Checked)
+                sliderBrightness.SetLimits(0, 255);
+            else
+                sliderBrightness.SetLimits(-255, 255);
+            
+            setSharedProperty((string)cblightabsolute.Tag, (object)cblightabsolute.Checked);
+            update();
+        }
+
+        private void cbRelativeMode_CheckedChanged(object sender, EventArgs e) {
+            relativeMode = cbRelativeMode.Checked;
+        }
+    }
+
+    public class KeyNames {
+//SCALE        
+        public static string GetScaleX(VisualGeometryType type) {
+            return getScale(type).Replace("$", "x");
+        }
+
+        public static string GetScaleY(VisualGeometryType type) {
+            return getScale(type).Replace("$", "y");
+        }
+
+        private static string getScale(VisualGeometryType type) {
+            switch(type){
+                case VisualGeometryType.CEILING:
+                    return "$scaleceiling";
+                    break;
+
+                case VisualGeometryType.FLOOR:
+                    return "$scalefloor";
+                    break;
+
+                case VisualGeometryType.WALL_UPPER:
+                    return "scale$_top";
+                    break;
+
+                case VisualGeometryType.WALL_MIDDLE:
+                    return "scale$_mid";
+                    break;
+
+                case VisualGeometryType.WALL_BOTTOM:
+                    return "scale$_bottom";
+                    break;
+            }
+            return "";
+        }
+
+//TRANSLATION
+        public static string GetTranslationX(VisualGeometryType type) {
+            return getTranslation(type).Replace("$", "x");
+        }
+
+        public static string GetTranslationY(VisualGeometryType type) {
+            return getTranslation(type).Replace("$", "y");
+        }
+
+        private static string getTranslation(VisualGeometryType type) {
+            switch (type) {
+                case VisualGeometryType.CEILING:
+                    return "$panningceiling";
+                    break;
+
+                case VisualGeometryType.FLOOR:
+                    return "$panningfloor";
+                    break;
+
+                case VisualGeometryType.WALL_UPPER:
+                    return "offset$_top";
+                    break;
+
+                case VisualGeometryType.WALL_MIDDLE:
+                    return "offset$_mid";
+                    break;
+
+                case VisualGeometryType.WALL_BOTTOM:
+                    return "offset$_bottom";
+                    break;
+            }
+            return "";
+        }
+
+//ROTATION
+        public static string GetRotation(VisualGeometryType type) {
+            switch (type) {
+                case VisualGeometryType.FLOOR:
+                    return "rotationfloor";
+                    break;
+
+                case VisualGeometryType.CEILING:
+                    return "rotationceiling";
+                    break;
+            }
+            return "";
+        }
+
+//LIGHT
+        public static string GetLight(VisualGeometryType type) {
+            switch (type) {
+                case VisualGeometryType.FLOOR:
+                    return "lightfloor";
+                    break;
+
+                case VisualGeometryType.CEILING:
+                    return "lightceiling";
+                    break;
+
+                case VisualGeometryType.WALL_BOTTOM:
+                case VisualGeometryType.WALL_MIDDLE:
+                case VisualGeometryType.WALL_UPPER:
+                    return "light";
+                    break;
+            }
+            return "";
+        }
+
+        public static string GetLightAbsolute(VisualGeometryType type) {
+            switch (type) {
+                case VisualGeometryType.FLOOR:
+                    return "lightfloorabsolute";
+                    break;
+
+                case VisualGeometryType.CEILING:
+                    return "lightceilingabsolute";
+                    break;
+
+                case VisualGeometryType.WALL_BOTTOM:
+                case VisualGeometryType.WALL_MIDDLE:
+                case VisualGeometryType.WALL_UPPER:
+                    return "lightabsolute";
+                    break;
+            }
+            return "";
+        }
+    }
+}
diff --git a/Source/Plugins/UMDFControls/Windows/UDMFControlsForm.resx b/Source/Plugins/UMDFControls/Windows/UDMFControlsForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..ff31a6db56e23b5a334f34387830ba5b4bd33eb8
--- /dev/null
+++ b/Source/Plugins/UMDFControls/Windows/UDMFControlsForm.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file