ZoneBuilder/Source/Core/Windows/VertexEditForm.cs
biwa f59fbed358 Sector/Linedef/Thing/Vertex Edit Form: the map will not be marked as changed anymore when canceling changes made in the forms, when the map wasn't marked as changed before
Copying map elements doesn't mark the map as changed anymore if the map wasn't marked as changed before copying
2023-05-08 13:21:15 +02:00

404 lines
No EOL
11 KiB
C#

#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* 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.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Map;
#endregion
namespace CodeImp.DoomBuilder.Windows
{
internal partial class VertexEditForm : DelayedForm
{
#region ================== Constants
private const string CLEAR_VALUE = "Unused"; //mxd
#endregion
#region ================== Events
public event EventHandler OnValuesChanged; //mxd
#endregion
#region ================== Variables
private ICollection<Vertex> vertices;
private bool preventchanges; //mxd
private bool undocreated; //mxd
private List<VertexProperties> vertexprops; //mxd
private bool oldmapischanged;
//mxd. Window setup stuff
private static Point location = Point.Empty;
private static int activetab;
private struct VertexProperties //mxd
{
public readonly float X;
public readonly float Y;
public readonly float ZCeiling;
public readonly float ZFloor;
public VertexProperties(Vertex v)
{
X = v.Position.x;
Y = v.Position.y;
ZCeiling = v.ZCeiling;
ZFloor = v.ZFloor;
}
}
#endregion
#region ================== Constructor
// Constructor
public VertexEditForm()
{
InitializeComponent();
//mxd. Widow setup
if(location != Point.Empty)
{
this.StartPosition = FormStartPosition.Manual;
this.Location = location;
if(General.Settings.StoreSelectedEditTab && activetab > 0 && activetab < tabs.TabCount) tabs.SelectTab(activetab);
}
if(General.Map.FormatInterface.HasCustomFields) //mxd
{
// Initialize custom fields editor
fieldslist.Setup("vertex");
// Fill universal fields list
fieldslist.ListFixedFields(General.Map.Config.VertexFields);
}
else
{
tabs.TabPages.Remove(tabcustom);
panelHeightControls.Visible = false;
}
// Decimals allowed?
if(General.Map.FormatInterface.VertexDecimals > 0)
{
positionx.AllowDecimal = true;
positiony.AllowDecimal = true;
positionx.ButtonStepSmall = 0.1f;
positiony.ButtonStepSmall = 0.1f;
positionx.UpdateButtonsTooltip();
positiony.UpdateButtonsTooltip();
//mxd
zceiling.AllowDecimal = true;
zfloor.AllowDecimal = true;
}
}
#endregion
#region ================== Methods
// This sets up the form to edit the given vertices
public void Setup(ICollection<Vertex> vertices, bool allowPositionChange)
{
preventchanges = true; //mxd
oldmapischanged = General.Map.IsChanged;
// Keep this list
this.vertices = vertices;
if(vertices.Count > 1) this.Text = "Edit Vertices (" + vertices.Count + ")";
vertexprops = new List<VertexProperties>(); //mxd
////////////////////////////////////////////////////////////////////////
// Set all options to the first vertex properties
////////////////////////////////////////////////////////////////////////
// Get first vertex
Vertex vc = General.GetByIndex(vertices, 0);
// Position
positionx.Text = vc.Position.x.ToString();
positiony.Text = vc.Position.y.ToString();
//mxd
positionx.Enabled = allowPositionChange;
positiony.Enabled = allowPositionChange;
// Custom fields
if(General.Map.FormatInterface.HasCustomFields) //mxd
fieldslist.SetValues(vc.Fields, true);
////////////////////////////////////////////////////////////////////////
// Now go for all sectors and change the options when a setting is different
////////////////////////////////////////////////////////////////////////
// Go for all vertices
foreach(Vertex v in vertices)
{
// Position
if(positionx.Text != v.Position.x.ToString()) positionx.Text = "";
if(positiony.Text != v.Position.y.ToString()) positiony.Text = "";
// Custom fields
if(General.Map.FormatInterface.HasCustomFields)
{
fieldslist.SetValues(v.Fields, false);
}
//mxd. Store initial properties
vertexprops.Add(new VertexProperties(v));
}
//mxd. Height offsets
if(General.Map.UDMF)
{
zceiling.Text = (float.IsNaN(vc.ZCeiling) ? CLEAR_VALUE : vc.ZCeiling.ToString());
zfloor.Text = (float.IsNaN(vc.ZFloor) ? CLEAR_VALUE : vc.ZFloor.ToString());
foreach(Vertex v in vertices)
{
string zc = (float.IsNaN(v.ZCeiling) ? CLEAR_VALUE : v.ZCeiling.ToString());
string zf = (float.IsNaN(v.ZFloor) ? CLEAR_VALUE : v.ZFloor.ToString());
if(zceiling.Text != zc) zceiling.Text = "";
if(zfloor.Text != zf) zfloor.Text = "";
}
}
preventchanges = false; //mxd
}
//mxd
private void MakeUndo()
{
if(undocreated) return;
undocreated = true;
//mxd. Make undo
General.Map.UndoRedo.CreateUndo("Edit " + (vertices.Count > 1 ? vertices.Count + " vertices" : "vertex"));
if(General.Map.FormatInterface.HasCustomFields)
{
foreach(Vertex v in vertices) v.Fields.BeforeFieldsChange();
}
}
#endregion
#region ================== mxd. Realtime Events
private void positionx_WhenTextChanged(object sender, EventArgs e)
{
if (preventchanges) return;
MakeUndo();
// Restore values
if (string.IsNullOrEmpty(positionx.Text))
{
// Apply position
int i = 0;
foreach (Vertex v in vertices) v.Move(new Vector2D(vertexprops[i++].X, v.Position.y));
}
// Update values
else
{
int i = 0;
foreach (Vertex v in vertices)
{
// Verify the coordinates
float px = positionx.GetResultFloat(vertexprops[i++].X);
// Apply new position
v.Move(new Vector2D(Math.Max(General.Map.FormatInterface.MinCoordinate, Math.Min(General.Map.FormatInterface.MaxCoordinate, px)), v.Position.y));
}
}
General.Map.IsChanged = true;
if (OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
}
private void positiony_WhenTextChanged(object sender, EventArgs e)
{
if (preventchanges) return;
MakeUndo();
// Restore values
if (string.IsNullOrEmpty(positiony.Text))
{
// Apply position
int i = 0;
foreach (Vertex v in vertices) v.Move(new Vector2D(v.Position.x, vertexprops[i++].Y));
}
// Update values
else
{
int i = 0;
foreach (Vertex v in vertices)
{
// Verify the coordinates
float py = positiony.GetResultFloat(vertexprops[i++].Y);
// Apply new position
v.Move(new Vector2D(v.Position.x, Math.Max(General.Map.FormatInterface.MinCoordinate, Math.Min(General.Map.FormatInterface.MaxCoordinate, py))));
}
}
General.Map.IsChanged = true;
if (OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
}
private void zceiling_WhenTextChanged(object sender, EventArgs e)
{
if(preventchanges) return;
MakeUndo();
int i = 0;
//restore values
if(string.IsNullOrEmpty(zceiling.Text))
{
foreach(Vertex v in vertices) v.ZCeiling = vertexprops[i++].ZCeiling;
}
else if(zceiling.Text == CLEAR_VALUE) //clear values
{
foreach(Vertex v in vertices) v.ZCeiling = float.NaN;
}
else //update values
{
foreach(Vertex v in vertices)
v.ZCeiling = zceiling.GetResultFloat(vertexprops[i++].ZCeiling);
}
General.Map.IsChanged = true;
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
}
private void zfloor_WhenTextChanged(object sender, EventArgs e)
{
if(preventchanges) return;
MakeUndo();
int i = 0;
//restore values
if(string.IsNullOrEmpty(zfloor.Text))
{
foreach(Vertex v in vertices)
v.ZFloor = vertexprops[i++].ZFloor;
}
else if(zfloor.Text == CLEAR_VALUE) //clear values
{
foreach(Vertex v in vertices) v.ZFloor = float.NaN;
}
else //update values
{
foreach(Vertex v in vertices)
v.ZFloor = zfloor.GetResultFloat(vertexprops[i++].ZFloor);
}
General.Map.IsChanged = true;
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
}
//mxd
private void clearZFloor_Click(object sender, EventArgs e)
{
zfloor.Text = CLEAR_VALUE;
}
//mxd
private void clearZCeiling_Click(object sender, EventArgs e)
{
zceiling.Text = CLEAR_VALUE;
}
#endregion
#region ================== Events
// OK clicked
private void apply_Click(object sender, EventArgs e)
{
//mxd. Make undo if required
MakeUndo();
// Apply custom fields
if(General.Map.FormatInterface.HasCustomFields)
{
foreach(Vertex v in vertices) fieldslist.Apply(v.Fields); //mxd
}
General.Map.IsChanged = true;
if(OnValuesChanged != null) OnValuesChanged(this, EventArgs.Empty);
// Done
this.DialogResult = DialogResult.OK;
this.Close();
}
// Cancel clicked
private void cancel_Click(object sender, EventArgs e)
{
//mxd. Perform undo if required
if (undocreated)
{
General.Map.UndoRedo.WithdrawUndo();
// Changing certain properties of the vertex, like the position, will set General.Map.IsChanged to true.
// But if cancel is pressed and the changes are discarded, and the map was not changed before, we have to force
// General.Map.IsChanged back to false
if (General.Map.IsChanged && oldmapischanged == false)
General.Map.ForceMapIsChangedFalse();
}
// And close
this.DialogResult = DialogResult.Cancel;
this.Close();
}
//mxd
private void tabcustom_MouseEnter(object sender, EventArgs e)
{
fieldslist.Focus();
}
//mxd
private void VertexEditForm_FormClosing(object sender, FormClosingEventArgs e)
{
location = this.Location;
activetab = tabs.SelectedIndex;
}
// Help requested
private void VertexEditForm_HelpRequested(object sender, HelpEventArgs hlpevent)
{
General.ShowHelp("w_vertexedit.html");
hlpevent.Handled = true;
}
#endregion
}
}