From aecb1e67b7d9059d7dc93e8cfa7199062f6246f4 Mon Sep 17 00:00:00 2001
From: biwa <6475593+biwa@users.noreply.github.com>
Date: Mon, 1 Jun 2020 09:50:35 +0200
Subject: [PATCH] Preliminary code for arching

---
 Source/Core/Geometry/Line3D.cs                |   7 +
 .../BuilderModes/Resources/Actions.cfg        |  10 ++
 .../VisualModes/BaseVisualMode.cs             | 148 ++++++++++++------
 3 files changed, 117 insertions(+), 48 deletions(-)

diff --git a/Source/Core/Geometry/Line3D.cs b/Source/Core/Geometry/Line3D.cs
index 458936eda..c15520e24 100755
--- a/Source/Core/Geometry/Line3D.cs
+++ b/Source/Core/Geometry/Line3D.cs
@@ -66,5 +66,12 @@ namespace CodeImp.DoomBuilder.Geometry
 			Vector2D d = GetDelta();
 			return -Math.Atan2(-d.y, d.x) + Angle2D.PIHALF;
 		}
+
+		public double GetAngleZ()
+		{
+			Vector3D d = GetDelta();
+
+			return Math.Atan2(Math.Sqrt(d.x*d.x + d.y*d.y), d.z);
+		}
 	}
 }
diff --git a/Source/Plugins/BuilderModes/Resources/Actions.cfg b/Source/Plugins/BuilderModes/Resources/Actions.cfg
index 0bf4b53e1..825b25596 100755
--- a/Source/Plugins/BuilderModes/Resources/Actions.cfg
+++ b/Source/Plugins/BuilderModes/Resources/Actions.cfg
@@ -1424,4 +1424,14 @@ slopebetweenhandles
 	allowkeys = true;
 	allowmouse = true;
 	allowscroll = false;
+}
+
+archbetweenhandles
+{
+	title = "Arch Between Slope Handles";
+	category = "visual";
+	Description = "Arches the selected floors and ceilings between the selected slope handles.";
+	allowkeys = true;
+	allowmouse = true;
+	allowscroll = false;
 }
\ No newline at end of file
diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
index f97c07291..c0208bb1e 100755
--- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
+++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs
@@ -751,6 +751,64 @@ namespace CodeImp.DoomBuilder.BuilderModes
 					break;
 			}
 		}
+
+		private List<VisualSidedefSlope> GetSlopeHandlePair()
+		{
+			List<VisualSidedefSlope> handles = GetSelectedSlopeHandles();
+
+			// No handles selected, try to slope between highlighted handle and it smart pivot
+			if (handles.Count == 0 && HighlightedTarget is VisualSidedefSlope)
+			{
+				VisualSidedefSlope handle = VisualSidedefSlope.GetSmartPivotHandle((VisualSidedefSlope)HighlightedTarget, this);
+				if (handle == null)
+				{
+					General.Interface.DisplayStatus(StatusType.Warning, "Couldn't find a smart pivot handle.");
+					return handles;
+				}
+
+				handles.Add((VisualSidedefSlope)HighlightedTarget);
+				handles.Add(handle);
+			}
+			// One handle selected, try to slope between it and the highlighted handle or the selected one's smart pivot
+			else if (handles.Count == 1)
+			{
+				if (HighlightedTarget == handles[0] || !(HighlightedTarget is VisualSidedefSlope))
+				{
+					VisualSidedefSlope handle;
+
+					if (HighlightedTarget is VisualSidedefSlope)
+						handle = VisualSidedefSlope.GetSmartPivotHandle((VisualSidedefSlope)HighlightedTarget, this);
+					else
+						handle = VisualSidedefSlope.GetSmartPivotHandle(handles[0], this);
+
+					if (handle == null)
+					{
+						General.Interface.DisplayStatus(StatusType.Warning, "Couldn't find a smart pivot handle.");
+						return handles;
+					}
+
+					handles.Add(handle);
+				}
+				else
+				{
+					handles.Add((VisualSidedefSlope)HighlightedTarget);
+				}
+			}
+			// Return if more than two handles are selected
+			else if (handles.Count > 2)
+			{
+				General.Interface.DisplayStatus(StatusType.Warning, "Too many slope handles selected.");
+				return handles;
+			}
+			// Everything else
+			else if (handles.Count != 2)
+			{
+				General.Interface.DisplayStatus(StatusType.Warning, "No slope handles selected or highlighted.");
+				return handles;
+			}
+
+			return handles;
+		}
 		
 		#endregion
 
@@ -4164,56 +4222,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
 				return;
 			}
 
-			List<VisualSidedefSlope> handles = GetSelectedSlopeHandles();
-
-			// No handles selected, try to slope between highlighted handle and it smart pivot
-			if (handles.Count == 0 && HighlightedTarget is VisualSidedefSlope)
-			{
-				VisualSidedefSlope handle = VisualSidedefSlope.GetSmartPivotHandle((VisualSidedefSlope)HighlightedTarget, this);
-				if (handle == null)
-				{
-					General.Interface.DisplayStatus(StatusType.Warning, "Couldn't find a smart pivot handle.");
-					return;
-				}
-
-				handles.Add((VisualSidedefSlope)HighlightedTarget);
-				handles.Add(handle);
-			}
-			// One handle selected, try to slope between it and the highlighted handle or the selected one's smart pivot
-			else if (handles.Count == 1)
-			{
-				if (HighlightedTarget == handles[0] || !(HighlightedTarget is VisualSidedefSlope))
-				{
-					VisualSidedefSlope handle;
-
-					if(HighlightedTarget is VisualSidedefSlope)
-						handle = VisualSidedefSlope.GetSmartPivotHandle((VisualSidedefSlope)HighlightedTarget, this);
-					else
-						handle = VisualSidedefSlope.GetSmartPivotHandle(handles[0], this);
-
-					if (handle == null)
-					{
-						General.Interface.DisplayStatus(StatusType.Warning, "Couldn't find a smart pivot handle.");
-						return;
-					}
+			List<VisualSidedefSlope> handles = GetSlopeHandlePair();
 
-					handles.Add(handle);
-				}
-				else
-				{
-					handles.Add((VisualSidedefSlope)HighlightedTarget);
-				}
-			}
-			// Return if more than two handles are selected
-			else if(handles.Count > 2)
-			{
-				General.Interface.DisplayStatus(StatusType.Warning, "Too many slope handles selected.");
-				return;
-			}
-			// Everything else
-			else if(handles.Count != 2)
+			if (handles.Count != 2)
 			{
-				General.Interface.DisplayStatus(StatusType.Warning, "No slope handles selected or highlighted.");
+				General.Interface.DisplayStatus(StatusType.Warning, "You need to select exactly two slope handles.");
 				return;
 			}
 
@@ -4237,6 +4250,45 @@ namespace CodeImp.DoomBuilder.BuilderModes
 			General.Interface.DisplayStatus(StatusType.Action, "Sloped between slope handles.");
 		}
 
+		[BeginAction("archbetweenhandles")]
+		public void ArchBetweenHandles()
+		{
+			List<IVisualEventReceiver> selectedsectors = GetSelectedObjects(true, false, false, false, false);
+			if (selectedsectors.Count < 2)
+			{
+				General.Interface.DisplayStatus(StatusType.Warning, "You need to select at least two floors and ceilings to slope arch between slope handles.");
+				return;
+			}
+
+			List<VisualSidedefSlope> handles = GetSlopeHandlePair();
+
+			if (handles.Count != 2)
+			{
+				General.Interface.DisplayStatus(StatusType.Warning, "You need to select exactly two slope handles.");
+				return;
+			}
+
+			double theta = Angle2D.DegToRad(90.0);
+
+			General.Map.UndoRedo.CreateUndo("Slope between slope handles");
+
+			Line3D line = new Line3D(handles[0].GetCenterPoint(), handles[1].GetCenterPoint());
+			double anglez = line.GetAngleZ();
+			
+
+			double angle = line.GetAngle();
+
+			Vector2D v1 = new Vector2D(line.Start).GetRotated(angle);
+			Vector2D v2 = new Vector2D(line.End).GetRotated(angle);
+
+			Line2D line2d = new Line2D(v1, v2);
+			double length = line2d.GetLength();
+			double startx = Math.Cos(anglez - theta / 2) * length;
+
+			Vector2D z1 = v1.GetRotated(-angle);
+			Vector2D z2 = v2.GetRotated(-angle);
+		}
+
 		#endregion
 
 		#region ================== Texture Alignment
-- 
GitLab