UltimateZoneBuilder/Source/Plugins/NodesViewer/NodesForm.cs
MaxED ea57d45eb3 Added: action argument inputs now support incremental increase/decrease prefixes (+++ and ---).
Probably fixed probable I/O race condition when loading images.
Fixed Visual mode stuttering due to floating point precision degradation when running the editor for several days without restarting (internal timer is now reset when saving the map or creating a new one).
Fixed, Nodes Viewer, cosmetic: Nodes Viewer window position was reset after pressing the "Rebuild Nodes" button.
Added Eternity Game configurations by printz.
Updated ZDoom_ACS.cfg (CheckClass).
Updated ZDoom ACC (CheckClass).
2016-08-29 10:06:16 +00:00

331 lines
9.1 KiB
C#

#region === Copyright (c) 2010 Pascal van der Heiden ===
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Geometry;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Windows;
#endregion
namespace CodeImp.DoomBuilder.Plugins.NodesViewer
{
public partial class NodesForm : DelayedForm
{
#region ================== Variables
private NodesViewerMode mode;
#endregion
#region ================== Properties
public int SelectedTab { get { return tabs.SelectedIndex; } }
public int ViewSplitIndex { get { return (int)splitindex.Value; } }
public int ViewSubsectorIndex { get { return (int)ssectorindex.Value; } }
public int ViewSegIndex { get { return viewsegbox.Checked ? (int)segindex.Value : -1; } }
public bool ShowSegsVertices { get { return showsegsvertices.Checked; } }
#endregion
#region ================== Constructor / Destructor
// Constructor
public NodesForm()
{
InitializeComponent();
}
// Constructor
public NodesForm(NodesViewerMode mode)
{
InitializeComponent();
this.mode = mode;
// Counts
numsegs.Text = mode.Segs.Length.ToString();
numsplits.Text = mode.Nodes.Length.ToString();
numssectors.Text = mode.Subsectors.Length.ToString();
numvertices.Text = mode.Vertices.Length.ToString();
showsegsvertices.Text = "Show additional vertices (" + (mode.Vertices.Length - General.Map.Map.Vertices.Count) + " seg splits)";
// Create stats on the tree
List<int> leafdepths = new List<int>();
DiveTree(mode.Nodes.Length - 1, 0, leafdepths);
int maxdepth = 0, mindepth = int.MaxValue;
foreach(int d in leafdepths)
{
if(d < mindepth) mindepth = d;
if(d > maxdepth) maxdepth = d;
}
treedepth.Text = maxdepth.ToString();
// Calculate the tree balance. The balance is 100% when all leafs are equal depth and
// 0% when 1 leaf equals peakdepth and the others are at level 1.
int balance = (int)(((float)mindepth / maxdepth) * 100f);
treebalance.Text = balance + "%";
// Start viewing root split
splitindex.Maximum = mode.Nodes.Length - 1;
splitindex.Value = mode.Nodes.Length - 1;
splitindex_ValueChanged(null, EventArgs.Empty);
// Viewing subsector
ssectorindex.Maximum = mode.Subsectors.Length - 1;
ssectorindex.Value = 0;
ssectorindex_ValueChanged(null, EventArgs.Empty);
segindex_ValueChanged(null, EventArgs.Empty);
}
// Clean up any resources being used.
protected override void Dispose(bool disposing)
{
if(disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#endregion
#region ================== Methods
// This calculates the tree depth recursively
private void DiveTree(int node, int level, List<int> leafdepths)
{
level++;
// Process left side
if(!mode.Nodes[node].leftsubsector)
DiveTree(mode.Nodes[node].leftchild, level, leafdepths);
else
leafdepths.Add(level);
// Process right side
if(!mode.Nodes[node].rightsubsector)
DiveTree(mode.Nodes[node].rightchild, level, leafdepths);
else
leafdepths.Add(level);
}
// Show this form
public void Show(Form owner)
{
// Position at left-top of owner
this.Location = new Point(owner.Location.X + 20, owner.Location.Y + 90);
// Show window
base.Show(owner);
}
// Switch to a subsector
public void ShowSubsector(int ssindex)
{
ssectorindex.Value = ssindex;
tabs.SelectTab(tabsubsectors);
}
#endregion
#region ================== Form / Overview Events
// Exit this mode
private void closebutton_Click(object sender, EventArgs e)
{
this.Close();
}
// Exit mode when dialog is closed
private void NodesForm_FormClosing(object sender, FormClosingEventArgs e)
{
General.Editing.CancelMode();
}
// Open tab changed
private void tabs_SelectedIndexChanged(object sender, EventArgs e)
{
General.Interface.RedrawDisplay();
}
// Show segs vertices changed
private void showsegsvertices_CheckedChanged(object sender, EventArgs e)
{
General.Interface.RedrawDisplay();
}
// (Re)build the nodes
private void buildnodesbutton_Click(object sender, EventArgs e)
{
General.Map.RebuildNodes(General.Map.ConfigSettings.NodebuilderSave, true);
// Restart the mode so that the new structures are loaded in.
// This will automatically close and re-open this window.
General.Editing.CancelMode();
NodesViewerMode newmode = new NodesViewerMode();
General.Editing.ChangeMode(newmode);
newmode.Form.showsegsvertices.Checked = this.showsegsvertices.Checked;
newmode.Form.Location = this.Location; //mxd
}
#endregion
#region ================== Splits Events
// Go to the root split
private void rootbutton_Click(object sender, EventArgs e)
{
splitindex.Value = splitindex.Maximum;
}
// Go to the parent split
private void parentbutton_Click(object sender, EventArgs e)
{
Node n = mode.Nodes[(int)splitindex.Value];
if(n.parent > -1) splitindex.Value = n.parent;
}
// Go to the left split/subsector
private void leftbutton_Click(object sender, EventArgs e)
{
Node n = mode.Nodes[(int)splitindex.Value];
if(n.leftsubsector)
ShowSubsector(n.leftchild);
else
splitindex.Value = n.leftchild;
}
// Go to the right split/subsector
private void rightbutton_Click(object sender, EventArgs e)
{
Node n = mode.Nodes[(int)splitindex.Value];
if(n.rightsubsector)
ShowSubsector(n.rightchild);
else
splitindex.Value = n.rightchild;
}
// Split changes
private void splitindex_ValueChanged(object sender, EventArgs e)
{
Node n = mode.Nodes[(int)splitindex.Value];
if(n.parent == -1)
{
parentsplit.Text = "(root split)";
parentsplit.Enabled = false;
parentbutton.Enabled = false;
}
else
{
parentsplit.Text = n.parent.ToString();
parentsplit.Enabled = true;
parentbutton.Enabled = true;
}
leftarea.Text = "(" + n.leftbox.Left + ", " + n.leftbox.Top + ") - (" + n.leftbox.Right + ", " + n.leftbox.Bottom + ")";
rightarea.Text = "(" + n.rightbox.Left + ", " + n.rightbox.Top + ") - (" + n.rightbox.Right + ", " + n.rightbox.Bottom + ")";
leftindex.Text = n.leftchild.ToString();
rightindex.Text = n.rightchild.ToString();
if(n.leftsubsector)
{
lefttype.Text = "Subsector:";
leftbutton.Text = "Go to subsector";
}
else
{
lefttype.Text = "Split:";
leftbutton.Text = "Go to split";
}
if(n.rightsubsector)
{
righttype.Text = "Subsector:";
rightbutton.Text = "Go to subsector";
}
else
{
righttype.Text = "Split:";
rightbutton.Text = "Go to split";
}
General.Interface.RedrawDisplay();
}
#endregion
#region ================== Subsectors Events
// Go to parent split for this subsector
private void ssparentsplit_Click(object sender, EventArgs e)
{
// Find parent split
int ss = (int)ssectorindex.Value;
int parentsplit = -1;
for(int i = 0; i < mode.Nodes.Length; i++)
{
Node n = mode.Nodes[i];
if((n.leftsubsector && (n.leftchild == ss)) || (n.rightsubsector && (n.rightchild == ss)))
{
parentsplit = i;
break;
}
}
if(parentsplit == -1) return;
splitindex.Value = parentsplit;
tabs.SelectTab(tabsplits);
}
// Subsector changes
private void ssectorindex_ValueChanged(object sender, EventArgs e)
{
Subsector s = mode.Subsectors[(int)ssectorindex.Value];
ssectornumsegs.Text = s.numsegs.ToString();
segindex.Minimum = s.firstseg;
segindex.Maximum = s.firstseg + s.numsegs - 1;
segindex.Value = s.firstseg;
General.Interface.RedrawDisplay();
}
// Segment changes
private void segindex_ValueChanged(object sender, EventArgs e)
{
Seg sg = mode.Segs[(int)segindex.Value];
Linedef ld = null; //mxd
if(sg.lineindex != -1) ld = General.Map.Map.GetLinedefByIndex(sg.lineindex); //mxd
lineindex.Text = sg.lineindex.ToString();
startvertex.Text = sg.startvertex + " (" + mode.Vertices[sg.startvertex].x + ", " + mode.Vertices[sg.startvertex].y + ")";
endvertex.Text = sg.endvertex + " (" + mode.Vertices[sg.endvertex].x + ", " + mode.Vertices[sg.endvertex].y + ")";
segside.Text = sg.leftside ? "Back" : "Front";
segangle.Text = Angle2D.RealToDoom(sg.angle) + "\u00B0";
segoffset.Text = sg.offset + " mp";
if(ld != null) //mxd
{
sideindex.Text = sg.leftside ? ld.Back.Index.ToString() : ld.Front.Index.ToString();
sectorindex.Text = sg.leftside ? ld.Back.Sector.Index.ToString() : ld.Front.Sector.Index.ToString();
}
else
{
sideindex.Text = "None";
sectorindex.Text = "None";
}
General.Interface.RedrawDisplay();
}
// View segment checkbox changes
private void viewsegbox_CheckedChanged(object sender, EventArgs e)
{
General.Interface.RedrawDisplay();
}
#endregion
}
}