diff --git a/Source/Plugins/BuilderModes/BuilderModes.csproj b/Source/Plugins/BuilderModes/BuilderModes.csproj index 5bbde87c..74e7ffa7 100755 --- a/Source/Plugins/BuilderModes/BuilderModes.csproj +++ b/Source/Plugins/BuilderModes/BuilderModes.csproj @@ -181,6 +181,12 @@ PreferencesForm.cs + + Form + + + SlopeArchForm.cs + True True @@ -196,6 +202,9 @@ + + SlopeArchForm.cs + diff --git a/Source/Plugins/BuilderModes/Interface/SlopeArchForm.Designer.cs b/Source/Plugins/BuilderModes/Interface/SlopeArchForm.Designer.cs new file mode 100644 index 00000000..719fa5bd --- /dev/null +++ b/Source/Plugins/BuilderModes/Interface/SlopeArchForm.Designer.cs @@ -0,0 +1,177 @@ +namespace CodeImp.DoomBuilder.BuilderModes.Interface +{ + partial class SlopeArchForm + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.theta = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox(); + this.label1 = new System.Windows.Forms.Label(); + this.offset = new CodeImp.DoomBuilder.Controls.ButtonsNumericTextbox(); + this.label2 = new System.Windows.Forms.Label(); + this.cancel = new System.Windows.Forms.Button(); + this.accept = new System.Windows.Forms.Button(); + this.up = new System.Windows.Forms.RadioButton(); + this.down = new System.Windows.Forms.RadioButton(); + this.SuspendLayout(); + // + // theta + // + this.theta.AllowDecimal = true; + this.theta.AllowExpressions = false; + this.theta.AllowNegative = false; + this.theta.AllowRelative = false; + this.theta.ButtonStep = 5; + this.theta.ButtonStepBig = 15F; + this.theta.ButtonStepFloat = 5F; + this.theta.ButtonStepSmall = 15F; + this.theta.ButtonStepsUseModifierKeys = true; + this.theta.ButtonStepsWrapAround = false; + this.theta.Location = new System.Drawing.Point(104, 7); + this.theta.Name = "theta"; + this.theta.Size = new System.Drawing.Size(63, 24); + this.theta.StepValues = null; + this.theta.TabIndex = 18; + this.theta.WhenTextChanged += new System.EventHandler(this.UpdateArch); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(19, 17); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(31, 13); + this.label1.TabIndex = 19; + this.label1.Text = "theta"; + // + // offset + // + this.offset.AllowDecimal = true; + this.offset.AllowExpressions = false; + this.offset.AllowNegative = false; + this.offset.AllowRelative = false; + this.offset.ButtonStep = 5; + this.offset.ButtonStepBig = 15F; + this.offset.ButtonStepFloat = 5F; + this.offset.ButtonStepSmall = 15F; + this.offset.ButtonStepsUseModifierKeys = true; + this.offset.ButtonStepsWrapAround = false; + this.offset.Location = new System.Drawing.Point(104, 37); + this.offset.Name = "offset"; + this.offset.Size = new System.Drawing.Size(63, 24); + this.offset.StepValues = null; + this.offset.TabIndex = 20; + this.offset.WhenTextChanged += new System.EventHandler(this.UpdateArch); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(22, 47); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(33, 13); + this.label2.TabIndex = 21; + this.label2.Text = "offset"; + // + // cancel + // + this.cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cancel.Location = new System.Drawing.Point(104, 197); + this.cancel.Name = "cancel"; + this.cancel.Size = new System.Drawing.Size(88, 24); + this.cancel.TabIndex = 22; + this.cancel.Text = "Cancel"; + this.cancel.UseVisualStyleBackColor = true; + // + // accept + // + this.accept.DialogResult = System.Windows.Forms.DialogResult.OK; + this.accept.Location = new System.Drawing.Point(10, 197); + this.accept.Name = "accept"; + this.accept.Size = new System.Drawing.Size(88, 24); + this.accept.TabIndex = 23; + this.accept.Text = "Apply"; + this.accept.UseVisualStyleBackColor = true; + // + // up + // + this.up.AutoSize = true; + this.up.Checked = true; + this.up.Location = new System.Drawing.Point(22, 96); + this.up.Name = "up"; + this.up.Size = new System.Drawing.Size(39, 17); + this.up.TabIndex = 24; + this.up.TabStop = true; + this.up.Text = "Up"; + this.up.UseVisualStyleBackColor = true; + this.up.CheckedChanged += new System.EventHandler(this.UpdateArch); + // + // down + // + this.down.AutoSize = true; + this.down.Location = new System.Drawing.Point(22, 119); + this.down.Name = "down"; + this.down.Size = new System.Drawing.Size(53, 17); + this.down.TabIndex = 25; + this.down.Text = "Down"; + this.down.UseVisualStyleBackColor = true; + this.down.CheckedChanged += new System.EventHandler(this.UpdateArch); + // + // SlopeArchForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.cancel; + this.ClientSize = new System.Drawing.Size(205, 251); + this.Controls.Add(this.down); + this.Controls.Add(this.up); + this.Controls.Add(this.accept); + this.Controls.Add(this.cancel); + this.Controls.Add(this.label2); + this.Controls.Add(this.offset); + this.Controls.Add(this.label1); + this.Controls.Add(this.theta); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "SlopeArchForm"; + this.ShowIcon = false; + this.Text = "SlopeArchForm"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private Controls.ButtonsNumericTextbox theta; + private System.Windows.Forms.Label label1; + private Controls.ButtonsNumericTextbox offset; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Button cancel; + private System.Windows.Forms.Button accept; + private System.Windows.Forms.RadioButton up; + private System.Windows.Forms.RadioButton down; + } +} \ No newline at end of file diff --git a/Source/Plugins/BuilderModes/Interface/SlopeArchForm.cs b/Source/Plugins/BuilderModes/Interface/SlopeArchForm.cs new file mode 100644 index 00000000..c7892ded --- /dev/null +++ b/Source/Plugins/BuilderModes/Interface/SlopeArchForm.cs @@ -0,0 +1,56 @@ +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; +using CodeImp.DoomBuilder.Windows; +using CodeImp.DoomBuilder.Controls; +using CodeImp.DoomBuilder.Editing; +using CodeImp.DoomBuilder.Geometry; + +namespace CodeImp.DoomBuilder.BuilderModes.Interface +{ + public partial class SlopeArchForm : DelayedForm + { + private EditMode mode; + private double originaltheta; + private double originaloffset; + private Vector2D p1; + private Vector2D p2; + + public SlopeArchForm(EditMode mode, Vector2D p1, Vector2D p2) + { + InitializeComponent(); + + this.mode = mode; + this.p1 = p1; + this.p2 = p2; + + originaltheta = 90.0; + originaloffset = 45.0; + + theta.Text = originaltheta.ToString(); + offset.Text = originaloffset.ToString(); + } + + private void UpdateArch(object sender, EventArgs e) + { + double t = theta.GetResultFloat(originaltheta); + double o = offset.GetResultFloat(originaloffset); + + if (t > 180.0) + theta.Text = "180"; + + if (t + o > 180.0 || t + o < 0.0) + return; + + double s = up.Checked ? 1.0 : -1.0; + + ((BaseVisualMode)mode).DoArchBetweenHandles(p1, p2, t, o, s); + } + } +} diff --git a/Source/Plugins/BuilderModes/Interface/SlopeArchForm.resx b/Source/Plugins/BuilderModes/Interface/SlopeArchForm.resx new file mode 100644 index 00000000..1af7de15 --- /dev/null +++ b/Source/Plugins/BuilderModes/Interface/SlopeArchForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs index 10586ac5..bbd17afa 100755 --- a/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs +++ b/Source/Plugins/BuilderModes/VisualModes/BaseVisualMode.cs @@ -4254,6 +4254,7 @@ namespace CodeImp.DoomBuilder.BuilderModes public void ArchBetweenHandles() { List 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."); @@ -4270,9 +4271,28 @@ namespace CodeImp.DoomBuilder.BuilderModes General.Map.UndoRedo.CreateUndo("Arch between slope handles"); - Line2D handleline = new Line2D(handles[0].GetCenterPoint(), handles[1].GetCenterPoint()); - double offsetangle = Angle2D.DegToRad(0.0); - double theta = Angle2D.DegToRad(180.0); + Vector2D p1 = handles[0].GetCenterPoint(); + Vector2D p2 = handles[1].GetCenterPoint(); + + SlopeArchForm saf = new SlopeArchForm(this, p1, p2); + DialogResult result = saf.ShowDialog(); + + if (result == DialogResult.Cancel) + General.Map.UndoRedo.WithdrawUndo(); + + + UpdateChangedObjects(); + + General.Interface.DisplayStatus(StatusType.Action, "Arched between slope handles."); + } + + public void DoArchBetweenHandles(Vector2D p1, Vector2D p2, double _theta, double _offsetangle, double scale) + { + List selectedsectors = GetSelectedObjects(true, false, false, false, false); + + Line2D handleline = new Line2D(p1, p2); + double offsetangle = Angle2D.DegToRad(_offsetangle); + double theta = Angle2D.DegToRad(_theta); double length = handleline.GetLength(); double right = Math.Cos(0.0); @@ -4287,32 +4307,48 @@ namespace CodeImp.DoomBuilder.BuilderModes foreach (BaseVisualGeometrySector bvgs in selectedsectors) { - double u1 = double.MaxValue; - double u2 = double.MinValue; + double u1 = 1.0; + double u2 = 0.0; + - 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, true)) + 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) - continue; + { + if(u1 >= 0.5) + { + u1 = 1.0; + } + else + { + u2 = 0.0; + } + + } double xpos1 = sectionstart + (u1 * length); double xpos2 = sectionstart + (u2 * length); - double height1 = Math.Sqrt(radius * radius - xpos1 * xpos1); - double height2 = Math.Sqrt(radius * radius - xpos2 * xpos2); + double height1 = Math.Sqrt(radius * radius - xpos1 * xpos1) * scale; + double height2 = Math.Sqrt(radius * radius - xpos2 * xpos2) * scale; + + if (double.IsNaN(height1)) + height1 = 0.0; + + if (double.IsNaN(height2)) + height2 = 0.0; + double slopeangle = Vector2D.GetAngle(new Vector2D(xpos1, height1), new Vector2D(xpos2, height2)); Plane plane = new Plane(new Vector3D(handleline.GetCoordinatesAt(u1), height1), handleline.GetAngle() + Angle2D.PIHALF, slopeangle, true); @@ -4324,8 +4360,6 @@ namespace CodeImp.DoomBuilder.BuilderModes } UpdateChangedObjects(); - - General.Interface.DisplayStatus(StatusType.Action, "Arched between slope handles."); } #endregion