From 7e29ba30998a2013cbf9ab005bd9df4073adac07 Mon Sep 17 00:00:00 2001 From: biwa <6475593+biwa@users.noreply.github.com> Date: Mon, 14 Aug 2023 23:00:42 +0200 Subject: [PATCH] 3D Floor Mode: fixed an issue where new control sectors could not be created if any sector's bounding box completely encompassed the Control Sector Area --- .../Plugins/3DFloorMode/ControlSectorArea.cs | 107 +++++++++++++----- 1 file changed, 81 insertions(+), 26 deletions(-) diff --git a/Source/Plugins/3DFloorMode/ControlSectorArea.cs b/Source/Plugins/3DFloorMode/ControlSectorArea.cs index 5d1f5e26..ceaf8a4f 100644 --- a/Source/Plugins/3DFloorMode/ControlSectorArea.cs +++ b/Source/Plugins/3DFloorMode/ControlSectorArea.cs @@ -317,14 +317,15 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode List blocks = blockmap.GetLineBlocks( new Vector2D(x + 1, y - 1), new Vector2D(x + gridsize - 1, y - gridsize + 1) - ); - - // The way our blockmap is built and queried we will always get exactly one block - if (blocks[0].Sectors.Count == 0) - { - positions.Add(new Vector2D(x + margin, y - margin)); - numsectors--; - } + ); + + // The way our blockmap is built and queried we will always get exactly one block + // Try the next position of the current one is occupied by another sector + if (blocks[0].Sectors.Any(s => SectorInNewControlSectorSpace(x, y, s))) + continue; + + positions.Add(new Vector2D(x + margin, y - margin)); + numsectors--; if (numsectors == 0) return positions; @@ -354,30 +355,84 @@ namespace CodeImp.DoomBuilder.ThreeDFloorMode List blocks = blockmap.GetLineBlocks( new Vector2D(x + 1, y - 1), new Vector2D(x + gridsize - 1, y - gridsize + 1) - ); - - // The way our blockmap is built and queried we will always get exactly one block - if (blocks[0].Sectors.Count == 0) - { - Point p = new Point(x + margin, y - margin); - - dv.Add(SectorVertex(p.X, p.Y)); - dv.Add(SectorVertex(p.X + BuilderPlug.Me.ControlSectorArea.SectorSize, p.Y)); - dv.Add(SectorVertex(p.X + BuilderPlug.Me.ControlSectorArea.SectorSize, p.Y - BuilderPlug.Me.ControlSectorArea.SectorSize)); - dv.Add(SectorVertex(p.X, p.Y - BuilderPlug.Me.ControlSectorArea.SectorSize)); - dv.Add(SectorVertex(p.X, p.Y)); - - numsectors--; - - if (numsectors == 0) - return dv; - } + ); + + // The way our blockmap is built and queried we will always get exactly one block + // Try the next position of the current one is occupied by another sector + if (blocks[0].Sectors.Any(s => SectorInNewControlSectorSpace(x, y, s))) + continue; + + Point p = new Point(x + margin, y - margin); + + dv.Add(SectorVertex(p.X, p.Y)); + dv.Add(SectorVertex(p.X + BuilderPlug.Me.ControlSectorArea.SectorSize, p.Y)); + dv.Add(SectorVertex(p.X + BuilderPlug.Me.ControlSectorArea.SectorSize, p.Y - BuilderPlug.Me.ControlSectorArea.SectorSize)); + dv.Add(SectorVertex(p.X, p.Y - BuilderPlug.Me.ControlSectorArea.SectorSize)); + dv.Add(SectorVertex(p.X, p.Y)); + + numsectors--; + + if (numsectors == 0) + return dv; } } throw new NoSpaceInCSAException("No space left for control sectors"); } + /// + /// Checks if the given sector and position for the new control sector intersect in any way. + /// + /// Leftmost X position of the new control sector space + /// Topmost Y position of the new control sector space + /// The sector to check against + /// true if there's an intersection, false if there isn't + private bool SectorInNewControlSectorSpace(int x, int y, Sector sector) + { + RectangleF rect = new RectangleF(x + 1, y - 1, gridsize - 2, gridsize - 2); + HashSet sectorvertices = new HashSet(); + + // Any of the sector's sidedef's linedef's vertices inside the new control sector's space? + foreach (Sidedef sd in sector.Sidedefs) + { + sectorvertices.Add(sd.Line.Start); + sectorvertices.Add(sd.Line.End); + } + + foreach (Vertex v in sectorvertices) + if (rect.Contains((float)v.Position.x, (float)v.Position.y)) + return true; + + // Any of the new vertex positions in the sector? + Vector2D[] points = new Vector2D[] + { + new Vector2D(x + 1, y - 1), + new Vector2D(x + gridsize - 1, y - 1), + new Vector2D(x + gridsize - 1, y + gridsize + 1), + new Vector2D(x + 1, y + gridsize + 1) + }; + + foreach (Vector2D v in points) + if (sector.Intersect(v)) + return true; + + // Any of the new lines and the sector's lines overlapping? + Line2D[] lines = new Line2D[] + { + new Line2D(points[0], points[1]), + new Line2D(points[1], points[2]), + new Line2D(points[2], points[3]), + new Line2D(points[3], points[0]) + }; + + foreach (Sidedef sd in sector.Sidedefs) + foreach (Line2D line in lines) + if (Line2D.GetIntersection(sd.Line.Line, line)) + return true; + + return false; + } + public bool Inside(float x, float y) { return Inside(new Vector2D(x, y));