some improvements in sector drawing (still very buggy though)

This commit is contained in:
codeimp 2008-05-05 18:21:13 +00:00
parent b5b7875f75
commit 3c0e66a36e
5 changed files with 195 additions and 38 deletions

View file

@ -174,14 +174,65 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
ld.Selected = true;
newlines.Add(ld);
// Should we split this line to merge with intersecting lines?
if(points[i - 1].stitch || points[i].stitch)
{
// Check if any other lines intersect this line
List<float> intersections = new List<float>();
foreach(Linedef ld2 in map.Linedefs)
{
// Not the same as the subject line
if(ld2 != ld)
{
// Intersecting?
// We only keep the unit length from the start of the line and
// do the real splitting later, when all intersections are known
float u = ld.GetIntersectionU(ld2);
if(!float.IsNaN(u) && (u > 0.0f) && (u < 1.0f)) intersections.Add(u);
}
}
// Sort the intersections
intersections.Sort();
// Go for all found intersections
Linedef splitline = ld;
Line2D measureline = ld.GetLine2D();
foreach(float u in intersections)
{
// Calculate exact coordinates where to split
// We use measureline for this, because the original line
// may already have changed in length due to a previous split
Vector2D splitpoint = measureline.GetCoordinatesAt(u);
// Make the vertex
Vertex splitvertex = map.CreateVertex((int)splitpoint.x, (int)splitpoint.y);
// The Split method ties the end of the original line to the given
// vertex and starts a new line at the given vertex, so continue
// splitting with the new line, because the intersections are sorted
// from low to high (beginning at the original line start)
splitline = splitline.Split(splitvertex);
newlines.Add(splitline);
newverts.Add(splitvertex);
mergeverts.Add(splitvertex);
}
}
// Next
v1 = v2;
}
// STEP 2: Merge the new geometry
foreach(Vertex v in mergeverts) v.Marked = true;
MapSet.JoinVertices(mergeverts, mergeverts, true, General.Settings.StitchDistance);
map.StitchGeometry();
// Re-find our new lines, because they have been merged with the other geometry
newlines = map.GetMarkedLinedefs(true);
// Split the new lines with the new vertices so that self-intersecting draws also work
MapSet.SplitLinesByVertices(newlines, mergeverts, General.Settings.StitchDistance, null);
// STEP 3: Make sectors where possible
bool[] frontsdone = new bool[newlines.Count];
@ -240,6 +291,9 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
}
}
}
// Make corrections for backward linedefs
MapSet.FlipBackwardLinedefs(newlines);
// Update cached values
map.Update();
@ -300,10 +354,12 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
// This updates the dragging
private void Update()
{
PixelColor color;
snaptogrid = General.Interface.ShiftState ^ General.Interface.SnapToGrid;
snaptonearest = General.Interface.CtrlState ^ General.Interface.AutoMerge;
Vector2D lastp = new Vector2D(0, 0);
DrawnVertex lastp = new DrawnVertex();
DrawnVertex curp = GetCurrentPosition();
float vsize = ((float)renderer.VertexSize + 1.0f) / renderer.Scale;
@ -314,15 +370,28 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
if(points.Count > 0)
{
// Render lines
lastp = points[0].pos;
lastp = points[0];
for(int i = 1; i < points.Count; i++)
{
renderer.RenderLine(lastp, points[i].pos, LINE_THICKNESS, General.Colors.Selection, true);
lastp = points[i].pos;
// Determine line color
if(lastp.stitch || points[i].stitch)
color = General.Colors.Highlight;
else
color = General.Colors.Selection;
// Render line
renderer.RenderLine(lastp.pos, points[i].pos, LINE_THICKNESS, color, true);
lastp = points[i];
}
// Determine line color
if(lastp.stitch || snaptonearest)
color = General.Colors.Highlight;
else
color = General.Colors.Selection;
// Render line to cursor
renderer.RenderLine(lastp, curp.pos, LINE_THICKNESS, General.Colors.Highlight, true);
renderer.RenderLine(lastp.pos, curp.pos, LINE_THICKNESS, color, true);
// Render vertices
for(int i = 0; i < points.Count; i++)
@ -338,8 +407,12 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
}
}
// Determine point color
if(snaptonearest) color = General.Colors.Highlight;
else color = General.Colors.Selection;
// Render vertex at cursor
renderer.RenderRectangleFilled(new RectangleF(curp.pos.x - vsize, curp.pos.y - vsize, vsize * 2.0f, vsize * 2.0f), General.Colors.Highlight, true);
renderer.RenderRectangleFilled(new RectangleF(curp.pos.x - vsize, curp.pos.y - vsize, vsize * 2.0f, vsize * 2.0f), color, true);
// Done
renderer.Finish();

View file

@ -329,36 +329,43 @@ namespace CodeImp.DoomBuilder.BuilderModes.Editing
{
// Find the nearest linedef within highlight range
Linedef l = General.Map.Map.NearestLinedef(mousemappos);
// Check on which side of the linedef the mouse is
float side = l.SideOfLine(mousemappos);
if(side > 0)
if(l != null)
{
// Is there a sidedef here?
if(l.Back != null)
// Check on which side of the linedef the mouse is
float side = l.SideOfLine(mousemappos);
if(side > 0)
{
// Highlight if not the same
if(l.Back.Sector != highlighted) Highlight(l.Back.Sector);
// Is there a sidedef here?
if(l.Back != null)
{
// Highlight if not the same
if(l.Back.Sector != highlighted) Highlight(l.Back.Sector);
}
else
{
// Highlight nothing
if(highlighted != null) Highlight(null);
}
}
else
{
// Highlight nothing
if(highlighted != null) Highlight(null);
// Is there a sidedef here?
if(l.Front != null)
{
// Highlight if not the same
if(l.Front.Sector != highlighted) Highlight(l.Front.Sector);
}
else
{
// Highlight nothing
if(highlighted != null) Highlight(null);
}
}
}
else
{
// Is there a sidedef here?
if(l.Front != null)
{
// Highlight if not the same
if(l.Front.Sector != highlighted) Highlight(l.Front.Sector);
}
else
{
// Highlight nothing
if(highlighted != null) Highlight(null);
}
// Highlight nothing
if(highlighted != null) Highlight(null);
}
}
}

View file

@ -258,7 +258,7 @@ namespace CodeImp.DoomBuilder.Geometry
if(lines.Count == 1)
{
// Are we allowed to trace along this line again?
if(tracecount[nextline] < 2)
if(!tracecount.ContainsKey(nextline) || (tracecount[nextline] < 2))
{
// Turn around and go back along the other side of the line
nextfront = !nextfront;
@ -275,9 +275,18 @@ namespace CodeImp.DoomBuilder.Geometry
Linedef prevline = nextline;
if(lines[0] == nextline) nextline = lines[1]; else nextline = lines[0];
// Check if front side changes
if((prevline.Start == nextline.Start) ||
(prevline.End == nextline.End)) nextfront = !nextfront;
// Are we allowed to trace this line again?
if(!tracecount.ContainsKey(nextline) || (tracecount[nextline] < 2))
{
// Check if front side changes
if((prevline.Start == nextline.Start) ||
(prevline.End == nextline.End)) nextfront = !nextfront;
}
else
{
// No more lines, trace ends here
path = null;
}
}
}
// Continue as long as we have not reached the start yet

View file

@ -306,6 +306,51 @@ namespace CodeImp.DoomBuilder.Map
#region ================== Methods
// This flips the linedef's vertex attachments
public void FlipVertices()
{
Vertex v = start;
start = end;
end = v;
NeedUpdate();
}
// This flips the sidedefs
public void FlipSidedefs()
{
Sidedef sd = front;
front = back;
back = sd;
}
// This makes a Line2D instance
public Line2D GetLine2D()
{
return new Line2D(start.Position, end.Position);
}
// This gets the intersection point with another line
public float GetIntersectionU(Linedef other)
{
return GetIntersectionU(other.GetLine2D());
}
// This gets the intersection point with another line
// Returns NaN when no intersection exists.
public float GetIntersectionU(Line2D otherline)
{
float u;
Line2D thisline = this.GetLine2D();
if(!otherline.GetIntersection(thisline, out u)) u = float.NaN;
return u;
}
// This returns a vector of coordinates at the given unit length
public Vector2D GetCoordinatesAt(float u)
{
return GetLine2D().GetCoordinatesAt(u);
}
// This returns a point for testing on one side
public Vector2D GetSidePoint(bool front)
{

View file

@ -470,7 +470,7 @@ namespace CodeImp.DoomBuilder.Map
}
// Returns a collection of vertices that match a marked state
public ICollection<Vertex> GetMarkedVertices(bool mark)
public List<Vertex> GetMarkedVertices(bool mark)
{
List<Vertex> list = new List<Vertex>(vertices.Count >> 1);
foreach(Vertex v in vertices) if(v.Marked == mark) list.Add(v);
@ -478,7 +478,7 @@ namespace CodeImp.DoomBuilder.Map
}
// Returns a collection of things that match a marked state
public ICollection<Thing> GetMarkedThings(bool mark)
public List<Thing> GetMarkedThings(bool mark)
{
List<Thing> list = new List<Thing>(things.Count >> 1);
foreach(Thing t in things) if(t.Marked == mark) list.Add(t);
@ -486,7 +486,7 @@ namespace CodeImp.DoomBuilder.Map
}
// Returns a collection of linedefs that match a marked state
public ICollection<Linedef> GetMarkedLinedefs(bool mark)
public List<Linedef> GetMarkedLinedefs(bool mark)
{
List<Linedef> list = new List<Linedef>(linedefs.Count >> 1);
foreach(Linedef l in linedefs) if(l.Marked == mark) list.Add(l);
@ -494,7 +494,7 @@ namespace CodeImp.DoomBuilder.Map
}
// Returns a collection of sectors that match a marked state
public ICollection<Sector> GetMarkedSectors(bool mark)
public List<Sector> GetMarkedSectors(bool mark)
{
List<Sector> list = new List<Sector>(sectors.Count >> 1);
foreach(Sector s in sectors) if(s.Marked == mark) list.Add(s);
@ -949,7 +949,30 @@ namespace CodeImp.DoomBuilder.Map
// Return result
return joinsdone;
}
// This corrects lines that have a back sidedef but no front
// sidedef by flipping them. Returns the number of flips made.
public static int FlipBackwardLinedefs(ICollection<Linedef> lines)
{
int flipsdone = 0;
// Examine all lines
foreach(Linedef l in lines)
{
// Back side but no front side?
if((l.Back != null) && (l.Front == null))
{
// Flip that linedef!
l.FlipVertices();
l.FlipSidedefs();
flipsdone++;
}
}
// Return result
return flipsdone;
}
// This splits the given lines with the given vertices
// All affected lines will be added to changedlines
// Returns the number of splits made