From 77611bd8d3083dc4443448c2ca7391f7b9f59571 Mon Sep 17 00:00:00 2001 From: MaxED Date: Wed, 18 May 2016 20:31:40 +0000 Subject: [PATCH] Added: sectors are now split into multiple sectors when their shape is divided into several closed shapes by drawing new geometry or dragging existing geometry using Edit Selection and Drag Geometry modes. Fixed: in some cases sidedefs belonging to linedefs, which were moved on top of existing linedefs, were incorrectly reassigned when applying Edit Selection and Drag Geometry modes. Fixed: Tag Explorer update fix from R2630 was accidentally placed in an UDMF-only if-block. Updated ZDoom_DECORATE.cfg (A_WeaponOffset). Updated documentation ("(G)ZDoom text lumps support" page). --- Build/Scripting/ZDoom_DECORATE.cfg | 5 + Help/gzdb/text_lumps.html | 15 +- Source/Core/Geometry/LinedefSide.cs | 4 +- Source/Core/Geometry/Tools.cs | 165 +++++++++++------- Source/Core/Map/Linedef.cs | 141 +++++++++------ Source/Core/Map/MapSet.cs | 25 +-- Source/Core/Map/Sector.cs | 16 +- Source/Core/Map/Sidedef.cs | 11 ++ Source/Core/Map/Vertex.cs | 4 + .../ClassicModes/DragGeometryMode.cs | 25 +-- .../ClassicModes/DragLinedefsMode.cs | 21 ++- .../ClassicModes/DragSectorsMode.cs | 3 + .../ClassicModes/DragVerticesMode.cs | 45 ++++- .../ClassicModes/DrawCurveMode.cs | 3 + .../ClassicModes/DrawGeometryMode.cs | 3 + .../BuilderModes/ClassicModes/DrawGridMode.cs | 5 +- .../ClassicModes/DrawRectangleMode.cs | 3 + .../ClassicModes/EditSelectionMode.cs | 33 +++- 18 files changed, 353 insertions(+), 174 deletions(-) diff --git a/Build/Scripting/ZDoom_DECORATE.cfg b/Build/Scripting/ZDoom_DECORATE.cfg index aafc65fc..d0dea09b 100644 --- a/Build/Scripting/ZDoom_DECORATE.cfg +++ b/Build/Scripting/ZDoom_DECORATE.cfg @@ -308,6 +308,7 @@ keywords A_Recoil = "A_Recoil(float force)"; A_ZoomFactor = "A_ZoomFactor[(float zoom = 1.0[, int flags = 0])]\nflags: ZOOM flags."; A_SetCrosshair = "A_SetCrosshair(int number)"; + A_WeaponOffset = "A_WeaponOffset[(float x = 0[, float y = 32[, int flags = 0])]\nflags: WOF flags."; //Weapon attack functions A_Punch = "A_Punch"; A_Saw = "A_Saw[(str fullsound = \"weapons/sawfull\"[, str hitsound = \"weapons/sawhit\"[, int damage = 0[, str pufftype = \"BulletPuff\"[, int flags = 0[, float range = 65.0[, float spread_xy = 2.8125[, float spread_z = 0.0[, float lifesteal = 0.0[, int lifestealmax = 0[, str armorbonustype = \"ArmorBonus\"]]]]]]]]]])]"; @@ -1343,4 +1344,8 @@ constants GZF_3DRESTRICT; GZF_NOPORTALS; GZF_NO3DFLOOR; +//A_WeaponOffset flags + WOF_KEEPX; + WOF_KEEPY; + WOF_ADD; } diff --git a/Help/gzdb/text_lumps.html b/Help/gzdb/text_lumps.html index 767349f4..25817d50 100644 --- a/Help/gzdb/text_lumps.html +++ b/Help/gzdb/text_lumps.html @@ -22,7 +22,11 @@
-

GZDoom Builder will automatically load data from the following lumps if they are present in the map's resources.

+

GZDoom Builder will automatically load data from the following lumps if they are present in the map's resources:

+

DECORATE:

+ Actor definitions are loaded and used to poulate Things list. Extra parameters can be assigned using special comments.
+ DamageTypes are loaded and used in the "Damage Type" drop-down of the Edit Sector window (UDMF only). +

TEXTURES:

You can use "//$GZDB_SKIP" special comment to abort parsing of the current file. Useful if you don't want textures from certain files or parts of files to show up in the Image Browser or want to increase resource loading speed.

GZDoom Builder adds support for the following TEXTURES parameters: @@ -53,6 +57,15 @@

SNDSEQ:

Sound Sequence and Sound Sequence Group definitions are loaded and can be selected in the "Sound sequence" drop-down of the Edit Sector window (UDMF only). + +

TERRAIN:

+ Terrain names are loaded and used in the floor and ceiling "Terrain" drop-downs of the Edit Sector window (UDMF only). + +

X11R6RGB:

+ Colors are loaded and used by other text parsers where appropriate. + +

CVARINFO:

+ CVARs are loaded. Currently the editor uses them only for "DistanceCheck" DECORATE property support.

MODELDEF:

diff --git a/Source/Core/Geometry/LinedefSide.cs b/Source/Core/Geometry/LinedefSide.cs index 58d6281b..030379e8 100644 --- a/Source/Core/Geometry/LinedefSide.cs +++ b/Source/Core/Geometry/LinedefSide.cs @@ -107,7 +107,9 @@ namespace CodeImp.DoomBuilder.Geometry //mxd. Useful when debugging... public override string ToString() { - return line + " (" + (front ? "front" : "back") + ")"; + Sidedef side = (front ? line.Front : line.Back); + Sector sector = (side != null ? side.Sector : null); + return line + " (" + (front ? "front" : "back") + ")" + (sector != null ? ", Sector " + sector.Index : ""); } #endif diff --git a/Source/Core/Geometry/Tools.cs b/Source/Core/Geometry/Tools.cs index 9ed03cc8..706a8bec 100644 --- a/Source/Core/Geometry/Tools.cs +++ b/Source/Core/Geometry/Tools.cs @@ -2157,6 +2157,63 @@ namespace CodeImp.DoomBuilder.Geometry #endregion + #region ================== Sectors (mxd) + + public static void SplitOuterSectors(IEnumerable drawnlines) + { + Dictionary> sectorsidesref = new Dictionary>(); + + // Create drawn lines per sector collection + foreach(Linedef l in drawnlines) + { + if(l.Front != null && l.Front.Sector != null) + { + if(!sectorsidesref.ContainsKey(l.Front.Sector)) sectorsidesref.Add(l.Front.Sector, new HashSet()); + sectorsidesref[l.Front.Sector].Add(l.Front); + } + + if(l.Back != null && l.Back.Sector != null) + { + if(!sectorsidesref.ContainsKey(l.Back.Sector)) sectorsidesref.Add(l.Back.Sector, new HashSet()); + sectorsidesref[l.Back.Sector].Add(l.Back); + } + } + + // Split sectors + foreach(KeyValuePair> group in sectorsidesref) + { + // Sector has all sides selected? + if(group.Key.Sidedefs.Count == group.Value.Count) + { + group.Key.Marked = true; // Sometimes those are not marked... + continue; + } + + // Process all sides + foreach(Sidedef side in group.Value) + { + // Sector was already split? + if(side.Sector != group.Key) continue; + + // Find drawing interior + List sides = FindPotentialSectorAt(side.Line, side.IsFront); + + // Number of potential sides fewer than the sector has? + if(sides != null && sides.Count > 0 && sides.Count < group.Key.Sidedefs.Count) + { + Sector newsector = MakeSector(sides, null, false); + if(newsector != null) + { + newsector.UpdateCache(); + group.Key.UpdateCache(); + } + } + } + } + } + + #endregion + #region ================== Linedefs (mxd) /// Flips sector linedefs so they all face either inward or outward. @@ -2349,91 +2406,46 @@ namespace CodeImp.DoomBuilder.Geometry // These steps must be done in 2 phases, otherwise we'll end up getting sidedefs modified in a previous adjustment loop step // Find sidedefs to join singlesided lines - Dictionary linenearestsideref = new Dictionary(); + Dictionary linesectorref = new Dictionary(); foreach(Linedef line in singlesidedlines) { - // Line is now inside a sector? - Vector2D testpoint = line.GetSidePoint(line.Front == null); - Sector nearest = General.Map.Map.GetSectorByCoordinates(testpoint, selectedsectors); + // Line is now inside a sector? (check from the missing side!) + Sector nearest = FindPotentialSector(line, (line.Front == null), outersides); - if(nearest != null) - { - Linedef nl = null; - float distance = float.MaxValue; - - // Find nearest linedef - foreach(Sidedef ns in nearest.Sidedefs) - { - float d = ns.Line.SafeDistanceToSq(testpoint, true); - if(d < distance) - { - // This one is closer - nl = ns.Line; - distance = d; - } - } - - // Find nearest sidedef - if(nl != null) - { - Sidedef ns = (nl.SideOfLine(testpoint) <= 0 ? nl.Front : nl.Back); - if(ns != null) linenearestsideref[line] = ns; - } - } + // We can reattach our line! + if(nearest != null) linesectorref[line] = nearest; } // Find sidedefs to join outer sides - Dictionary sidenearestsideref = new Dictionary(); + Dictionary sidesectorref = new Dictionary(); foreach(Sidedef side in outersides) { // Side is inside a sector? - Vector2D testpoint = side.Line.GetSidePoint(side.IsFront); - Sector nearest = General.Map.Map.GetSectorByCoordinates(testpoint, selectedsectors); - sidenearestsideref[side] = null; // This side will be removed in phase 2 + Sector nearest = FindPotentialSector(side.Line, side.IsFront, outersides); + // We can reattach our side! if(nearest != null) { - Linedef nl = null; - float distance = float.MaxValue; - - // Find nearest linedef - foreach(Sidedef ns in nearest.Sidedefs) - { - float d = ns.Line.SafeDistanceToSq(testpoint, true); - if(d < distance) - { - // This one is closer - nl = ns.Line; - distance = d; - } - } - - // Find nearest sidedef - if(nl != null) - { - Sidedef ns = (nl.SideOfLine(testpoint) <= 0 ? nl.Front : nl.Back); - if(ns != null && ns.Sector != null) - { - if(side.Sector != ns.Sector) - sidenearestsideref[side] = ns; // This side will be reattached in phase 2 - else - sidenearestsideref.Remove(side); // This side is already attached where it needs to be - } - } + if(side.Sector != nearest) sidesectorref[side] = nearest; // This side will be reattached in phase 2 + else sidesectorref.Remove(side); // This side is already attached where it needs to be + } + else + { + sidesectorref[side] = null; // This side will be removed in phase 2 } } // Check single-sided lines. Add new sidedefs if necessary - // Key is dragged single-sided line, value is the nearset side of a sector dragged line ended up in. - foreach(KeyValuePair group in linenearestsideref) + // Key is dragged single-sided line, value is a sector dragged line ended up in. + foreach(KeyValuePair group in linesectorref) { Linedef line = group.Key; // Create new sidedef - Sidedef newside = General.Map.Map.CreateSidedef(line, line.Front == null, group.Value.Sector); + Sidedef newside = General.Map.Map.CreateSidedef(line, line.Front == null, group.Value); // Copy props from the other side - Sidedef propssource = ((line.Front ?? line.Back) ?? group.Value); + Sidedef propssource = (line.Front ?? line.Back); propssource.CopyPropertiesTo(newside); newside.RemoveUnneededTextures(true, true, true); newside.Other.RemoveUnneededTextures(true, true, true); @@ -2450,8 +2462,8 @@ namespace CodeImp.DoomBuilder.Geometry } // Check outer sidedefs. Remove/change sector if necessary - // Key is outer sidedef of dragged geometry, value is nearset side of a sector dragged side ended up in. - foreach(KeyValuePair group in sidenearestsideref) + // Key is outer sidedef of dragged geometry, value is a sector dragged side ended up in. + foreach(KeyValuePair group in sidesectorref) { if(group.Value == null) { @@ -2472,7 +2484,7 @@ namespace CodeImp.DoomBuilder.Geometry else { // Reattach side - group.Key.SetSector(group.Value.Sector); + group.Key.SetSector(group.Value); group.Key.RemoveUnneededTextures(true, true, true); } } @@ -2481,6 +2493,27 @@ namespace CodeImp.DoomBuilder.Geometry General.Map.Map.Update(); } + //mxd + private static Sector FindPotentialSector(Linedef line, bool front, HashSet sidestoexclude) + { + List sectorsides = FindPotentialSectorAt(line, front); + if(sectorsides == null) return null; + + // Filter outersides from the list, proceed only if all sectorsides reference the same sector + Sector result = null; + foreach(LinedefSide sectorside in sectorsides) + { + Sidedef target = (sectorside.Front ? sectorside.Line.Front : sectorside.Line.Back); + if(target != null && !sidestoexclude.Contains(target)) + { + if(result == null) result = target.Sector; + else if(result != target.Sector) return null; // Fial... + } + } + + return result; + } + #endregion #region ================== Misc Exported Functions diff --git a/Source/Core/Map/Linedef.cs b/Source/Core/Map/Linedef.cs index abbf3caa..1b24de05 100644 --- a/Source/Core/Map/Linedef.cs +++ b/Source/Core/Map/Linedef.cs @@ -1073,23 +1073,23 @@ namespace CodeImp.DoomBuilder.Map public bool Join(Linedef other) { // Check which lines were 2 sided - bool l1was2s = ((other.Front != null) && (other.Back != null)); - bool l2was2s = ((this.Front != null) && (this.Back != null)); + bool otherwas2s = ((other.Front != null) && (other.Back != null)); + bool thiswas2s = ((this.Front != null) && (this.Back != null)); // Get sector references - Sector l1fs = other.front != null ? other.front.Sector : null; - Sector l1bs = other.back != null ? other.back.Sector : null; - Sector l2fs = this.front != null ? this.front.Sector : null; - Sector l2bs = this.back != null ? this.back.Sector : null; + Sector otherfs = (other.front != null ? other.front.Sector : null); + Sector otherbs = (other.back != null ? other.back.Sector : null); + Sector thisfs = (this.front != null ? this.front.Sector : null); + Sector thisbs = (this.back != null ? this.back.Sector : null); // This line has no sidedefs? - if((l2fs == null) && (l2bs == null)) + if((thisfs == null) && (thisbs == 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)) + else if((otherfs == null) && (otherbs == null)) { // The other has no sidedefs, so it has no influence // Copy my sidedefs to the other @@ -1110,44 +1110,44 @@ namespace CodeImp.DoomBuilder.Map else { // Compare front sectors - if((l1fs != null) && (l1fs == l2fs)) + if((otherfs != null) && (otherfs == thisfs)) { // Copy textures if(other.front != null) other.front.AddTexturesTo(this.back); if(this.front != null) this.front.AddTexturesTo(other.back); - // Change sidedefs - if(!JoinChangeSidedefs(other, true, back)) return false; + // Change sidedefs? + if(back != null && !JoinChangeSidedefs(other, true, back)) return false; } // Compare back sectors - else if((l1bs != null) && (l1bs == l2bs)) + else if((otherbs != null) && (otherbs == thisbs)) { // Copy textures if(other.back != null) other.back.AddTexturesTo(this.front); if(this.back != null) this.back.AddTexturesTo(other.front); - // Change sidedefs - if(!JoinChangeSidedefs(other, false, front)) return false; + // Change sidedefs? + if(front != null && !JoinChangeSidedefs(other, false, front)) return false; } // Compare front and back - else if((l1fs != null) && (l1fs == l2bs)) + else if((otherfs != null) && (otherfs == thisbs)) { // Copy textures if(other.front != null) other.front.AddTexturesTo(this.front); if(this.back != null) this.back.AddTexturesTo(other.back); - // Change sidedefs - if(!JoinChangeSidedefs(other, true, front)) return false; + // Change sidedefs? + if(front != null && !JoinChangeSidedefs(other, true, front)) return false; } // Compare back and front - else if((l1bs != null) && (l1bs == l2fs)) + else if((otherbs != null) && (otherbs == thisfs)) { // Copy textures if(other.back != null) other.back.AddTexturesTo(this.back); if(this.front != null) this.front.AddTexturesTo(other.front); - // Change sidedefs - if(!JoinChangeSidedefs(other, false, back)) return false; + // Change sidedefs? + if(back != null && !JoinChangeSidedefs(other, false, back)) return false; } else { @@ -1158,20 +1158,18 @@ namespace CodeImp.DoomBuilder.Map if(this.start == other.end) { // Copy textures - if(other.back != null) other.back.AddTexturesTo(this.front); if(this.back != null) this.back.AddTexturesTo(other.front); - // Change sidedefs - if(!JoinChangeSidedefs(other, false, front)) return false; + // Change sidedefs? + if(front != null && !JoinChangeSidedefs(other, false, front)) return false; } else { // Copy textures - if(other.back != null) other.back.AddTexturesTo(this.back); if(this.front != null) this.front.AddTexturesTo(other.front); - // Change sidedefs - if(!JoinChangeSidedefs(other, false, back)) return false; + // Change sidedefs? + if(back != null && !JoinChangeSidedefs(other, false, back)) return false; } } // This line single sided? @@ -1180,21 +1178,27 @@ namespace CodeImp.DoomBuilder.Map // Other line with its back to this? if(other.start == this.end) { - // Copy textures - if(other.back != null) other.back.AddTexturesTo(this.front); - if(this.back != null) this.back.AddTexturesTo(other.front); + //mxd. Marked sector means other side belongs to a sector being moved... + if(otherbs == null || !otherbs.Marked) + { + // Copy textures + if(other.back != null) other.back.AddTexturesTo(this.front); - // Change sidedefs - if(!JoinChangeSidedefs(other, false, front)) return false; + // Change sidedefs + if(!JoinChangeSidedefs(other, false, front)) return false; + } } else { - // Copy textures - if(other.front != null) other.front.AddTexturesTo(this.front); - if(this.back != null) this.back.AddTexturesTo(other.back); + //mxd. Marked sector means other side belongs to a sector being moved... + if(otherfs == null || !otherfs.Marked) + { + // Copy textures + if(other.front != null) other.front.AddTexturesTo(this.front); - // Change sidedefs - if(!JoinChangeSidedefs(other, true, front)) return false; + // Change sidedefs + if(!JoinChangeSidedefs(other, true, front)) return false; + } } } else @@ -1202,33 +1206,64 @@ namespace CodeImp.DoomBuilder.Map // This line with its back to the other? if(this.start == other.end) { - // Copy textures - if(other.back != null) other.back.AddTexturesTo(this.front); - if(this.back != null) this.back.AddTexturesTo(other.front); + //mxd. Marked sector means other side belongs to a sector being moved... + //mxd. Attach our front to other back? + if(otherbs == null || !otherbs.Marked) + { + // Copy textures + if(other.back != null) other.back.AddTexturesTo(this.front); + if(this.back != null) this.back.AddTexturesTo(other.front); - // Change sidedefs - if(!JoinChangeSidedefs(other, false, front)) return false; + // Change sidedefs (replace other back with our front) + if(front != null && !JoinChangeSidedefs(other, false, front)) return false; + } + //mxd. Attach our back to other front? + else if(otherfs == null || !otherfs.Marked) + { + // Copy textures + if(other.front != null) other.front.AddTexturesTo(this.back); + if(this.front != null) this.front.AddTexturesTo(other.back); + + // Change sidedefs (replace other back with our front) + if(back != null && !JoinChangeSidedefs(other, true, back)) return false; + } } + // Both lines face the same way else { - // Copy textures - if(other.back != null) other.back.AddTexturesTo(this.back); - if(this.front != null) this.front.AddTexturesTo(other.front); + //mxd. Marked sector means other side belongs to a sector being moved... + //mxd. Attach our back to other back? + if(otherbs == null || !otherbs.Marked) + { + // Copy textures + if(other.back != null) other.back.AddTexturesTo(this.back); + if(this.front != null) this.front.AddTexturesTo(other.front); - // Change sidedefs - if(!JoinChangeSidedefs(other, false, back)) return false; + // Change sidedefs + if(back != null && !JoinChangeSidedefs(other, false, back)) return false; + } + //mxd. Attach our front to other front? + else if(otherfs == null || !otherfs.Marked) + { + // Copy textures + if(other.front != null) other.front.AddTexturesTo(this.front); + if(this.back != null) this.back.AddTexturesTo(other.back); + + // Change sidedefs + if(front != null && !JoinChangeSidedefs(other, true, front)) return false; + } } } } // Apply single/double sided flags if the double-sided-ness changed - if( (!l1was2s && ((other.Front != null) && (other.Back != null))) || - (l1was2s && ((other.Front == null) || (other.Back == null))) ) + if( (!otherwas2s && (other.Front != null && other.Back != null)) || + (otherwas2s && (other.Front == null || other.Back == null)) ) other.ApplySidedFlags(); // Remove unneeded textures - if(other.front != null) other.front.RemoveUnneededTextures(!(l1was2s && l2was2s)); - if(other.back != null) other.back.RemoveUnneededTextures(!(l1was2s && l2was2s)); + if(other.front != null) other.front.RemoveUnneededTextures(!(otherwas2s && thiswas2s)); + if(other.back != null) other.back.RemoveUnneededTextures(!(otherwas2s && thiswas2s)); } // If either of the two lines was selected, keep the other selected @@ -1287,7 +1322,13 @@ namespace CodeImp.DoomBuilder.Map // String representation public override string ToString() { +#if DEBUG + string starttext = (start != null ? " (" + start : string.Empty); + string endtext = (end != null ? ", " + end + ")" : string.Empty); + return "Linedef " + listindex + (marked ? " (marked)" : "") + starttext + endtext; //mxd +#else return "Linedef " + listindex; +#endif } #endregion diff --git a/Source/Core/Map/MapSet.cs b/Source/Core/Map/MapSet.cs index 39632254..f6b51dfb 100644 --- a/Source/Core/Map/MapSet.cs +++ b/Source/Core/Map/MapSet.cs @@ -2167,8 +2167,7 @@ namespace CodeImp.DoomBuilder.Map if(l1.Index == l2.Index) continue; // Sharing vertices? - if((l1.End == l2.End) || - (l1.End == l2.Start)) + if(l1.End == l2.End || l1.End == l2.Start) { bool oppositedirection = (l1.End == l2.Start); bool l2marked = l2.Marked; @@ -2183,8 +2182,8 @@ namespace CodeImp.DoomBuilder.Map { l1.FrontInterior = l2.FrontInterior ^ oppositedirection; } - // If l1 is marked as new geometry, we may need to flip it to preserve - // orientation of the original geometry, and update its FrontInterior + // If l1 is marked as new geometry, we may need to flip it to preserve + // orientation of the original geometry, and update its FrontInterior else if(l1.Marked) { if(oppositedirection) @@ -2209,8 +2208,7 @@ namespace CodeImp.DoomBuilder.Map if(l1.Index == l2.Index) continue; // Sharing vertices? - if((l1.Start == l2.End) || - (l1.Start == l2.Start)) + if(l1.Start == l2.End || l1.Start == l2.Start) { bool oppositedirection = (l1.Start == l2.End); bool l2marked = l2.Marked; @@ -2225,8 +2223,8 @@ namespace CodeImp.DoomBuilder.Map { l1.FrontInterior = l2.FrontInterior ^ oppositedirection; } - // If l1 is marked as new geometry, we may need to flip it to preserve - // orientation of the original geometry, and update its FrontInterior + // If l1 is marked as new geometry, we may need to flip it to preserve + // orientation of the original geometry, and update its FrontInterior else if(l1.Marked) { if(oppositedirection) @@ -3098,17 +3096,6 @@ namespace CodeImp.DoomBuilder.Map return null; } - //mxd - /// This returns a sector if given coordinates are inside one. - public Sector GetSectorByCoordinates(Vector2D pos, HashSet sectorsToExclude) - { - foreach(Sector s in sectors) - { - if(!sectorsToExclude.Contains(s) && s.Intersect(pos)) return s; - } - return null; - } - //mxd /// This returns a sector if given coordinates are inside one. public Sector GetSectorByCoordinates(Vector2D pos, VisualBlockMap blockmap) diff --git a/Source/Core/Map/Sector.cs b/Source/Core/Map/Sector.cs index 8591a75d..53f9f89a 100644 --- a/Source/Core/Map/Sector.cs +++ b/Source/Core/Map/Sector.cs @@ -568,7 +568,7 @@ namespace CodeImp.DoomBuilder.Map // This requires the sector triangulation to be up-to-date! private RectangleF CreateBBox() { - if(sidedefs.Count == 0) return new RectangleF(); //mxd + if(sidedefs.Count == 0) return new RectangleF(); //mxd // Setup float left = float.MaxValue; @@ -576,29 +576,29 @@ namespace CodeImp.DoomBuilder.Map float right = float.MinValue; float bottom = float.MinValue; - Dictionary processed = new Dictionary(); //mxd + HashSet processed = new HashSet(); //mxd //mxd. This way bbox will be created even if triangulation failed (sector with 2 or less sidedefs and 2 vertices) foreach(Sidedef s in sidedefs) { //start... - if(!processed.ContainsKey(s.Line.Start)) + if(!processed.Contains(s.Line.Start)) { if(s.Line.Start.Position.x < left) left = s.Line.Start.Position.x; if(s.Line.Start.Position.x > right) right = s.Line.Start.Position.x; if(s.Line.Start.Position.y < top) top = s.Line.Start.Position.y; if(s.Line.Start.Position.y > bottom) bottom = s.Line.Start.Position.y; - processed.Add(s.Line.Start, false); + processed.Add(s.Line.Start); } //end... - if(!processed.ContainsKey(s.Line.End)) + if(!processed.Contains(s.Line.End)) { if(s.Line.End.Position.x < left) left = s.Line.End.Position.x; if(s.Line.End.Position.x > right) right = s.Line.End.Position.x; if(s.Line.End.Position.y < top) top = s.Line.End.Position.y; if(s.Line.End.Position.y > bottom) bottom = s.Line.End.Position.y; - processed.Add(s.Line.End, false); + processed.Add(s.Line.End); } } @@ -791,7 +791,11 @@ namespace CodeImp.DoomBuilder.Map // String representation public override string ToString() { +#if DEBUG + return "Sector " + listindex + (marked ? " (marked)" : ""); //mxd +#else return "Sector " + listindex; +#endif } #endregion diff --git a/Source/Core/Map/Sidedef.cs b/Source/Core/Map/Sidedef.cs index cc24717a..c3bafcba 100644 --- a/Source/Core/Map/Sidedef.cs +++ b/Source/Core/Map/Sidedef.cs @@ -633,6 +633,17 @@ namespace CodeImp.DoomBuilder.Map General.Map.IsChanged = true; } + + //mxd. String representation + public override string ToString() + { +#if DEBUG + return "Sidedef " + listindex + (marked ? " (marked)" : "") + " (Line " + linedef.Index + (linedef.Marked ? " (marked)" : "") + ", Sector " + sector.Index + (sector.Marked ? " (marked)" : "") + ")"; +#else + return "Sidedef " + listindex; +#endif + } + #endregion diff --git a/Source/Core/Map/Vertex.cs b/Source/Core/Map/Vertex.cs index 44e25dbc..d0c80fab 100644 --- a/Source/Core/Map/Vertex.cs +++ b/Source/Core/Map/Vertex.cs @@ -329,7 +329,11 @@ namespace CodeImp.DoomBuilder.Map // String representation public override string ToString() { +#if DEBUG + return "Vertex (" + pos + (marked ? "; marked" : "") + ")"; +#else return "Vertex (" + pos + ")"; +#endif } #endregion diff --git a/Source/Plugins/BuilderModes/ClassicModes/DragGeometryMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DragGeometryMode.cs index b84e25be..dca8e834 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/DragGeometryMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DragGeometryMode.cs @@ -419,8 +419,11 @@ namespace CodeImp.DoomBuilder.BuilderModes // Move selected geometry to final position MoveGeometryRelative(mousemappos - dragstartmappos, snaptogrid, snaptogridincrement, snaptonearest, snaptocardinaldirection); + //mxd. Used in Linedef.Join()... + General.Map.Map.MarkSelectedSectors(true, true); + // Stitch geometry - if(snaptonearest) General.Map.Map.StitchGeometry(); + General.Map.Map.StitchGeometry(); // Make corrections for backward linedefs MapSet.FlipBackwardLinedefs(General.Map.Map.Linedefs); @@ -516,17 +519,17 @@ namespace CodeImp.DoomBuilder.BuilderModes s.CeilSlopeOffset = -Vector3D.DotProduct(s.CeilSlope, new Vector3D(center + offset, ceiling.GetZ(center))); } } - - // Update cached values - General.Map.Map.Update(); - - //mxd. Let the plugins know - General.Editing.AcceptMode(); - - // Done - Cursor.Current = Cursors.Default; - General.Map.IsChanged = true; } + + // Update cached values + General.Map.Map.Update(); + + //mxd. Let the plugins know + General.Editing.AcceptMode(); + + // Done + Cursor.Current = Cursors.Default; + General.Map.IsChanged = true; } } diff --git a/Source/Plugins/BuilderModes/ClassicModes/DragLinedefsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DragLinedefsMode.cs index 1670d26e..ebd9dce6 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/DragLinedefsMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DragLinedefsMode.cs @@ -102,6 +102,10 @@ namespace CodeImp.DoomBuilder.BuilderModes ICollection verts = General.Map.Map.GetVerticesFromLinesMarks(true); foreach(Vertex v in verts) v.Selected = true; + //mxd. Mark moved sectors (used in Linedef.Join()) + HashSet draggeddsectors = General.Map.Map.GetUnselectedSectorsFromLinedefs(selectedlines); + foreach(Sector s in draggeddsectors) s.Marked = true; + // Perform normal disengage base.OnDisengage(); @@ -114,12 +118,21 @@ namespace CodeImp.DoomBuilder.BuilderModes //mxd. Reattach/add/remove sidedefs only when there are no unstable lines in selection if(unstablelines.Count == 0) { - // Add sectors, which have all their linedefs selected - // (otherwise those would be destroyed after moving the selection) - HashSet toadjust = General.Map.Map.GetUnselectedSectorsFromLinedefs(selectedlines); + // Get new lines from linedef marks... + HashSet newlines = new HashSet(General.Map.Map.GetMarkedLinedefs(true)); + + // Marked lines were created during linedef splitting + HashSet changedlines = new HashSet(selectedlines); + changedlines.UnionWith(newlines); + + // Add sectors, which have all their linedefs selected (otherwise those would be destroyed after moving the selection) + HashSet toadjust = General.Map.Map.GetUnselectedSectorsFromLinedefs(changedlines); // Process outer sidedefs - Tools.AdjustOuterSidedefs(toadjust, new HashSet(selectedlines)); + Tools.AdjustOuterSidedefs(toadjust, changedlines); + + // Split outer sectors + Tools.SplitOuterSectors(changedlines); } // If only a single linedef was selected, deselect it now diff --git a/Source/Plugins/BuilderModes/ClassicModes/DragSectorsMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DragSectorsMode.cs index 4235b5f8..e23c506e 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/DragSectorsMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DragSectorsMode.cs @@ -129,6 +129,9 @@ namespace CodeImp.DoomBuilder.BuilderModes // Process outer sidedefs Tools.AdjustOuterSidedefs(toadjust, new HashSet(selectedlines)); + + // Split outer sectors + Tools.SplitOuterSectors(selectedlines); } // If only a single sector was selected, deselect it now diff --git a/Source/Plugins/BuilderModes/ClassicModes/DragVerticesMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DragVerticesMode.cs index 59f6a963..70c466fb 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/DragVerticesMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DragVerticesMode.cs @@ -91,7 +91,15 @@ namespace CodeImp.DoomBuilder.BuilderModes // Select vertices from marks General.Map.Map.ClearSelectedVertices(); General.Map.Map.SelectMarkedVertices(true, true); - + + //mxd. Mark stable lines now (marks will be carried to split lines by MapSet.StitchGeometry()) + HashSet stablelines = (!cancelled ? new HashSet(General.Map.Map.LinedefsFromMarkedVertices(false, true, false)) : new HashSet()); + foreach(Linedef l in stablelines) l.Marked = true; + + //mxd. Mark moved sectors (used in Linedef.Join()) + HashSet draggeddsectors = (!cancelled ? General.Map.Map.GetUnselectedSectorsFromLinedefs(stablelines) : new HashSet()); + foreach(Sector s in draggeddsectors) s.Marked = true; + // Perform normal disengage base.OnDisengage(); @@ -99,15 +107,36 @@ namespace CodeImp.DoomBuilder.BuilderModes if(!cancelled) { //mxd. Reattach/add/remove sidedefs only when there are no unstable lines in selection - if(selectedverts.Count > 1 && unstablelines.Count == 0) + if(stablelines.Count > 0 && unstablelines.Count == 0) { - // Add sectors, which have all their linedefs selected - // (otherwise those would be destroyed after moving the selection) - HashSet selectedlines = new HashSet(General.Map.Map.LinedefsFromMarkedVertices(false, true, false)); - HashSet toadjust = General.Map.Map.GetUnselectedSectorsFromLinedefs(selectedlines); + // Get new lines from linedef marks... + HashSet newlines = new HashSet(General.Map.Map.GetMarkedLinedefs(true)); - // Process outer sidedefs - Tools.AdjustOuterSidedefs(toadjust, selectedlines); + // Marked lines were created during linedef splitting + HashSet changedlines = new HashSet(stablelines); + changedlines.UnionWith(newlines); + + // Get sectors, which have all their linedefs selected (otherwise those would be destroyed after moving the selection) + HashSet toadjust = General.Map.Map.GetUnselectedSectorsFromLinedefs(changedlines); + + if(changedlines.Count > 0) + { + // Process outer sidedefs + Tools.AdjustOuterSidedefs(toadjust, changedlines); + + // Split outer sectors + Tools.SplitOuterSectors(changedlines); + + // Additional verts may've been created + if(selectedverts.Count > 1) + { + foreach(Linedef l in changedlines) + { + l.Start.Selected = true; + l.End.Selected = true; + } + } + } } // If only a single vertex was selected, deselect it now diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs index b7552123..81c77308 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DrawCurveMode.cs @@ -248,6 +248,9 @@ namespace CodeImp.DoomBuilder.BuilderModes // Update cached values General.Map.Map.Update(); + //mxd. Outer sectors may require some splittin... + Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true)); + // Edit new sectors? List newsectors = General.Map.Map.GetMarkedSectors(true); if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0)) diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs index 08145727..04907c29 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs @@ -767,6 +767,9 @@ namespace CodeImp.DoomBuilder.BuilderModes // Update cached values General.Map.Map.Update(); + //mxd. Outer sectors may require some splittin... + Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true)); + // Edit new sectors? List newsectors = General.Map.Map.GetMarkedSectors(true); if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0)) diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs index 04726c95..b9ac6b77 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DrawGridMode.cs @@ -92,7 +92,7 @@ namespace CodeImp.DoomBuilder.BuilderModes General.Map.UndoRedo.CreateUndo("Grid draw"); // Make an analysis and show info - string[] adjectives = new[] { "gloomy", "sad", "unhappy", "lonely", "troubled", "depressed", "heartsick", "glum", "pessimistic", "bitter", "downcast" }; // aaand my english vocabulary ends here :) + string[] adjectives = { "gloomy", "sad", "unhappy", "lonely", "troubled", "depressed", "heartsick", "glum", "pessimistic", "bitter", "downcast" }; // aaand my english vocabulary ends here :) string word = adjectives[new Random().Next(adjectives.Length - 1)]; string a = (word[0] == 'u' ? "an " : "a "); @@ -114,6 +114,9 @@ namespace CodeImp.DoomBuilder.BuilderModes // Clear selection General.Map.Map.ClearAllSelected(); + //mxd. Outer sectors may require some splittin... + Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true)); + // Edit new sectors? if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0)) General.Interface.ShowEditSectors(newsectors); diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs index efdc401f..0f07350c 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DrawRectangleMode.cs @@ -385,6 +385,9 @@ namespace CodeImp.DoomBuilder.BuilderModes // Update cached values General.Map.Map.Update(); + //mxd. Outer sectors may require some splittin... + Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true)); + // Edit new sectors? List newsectors = General.Map.Map.GetMarkedSectors(true); if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0)) diff --git a/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs b/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs index 83ca893d..924257e6 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/EditSelectionMode.cs @@ -1480,23 +1480,42 @@ namespace CodeImp.DoomBuilder.BuilderModes } // Stitch geometry - if(snaptonearest) General.Map.Map.StitchGeometry(); + General.Map.Map.StitchGeometry(); // Make corrections for backward linedefs MapSet.FlipBackwardLinedefs(General.Map.Map.Linedefs); + // Snap to map format accuracy + General.Map.Map.SnapAllToAccuracy(General.Map.UDMF && usepreciseposition); + //mxd. Reattach/add/remove sidedefs only when there are no unstable lines in selection if(unstablelines.Count == 0) { + // Update cached values + General.Map.Map.Update(); + + // Get new lines from linedef marks... + HashSet newlines = new HashSet(General.Map.Map.GetMarkedLinedefs(true)); + + // Marked lines were created during linedef splitting + HashSet changedlines = new HashSet(selectedlines); + changedlines.UnionWith(newlines); + // Update outer sides of the selection - HashSet affectedsectors = new HashSet(General.Map.Map.GetSelectedSectors(true)); - affectedsectors.UnionWith(General.Map.Map.GetUnselectedSectorsFromLinedefs(selectedlines)); - Tools.AdjustOuterSidedefs(affectedsectors, new HashSet(selectedlines)); + if(changedlines.Count > 0) + { + // Get affected sectors + HashSet affectedsectors = new HashSet(General.Map.Map.GetSelectedSectors(true)); + affectedsectors.UnionWith(General.Map.Map.GetUnselectedSectorsFromLinedefs(changedlines)); + + // Process outer sidedefs + Tools.AdjustOuterSidedefs(affectedsectors, new HashSet(changedlines)); + + // Split outer sectors + Tools.SplitOuterSectors(changedlines); + } } - // Snap to map format accuracy - General.Map.Map.SnapAllToAccuracy(General.Map.UDMF && usepreciseposition); - // Update cached values General.Map.Data.UpdateUsedTextures(); General.Map.Map.Update();