diff --git a/Source/Core/Editing/CopyPasteManager.cs b/Source/Core/Editing/CopyPasteManager.cs
index b4750169e860fed08a829a5539b5e8058a2dcbe6..edd4d5463bf4172cd146b899586e155cc1ffc0aa 100644
--- a/Source/Core/Editing/CopyPasteManager.cs
+++ b/Source/Core/Editing/CopyPasteManager.cs
@@ -178,7 +178,7 @@ namespace CodeImp.DoomBuilder.Editing
 			General.Map.Map.ClearAllMarks(true);
 			
 			// Read data stream
-			UniversalStreamReader reader = new UniversalStreamReader();
+			UniversalStreamReader reader = new UniversalStreamReader(General.Map.FormatInterface.UIFields); //mxd
 			reader.StrictChecking = false;
 			General.Map.Map.BeginAddRemove();
 			reader.Read(General.Map.Map, memstream);
@@ -283,7 +283,7 @@ namespace CodeImp.DoomBuilder.Editing
 							General.Map.Map.ClearAllMarks(true);
 
 							// Read data stream
-							UniversalStreamReader reader = new UniversalStreamReader();
+							UniversalStreamReader reader = new UniversalStreamReader(General.Map.FormatInterface.UIFields); //mxd
 							reader.StrictChecking = false;
 							General.Map.Map.BeginAddRemove();
 							reader.Read(General.Map.Map, memstream);
diff --git a/Source/Core/IO/UniversalMapSetIO.cs b/Source/Core/IO/UniversalMapSetIO.cs
index 185989766613e4594c524b34b8662a14216c05b1..311d3034e6c683b923496b112722fffffa20df54 100644
--- a/Source/Core/IO/UniversalMapSetIO.cs
+++ b/Source/Core/IO/UniversalMapSetIO.cs
@@ -140,7 +140,7 @@ namespace CodeImp.DoomBuilder.IO
 		// This reads a map from the file and returns a MapSet
 		public override MapSet Read(MapSet map, string mapname)
 		{
-			UniversalStreamReader udmfreader = new UniversalStreamReader();
+			UniversalStreamReader udmfreader = new UniversalStreamReader(uifields); //mxd
 			
 			// Find the index where first map lump begins
 			int firstindex = wad.FindLumpIndex(mapname) + 1;
diff --git a/Source/Core/IO/UniversalStreamReader.cs b/Source/Core/IO/UniversalStreamReader.cs
index 8bb093c6f98b0895a37c177184a2833430011ca2..ffbf54e00857a63f93d14f3fefc0de9e2da2975d 100644
--- a/Source/Core/IO/UniversalStreamReader.cs
+++ b/Source/Core/IO/UniversalStreamReader.cs
@@ -34,18 +34,17 @@ namespace CodeImp.DoomBuilder.IO
 	{
 		#region ================== Constants
 
-		// Name of the UDMF configuration files
+		// Name of the UDMF configuration file
 		private const string UDMF_CONFIG_NAME = "UDMF.cfg";
-		private const string UDMF_UI_CONFIG_NAME = "UDMF_UI.cfg"; //mxd
 
 		#endregion
 
 		#region ================== Variables
 
 		private Configuration config;
-		private Configuration uiconfig; //mxd
 		private bool setknowncustomtypes;
 		private bool strictchecking = true;
+		private Dictionary<string, Dictionary<string, UniversalType>> uifields; //mxd
 		
 		#endregion
 
@@ -59,8 +58,10 @@ namespace CodeImp.DoomBuilder.IO
 		#region ================== Constructor / Disposer
 
 		// Constructor
-		public UniversalStreamReader()
+		public UniversalStreamReader(Dictionary<string, Dictionary<string, UniversalType>> uifields)
 		{
+			this.uifields = uifields;
+			
 			// Make configuration
 			config = new Configuration();
 			
@@ -122,26 +123,6 @@ namespace CodeImp.DoomBuilder.IO
 					break;
 				}
 			}
-
-			//mxd. Load UI fields configuration
-			uiconfig = new Configuration();
-
-			foreach (string rn in resnames) {
-				// Found it?
-				if (rn.EndsWith(UDMF_UI_CONFIG_NAME, StringComparison.InvariantCultureIgnoreCase)) {
-					// Get a stream from the resource
-					Stream udmfcfg = General.ThisAssembly.GetManifestResourceStream(rn);
-					StreamReader udmfcfgreader = new StreamReader(udmfcfg, Encoding.ASCII);
-
-					// Load configuration from stream
-					uiconfig.InputConfiguration(udmfcfgreader.ReadToEnd());
-
-					// Done
-					udmfcfgreader.Dispose();
-					udmfcfg.Dispose();
-					break;
-				}
-			}
 		}
 
 		#endregion
@@ -455,29 +436,31 @@ namespace CodeImp.DoomBuilder.IO
 			// Go for all the elements in the collection
 			foreach(UniversalEntry e in collection)
 			{
-				// Check if not a managed field
-				if(!config.SettingExists("managedfields." + elementname + "." + e.Key))
-				{
-					int type = (int)UniversalType.Integer;
+				// mxd. Check if uifield
+				if(uifields.ContainsKey(elementname) && uifields[elementname].ContainsKey(e.Key)) {
+					int type = (int)uifields[elementname][e.Key];
+
+					//mxd. Check type
+					object value = e.Value;
 
-					//mxd
-					if (uiconfig.SettingExists("uifields." + elementname + "." + e.Key)) {
-						type = uiconfig.ReadSetting("uifields." + elementname + "." + e.Key, type);
+					// Let's be kind and cast any int to a float if needed
+					if(type == (int)UniversalType.Float && e.Value is int) {
+						value = (float)(int)e.Value;
+					} else if(!e.IsValidType(e.Value.GetType())) {
+						General.ErrorLogger.Add(ErrorType.Warning, element + ": the value of entry '" + e.Key + "' is of incompatible type (expected " + e.GetType().Name + ", but got " + e.Value.GetType().Name + "). If you save the map, this value will be ignored.");
+						continue;
+					}
 
-						//mxd. Check type
-						object value = e.Value;
+					// Make custom field
+					element.Fields[e.Key] = new UniValue(type, value);
 
-						// Let's be kind and cast any int to a float if needed
-						if(type == (int)UniversalType.Float && e.Value is int) {
-							value = (float)(int)e.Value;
-						} else if(!e.IsValidType(e.Value.GetType())) {
-							General.ErrorLogger.Add(ErrorType.Warning, element + ": the value of entry '" + e.Key + "' is of incompatible type (expected " + e.GetType().Name + ", but got " + e.Value.GetType().Name + "). If you save the map, this value will be ignored.");
-							continue;
-						}
 
-						// Make custom field
-						element.Fields[e.Key] = new UniValue(type, value);
-					} else if(setknowncustomtypes) { // Try to find the type from configuration
+				} // Check if not a managed field
+				else if(!config.SettingExists("managedfields." + elementname + "." + e.Key))
+				{
+					int type = (int)UniversalType.Integer;
+
+					if(setknowncustomtypes) { // Try to find the type from configuration
                         type = General.Map.Options.GetUniversalFieldType(elementname, e.Key, type);
 
                         //mxd. Check type
diff --git a/Source/Core/Windows/SectorEditFormUDMF.Designer.cs b/Source/Core/Windows/SectorEditFormUDMF.Designer.cs
index f926cbff65580154d63200f4db5f9f58b4962bf1..78231ac043e001c7ec905e209efbea3c94ce5149 100644
--- a/Source/Core/Windows/SectorEditFormUDMF.Designer.cs
+++ b/Source/Core/Windows/SectorEditFormUDMF.Designer.cs
@@ -85,6 +85,8 @@
 			this.fieldslist = new CodeImp.DoomBuilder.Controls.FieldsEditorControl();
 			this.cancel = new System.Windows.Forms.Button();
 			this.apply = new System.Windows.Forms.Button();
+			this.cbUseCeilLineAngles = new System.Windows.Forms.CheckBox();
+			this.cbUseFloorLineAngles = new System.Windows.Forms.CheckBox();
 			groupaction = new System.Windows.Forms.GroupBox();
 			groupeffect = new System.Windows.Forms.GroupBox();
 			label14 = new System.Windows.Forms.Label();
@@ -438,6 +440,7 @@
 			// 
 			this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
 						| System.Windows.Forms.AnchorStyles.Right)));
+			this.groupBox2.Controls.Add(this.cbUseFloorLineAngles);
 			this.groupBox2.Controls.Add(this.floorAngleControl);
 			this.groupBox2.Controls.Add(this.label7);
 			this.groupBox2.Controls.Add(this.label10);
@@ -623,6 +626,7 @@
 			// 
 			this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
 						| System.Windows.Forms.AnchorStyles.Right)));
+			this.groupBox1.Controls.Add(this.cbUseCeilLineAngles);
 			this.groupBox1.Controls.Add(this.ceilAngleControl);
 			this.groupBox1.Controls.Add(this.label3);
 			this.groupBox1.Controls.Add(this.label4);
@@ -861,6 +865,30 @@
 			this.apply.UseVisualStyleBackColor = true;
 			this.apply.Click += new System.EventHandler(this.apply_Click);
 			// 
+			// cbUseCeilLineAngles
+			// 
+			this.cbUseCeilLineAngles.AutoSize = true;
+			this.cbUseCeilLineAngles.Location = new System.Drawing.Point(230, 119);
+			this.cbUseCeilLineAngles.Name = "cbUseCeilLineAngles";
+			this.cbUseCeilLineAngles.Size = new System.Drawing.Size(99, 18);
+			this.cbUseCeilLineAngles.TabIndex = 56;
+			this.cbUseCeilLineAngles.Tag = "";
+			this.cbUseCeilLineAngles.Text = "Use line angles";
+			this.cbUseCeilLineAngles.UseVisualStyleBackColor = true;
+			this.cbUseCeilLineAngles.CheckedChanged += new System.EventHandler(this.cbUseCeilLineAngles_CheckedChanged);
+			// 
+			// cbUseFloorLineAngles
+			// 
+			this.cbUseFloorLineAngles.AutoSize = true;
+			this.cbUseFloorLineAngles.Location = new System.Drawing.Point(230, 119);
+			this.cbUseFloorLineAngles.Name = "cbUseFloorLineAngles";
+			this.cbUseFloorLineAngles.Size = new System.Drawing.Size(99, 18);
+			this.cbUseFloorLineAngles.TabIndex = 57;
+			this.cbUseFloorLineAngles.Tag = "";
+			this.cbUseFloorLineAngles.Text = "Use line angles";
+			this.cbUseFloorLineAngles.UseVisualStyleBackColor = true;
+			this.cbUseFloorLineAngles.CheckedChanged += new System.EventHandler(this.cbUseFloorLineAngles_CheckedChanged);
+			// 
 			// SectorEditFormUDMF
 			// 
 			this.AcceptButton = this.apply;
@@ -952,5 +980,7 @@
 		private CodeImp.DoomBuilder.GZBuilder.Controls.ColorFieldsControl fadeColor;
 		private CodeImp.DoomBuilder.GZBuilder.Controls.ColorFieldsControl lightColor;
 		private CodeImp.DoomBuilder.Controls.CheckboxArrayControl flags;
+		private System.Windows.Forms.CheckBox cbUseFloorLineAngles;
+		private System.Windows.Forms.CheckBox cbUseCeilLineAngles;
 	}
 }
\ No newline at end of file
diff --git a/Source/Core/Windows/SectorEditFormUDMF.cs b/Source/Core/Windows/SectorEditFormUDMF.cs
index 9646a1c8d39ca739df448846c707955ce6be813d..0e12de4127255e007915885d296f95917f4895df 100644
--- a/Source/Core/Windows/SectorEditFormUDMF.cs
+++ b/Source/Core/Windows/SectorEditFormUDMF.cs
@@ -20,10 +20,13 @@ namespace CodeImp.DoomBuilder.Windows
 		private ICollection<Sector> sectors;
 		private List<SectorProperties> sectorProps; //mxd
 		private bool blockUpdate; //mxd
+		private StepsList angleSteps; //mxd
 
-		//Value linking
+		//Persistent settings
 		private static bool linkCeilingScale;
 		private static bool linkFloorScale;
+		private static bool useFloorLineAngles;
+		private static bool useCeilLineAngles;
 
 		private struct SectorProperties //mxd
 		{
@@ -121,6 +124,9 @@ namespace CodeImp.DoomBuilder.Windows
 			// Value linking
 			ceilScale.LinkValues = linkCeilingScale;
 			floorScale.LinkValues = linkFloorScale;
+
+			cbUseCeilLineAngles.Checked = useCeilLineAngles;
+			cbUseFloorLineAngles.Checked = useFloorLineAngles;
 		}
 
 		#endregion
@@ -211,6 +217,8 @@ namespace CodeImp.DoomBuilder.Windows
 			// Custom fields
 			fieldslist.SetValues(sc.Fields, true);
 
+			angleSteps = new StepsList();
+
 			////////////////////////////////////////////////////////////////////////
 			// Now go for all sectors and change the options when a setting is different
 			////////////////////////////////////////////////////////////////////////
@@ -295,11 +303,27 @@ namespace CodeImp.DoomBuilder.Windows
 
 				//mxd. Store initial properties
 				sectorProps.Add(new SectorProperties(s));
+
+				//mxd. Angle steps
+				int angle;
+				foreach(Sidedef side in s.Sidedefs){
+					if (side.Line.Front != null && side.Index == side.Line.Front.Index)
+						angle = General.ClampAngle(270 - side.Line.AngleDeg);
+					else
+						angle = General.ClampAngle(90 - side.Line.AngleDeg);
+
+					if(!angleSteps.Contains(angle)) angleSteps.Add(angle);
+				}
 			}
 
 			// Show sector height
 			UpdateSectorHeight();
 
+			//mxd. Angle steps
+			angleSteps.Sort();
+			if(useCeilLineAngles) ceilRotation.StepValues = angleSteps;
+			if(useFloorLineAngles) floorRotation.StepValues = angleSteps;
+
 			blockUpdate = false; //mxd
 		}
 
@@ -316,13 +340,11 @@ namespace CodeImp.DoomBuilder.Windows
 					delta = s.CeilHeight - s.FloorHeight;
 					showheight = true;
 					first = s;
-				} else {
-					if(delta != (s.CeilHeight - s.FloorHeight)) {
-						// We can't show heights because the delta
-						// heights for the sectors is different
-						showheight = false;
-						break;
-					}
+				} else if(delta != (s.CeilHeight - s.FloorHeight)) {
+					// We can't show heights because the delta
+					// heights for the sectors is different
+					showheight = false;
+					break;
 				}
 			}
 
@@ -415,6 +437,8 @@ namespace CodeImp.DoomBuilder.Windows
 			// Store value linking
 			linkCeilingScale = ceilScale.LinkValues;
 			linkFloorScale = floorScale.LinkValues;
+			useCeilLineAngles = cbUseCeilLineAngles.Checked;
+			useFloorLineAngles = cbUseFloorLineAngles.Checked;
 
 			// Done
 			General.Map.IsChanged = true;
@@ -453,6 +477,14 @@ namespace CodeImp.DoomBuilder.Windows
 			floorRotation.Text = (General.ClampAngle(360 - floorAngleControl.Angle)).ToString();
 		}
 
+		private void cbUseCeilLineAngles_CheckedChanged(object sender, EventArgs e) {
+			ceilRotation.StepValues = (cbUseCeilLineAngles.Checked ? angleSteps : null);
+		}
+
+		private void cbUseFloorLineAngles_CheckedChanged(object sender, EventArgs e) {
+			floorRotation.StepValues = (cbUseFloorLineAngles.Checked ? angleSteps : null);
+		}
+
 		#endregion
 
 		#region mxd. Sector Realtime events
diff --git a/Source/Core/Windows/SectorEditFormUDMF.resx b/Source/Core/Windows/SectorEditFormUDMF.resx
index 53aec6270ba5fb2db48e666fd7f10938c75d8892..90add83371941efe06a10f7ff476635aa0b77322 100644
--- a/Source/Core/Windows/SectorEditFormUDMF.resx
+++ b/Source/Core/Windows/SectorEditFormUDMF.resx
@@ -138,6 +138,21 @@
   <metadata name="label8.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>False</value>
   </metadata>
+  <metadata name="label14.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </metadata>
+  <metadata name="label9.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </metadata>
+  <metadata name="label13.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </metadata>
+  <metadata name="label2.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </metadata>
+  <metadata name="label8.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </metadata>
   <metadata name="groupfloorceiling.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>False</value>
   </metadata>
@@ -147,6 +162,12 @@
   <metadata name="label5.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>False</value>
   </metadata>
+  <metadata name="label6.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </metadata>
+  <metadata name="label5.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>False</value>
+  </metadata>
   <metadata name="tabproperties.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
@@ -156,4 +177,7 @@
   <metadata name="fieldslist.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
     <value>True</value>
   </metadata>
+  <metadata name="fieldslist.Locked" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
 </root>
\ No newline at end of file