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