UltimateZoneBuilder/Source/Plugins/NodesViewer/NodesForm.cs

323 lines
8.9 KiB
C#
Raw Normal View History

2013-03-18 13:52:27 +00:00
#region === Copyright (c) 2010 Pascal van der Heiden ===
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using CodeImp.DoomBuilder.Editing;
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 / (float)maxdepth) * 100f);
treebalance.Text = balance.ToString() + "%";
// 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)
{
mode.BuildNodes();
// 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;
}
#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 = General.Map.Map.GetLinedefByIndex(sg.lineindex);
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";
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();
General.Interface.RedrawDisplay();
}
// View segment checkbox changes
private void viewsegbox_CheckedChanged(object sender, EventArgs e)
{
General.Interface.RedrawDisplay();
}
#endregion
}
}