diff --git a/Build/Scripting/ZDoom_DECORATE.cfg b/Build/Scripting/ZDoom_DECORATE.cfg index aafc65fcd78ae3558c57ae8bb5d4e83e4ad7d9bd..d0dea09b2c60763665601dd8c99ca4fe21b8abe9 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 767349f461060e80bd1a0bb631afface6984813f..25817d507775628330f563fd8959b0867e8388db 100644 --- a/Help/gzdb/text_lumps.html +++ b/Help/gzdb/text_lumps.html @@ -22,7 +22,11 @@ </div> <div id="contents"> - <p>GZDoom Builder will automatically load data from the following lumps if they are present in the map's resources.</p> + <p>GZDoom Builder will automatically load data from the following lumps if they are present in the map's resources:</p> + <h2>DECORATE:</h2> + Actor definitions are loaded and used to poulate Things list. Extra parameters can be assigned using <a href="../gc_decoratekeys.html">special comments</a>.<br /> + DamageTypes are loaded and used in the "Damage Type" drop-down of the Edit Sector window (UDMF only). + <a name="textures" id="textures"></a><h2>TEXTURES:</h2> You can use "<strong>//$GZDB_SKIP</strong>" 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 <a href="w_imagesbrowser.html">Image Browser</a> or want to increase resource loading speed.<br /><br /> GZDoom Builder adds support for the following TEXTURES parameters: @@ -53,6 +57,15 @@ <h2>SNDSEQ:</h2> 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). + + <h2>TERRAIN:</h2> + Terrain names are loaded and used in the floor and ceiling "Terrain" drop-downs of the Edit Sector window (UDMF only). + + <h2>X11R6RGB:</h2> + Colors are loaded and used by other text parsers where appropriate. + + <h2>CVARINFO:</h2> + CVARs are loaded. Currently the editor uses them only for "DistanceCheck" DECORATE property support. <a name="modeldef" id="modeldef"></a> <h2>MODELDEF:</h2> diff --git a/Source/Core/Geometry/LinedefSide.cs b/Source/Core/Geometry/LinedefSide.cs index 58d6281b8c689645d59aa098496644b951df8790..030379e8d45e73c110afae76b91eede18a770747 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 9ed03cc8e9ea6d2b1a45cbfb6dfd4433dbbca1ba..706a8bec37e7e3c51e66f8b0b9fc1f2ebabdb80b 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<Linedef> drawnlines) + { + Dictionary<Sector, HashSet<Sidedef>> sectorsidesref = new Dictionary<Sector, HashSet<Sidedef>>(); + + // 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<Sidedef>()); + 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<Sidedef>()); + sectorsidesref[l.Back.Sector].Add(l.Back); + } + } + + // Split sectors + foreach(KeyValuePair<Sector, HashSet<Sidedef>> 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<LinedefSide> 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) /// <summary>Flips sector linedefs so they all face either inward or outward.</summary> @@ -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<Linedef, Sidedef> linenearestsideref = new Dictionary<Linedef, Sidedef>(); + Dictionary<Linedef, Sector> linesectorref = new Dictionary<Linedef, Sector>(); 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<Sidedef, Sidedef> sidenearestsideref = new Dictionary<Sidedef, Sidedef>(); + Dictionary<Sidedef, Sector> sidesectorref = new Dictionary<Sidedef, Sector>(); 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<Linedef, Sidedef> group in linenearestsideref) + // Key is dragged single-sided line, value is a sector dragged line ended up in. + foreach(KeyValuePair<Linedef, Sector> 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<Sidedef, Sidedef> group in sidenearestsideref) + // Key is outer sidedef of dragged geometry, value is a sector dragged side ended up in. + foreach(KeyValuePair<Sidedef, Sector> 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<Sidedef> sidestoexclude) + { + List<LinedefSide> 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 abbf3caa280ac4c5d2b2d8c3ad2bf22aff350a05..1b24de054adfdd9ffe8c3ecba6221152c4bcec16 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 (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 - if(!JoinChangeSidedefs(other, false, front)) return false; + // 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(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(!JoinChangeSidedefs(other, false, back)) return false; + // 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 3963225469cc0bb08a01f0000883dc98b2b180a7..f6b51dfb7af94340b131c0934656d8e6b5c180dd 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 - /// <summary>This returns a sector if given coordinates are inside one.</summary> - public Sector GetSectorByCoordinates(Vector2D pos, HashSet<Sector> sectorsToExclude) - { - foreach(Sector s in sectors) - { - if(!sectorsToExclude.Contains(s) && s.Intersect(pos)) return s; - } - return null; - } - //mxd /// <summary>This returns a sector if given coordinates are inside one.</summary> public Sector GetSectorByCoordinates(Vector2D pos, VisualBlockMap blockmap) diff --git a/Source/Core/Map/Sector.cs b/Source/Core/Map/Sector.cs index 8591a75d7df1c1c3a36f6b6c7a4e9bcef9266c88..53f9f89a4ad36de2fa88dac323dfbcc5a81e7a20 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<Vertex, bool> processed = new Dictionary<Vertex, bool>(); //mxd + HashSet<Vertex> processed = new HashSet<Vertex>(); //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 cc24717a8afbd4afa8b5f77dbfa593dbd293eab4..c3bafcbaac88ea0602646248e7ae129e1d7fc307 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 44e25dbce8ff291ae8d37a6cabd9a7d3757512db..d0c80fab10a441ef1173de2e6dd8f85be6dd9b35 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 b84e25beb0035f2939e1e8716db4980a75cef70d..dca8e83423371231838c9061b74dde3cc67a234d 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(); + // Update cached values + General.Map.Map.Update(); - //mxd. Let the plugins know - General.Editing.AcceptMode(); + //mxd. Let the plugins know + General.Editing.AcceptMode(); - // Done - Cursor.Current = Cursors.Default; - General.Map.IsChanged = true; - } + // 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 1670d26e28bad370350a51539a1818e22f7410f6..ebd9dce6e5ad9f96fca145f8d50ce74a3ebe38ff 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/DragLinedefsMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DragLinedefsMode.cs @@ -102,6 +102,10 @@ namespace CodeImp.DoomBuilder.BuilderModes ICollection<Vertex> verts = General.Map.Map.GetVerticesFromLinesMarks(true); foreach(Vertex v in verts) v.Selected = true; + //mxd. Mark moved sectors (used in Linedef.Join()) + HashSet<Sector> 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<Sector> toadjust = General.Map.Map.GetUnselectedSectorsFromLinedefs(selectedlines); + // Get new lines from linedef marks... + HashSet<Linedef> newlines = new HashSet<Linedef>(General.Map.Map.GetMarkedLinedefs(true)); + + // Marked lines were created during linedef splitting + HashSet<Linedef> changedlines = new HashSet<Linedef>(selectedlines); + changedlines.UnionWith(newlines); + + // Add sectors, which have all their linedefs selected (otherwise those would be destroyed after moving the selection) + HashSet<Sector> toadjust = General.Map.Map.GetUnselectedSectorsFromLinedefs(changedlines); // Process outer sidedefs - Tools.AdjustOuterSidedefs(toadjust, new HashSet<Linedef>(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 4235b5f8b92b205f7eddff85b8b53983aaeaeaf1..e23c506ed709ebc30876ba31bfa1ee6afb9af088 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<Linedef>(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 59f6a963b39bb005d84b1e7987a5888d531a91e0..70c466fb37f72908247a024904e98f7f3d738c8e 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<Linedef> stablelines = (!cancelled ? new HashSet<Linedef>(General.Map.Map.LinedefsFromMarkedVertices(false, true, false)) : new HashSet<Linedef>()); + foreach(Linedef l in stablelines) l.Marked = true; + + //mxd. Mark moved sectors (used in Linedef.Join()) + HashSet<Sector> draggeddsectors = (!cancelled ? General.Map.Map.GetUnselectedSectorsFromLinedefs(stablelines) : new HashSet<Sector>()); + 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<Linedef> selectedlines = new HashSet<Linedef>(General.Map.Map.LinedefsFromMarkedVertices(false, true, false)); - HashSet<Sector> toadjust = General.Map.Map.GetUnselectedSectorsFromLinedefs(selectedlines); - - // Process outer sidedefs - Tools.AdjustOuterSidedefs(toadjust, selectedlines); + // Get new lines from linedef marks... + HashSet<Linedef> newlines = new HashSet<Linedef>(General.Map.Map.GetMarkedLinedefs(true)); + + // Marked lines were created during linedef splitting + HashSet<Linedef> changedlines = new HashSet<Linedef>(stablelines); + changedlines.UnionWith(newlines); + + // Get sectors, which have all their linedefs selected (otherwise those would be destroyed after moving the selection) + HashSet<Sector> 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 b755212326309b3bd8677906c9aae73be70d4c11..81c77308ef48e6888a0fdf67f9e06b26c09097fc 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<Sector> 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 0814572763e0f39c2656b1d22350a6e782209457..04907c298a8ac73ae13dcde9ad090272d961913f 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<Sector> 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 04726c9515890645b5d346ec88c1cbf89881ef8b..b9ac6b774e10825ee5518654e26af038b0f09733 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 efdc401fbf17fb1b72537bb762d45df43a6db32f..0f07350c7770fff46c4f9f4f6ff758cf1713c635 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<Sector> 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 83ca893dca00b445f48be52cfcc38db7b30f77e4..924257e669fe268d04c125f223ea10f5f30508e7 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<Linedef> newlines = new HashSet<Linedef>(General.Map.Map.GetMarkedLinedefs(true)); + + // Marked lines were created during linedef splitting + HashSet<Linedef> changedlines = new HashSet<Linedef>(selectedlines); + changedlines.UnionWith(newlines); + // Update outer sides of the selection - HashSet<Sector> affectedsectors = new HashSet<Sector>(General.Map.Map.GetSelectedSectors(true)); - affectedsectors.UnionWith(General.Map.Map.GetUnselectedSectorsFromLinedefs(selectedlines)); - Tools.AdjustOuterSidedefs(affectedsectors, new HashSet<Linedef>(selectedlines)); + if(changedlines.Count > 0) + { + // Get affected sectors + HashSet<Sector> affectedsectors = new HashSet<Sector>(General.Map.Map.GetSelectedSectors(true)); + affectedsectors.UnionWith(General.Map.Map.GetUnselectedSectorsFromLinedefs(changedlines)); + + // Process outer sidedefs + Tools.AdjustOuterSidedefs(affectedsectors, new HashSet<Linedef>(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();