#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.
*/
#endregion
using System;
using CodeImp.DoomBuilder.Windows;
using CodeImp.DoomBuilder.Geometry;
namespace CodeImp.DoomBuilder.BuilderModes
{
internal partial class SlopeArchForm : DelayedForm
{
#region ================== Variables
private double originaltheta;
private double originaloffset;
private double originalscale;
private double originalheightoffset;
private double oldtheta;
private double oldoffset;
private double oldscale;
private SlopeArcher slopearcher;
public event EventHandler UpdateChangedObjects;
#endregion
#region ================== Constructor / Destructor
internal SlopeArchForm(SlopeArcher slopearcher)
{
InitializeComponent();
this.slopearcher = slopearcher;
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;
theta.Text = originaltheta.ToString();
offset.Text = originaloffset.ToString();
scale.Text = (originalscale * 100.0).ToString();
heightoffset.Text = originalheightoffset.ToString();
}
#endregion
#region ================== Methods
///
/// Updates the arch with the values currently entered in the dialog
///
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;
slopearcher.Theta = Angle2D.DegToRad(t);
slopearcher.OffsetAngle = Angle2D.DegToRad(o);
slopearcher.Scale = s;
slopearcher.HeightOffset = heightoffset.GetResultFloat(originalheightoffset);
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
///
/// Immediately apply the arch when the form is shown
///
/// sender
/// event arguments
private void SlopeArchForm_Shown(object sender, EventArgs e)
{
slopearcher.ApplySlope();
UpdateChangedObjects?.Invoke(this, EventArgs.Empty);
}
///
/// Sets the values for theta and angle offset for a half circle
///
/// sender
/// event arguments
private void halfcircle_Click(object sender, EventArgs e)
{
theta.Text = "180";
offset.Text = "0";
oldtheta = 180.0;
oldoffset = 0.0;
UpdateArch();
}
///
/// Sets the values for theta and angle offset for a quarter circle (top left quadrant viewed from the first selected slope hande)
///
/// sender
/// event arguments
private void quartercircleleft_Click(object sender, EventArgs e)
{
theta.Text = "90";
offset.Text = "90";
oldtheta = 90.0;
oldoffset = 90.0;
UpdateArch();
}
///
/// Sets the values for theta and angle offset for a quarter circle (top right quadrant viewed from the first selected slope hande)
///
/// sender
/// event arguments
private void quartercircleright_Click(object sender, EventArgs e)
{
theta.Text = "90";
offset.Text = "0";
oldtheta = 90.0;
UpdateArch();
}
///
/// Handles updates of the theta value. Also does sanity checks and modifies the values if necessary
///
/// sender
/// event arguments
private void theta_changed(object sender, EventArgs e)
{
double newtheta = theta.GetResultFloat(originaltheta);
double newoffset = offset.GetResultFloat(originaloffset);
// Make sure that the new theta is between 0.0 and 180.0
if (newtheta > 180.0)
{
newtheta = 180.0;
theta.Text = "180";
General.Interface.DisplayStatus(StatusType.Warning, "The angle can not be greater than 180.");
}
else if (newtheta <= 0.0)
{
newtheta = oldtheta;
theta.Text = oldtheta.ToString();
}
// If the angle offset it locked automatically change its value to reflect the changed theta value
if (lockoffset.Checked)
{
double diff = oldtheta - newtheta;
newoffset = offset.GetResultFloat(originaloffset) + diff / 2.0;
// Make sure that the result isn't invalid
if(newoffset < 0.0)
{
theta.Text = oldtheta.ToString();
offset.Text = oldoffset.ToString();
}
else
offset.Text = (offset.GetResultFloat(originaloffset) + diff / 2.0).ToString();
}
// 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();
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();
}
///
/// Handles updates of the angle offset value. Also does sanity checks and modifies the values if necessary
///
/// sender
/// event arguments
private void offset_changed(object sender, EventArgs e)
{
double newtheta = theta.GetResultFloat(originaltheta);
double newoffset = offset.GetResultFloat(originaloffset);
// 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();
}
///
/// Handles updates of the scale value. Also does sanity checks and modifies the values if necessary
///
/// sender
/// event arguments
private void scale_changed(object sender, EventArgs e)
{
double newscale = scale.GetResultFloat(originalscale);
if (newscale <= 0.0)
scale.Text = oldscale.ToString();
// Remember the old value
oldscale = scale.GetResultFloat(originalscale);
UpdateArch();
}
///
/// Handles updates of the height offset value.
///
/// sender
/// event arguments
private void heightoffset_changed(object sender, EventArgs e)
{
UpdateArch();
}
///
/// Handles updates of the "up" radio box.
///
/// sender
/// event arguments
private void up_CheckedChanged(object sender, EventArgs e)
{
UpdateArch();
}
///
/// Handles updates of the "down" radio box.
///
/// sender
/// event arguments
private void down_CheckedChanged(object sender, EventArgs e)
{
UpdateArch();
}
///
/// Toggles the "lock offset angle" checkbox.
///
/// sender
/// event arguments
private void lockoffset_CheckedChanged(object sender, EventArgs e)
{
offset.Enabled = !offset.Enabled;
}
///
/// Inverts the current slope
///
///
///
private void invert_Click(object sender, EventArgs e)
{
// Flip up/down direction
if(up.Checked)
{
up.Checked = false;
down.Checked = true;
}
else
{
up.Checked = true;
down.Checked = false;
}
double t = theta.GetResultFloat(originaltheta);
double o = offset.GetResultFloat(originaloffset);
// Subtract theta from the offset, if the result is greater than 0, otherwise add theta
if (o - t < 0.0)
o = o + t;
else
o = o - t;
offset.Text = o.ToString();
UpdateArch();
}
#endregion
}
}