From d01cbb2c37f20b134b03981e47c488f9ebdf677f Mon Sep 17 00:00:00 2001
From: biwa <6475593+biwa@users.noreply.github.com>
Date: Mon, 8 Jun 2020 20:58:00 +0200
Subject: [PATCH] Some code cleanup Added comments to code

---
 .../Interface/SlopeArchForm.Designer.cs       |   2 +-
 .../BuilderModes/Interface/SlopeArchForm.cs   | 122 ++++++++++++++++--
 .../VisualModes/BaseVisualMode.cs             |  55 ++++----
 .../BuilderModes/VisualModes/SlopeArcher.cs   | 118 ++++++++---------
 4 files changed, 195 insertions(+), 102 deletions(-)

diff --git a/Source/Plugins/BuilderModes/Interface/SlopeArchForm.Designer.cs b/Source/Plugins/BuilderModes/Interface/SlopeArchForm.Designer.cs
index db3f78d19..e6d70116f 100644
--- a/Source/Plugins/BuilderModes/Interface/SlopeArchForm.Designer.cs
+++ b/Source/Plugins/BuilderModes/Interface/SlopeArchForm.Designer.cs
@@ -96,7 +96,7 @@
 			this.offset.Size = new System.Drawing.Size(63, 24);
 			this.offset.StepValues = null;
 			this.offset.TabIndex = 20;
-			this.offset.WhenTextChanged += new System.EventHandler(this.offset_changed);
+			this.offset.WhenButtonsClicked += new System.EventHandler(this.offset_changed);
 			this.offset.WhenEnterPressed += new System.EventHandler(this.offset_changed);
 			this.offset.Leave += new System.EventHandler(this.offset_changed);
 			// 
diff --git a/Source/Plugins/BuilderModes/Interface/SlopeArchForm.cs b/Source/Plugins/BuilderModes/Interface/SlopeArchForm.cs
index f89353450..29b04761a 100644
--- a/Source/Plugins/BuilderModes/Interface/SlopeArchForm.cs
+++ b/Source/Plugins/BuilderModes/Interface/SlopeArchForm.cs
@@ -1,21 +1,36 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Forms;
+#region ================== Copyright (c) 2020 Boris Iwanski
+
+/*
+ * This program is free software: you can redistribute it and/or modify
+ *
+ * it under the terms of the GNU General Public License as published by
+ * 
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * 
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.If not, see<http://www.gnu.org/licenses/>.
+ */
+
+#endregion
+
+using System;
 using CodeImp.DoomBuilder.Windows;
-using CodeImp.DoomBuilder.Controls;
-using CodeImp.DoomBuilder.Editing;
 using CodeImp.DoomBuilder.Geometry;
 
 namespace CodeImp.DoomBuilder.BuilderModes
 {
 	internal partial class SlopeArchForm : DelayedForm
 	{
+		#region ================== Variables
+
 		private double originaltheta;
 		private double originaloffset;
 		private double originalscale;
@@ -26,13 +41,17 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		private SlopeArcher slopearcher;
 		public event EventHandler UpdateChangedObjects;
 
+		#endregion
+
+		#region ================== Constructor / Destructor
+
 		internal SlopeArchForm(SlopeArcher slopearcher)
 		{
 			InitializeComponent();
 			this.slopearcher = slopearcher;
 
-			oldtheta = originaltheta = Angle2D.RadToDeg(this.slopearcher.Theta);
-			oldoffset = originaloffset = Angle2D.RadToDeg(this.slopearcher.OffsetAngle);
+			oldtheta = originaltheta = Math.Round(Angle2D.RadToDeg(this.slopearcher.Theta), 2);
+			oldoffset = originaloffset = Math.Round(Angle2D.RadToDeg(this.slopearcher.OffsetAngle), 2);
 			oldscale = originalscale = this.slopearcher.Scale;
 			originalheightoffset = this.slopearcher.HeightOffset;
 
@@ -42,12 +61,20 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			heightoffset.Text = originalheightoffset.ToString();
 		}
 
+		#endregion
+
+		#region ================== Methods
+
+		/// <summary>
+		/// Updates the arch with the values currently entered in the dialog
+		/// </summary>
 		private void UpdateArch()
 		{
 			double t = theta.GetResultFloat(originaltheta);
 			double o = offset.GetResultFloat(originaloffset);
 			double s = scale.GetResultFloat(originalscale * 100.0) / 100.0;
 
+			// Flip the scale if "down" is checked
 			if(!up.Checked)
 				s *= -1.0;
 
@@ -58,15 +85,30 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 			slopearcher.ApplySlope();
 
+			// BaseVisualMode added a event handler to the dialog, so BaseVisualMode will update the geometry when we tell it to
 			UpdateChangedObjects?.Invoke(this, EventArgs.Empty);
 		}
 
+		#endregion
+
+		#region ================== Events
+
+		/// <summary>
+		/// Immediately apply the arch when the form is shown
+		/// </summary>
+		/// <param name="sender">sender</param>
+		/// <param name="e">event arguments</param>
 		private void SlopeArchForm_Shown(object sender, EventArgs e)
 		{
 			slopearcher.ApplySlope();
 			UpdateChangedObjects?.Invoke(this, EventArgs.Empty);
 		}
 
+		/// <summary>
+		/// Sets the values for theta and angle offset for a half circle
+		/// </summary>
+		/// <param name="sender">sender</param>
+		/// <param name="e">event arguments</param>
 		private void halfcircle_Click(object sender, EventArgs e)
 		{
 			theta.Text = "180";
@@ -78,6 +120,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			UpdateArch();
 		}
 
+		/// <summary>
+		/// Sets the values for theta and angle offset for a quarter circle (top left quadrant viewed from the first selected slope hande)
+		/// </summary>
+		/// <param name="sender">sender</param>
+		/// <param name="e">event arguments</param>
 		private void quartercircleleft_Click(object sender, EventArgs e)
 		{
 			theta.Text = "90";
@@ -89,6 +136,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			UpdateArch();
 		}
 
+		/// <summary>
+		/// Sets the values for theta and angle offset for a quarter circle (top right quadrant viewed from the first selected slope hande)
+		/// </summary>
+		/// <param name="sender">sender</param>
+		/// <param name="e">event arguments</param>
 		private void quartercircleright_Click(object sender, EventArgs e)
 		{
 			theta.Text = "90";
@@ -99,6 +151,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			UpdateArch();
 		}
 
+		/// <summary>
+		/// Handles updates of the theta value. Also does sanity checks and modifies the values if necessary
+		/// </summary>
+		/// <param name="sender">sender</param>
+		/// <param name="e">event arguments</param>
 		private void theta_changed(object sender, EventArgs e)
 		{
 			double newtheta = theta.GetResultFloat(originaltheta);
@@ -143,28 +200,42 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				General.Interface.DisplayStatus(StatusType.Warning, "The sum of the angle and offset angle can not be greater than 180.");
 			}
 
+			// Remember the old values
 			oldtheta = theta.GetResultFloat(originaltheta);
 			oldoffset = offset.GetResultFloat(originaloffset);
 
 			UpdateArch();
 		}
 
+		/// <summary>
+		/// Handles updates of the angle offset value. Also does sanity checks and modifies the values if necessary
+		/// </summary>
+		/// <param name="sender">sender</param>
+		/// <param name="e">event arguments</param>
 		private void offset_changed(object sender, EventArgs e)
 		{
 			double newtheta = theta.GetResultFloat(originaltheta);
 			double newoffset = offset.GetResultFloat(originaloffset);
 
-			if(newtheta + newoffset > 180.0)
+			// If the new result is larger than 180.0 reset to the previous values
+			if (newtheta + newoffset > 180.0)
 			{
 				theta.Text = oldtheta.ToString();
 				offset.Text = oldoffset.ToString();
 			}
 
+			// Remember the old values
+			oldtheta = theta.GetResultFloat(originaltheta);
 			oldoffset = offset.GetResultFloat(originaloffset);
 
 			UpdateArch();
 		}
 
+		/// <summary>
+		/// Handles updates of the scale value. Also does sanity checks and modifies the values if necessary
+		/// </summary>
+		/// <param name="sender">sender</param>
+		/// <param name="e">event arguments</param>
 		private void scale_changed(object sender, EventArgs e)
 		{
 			double newscale = scale.GetResultFloat(originalscale);
@@ -172,29 +243,52 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			if (newscale <= 0.0)
 				scale.Text = oldscale.ToString();
 
+			// Remember the old value
 			oldscale = scale.GetResultFloat(originalscale);
 
 			UpdateArch();
 		}
 
+		/// <summary>
+		/// Handles updates of the height offset value.
+		/// </summary>
+		/// <param name="sender">sender</param>
+		/// <param name="e">event arguments</param>
 		private void heightoffset_changed(object sender, EventArgs e)
 		{
 			UpdateArch();
 		}
 
+		/// <summary>
+		/// Handles updates of the "up" radio box.
+		/// </summary>
+		/// <param name="sender">sender</param>
+		/// <param name="e">event arguments</param>
 		private void up_CheckedChanged(object sender, EventArgs e)
 		{
 			UpdateArch();
 		}
 
+		/// <summary>
+		/// Handles updates of the "down" radio box.
+		/// </summary>
+		/// <param name="sender">sender</param>
+		/// <param name="e">event arguments</param>
 		private void down_CheckedChanged(object sender, EventArgs e)
 		{
 			UpdateArch();
 		}
 
+		/// <summary>
+		/// Toggles the "lock offset angle" checkbox.
+		/// </summary>
+		/// <param name="sender">sender</param>
+		/// <param name="e">event arguments</param>
 		private void lockoffset_CheckedChanged(object sender, EventArgs e)
 		{
 			offset.Enabled = !offset.Enabled;
 		}
+
+		#endregion
 	}
 }
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
index 47233fc98..4efa835b8 100755
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
@@ -1835,6 +1835,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			ShowTargetInfo();
 		}
 
+		private void Interface_OnUpdateChangedObjects(object sender, EventArgs e)
+		{
+			UpdateChangedObjects();
+		}
+
 		//mxd
 		private void SelectioninfoupdatetimerOnTick(object sender, EventArgs eventArgs) 
 		{
@@ -4250,6 +4255,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			General.Interface.DisplayStatus(StatusType.Action, "Sloped between slope handles.");
 		}
 
+		/// <summary>
+		/// Applies plane equation slopes to selected sectors, based on the selected slope handles
+		/// </summary>
 		[BeginAction("archbetweenhandles")]
 		public void ArchBetweenHandles()
 		{
@@ -4273,26 +4281,27 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 			Vector3D p1 = handles[0].GetCenterPoint();
 			Vector3D p2 = handles[1].GetCenterPoint();
-			double linelength = new Line2D(p1, p2).GetLength();
+			double linelength = Line2D.GetLength(p2.x - p1.x, p2.y - p1.y);
 			double zdiff = Math.Abs(p1.z - p2.z);
-			double zangle = (p1 - p2).GetAngleZ();
-
-			if (zangle == Math.PI)
-				zangle = 0.0;
-			else if (zangle > Math.PI)
-				zangle -= Math.PI;
+			double theta;
+			double offsetangle;
 
-			// zangle += Math.PI / 4.0;
-			zangle *= 4;
-			double angle = Math.Sqrt(linelength * linelength + zdiff * zdiff) - zangle;
-
-			double bla = Angle2D.RadToDeg(angle);
-			double blaz = Angle2D.RadToDeg(zangle);
+			// Compute theta and the offset angle. Special handling if the slope handles are at the same height
+			if (zdiff == 0.0)
+			{
+				theta = Math.PI;
+				offsetangle = 0.0;
+			}
+			else
+			{
+				theta = Math.Atan(zdiff / linelength) * 2;
+				offsetangle = Math.PI / 2.0;
 
-			int baseheight = handles[0].Level.type == SectorLevelType.Ceiling ? handles[0].Sidedef.Sector.CeilHeight : handles[0].Sidedef.Sector.FloorHeight;
+				if (p2.z < p1.z)
+					offsetangle -= theta;
+			}
 
-			//SlopeArcher sa = new SlopeArcher(this, selectedsectors, handles[0], handles[1], Angle2D.DegToRad(90.0), Angle2D.DegToRad(45.0), 1.0);
-			SlopeArcher sa = new SlopeArcher(this, selectedsectors, handles[0], handles[1], angle, zangle, 1.0);
+			SlopeArcher sa = new SlopeArcher(this, selectedsectors, handles[0], handles[1], theta, offsetangle, 1.0);
 
 			SlopeArchForm saf = new SlopeArchForm(sa);
 			saf.UpdateChangedObjects += Interface_OnUpdateChangedObjects;
@@ -4301,16 +4310,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
 
 			if (result == DialogResult.Cancel)
 				General.Map.UndoRedo.WithdrawUndo();
-			
-
-			UpdateChangedObjects();
-
-			General.Interface.DisplayStatus(StatusType.Action, "Arched between slope handles.");
-		}
+			else
+			{
+				UpdateChangedObjects();
 
-		private void Interface_OnUpdateChangedObjects(object sender, EventArgs e)
-		{
-			UpdateChangedObjects();
+				General.Interface.DisplayStatus(StatusType.Action, "Arched between slope handles.");
+			}
 		}
 
 		#endregion
diff --git a/Source/Plugins/BuilderModes/VisualModes/SlopeArcher.cs b/Source/Plugins/BuilderModes/VisualModes/SlopeArcher.cs
index 0aef23a97..a532c5382 100644
--- a/Source/Plugins/BuilderModes/VisualModes/SlopeArcher.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/SlopeArcher.cs
@@ -1,9 +1,28 @@
-using System;
+#region ================== Copyright (c) 2020 Boris Iwanski
+
+/*
+ * This program is free software: you can redistribute it and/or modify
+ *
+ * it under the terms of the GNU General Public License as published by
+ * 
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * 
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
+ * 
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.If not, see<http://www.gnu.org/licenses/>.
+ */
+
+#endregion
+
+using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using CodeImp.DoomBuilder.Editing;
 using CodeImp.DoomBuilder.Map;
 using CodeImp.DoomBuilder.VisualModes;
 using CodeImp.DoomBuilder.Geometry;
@@ -25,9 +44,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
 		private Line2D handleline;
 		private double length;
 
-		public double Theta { get { return theta; } set { theta = value; CalculateBaseHeightOffset(); } }
-		public double OffsetAngle { get { return offsetangle; } set { offsetangle = value; CalculateBaseHeightOffset(); } }
-		public double Scale { get { return scale; } set { scale = value; CalculateBaseHeightOffset(); } }
+		public double Theta { get { return theta; } set { theta = value; } }
+		public double OffsetAngle { get { return offsetangle; } set { offsetangle = value; } }
+		public double Scale { get { return scale; } set { scale = value; } }
 		public int Baseheight { get { return baseheight; } }
 		public double HeightOffset { get { return heightoffset; } set { heightoffset = value; } }
 
@@ -53,22 +72,27 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			baseheightoffset = 0.0;
 		}
 
-		private void CalculateBaseHeightOffset()
-		{
-			/*
-			double left = Math.Cos(theta + offsetangle);
-			double middle = Math.Cos(offsetangle);
-
-			double radius = length / (middle - left);
-			double leftdelimiter = Math.Cos(offsetangle + theta);
-			double rightdelimiter = Math.Cos(offsetangle);
-
-			double sectionstart = Math.Cos(offsetangle + theta) * radius;
-
-			baseheightoffset = Math.Sqrt(radius * radius - sectionstart * sectionstart) * scale;
-			*/
-		}
-
+		/// <summary>
+		/// Applies the slopes to the sectors.
+		/// 
+		/// We have:
+		/// - theta
+		/// - offset angle ("offset")
+		/// - horizontal line length ("length")
+		///
+		/// What we need to compute:
+		/// - x coordinate where the line starts in the circle ("left", this is cos(theta + offset angle))
+		/// - x coordinate where the line ends in the circle ("middle", this is cos(offset angle))
+		///
+		/// With this data we can calculate some more required variables:
+		/// - radius: length / (middle - left)
+		/// - left delimiter: cos(offset + theta) * radius
+		/// - right delimiter: cos(rotation) * radius (should be same as left delimiter + length)
+		/// - section start, in map units: cos(offset + theta) * radius
+		/// - base height offset (where the slope starts)
+		///
+		/// Then we can simply use pythagoras to compute the y position for an x position on the length
+		/// </summary>
 		public void ApplySlope()
 		{
 			double left = Math.Cos(theta + offsetangle);
@@ -94,6 +118,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 					vertices.Add(sd.Line.End);
 				}
 
+				// Get the two points that are the furthest apart on the line between the slope handles
 				foreach(Vertex v in vertices)
 				{
 					double intersection = handleline.GetNearestOnLine(v.Position);
@@ -104,37 +129,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
 						u2 = intersection;
 				}
 
-				/*
-				foreach (Sidedef sd in bvgs.Sector.Sides.Keys)
-				{
-					double intersection;
-					double bla;
-
-					if (!Line2D.GetIntersection(handleline.v1, handleline.v2, sd.Line.Line.v1.x, sd.Line.Line.v1.y, sd.Line.Line.v2.x, sd.Line.Line.v2.y, out bla, out intersection, false))
-						continue;
-
-					if (intersection < u1)
-						u1 = intersection;
-					if (intersection > u2)
-						u2 = intersection;
-				}
-				*/
-
-				/*
-				if (u1 == u2)
-				{
-					if (u1 >= 0.5)
-					{
-						u1 = 1.0;
-					}
-					else
-					{
-						u2 = 0.0;
-					}
-
-				}
-				*/
-
+				// Compute the x position and the corrosponding height of the coordinates
 				double xpos1 = sectionstart + (u1 * length);
 				double xpos2 = sectionstart + (u2 * length);
 				double height1 = Math.Sqrt(radius * radius - xpos1 * xpos1) * scale;
@@ -146,20 +141,19 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				if (double.IsNaN(height2))
 					height2 = 0.0;
 
-				height1 = height1 - baseheightoffset + baseheight;
-				height2 = height2 - baseheightoffset + baseheight;
-
-				height1 += heightoffset;
-				height2 += heightoffset;
+				// Adjust the heights
+				height1 = height1 - baseheightoffset + baseheight + heightoffset;
+				height2 = height2 - baseheightoffset + baseheight + heightoffset;
 
+				// Get the angle of the slope. We cheat a bit and substitute the y value of the vectors with the height of the points
 				double slopeangle = Vector2D.GetAngle(new Vector2D(xpos1, height1), new Vector2D(xpos2, height2));
 
+				// Always let the plane point up, VisualSidedefSlope.ApplySlope will invert it if necessary
 				Plane plane = new Plane(new Vector3D(handleline.GetCoordinatesAt(u1), height1), handleline.GetAngle() + Angle2D.PIHALF, slopeangle, true);
 
 				VisualSidedefSlope.ApplySlope(bvgs.Level, plane, mode);
-				bvgs.Sector.UpdateSectorGeometry(true);
 
-				//Debug.WriteLine(string.Format("sector: {0} | xpos1: {1}, height1: {2} | xpos2: {3}, height2: {4} | slope angle: {5}", bvgs.Sector.Sector.Index, xpos1, xpos2, height1, height2, slopeangle));
+				bvgs.Sector.UpdateSectorGeometry(true);
 			}
 		}
 	}
-- 
GitLab