mirror of
https://git.do.srb2.org/STJr/ZoneBuilder.git
synced 2024-11-10 06:41:49 +00:00
Use BSP tree instead of blockmap to find the sector a Thing is in (unless explicitly disabled in Preferences)
This commit is contained in:
parent
c9037f18f3
commit
4f6f748b31
15 changed files with 1007 additions and 580 deletions
|
@ -750,6 +750,7 @@ plugins
|
|||
editnewthing = true;
|
||||
editnewsector = false;
|
||||
additiveselect = false;
|
||||
dontusenodes = false;
|
||||
stitchrange = 20;
|
||||
highlightrange = 20;
|
||||
highlightthingsrange = 10;
|
||||
|
|
|
@ -187,6 +187,10 @@
|
|||
<DependentUpon>ThingStatisticsForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="IO\SRB2MapSetIO.cs" />
|
||||
<Compile Include="Map\BSP.cs" />
|
||||
<Compile Include="Map\Node.cs" />
|
||||
<Compile Include="Map\Seg.cs" />
|
||||
<Compile Include="Map\Subsector.cs" />
|
||||
<Compile Include="VisualModes\VisualBlockMap.cs" />
|
||||
<Compile Include="VisualModes\VisualMode.cs" />
|
||||
<Compile Include="General\Clock.cs" />
|
||||
|
|
|
@ -46,10 +46,10 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
public Vector3D Position { get { return position; } }
|
||||
public bool IsCurved;
|
||||
|
||||
public PathNode(Thing t, VisualBlockMap blockmap)
|
||||
public PathNode(Thing t, VisualBlockMap blockmap, BSP bsp, bool useblockmap)
|
||||
{
|
||||
thing = t;
|
||||
position = new Vector3D(t.Position, (blockmap != null ? t.Position.z + GetCorrectHeight(t, blockmap) : t.Position.z));
|
||||
position = new Vector3D(t.Position, (blockmap != null ? t.Position.z + GetCorrectHeight(t, blockmap, bsp, useblockmap) : t.Position.z));
|
||||
nextnodes = new Dictionary<int, PathNode>();
|
||||
prevnodes = new Dictionary<int, PathNode>();
|
||||
}
|
||||
|
@ -72,13 +72,13 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
}
|
||||
}
|
||||
|
||||
public static List<Line3D> GetThingLinks(IEnumerable<Thing> things) { return GetThingLinks(things, null); }
|
||||
public static List<Line3D> GetThingLinks(IEnumerable<Thing> things, VisualBlockMap blockmap)
|
||||
public static List<Line3D> GetThingLinks(IEnumerable<Thing> things) { return GetThingLinks(things, null, null, false); }
|
||||
public static List<Line3D> GetThingLinks(IEnumerable<Thing> things, VisualBlockMap blockmap, BSP bsp, bool useblockmap)
|
||||
{
|
||||
return GetThingLinks(GetSpecialThings(things, blockmap), blockmap);
|
||||
return GetThingLinks(GetSpecialThings(things, blockmap, bsp, useblockmap), blockmap, bsp, useblockmap);
|
||||
}
|
||||
|
||||
private static SpecialThings GetSpecialThings(IEnumerable<Thing> things, VisualBlockMap blockmap)
|
||||
private static SpecialThings GetSpecialThings(IEnumerable<Thing> things, VisualBlockMap blockmap, BSP bsp, bool useblockmap)
|
||||
{
|
||||
SpecialThings result = new SpecialThings();
|
||||
|
||||
|
@ -130,7 +130,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
{
|
||||
case "interpolationpoint":
|
||||
if(!result.InterpolationPoints.ContainsKey(t.Tag)) result.InterpolationPoints.Add(t.Tag, new List<PathNode>());
|
||||
result.InterpolationPoints[t.Tag].Add(new PathNode(t, blockmap));
|
||||
result.InterpolationPoints[t.Tag].Add(new PathNode(t, blockmap, bsp, useblockmap));
|
||||
break;
|
||||
|
||||
case "movingcamera":
|
||||
|
@ -154,7 +154,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
return result;
|
||||
}
|
||||
|
||||
private static List<Line3D> GetThingLinks(SpecialThings result, VisualBlockMap blockmap)
|
||||
private static List<Line3D> GetThingLinks(SpecialThings result, VisualBlockMap blockmap, BSP bsp, bool useblockmap)
|
||||
{
|
||||
var lines = new List<Line3D>();
|
||||
var actormovertargets = new Dictionary<int, List<Thing>>();
|
||||
|
@ -180,12 +180,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
if(!result.PatrolPoints.ContainsKey(t.Args[0])) continue;
|
||||
|
||||
start = t.Position;
|
||||
start.z += GetCorrectHeight(t, blockmap);
|
||||
start.z += GetCorrectHeight(t, blockmap, bsp, useblockmap);
|
||||
|
||||
foreach(Thing tt in result.PatrolPoints[t.Args[0]])
|
||||
{
|
||||
end = tt.Position;
|
||||
end.z += GetCorrectHeight(tt, blockmap);
|
||||
end.z += GetCorrectHeight(tt, blockmap, bsp, useblockmap);
|
||||
lines.Add(new Line3D(start, end));
|
||||
}
|
||||
}
|
||||
|
@ -197,12 +197,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
if(!result.PatrolPoints.ContainsKey(t.Args[1])) continue;
|
||||
|
||||
start = t.Position;
|
||||
start.z += GetCorrectHeight(t, blockmap);
|
||||
start.z += GetCorrectHeight(t, blockmap, bsp, useblockmap);
|
||||
|
||||
foreach(Thing tt in result.PatrolPoints[t.Args[1]])
|
||||
{
|
||||
end = tt.Position;
|
||||
end.z += GetCorrectHeight(tt, blockmap);
|
||||
end.z += GetCorrectHeight(tt, blockmap, bsp, useblockmap);
|
||||
|
||||
lines.Add(new Line3D(start, end, General.Colors.Selection));
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
bool interpolatepath = ((t.Args[2] & 1) != 1);
|
||||
|
||||
start = t.Position;
|
||||
start.z += GetCorrectHeight(t, blockmap);
|
||||
start.z += GetCorrectHeight(t, blockmap, bsp, useblockmap);
|
||||
|
||||
foreach(PathNode node in result.InterpolationPoints[targettag])
|
||||
{
|
||||
|
@ -237,7 +237,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
{
|
||||
bool interpolatepath = ((t.Args[2] & 1) != 1);
|
||||
start = t.Position;
|
||||
start.z += GetCorrectHeight(t, blockmap);
|
||||
start.z += GetCorrectHeight(t, blockmap, bsp, useblockmap);
|
||||
|
||||
foreach(PathNode node in result.InterpolationPoints[targettag])
|
||||
{
|
||||
|
@ -250,12 +250,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
if(actormovertargets.ContainsKey(t.Args[3]))
|
||||
{
|
||||
start = t.Position;
|
||||
start.z += GetCorrectHeight(t, blockmap);
|
||||
start.z += GetCorrectHeight(t, blockmap, bsp, useblockmap);
|
||||
|
||||
foreach(Thing tt in actormovertargets[t.Args[3]])
|
||||
{
|
||||
end = tt.Position;
|
||||
end.z += GetCorrectHeight(tt, blockmap);
|
||||
end.z += GetCorrectHeight(tt, blockmap, bsp, useblockmap);
|
||||
lines.Add(new Line3D(start, end, General.Colors.Selection));
|
||||
}
|
||||
}
|
||||
|
@ -270,7 +270,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
bool interpolatepath = (t.Args[2] & 1) != 1;
|
||||
|
||||
start = t.Position;
|
||||
start.z += GetCorrectHeight(t, blockmap);
|
||||
start.z += GetCorrectHeight(t, blockmap, bsp, useblockmap);
|
||||
|
||||
foreach(PathNode node in result.InterpolationPoints[targettag])
|
||||
{
|
||||
|
@ -286,12 +286,12 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
foreach(Thing anchor in group.Value)
|
||||
{
|
||||
start = anchor.Position;
|
||||
start.z += GetCorrectHeight(anchor, blockmap);
|
||||
start.z += GetCorrectHeight(anchor, blockmap, bsp, useblockmap);
|
||||
|
||||
foreach(Thing startspot in result.PolyobjectStartSpots[group.Key])
|
||||
{
|
||||
end = startspot.Position;
|
||||
end.z += GetCorrectHeight(startspot, blockmap);
|
||||
end.z += GetCorrectHeight(startspot, blockmap, bsp, useblockmap);
|
||||
lines.Add(new Line3D(start, end, General.Colors.Selection));
|
||||
}
|
||||
}
|
||||
|
@ -385,11 +385,17 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
|
|||
}
|
||||
|
||||
// Required only when called from VisualMode
|
||||
private static float GetCorrectHeight(Thing thing, VisualBlockMap blockmap)
|
||||
private static float GetCorrectHeight(Thing thing, VisualBlockMap blockmap, BSP bsp, bool useblockmap)
|
||||
{
|
||||
if(blockmap == null) return 0f;
|
||||
float height = thing.Height / 2f;
|
||||
if(thing.Sector == null) thing.DetermineSector(blockmap);
|
||||
if (thing.Sector == null)
|
||||
{
|
||||
if (useblockmap)
|
||||
thing.DetermineSector(blockmap);
|
||||
else
|
||||
thing.DetermineSector(bsp);
|
||||
}
|
||||
if(thing.Sector != null) height += thing.Sector.FloorHeight;
|
||||
return height;
|
||||
}
|
||||
|
|
298
Source/Core/Map/BSP.cs
Normal file
298
Source/Core/Map/BSP.cs
Normal file
|
@ -0,0 +1,298 @@
|
|||
#region ================== Namespaces
|
||||
|
||||
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.Rendering;
|
||||
using CodeImp.DoomBuilder.Windows;
|
||||
using CodeImp.DoomBuilder.Map;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.Map
|
||||
{
|
||||
public class BSP
|
||||
{
|
||||
#region ================== Constants
|
||||
#endregion
|
||||
|
||||
#region ================== Variables
|
||||
|
||||
private Seg[] segs;
|
||||
private Node[] nodes;
|
||||
private Vector2D[] verts;
|
||||
private Subsector[] ssectors;
|
||||
private bool deactivate;
|
||||
private bool isdisposed;
|
||||
#endregion
|
||||
|
||||
#region ================== Properties
|
||||
|
||||
public Seg[] Segs { get { return segs; } }
|
||||
public Node[] Nodes { get { return nodes; } }
|
||||
public Vector2D[] Vertices { get { return verts; } }
|
||||
public Subsector[] Subsectors { get { return ssectors; } }
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor / Destructor
|
||||
|
||||
// Constructor
|
||||
public BSP(bool deactivate)
|
||||
{
|
||||
this.deactivate = deactivate;
|
||||
if (!deactivate)
|
||||
{
|
||||
if (General.Map.IsChanged) BuildNodes();
|
||||
LoadStructures();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Disposer
|
||||
public void Dispose()
|
||||
{
|
||||
// Not already disposed?
|
||||
if (!isdisposed)
|
||||
{
|
||||
// Clean up
|
||||
segs = null;
|
||||
nodes = null;
|
||||
verts = null;
|
||||
ssectors = null;
|
||||
|
||||
// Done
|
||||
isdisposed = true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ================== Methods
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!deactivate && General.Map.IsChanged)
|
||||
{
|
||||
BuildNodes();
|
||||
LoadStructures();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This (re)builds the nodes for the whole map.
|
||||
/// </summary>
|
||||
private void BuildNodes()
|
||||
{
|
||||
// There is no API available to do this directly, but we export the map which will
|
||||
// cause the DB core to build the nodes (with testing parameters)
|
||||
General.Interface.DisplayStatus(StatusType.Busy, "Building map nodes...");
|
||||
string tempfile = General.MakeTempFilename(General.Map.TempPath, "wad");
|
||||
General.Map.IsChanged = true;
|
||||
General.Map.ExportToFile(tempfile);
|
||||
File.Delete(tempfile);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This loads all nodes structures data from the lumps
|
||||
/// </summary>
|
||||
private bool LoadStructures()
|
||||
{
|
||||
// Load the nodes structure
|
||||
MemoryStream nodesstream = General.Map.GetLumpData("NODES");
|
||||
int numnodes = (int)nodesstream.Length / 28;
|
||||
|
||||
//mxd. Boilerplate!
|
||||
if(numnodes < 1)
|
||||
{
|
||||
// Cancel mode
|
||||
MessageBox.Show("The map has only one subsector. Please add more sectors, then try running this mode again.", "THY NODETH ARETH BROKH!", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
General.Editing.CancelMode();
|
||||
return false;
|
||||
}
|
||||
|
||||
BinaryReader nodesreader = new BinaryReader(nodesstream);
|
||||
nodes = new Node[numnodes];
|
||||
for(int i = 0; i < nodes.Length; i++)
|
||||
{
|
||||
nodes[i].linestart.x = nodesreader.ReadInt16();
|
||||
nodes[i].linestart.y = nodesreader.ReadInt16();
|
||||
nodes[i].linedelta.x = nodesreader.ReadInt16();
|
||||
nodes[i].linedelta.y = nodesreader.ReadInt16();
|
||||
float top = nodesreader.ReadInt16();
|
||||
float bot = nodesreader.ReadInt16();
|
||||
float left = nodesreader.ReadInt16();
|
||||
float right = nodesreader.ReadInt16();
|
||||
nodes[i].rightbox = new RectangleF(left, top, (right - left), (bot - top));
|
||||
top = nodesreader.ReadInt16();
|
||||
bot = nodesreader.ReadInt16();
|
||||
left = nodesreader.ReadInt16();
|
||||
right = nodesreader.ReadInt16();
|
||||
nodes[i].leftbox = new RectangleF(left, top, (right - left), (bot - top));
|
||||
int rightindex = nodesreader.ReadInt16();
|
||||
int leftindex = nodesreader.ReadInt16();
|
||||
nodes[i].rightchild = rightindex & 0x7FFF;
|
||||
nodes[i].leftchild = leftindex & 0x7FFF;
|
||||
nodes[i].rightsubsector = (rightindex & 0x8000) != 0;
|
||||
nodes[i].leftsubsector = (leftindex & 0x8000) != 0;
|
||||
}
|
||||
nodesreader.Close();
|
||||
nodesstream.Close();
|
||||
nodesstream.Dispose();
|
||||
|
||||
// Add additional properties to nodes
|
||||
nodes[nodes.Length - 1].parent = -1;
|
||||
RecursiveSetupNodes(nodes.Length - 1);
|
||||
|
||||
// Load the segs structure
|
||||
MemoryStream segsstream = General.Map.GetLumpData("SEGS");
|
||||
BinaryReader segsreader = new BinaryReader(segsstream);
|
||||
int numsegs = (int)segsstream.Length / 12;
|
||||
|
||||
//mxd. Boilerplate!
|
||||
if(numsegs < 1)
|
||||
{
|
||||
// Cancel mode
|
||||
MessageBox.Show("The map has empty SEGS lump. Please rebuild the nodes, then try running this mode again.", "THY SEGS HATH SINNETH!", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
General.Editing.CancelMode();
|
||||
return false;
|
||||
}
|
||||
|
||||
segs = new Seg[numsegs];
|
||||
for(int i = 0; i < segs.Length; i++)
|
||||
{
|
||||
segs[i].startvertex = segsreader.ReadInt16();
|
||||
segs[i].endvertex = segsreader.ReadInt16();
|
||||
segs[i].angle = Angle2D.DoomToReal(segsreader.ReadInt16());
|
||||
segs[i].lineindex = segsreader.ReadInt16();
|
||||
segs[i].leftside = segsreader.ReadInt16() != 0;
|
||||
segs[i].offset = segsreader.ReadInt16();
|
||||
}
|
||||
segsreader.Close();
|
||||
segsstream.Close();
|
||||
segsstream.Dispose();
|
||||
|
||||
// Load the vertexes structure
|
||||
MemoryStream vertsstream = General.Map.GetLumpData("VERTEXES");
|
||||
BinaryReader vertsreader = new BinaryReader(vertsstream);
|
||||
int numverts = (int)vertsstream.Length / 4;
|
||||
|
||||
//mxd. Boilerplate!
|
||||
if(numverts < 1)
|
||||
{
|
||||
// Cancel mode
|
||||
MessageBox.Show("The map has empty VERTEXES lump. Please rebuild the nodes, then try running this mode again.", "THY VERTEXES ARETH FOUL!", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
General.Editing.CancelMode();
|
||||
return false;
|
||||
}
|
||||
|
||||
verts = new Vector2D[numverts];
|
||||
for(int i = 0; i < verts.Length; i++)
|
||||
{
|
||||
verts[i].x = vertsreader.ReadInt16();
|
||||
verts[i].y = vertsreader.ReadInt16();
|
||||
}
|
||||
vertsreader.Close();
|
||||
vertsstream.Close();
|
||||
vertsstream.Dispose();
|
||||
|
||||
// Load the subsectors structure
|
||||
MemoryStream ssecstream = General.Map.GetLumpData("SSECTORS");
|
||||
BinaryReader ssecreader = new BinaryReader(ssecstream);
|
||||
int numssec = (int)ssecstream.Length / 4;
|
||||
|
||||
//mxd. Boilerplate!
|
||||
if(numssec < 1)
|
||||
{
|
||||
// Cancel mode
|
||||
MessageBox.Show("The map has empty SSECTORS lump. Please rebuild the nodes, then try running this mode again.", "THY SSECTORS ARETH HERETYSH!", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
General.Editing.CancelMode();
|
||||
return false;
|
||||
}
|
||||
|
||||
ssectors = new Subsector[numssec];
|
||||
for(int i = 0; i < ssectors.Length; i++)
|
||||
{
|
||||
ssectors[i].numsegs = ssecreader.ReadInt16();
|
||||
ssectors[i].firstseg = ssecreader.ReadInt16();
|
||||
}
|
||||
ssecreader.Close();
|
||||
ssecstream.Close();
|
||||
ssecstream.Dispose();
|
||||
|
||||
// Link all segs to their subsectors
|
||||
for(int i = 0; i < ssectors.Length; i++)
|
||||
{
|
||||
int lastseg = ssectors[i].firstseg + ssectors[i].numsegs - 1;
|
||||
for(int sg = ssectors[i].firstseg; sg <= lastseg; sg++)
|
||||
{
|
||||
segs[sg].ssector = i;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This recursively sets up the nodes structure with additional properties
|
||||
/// </summary>
|
||||
private void RecursiveSetupNodes(int nodeindex)
|
||||
{
|
||||
Node n = nodes[nodeindex];
|
||||
if(!n.leftsubsector)
|
||||
{
|
||||
nodes[n.leftchild].parent = nodeindex;
|
||||
RecursiveSetupNodes(n.leftchild);
|
||||
}
|
||||
if(!n.rightsubsector)
|
||||
{
|
||||
nodes[n.rightchild].parent = nodeindex;
|
||||
RecursiveSetupNodes(n.rightchild);
|
||||
}
|
||||
}
|
||||
|
||||
private bool PointOnSide(Vector2D p, Node node)
|
||||
{
|
||||
if (node.linedelta.x == 0)
|
||||
return p.x <= node.linestart.x ? node.linedelta.y > 0 : node.linedelta.y < 0;
|
||||
|
||||
if (node.linedelta.y == 0)
|
||||
return p.y <= node.linestart.y ? node.linedelta.x < 0 : node.linedelta.x > 0;
|
||||
|
||||
float dx = p.x - node.linestart.x;
|
||||
float dy = p.y - node.linestart.y;
|
||||
|
||||
// Try to quickly decide by looking at sign bits.
|
||||
if (((node.linedelta.y < 0) ^ (node.linedelta.x < 0) ^ (dx < 0) ^ (dy < 0)))
|
||||
return (node.linedelta.y < 0) ^ (dx < 0); // (left is negative)
|
||||
return dy*node.linedelta.x/65536 >= dx*node.linedelta.y/65536;
|
||||
}
|
||||
|
||||
private Subsector PointInSubsector(Vector2D p)
|
||||
{
|
||||
int nodenum = nodes.Length - 1;
|
||||
bool reachedsubsector = false;
|
||||
|
||||
while (!reachedsubsector)
|
||||
{
|
||||
bool side = !PointOnSide(p, nodes[nodenum]);
|
||||
reachedsubsector = side ? nodes[nodenum].rightsubsector : nodes[nodenum].leftsubsector;
|
||||
nodenum = side ? nodes[nodenum].rightchild : nodes[nodenum].leftchild;
|
||||
}
|
||||
|
||||
return ssectors[nodenum];
|
||||
}
|
||||
|
||||
public Sector GetSector(Vector2D p)
|
||||
{
|
||||
Subsector ss = PointInSubsector(p);
|
||||
Seg seg = segs[ss.firstseg];
|
||||
Linedef line = General.Map.Map.GetLinedefByIndex(seg.lineindex);
|
||||
Sidedef sidedef = seg.leftside ? line.Back : line.Front;
|
||||
return sidedef.Sector;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
22
Source/Core/Map/Node.cs
Normal file
22
Source/Core/Map/Node.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
#region === Copyright (c) 2010 Pascal van der Heiden ===
|
||||
|
||||
using System.Drawing;
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.Map
|
||||
{
|
||||
public struct Node
|
||||
{
|
||||
public Vector2D linestart;
|
||||
public Vector2D linedelta;
|
||||
public RectangleF rightbox;
|
||||
public RectangleF leftbox;
|
||||
public int rightchild;
|
||||
public int leftchild;
|
||||
public bool rightsubsector;
|
||||
public bool leftsubsector;
|
||||
public int parent;
|
||||
}
|
||||
}
|
17
Source/Core/Map/Seg.cs
Normal file
17
Source/Core/Map/Seg.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
#region === Copyright (c) 2010 Pascal van der Heiden ===
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.Map
|
||||
{
|
||||
public struct Seg
|
||||
{
|
||||
public int startvertex;
|
||||
public int endvertex;
|
||||
public float angle;
|
||||
public int lineindex;
|
||||
public bool leftside;
|
||||
public float offset;
|
||||
public int ssector;
|
||||
}
|
||||
}
|
18
Source/Core/Map/Subsector.cs
Normal file
18
Source/Core/Map/Subsector.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
#region === Copyright (c) 2010 Pascal van der Heiden ===
|
||||
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
using CodeImp.DoomBuilder.Rendering;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace CodeImp.DoomBuilder.Map
|
||||
{
|
||||
public struct Subsector
|
||||
{
|
||||
public int numsegs;
|
||||
public int firstseg;
|
||||
|
||||
public Vector2D[] points;
|
||||
public FlatVertex[] vertices;
|
||||
}
|
||||
}
|
|
@ -274,7 +274,7 @@ namespace CodeImp.DoomBuilder.Map
|
|||
sector = map.GetSectorByCoordinates(pos);
|
||||
}
|
||||
|
||||
// This determines which sector the thing is in and links it
|
||||
// This determines which sector the thing is in by looking at the blockmap and links it
|
||||
public void DetermineSector(VisualBlockMap blockmap)
|
||||
{
|
||||
// Find nearest sectors using the blockmap
|
||||
|
@ -292,8 +292,14 @@ namespace CodeImp.DoomBuilder.Map
|
|||
}
|
||||
}
|
||||
|
||||
// This translates the flags into UDMF fields
|
||||
internal void TranslateToUDMF()
|
||||
// This determines which sector the thing is in by looking at the BSP tree and links it
|
||||
public void DetermineSector(BSP bsp)
|
||||
{
|
||||
sector = bsp.GetSector((Vector2D)pos);
|
||||
}
|
||||
|
||||
// This translates the flags into UDMF fields
|
||||
internal void TranslateToUDMF()
|
||||
{
|
||||
// First make a single integer with all flags
|
||||
int bits = 0;
|
||||
|
|
|
@ -104,7 +104,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
private bool editnewthing;
|
||||
private bool editnewsector;
|
||||
private bool additiveselect;
|
||||
private bool autoclearselection;
|
||||
private bool dontusenodes;
|
||||
private bool autoclearselection;
|
||||
private bool visualmodeclearselection;
|
||||
private string copiedtexture;
|
||||
private string copiedflat;
|
||||
|
@ -155,7 +156,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
public bool EditNewThing { get { return editnewthing; } }
|
||||
public bool EditNewSector { get { return editnewsector; } }
|
||||
public bool AdditiveSelect { get { return additiveselect; } }
|
||||
public bool AutoClearSelection { get { return autoclearselection; } }
|
||||
public bool DontUseNodes { get { return dontusenodes; } }
|
||||
public bool AutoClearSelection { get { return autoclearselection; } }
|
||||
public bool VisualModeClearSelection { get { return visualmodeclearselection; } }
|
||||
public string CopiedTexture { get { return copiedtexture; } set { copiedtexture = value; } }
|
||||
public string CopiedFlat { get { return copiedflat; } set { copiedflat = value; } }
|
||||
|
@ -280,7 +282,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
editnewthing = General.Settings.ReadPluginSetting("editnewthing", true);
|
||||
editnewsector = General.Settings.ReadPluginSetting("editnewsector", false);
|
||||
additiveselect = General.Settings.ReadPluginSetting("additiveselect", false);
|
||||
autoclearselection = General.Settings.ReadPluginSetting("autoclearselection", false);
|
||||
dontusenodes = General.Settings.ReadPluginSetting("dontusenodes", false);
|
||||
autoclearselection = General.Settings.ReadPluginSetting("autoclearselection", false);
|
||||
visualmodeclearselection = General.Settings.ReadPluginSetting("visualmodeclearselection", false);
|
||||
stitchrange = General.Settings.ReadPluginSetting("stitchrange", 20);
|
||||
highlightrange = General.Settings.ReadPluginSetting("highlightrange", 20);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -46,7 +46,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
editnewthing.Checked = General.Settings.ReadPluginSetting("editnewthing", true);
|
||||
editnewsector.Checked = General.Settings.ReadPluginSetting("editnewsector", false);
|
||||
additiveselect.Checked = General.Settings.ReadPluginSetting("additiveselect", false);
|
||||
stitchrange.Text = General.Settings.ReadPluginSetting("stitchrange", 20).ToString();
|
||||
dontusenodes.Checked = General.Settings.ReadPluginSetting("dontusenodes", false);
|
||||
stitchrange.Text = General.Settings.ReadPluginSetting("stitchrange", 20).ToString();
|
||||
highlightrange.Text = General.Settings.ReadPluginSetting("highlightrange", 20).ToString();
|
||||
highlightthingsrange.Text = General.Settings.ReadPluginSetting("highlightthingsrange", 10).ToString();
|
||||
splitlinedefsrange.Text = General.Settings.ReadPluginSetting("splitlinedefsrange", 10).ToString();
|
||||
|
@ -75,7 +76,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
General.Settings.WritePluginSetting("editnewthing", editnewthing.Checked);
|
||||
General.Settings.WritePluginSetting("editnewsector", editnewsector.Checked);
|
||||
General.Settings.WritePluginSetting("additiveselect", additiveselect.Checked);
|
||||
General.Settings.WritePluginSetting("stitchrange", stitchrange.GetResult(0));
|
||||
General.Settings.WritePluginSetting("dontusenodes", dontusenodes.Checked);
|
||||
General.Settings.WritePluginSetting("stitchrange", stitchrange.GetResult(0));
|
||||
General.Settings.WritePluginSetting("highlightrange", highlightrange.GetResult(0));
|
||||
General.Settings.WritePluginSetting("highlightthingsrange", highlightthingsrange.GetResult(0));
|
||||
General.Settings.WritePluginSetting("splitlinedefsrange", splitlinedefsrange.GetResult(0));
|
||||
|
|
|
@ -97,8 +97,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
|
||||
private static bool gzdoomRenderingEffects = true; //mxd
|
||||
|
||||
//mxd. Moved here from Tools
|
||||
private struct SidedefAlignJob
|
||||
private BSP bsp;
|
||||
|
||||
//mxd. Moved here from Tools
|
||||
private struct SidedefAlignJob
|
||||
{
|
||||
public Sidedef sidedef;
|
||||
|
||||
|
@ -166,13 +168,14 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
|
||||
public bool IsSingleSelection { get { return singleselection; } }
|
||||
public bool SelectionChanged { get { return selectionchanged; } set { selectionchanged |= value; } }
|
||||
public BSP BSP { get { return bsp; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region ================== Constructor / Disposer
|
||||
#endregion
|
||||
|
||||
// Constructor
|
||||
public BaseVisualMode()
|
||||
#region ================== Constructor / Disposer
|
||||
|
||||
// Constructor
|
||||
public BaseVisualMode()
|
||||
{
|
||||
// Initialize
|
||||
this.gravity = new Vector3D(0.0f, 0.0f, 0.0f);
|
||||
|
@ -183,6 +186,8 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
this.selectioninfoupdatetimer = new Timer();
|
||||
selectioninfoupdatetimer.Interval = 100;
|
||||
selectioninfoupdatetimer.Tick += SelectioninfoupdatetimerOnTick;
|
||||
|
||||
bsp = new BSP(BuilderPlug.Me.DontUseNodes);
|
||||
|
||||
// We have no destructor
|
||||
GC.SuppressFinalize(this);
|
||||
|
@ -194,10 +199,12 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
// Not already disposed?
|
||||
if(!isdisposed)
|
||||
{
|
||||
// Clean up
|
||||
|
||||
// Done
|
||||
base.Dispose();
|
||||
// Clean up
|
||||
bsp.Dispose();
|
||||
bsp = null;
|
||||
|
||||
// Done
|
||||
base.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -523,7 +530,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
}
|
||||
|
||||
//mxd. Update event lines (still better than updating them on every frame redraw)
|
||||
renderer.SetEventLines(LinksCollector.GetThingLinks(General.Map.ThingsFilter.VisibleThings, blockmap));
|
||||
renderer.SetEventLines(LinksCollector.GetThingLinks(General.Map.ThingsFilter.VisibleThings, blockmap, bsp, BuilderPlug.Me.DontUseNodes));
|
||||
}
|
||||
|
||||
//mxd
|
||||
|
@ -776,6 +783,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
{
|
||||
//mxd
|
||||
Sector[] sectorsWithEffects = null;
|
||||
bsp.Update();
|
||||
|
||||
if(!gzdoomRenderingEffects)
|
||||
{
|
||||
|
@ -1077,7 +1085,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
if (slopevertices.Count >= 3)
|
||||
{
|
||||
SectorData sd = GetSectorData(s);
|
||||
sd.AddEffectSRB2ThingVertexSlope(slopevertices, slopefloor, blockmap);
|
||||
sd.AddEffectSRB2ThingVertexSlope(slopevertices, slopefloor, blockmap, bsp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1223,7 +1231,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
RebuildElementData();
|
||||
|
||||
//mxd. Update event lines
|
||||
renderer.SetEventLines(LinksCollector.GetThingLinks(General.Map.ThingsFilter.VisibleThings, blockmap));
|
||||
renderer.SetEventLines(LinksCollector.GetThingLinks(General.Map.ThingsFilter.VisibleThings, blockmap, bsp, BuilderPlug.Me.DontUseNodes));
|
||||
}
|
||||
|
||||
// When returning to another mode
|
||||
|
@ -3355,7 +3363,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
General.Map.ThingsFilter.Update();
|
||||
|
||||
// Update event lines
|
||||
renderer.SetEventLines(LinksCollector.GetThingLinks(General.Map.ThingsFilter.VisibleThings, blockmap));
|
||||
renderer.SetEventLines(LinksCollector.GetThingLinks(General.Map.ThingsFilter.VisibleThings, blockmap, bsp, BuilderPlug.Me.DontUseNodes));
|
||||
}
|
||||
|
||||
//mxd. We'll just use currently selected objects
|
||||
|
|
|
@ -101,8 +101,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
// This builds the thing geometry. Returns false when nothing was created.
|
||||
public bool Setup()
|
||||
{
|
||||
// Find the sector in which the thing resides
|
||||
Thing.DetermineSector(mode.BlockMap);
|
||||
// Find the sector in which the thing resides
|
||||
if (BuilderPlug.Me.DontUseNodes)
|
||||
Thing.DetermineSector(mode.BlockMap);
|
||||
else
|
||||
Thing.DetermineSector(mode.BSP);
|
||||
|
||||
//mxd. If the thing is inside a sector, apply DECORATE/UDMF alpha/renderstyle overrides
|
||||
byte alpha = 255;
|
||||
|
|
|
@ -21,13 +21,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
private bool slopefloor;
|
||||
|
||||
private VisualBlockMap blockmap;
|
||||
private BSP bsp;
|
||||
|
||||
// Constructor
|
||||
public EffectSRB2ThingVertexSlope(SectorData data, List<Thing> sourcethings, bool floor, VisualBlockMap bmap) : base(data)
|
||||
public EffectSRB2ThingVertexSlope(SectorData data, List<Thing> sourcethings, bool floor, VisualBlockMap bmap, BSP bsptree) : base(data)
|
||||
{
|
||||
things = sourcethings;
|
||||
slopefloor = floor;
|
||||
blockmap = bmap;
|
||||
bsp = bsptree;
|
||||
|
||||
// New effect added: This sector needs an update!
|
||||
if(data.Mode.VisualSectorExists(data.Sector))
|
||||
|
@ -48,7 +50,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
ThingData td = data.Mode.GetThingData(t);
|
||||
td.AddUpdateSector(data.Sector, true);
|
||||
Vector3D position = t.Position;
|
||||
t.DetermineSector(blockmap);
|
||||
if (BuilderPlug.Me.DontUseNodes)
|
||||
t.DetermineSector(blockmap);
|
||||
else
|
||||
t.DetermineSector(bsp);
|
||||
position.z += t.Sector.FloorHeight;
|
||||
verts[index] = position;
|
||||
index++;
|
||||
|
|
|
@ -179,9 +179,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
|
|||
}
|
||||
|
||||
// SRB2-style Thing vertex slope effect
|
||||
public void AddEffectSRB2ThingVertexSlope(List<Thing> sourcethings, bool slopefloor, VisualBlockMap blockmap)
|
||||
public void AddEffectSRB2ThingVertexSlope(List<Thing> sourcethings, bool slopefloor, VisualBlockMap blockmap, BSP bsp)
|
||||
{
|
||||
EffectSRB2ThingVertexSlope e = new EffectSRB2ThingVertexSlope(this, sourcethings, slopefloor, blockmap);
|
||||
EffectSRB2ThingVertexSlope e = new EffectSRB2ThingVertexSlope(this, sourcethings, slopefloor, blockmap, bsp);
|
||||
alleffects.Add(e);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue