mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-26 22:01:45 +00:00
geometry drawing fixes
This commit is contained in:
parent
3214ef4593
commit
51f57471c7
4 changed files with 268 additions and 103 deletions
|
@ -135,6 +135,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
List<Vertex> newverts = new List<Vertex>();
|
||||
List<Vertex> intersectverts = new List<Vertex>();
|
||||
List<Linedef> newlines = new List<Linedef>();
|
||||
List<Linedef> oldlines = new List<Linedef>(General.Map.Map.Linedefs);
|
||||
List<Vertex> mergeverts = new List<Vertex>();
|
||||
List<Vertex> nonmergeverts = new List<Vertex>(General.Map.Map.Vertices);
|
||||
|
||||
|
@ -182,7 +183,7 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
newlines.Add(ld);
|
||||
|
||||
// Should we split this line to merge with intersecting lines?
|
||||
if(points[i - 1].stitch || points[i].stitch)
|
||||
if(points[i - 1].stitch && points[i].stitch)
|
||||
{
|
||||
// Check if any other lines intersect this line
|
||||
List<float> intersections = new List<float>();
|
||||
|
@ -236,6 +237,97 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
// Join merge vertices so that overlapping vertices in the draw become one.
|
||||
MapSet.JoinVertices(mergeverts, mergeverts, false, MapSet.STITCH_DISTANCE);
|
||||
|
||||
// We prefer a closed polygon, because then we can determine the interior properly
|
||||
// Check if the two ends of the polygon are closed
|
||||
bool drawingclosed = false;
|
||||
if(newlines.Count > 0)
|
||||
{
|
||||
// When not closed, we will try to find a path to close it
|
||||
Linedef firstline = newlines[0];
|
||||
Linedef lastline = newlines[newlines.Count - 1];
|
||||
drawingclosed = (firstline.Start == lastline.End);
|
||||
if(!drawingclosed)
|
||||
{
|
||||
// First and last vertex stitch with geometry?
|
||||
if(points[0].stitch && points[points.Count - 1].stitch)
|
||||
{
|
||||
// Find out where they will stitch
|
||||
Linedef l1 = MapSet.NearestLinedefRange(oldlines, firstline.Start.Position, MapSet.STITCH_DISTANCE);
|
||||
Linedef l2 = MapSet.NearestLinedefRange(oldlines, lastline.End.Position, MapSet.STITCH_DISTANCE);
|
||||
if((l1 != null) && (l2 != null))
|
||||
{
|
||||
List<LinedefSide> shortestpath = null;
|
||||
|
||||
// Same line?
|
||||
if(l1 == l2)
|
||||
{
|
||||
// Then just connect the two
|
||||
shortestpath = new List<LinedefSide>();
|
||||
shortestpath.Add(new LinedefSide(l1, true));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find the shortest, closest path between these lines
|
||||
List<List<LinedefSide>> paths = new List<List<LinedefSide>>(8);
|
||||
paths.Add(SectorTools.FindClosestPath(l1, true, l2, true, true));
|
||||
paths.Add(SectorTools.FindClosestPath(l1, true, l2, false, true));
|
||||
paths.Add(SectorTools.FindClosestPath(l1, false, l2, true, true));
|
||||
paths.Add(SectorTools.FindClosestPath(l1, false, l2, false, true));
|
||||
paths.Add(SectorTools.FindClosestPath(l2, true, l1, true, true));
|
||||
paths.Add(SectorTools.FindClosestPath(l2, true, l1, false, true));
|
||||
paths.Add(SectorTools.FindClosestPath(l2, false, l1, true, true));
|
||||
paths.Add(SectorTools.FindClosestPath(l2, false, l1, false, true));
|
||||
|
||||
foreach(List<LinedefSide> p in paths)
|
||||
if((p != null) && ((shortestpath == null) || (p.Count < shortestpath.Count))) shortestpath = p;
|
||||
}
|
||||
|
||||
// Found a path?
|
||||
if(shortestpath != null)
|
||||
{
|
||||
// Go for all vertices in the path to make additional lines
|
||||
v1 = firstline.Start;
|
||||
for(int i = 1; i < shortestpath.Count; i++)
|
||||
{
|
||||
// Get the next position
|
||||
Vector2D v2pos = shortestpath[i].Front ? shortestpath[i].Line.Start.Position : shortestpath[i].Line.End.Position;
|
||||
|
||||
// Make the new vertex
|
||||
Vertex v2 = map.CreateVertex(v2pos);
|
||||
v2.Marked = true;
|
||||
mergeverts.Add(v2);
|
||||
|
||||
// Make the line
|
||||
Linedef ld = map.CreateLinedef(v1, v2);
|
||||
ld.Marked = true;
|
||||
ld.Selected = true;
|
||||
ld.ApplySidedFlags();
|
||||
ld.UpdateCache();
|
||||
newlines.Add(ld);
|
||||
|
||||
// Next
|
||||
v1 = v2;
|
||||
}
|
||||
|
||||
// Make the final line
|
||||
Linedef lld = map.CreateLinedef(v1, lastline.End);
|
||||
lld.Marked = true;
|
||||
lld.Selected = true;
|
||||
lld.ApplySidedFlags();
|
||||
lld.UpdateCache();
|
||||
newlines.Add(lld);
|
||||
|
||||
// Drawing is now closed
|
||||
drawingclosed = true;
|
||||
|
||||
// Join merge vertices so that overlapping vertices in the draw become one.
|
||||
MapSet.JoinVertices(mergeverts, mergeverts, false, MapSet.STITCH_DISTANCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge intersetion vertices with the new lines. This completes the
|
||||
// self intersections for which splits were made above.
|
||||
map.Update(true, false);
|
||||
|
@ -304,6 +396,9 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
|
|||
STEP 3: Join and create new sectors
|
||||
\***************************************************/
|
||||
|
||||
// The code below atempts to create sectors on the front sides of the drawn
|
||||
// geometry and joins sectors on the back sides of the drawn geometry.
|
||||
// This code does not change any geometry, it only makes/updates sidedefs.
|
||||
bool[] frontsdone = new bool[newlines.Count];
|
||||
bool[] backsdone = new bool[newlines.Count];
|
||||
for(int i = 0; i < newlines.Count; i++)
|
||||
|
|
|
@ -274,12 +274,22 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
/// When turnatends is true, the algorithm will continue at the other side of the
|
||||
/// line when a dead end has been reached. Returns null when no path could be found.
|
||||
/// </summary>
|
||||
public static List<LinedefSide> FindClosestPath(Linedef start, bool front, bool turnatends)
|
||||
public static List<LinedefSide> FindClosestPath(Linedef startline, bool startfront, bool turnatends)
|
||||
{
|
||||
return FindClosestPath(startline, startfront, startline, startfront, turnatends);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This finds the closest path from the beginning of a line to the end of the line.
|
||||
/// When turnatends is true, the algorithm will continue at the other side of the
|
||||
/// line when a dead end has been reached. Returns null when no path could be found.
|
||||
/// </summary>
|
||||
public static List<LinedefSide> FindClosestPath(Linedef startline, bool startfront, Linedef endline, bool endfront, bool turnatends)
|
||||
{
|
||||
List<LinedefSide> path = new List<LinedefSide>();
|
||||
Dictionary<Linedef, int> tracecount = new Dictionary<Linedef, int>();
|
||||
Linedef nextline = start;
|
||||
bool nextfront = front;
|
||||
Linedef nextline = startline;
|
||||
bool nextfront = startfront;
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -332,7 +342,11 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
}
|
||||
// Continue as long as we have not reached the start yet
|
||||
// or we have no next line to trace
|
||||
while((path != null) && ((nextline != start) || (nextfront != front)));
|
||||
while((path != null) && ((nextline != endline) || (nextfront != endfront)));
|
||||
|
||||
// If start and front are not the same, add the end to the list also
|
||||
if((path != null) && ((startline != endline) || (startfront != endfront)))
|
||||
path.Add(new LinedefSide(endline, endfront));
|
||||
|
||||
// Return path (null when trace failed)
|
||||
return path;
|
||||
|
|
|
@ -563,6 +563,11 @@ namespace CodeImp.DoomBuilder.Map
|
|||
public void Join(Linedef other)
|
||||
{
|
||||
Sector l1fs, l1bs, l2fs, l2bs;
|
||||
bool l1was2s, l2was2s;
|
||||
|
||||
// Check which lines were 2 sided
|
||||
l1was2s = ((other.Front != null) && (other.Back != null));
|
||||
l2was2s = ((this.Front != null) && (this.Back != null));
|
||||
|
||||
// Get sector references
|
||||
if(other.front != null) l1fs = other.front.Sector; else l1fs = null;
|
||||
|
@ -570,6 +575,30 @@ namespace CodeImp.DoomBuilder.Map
|
|||
if(this.front != null) l2fs = this.front.Sector; else l2fs = null;
|
||||
if(this.back != null) l2bs = this.back.Sector; else l2bs = null;
|
||||
|
||||
// This line has no sidedefs?
|
||||
if((l2fs == null) && (l2bs == null))
|
||||
{
|
||||
// We have no sidedefs, so we have no influence
|
||||
// Nothing to change on the other line
|
||||
}
|
||||
// Other line has no sidedefs?
|
||||
else if((l1fs == null) && (l1bs == null))
|
||||
{
|
||||
// The other has no sidedefs, so it has no influence
|
||||
// Copy my sidedefs to the other
|
||||
if(this.Start == other.Start)
|
||||
{
|
||||
JoinChangeSidedefs(other, true, front);
|
||||
JoinChangeSidedefs(other, false, back);
|
||||
}
|
||||
else
|
||||
{
|
||||
JoinChangeSidedefs(other, false, front);
|
||||
JoinChangeSidedefs(other, true, back);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compare front sectors
|
||||
if(l1fs == l2fs)
|
||||
{
|
||||
|
@ -681,6 +710,7 @@ namespace CodeImp.DoomBuilder.Map
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If either of the two lines was selected, keep the other selected
|
||||
if(this.selected) other.selected = true;
|
||||
|
@ -689,6 +719,10 @@ namespace CodeImp.DoomBuilder.Map
|
|||
// Apply single/double sided flags
|
||||
other.ApplySidedFlags();
|
||||
|
||||
// Remove unneeded textures
|
||||
if(other.front != null) other.front.RemoveUnneededTextures(!(l1was2s && l2was2s));
|
||||
if(other.back != null) other.back.RemoveUnneededTextures(!(l1was2s && l2was2s));
|
||||
|
||||
// I got killed by the other.
|
||||
this.Dispose();
|
||||
}
|
||||
|
|
|
@ -237,6 +237,28 @@ namespace CodeImp.DoomBuilder.Map
|
|||
|
||||
#region ================== Methods
|
||||
|
||||
// This removes textures that are not required
|
||||
public void RemoveUnneededTextures(bool removemiddle)
|
||||
{
|
||||
if(!HighRequired())
|
||||
{
|
||||
this.texnamehigh = "-";
|
||||
this.longtexnamehigh = map.EmptyLongName;
|
||||
}
|
||||
|
||||
if(!MiddleRequired() && removemiddle)
|
||||
{
|
||||
this.texnamemid = "-";
|
||||
this.longtexnamemid = map.EmptyLongName;
|
||||
}
|
||||
|
||||
if(!LowRequired())
|
||||
{
|
||||
this.texnamelow = "-";
|
||||
this.longtexnamelow = map.EmptyLongName;
|
||||
}
|
||||
}
|
||||
|
||||
// This checks if a texture is required
|
||||
public bool HighRequired()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue