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).
This commit is contained in:
MaxED 2016-05-18 20:31:40 +00:00
parent 8ee504f9cf
commit 77611bd8d3
18 changed files with 353 additions and 174 deletions

View file

@ -308,6 +308,7 @@ keywords
A_Recoil = "A_Recoil(float force)"; A_Recoil = "A_Recoil(float force)";
A_ZoomFactor = "A_ZoomFactor[(float zoom = 1.0[, int flags = 0])]\nflags: ZOOM flags."; A_ZoomFactor = "A_ZoomFactor[(float zoom = 1.0[, int flags = 0])]\nflags: ZOOM flags.";
A_SetCrosshair = "A_SetCrosshair(int number)"; 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 //Weapon attack functions
A_Punch = "A_Punch"; 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\"]]]]]]]]]])]"; 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_3DRESTRICT;
GZF_NOPORTALS; GZF_NOPORTALS;
GZF_NO3DFLOOR; GZF_NO3DFLOOR;
//A_WeaponOffset flags
WOF_KEEPX;
WOF_KEEPY;
WOF_ADD;
} }

View file

@ -22,7 +22,11 @@
</div> </div>
<div id="contents"> <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> <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 /> 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: GZDoom Builder adds support for the following TEXTURES parameters:
@ -53,6 +57,15 @@
<h2>SNDSEQ:</h2> <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). 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> <a name="modeldef" id="modeldef"></a>
<h2>MODELDEF:</h2> <h2>MODELDEF:</h2>

View file

@ -107,7 +107,9 @@ namespace CodeImp.DoomBuilder.Geometry
//mxd. Useful when debugging... //mxd. Useful when debugging...
public override string ToString() 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 #endif

View file

@ -2157,6 +2157,63 @@ namespace CodeImp.DoomBuilder.Geometry
#endregion #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) #region ================== Linedefs (mxd)
/// <summary>Flips sector linedefs so they all face either inward or outward.</summary> /// <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 // 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 // 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) foreach(Linedef line in singlesidedlines)
{ {
// Line is now inside a sector? // Line is now inside a sector? (check from the missing side!)
Vector2D testpoint = line.GetSidePoint(line.Front == null); Sector nearest = FindPotentialSector(line, (line.Front == null), outersides);
Sector nearest = General.Map.Map.GetSectorByCoordinates(testpoint, selectedsectors);
if(nearest != null) // We can reattach our line!
{ if(nearest != null) linesectorref[line] = nearest;
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;
}
}
} }
// Find sidedefs to join outer sides // 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) foreach(Sidedef side in outersides)
{ {
// Side is inside a sector? // Side is inside a sector?
Vector2D testpoint = side.Line.GetSidePoint(side.IsFront); Sector nearest = FindPotentialSector(side.Line, side.IsFront, outersides);
Sector nearest = General.Map.Map.GetSectorByCoordinates(testpoint, selectedsectors);
sidenearestsideref[side] = null; // This side will be removed in phase 2
// We can reattach our side!
if(nearest != null) if(nearest != null)
{ {
Linedef nl = null; if(side.Sector != nearest) sidesectorref[side] = nearest; // This side will be reattached in phase 2
float distance = float.MaxValue; else sidesectorref.Remove(side); // This side is already attached where it needs to be
}
// Find nearest linedef else
foreach(Sidedef ns in nearest.Sidedefs) {
{ sidesectorref[side] = null; // This side will be removed in phase 2
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
}
}
} }
} }
// Check single-sided lines. Add new sidedefs if necessary // 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. // Key is dragged single-sided line, value is a sector dragged line ended up in.
foreach(KeyValuePair<Linedef, Sidedef> group in linenearestsideref) foreach(KeyValuePair<Linedef, Sector> group in linesectorref)
{ {
Linedef line = group.Key; Linedef line = group.Key;
// Create new sidedef // 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 // Copy props from the other side
Sidedef propssource = ((line.Front ?? line.Back) ?? group.Value); Sidedef propssource = (line.Front ?? line.Back);
propssource.CopyPropertiesTo(newside); propssource.CopyPropertiesTo(newside);
newside.RemoveUnneededTextures(true, true, true); newside.RemoveUnneededTextures(true, true, true);
newside.Other.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 // 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. // Key is outer sidedef of dragged geometry, value is a sector dragged side ended up in.
foreach(KeyValuePair<Sidedef, Sidedef> group in sidenearestsideref) foreach(KeyValuePair<Sidedef, Sector> group in sidesectorref)
{ {
if(group.Value == null) if(group.Value == null)
{ {
@ -2472,7 +2484,7 @@ namespace CodeImp.DoomBuilder.Geometry
else else
{ {
// Reattach side // Reattach side
group.Key.SetSector(group.Value.Sector); group.Key.SetSector(group.Value);
group.Key.RemoveUnneededTextures(true, true, true); group.Key.RemoveUnneededTextures(true, true, true);
} }
} }
@ -2481,6 +2493,27 @@ namespace CodeImp.DoomBuilder.Geometry
General.Map.Map.Update(); 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 #endregion
#region ================== Misc Exported Functions #region ================== Misc Exported Functions

View file

@ -1073,23 +1073,23 @@ namespace CodeImp.DoomBuilder.Map
public bool Join(Linedef other) public bool Join(Linedef other)
{ {
// Check which lines were 2 sided // Check which lines were 2 sided
bool l1was2s = ((other.Front != null) && (other.Back != null)); bool otherwas2s = ((other.Front != null) && (other.Back != null));
bool l2was2s = ((this.Front != null) && (this.Back != null)); bool thiswas2s = ((this.Front != null) && (this.Back != null));
// Get sector references // Get sector references
Sector l1fs = other.front != null ? other.front.Sector : null; Sector otherfs = (other.front != null ? other.front.Sector : null);
Sector l1bs = other.back != null ? other.back.Sector : null; Sector otherbs = (other.back != null ? other.back.Sector : null);
Sector l2fs = this.front != null ? this.front.Sector : null; Sector thisfs = (this.front != null ? this.front.Sector : null);
Sector l2bs = this.back != null ? this.back.Sector : null; Sector thisbs = (this.back != null ? this.back.Sector : null);
// This line has no sidedefs? // This line has no sidedefs?
if((l2fs == null) && (l2bs == null)) if((thisfs == null) && (thisbs == null))
{ {
// We have no sidedefs, so we have no influence // We have no sidedefs, so we have no influence
// Nothing to change on the other line // Nothing to change on the other line
} }
// Other line has no sidedefs? // 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 // The other has no sidedefs, so it has no influence
// Copy my sidedefs to the other // Copy my sidedefs to the other
@ -1110,44 +1110,44 @@ namespace CodeImp.DoomBuilder.Map
else else
{ {
// Compare front sectors // Compare front sectors
if((l1fs != null) && (l1fs == l2fs)) if((otherfs != null) && (otherfs == thisfs))
{ {
// Copy textures // Copy textures
if(other.front != null) other.front.AddTexturesTo(this.back); if(other.front != null) other.front.AddTexturesTo(this.back);
if(this.front != null) this.front.AddTexturesTo(other.back); if(this.front != null) this.front.AddTexturesTo(other.back);
// Change sidedefs // Change sidedefs?
if(!JoinChangeSidedefs(other, true, back)) return false; if(back != null && !JoinChangeSidedefs(other, true, back)) return false;
} }
// Compare back sectors // Compare back sectors
else if((l1bs != null) && (l1bs == l2bs)) else if((otherbs != null) && (otherbs == thisbs))
{ {
// Copy textures // Copy textures
if(other.back != null) other.back.AddTexturesTo(this.front); if(other.back != null) other.back.AddTexturesTo(this.front);
if(this.back != null) this.back.AddTexturesTo(other.front); if(this.back != null) this.back.AddTexturesTo(other.front);
// Change sidedefs // Change sidedefs?
if(!JoinChangeSidedefs(other, false, front)) return false; if(front != null && !JoinChangeSidedefs(other, false, front)) return false;
} }
// Compare front and back // Compare front and back
else if((l1fs != null) && (l1fs == l2bs)) else if((otherfs != null) && (otherfs == thisbs))
{ {
// Copy textures // Copy textures
if(other.front != null) other.front.AddTexturesTo(this.front); if(other.front != null) other.front.AddTexturesTo(this.front);
if(this.back != null) this.back.AddTexturesTo(other.back); if(this.back != null) this.back.AddTexturesTo(other.back);
// Change sidedefs // Change sidedefs?
if(!JoinChangeSidedefs(other, true, front)) return false; if(front != null && !JoinChangeSidedefs(other, true, front)) return false;
} }
// Compare back and front // Compare back and front
else if((l1bs != null) && (l1bs == l2fs)) else if((otherbs != null) && (otherbs == thisfs))
{ {
// Copy textures // Copy textures
if(other.back != null) other.back.AddTexturesTo(this.back); if(other.back != null) other.back.AddTexturesTo(this.back);
if(this.front != null) this.front.AddTexturesTo(other.front); if(this.front != null) this.front.AddTexturesTo(other.front);
// Change sidedefs // Change sidedefs?
if(!JoinChangeSidedefs(other, false, back)) return false; if(back != null && !JoinChangeSidedefs(other, false, back)) return false;
} }
else else
{ {
@ -1158,20 +1158,18 @@ namespace CodeImp.DoomBuilder.Map
if(this.start == other.end) if(this.start == other.end)
{ {
// Copy textures // Copy textures
if(other.back != null) other.back.AddTexturesTo(this.front);
if(this.back != null) this.back.AddTexturesTo(other.front); if(this.back != null) this.back.AddTexturesTo(other.front);
// Change sidedefs // Change sidedefs?
if(!JoinChangeSidedefs(other, false, front)) return false; if(front != null && !JoinChangeSidedefs(other, false, front)) return false;
} }
else else
{ {
// Copy textures // Copy textures
if(other.back != null) other.back.AddTexturesTo(this.back);
if(this.front != null) this.front.AddTexturesTo(other.front); if(this.front != null) this.front.AddTexturesTo(other.front);
// Change sidedefs // Change sidedefs?
if(!JoinChangeSidedefs(other, false, back)) return false; if(back != null && !JoinChangeSidedefs(other, false, back)) return false;
} }
} }
// This line single sided? // This line single sided?
@ -1180,21 +1178,27 @@ namespace CodeImp.DoomBuilder.Map
// Other line with its back to this? // Other line with its back to this?
if(other.start == this.end) if(other.start == this.end)
{ {
// Copy textures //mxd. Marked sector means other side belongs to a sector being moved...
if(other.back != null) other.back.AddTexturesTo(this.front); if(otherbs == null || !otherbs.Marked)
if(this.back != null) this.back.AddTexturesTo(other.front); {
// Copy textures
if(other.back != null) other.back.AddTexturesTo(this.front);
// Change sidedefs // Change sidedefs
if(!JoinChangeSidedefs(other, false, front)) return false; if(!JoinChangeSidedefs(other, false, front)) return false;
}
} }
else else
{ {
// Copy textures //mxd. Marked sector means other side belongs to a sector being moved...
if(other.front != null) other.front.AddTexturesTo(this.front); if(otherfs == null || !otherfs.Marked)
if(this.back != null) this.back.AddTexturesTo(other.back); {
// Copy textures
if(other.front != null) other.front.AddTexturesTo(this.front);
// Change sidedefs // Change sidedefs
if(!JoinChangeSidedefs(other, true, front)) return false; if(!JoinChangeSidedefs(other, true, front)) return false;
}
} }
} }
else else
@ -1202,33 +1206,64 @@ namespace CodeImp.DoomBuilder.Map
// This line with its back to the other? // This line with its back to the other?
if(this.start == other.end) if(this.start == other.end)
{ {
// Copy textures //mxd. Marked sector means other side belongs to a sector being moved...
if(other.back != null) other.back.AddTexturesTo(this.front); //mxd. Attach our front to other back?
if(this.back != null) this.back.AddTexturesTo(other.front); 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 // Change sidedefs (replace other back with our front)
if(!JoinChangeSidedefs(other, false, front)) return false; 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 else
{ {
// Copy textures //mxd. Marked sector means other side belongs to a sector being moved...
if(other.back != null) other.back.AddTexturesTo(this.back); //mxd. Attach our back to other back?
if(this.front != null) this.front.AddTexturesTo(other.front); 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 // Change sidedefs
if(!JoinChangeSidedefs(other, false, back)) return false; 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 // Apply single/double sided flags if the double-sided-ness changed
if( (!l1was2s && ((other.Front != null) && (other.Back != null))) || if( (!otherwas2s && (other.Front != null && other.Back != null)) ||
(l1was2s && ((other.Front == null) || (other.Back == null))) ) (otherwas2s && (other.Front == null || other.Back == null)) )
other.ApplySidedFlags(); other.ApplySidedFlags();
// Remove unneeded textures // Remove unneeded textures
if(other.front != null) other.front.RemoveUnneededTextures(!(l1was2s && l2was2s)); if(other.front != null) other.front.RemoveUnneededTextures(!(otherwas2s && thiswas2s));
if(other.back != null) other.back.RemoveUnneededTextures(!(l1was2s && l2was2s)); if(other.back != null) other.back.RemoveUnneededTextures(!(otherwas2s && thiswas2s));
} }
// If either of the two lines was selected, keep the other selected // If either of the two lines was selected, keep the other selected
@ -1287,7 +1322,13 @@ namespace CodeImp.DoomBuilder.Map
// String representation // String representation
public override string ToString() 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; return "Linedef " + listindex;
#endif
} }
#endregion #endregion

View file

@ -2167,8 +2167,7 @@ namespace CodeImp.DoomBuilder.Map
if(l1.Index == l2.Index) continue; if(l1.Index == l2.Index) continue;
// Sharing vertices? // Sharing vertices?
if((l1.End == l2.End) || if(l1.End == l2.End || l1.End == l2.Start)
(l1.End == l2.Start))
{ {
bool oppositedirection = (l1.End == l2.Start); bool oppositedirection = (l1.End == l2.Start);
bool l2marked = l2.Marked; bool l2marked = l2.Marked;
@ -2183,8 +2182,8 @@ namespace CodeImp.DoomBuilder.Map
{ {
l1.FrontInterior = l2.FrontInterior ^ oppositedirection; l1.FrontInterior = l2.FrontInterior ^ oppositedirection;
} }
// If l1 is marked as new geometry, we may need to flip it to preserve // If l1 is marked as new geometry, we may need to flip it to preserve
// orientation of the original geometry, and update its FrontInterior // orientation of the original geometry, and update its FrontInterior
else if(l1.Marked) else if(l1.Marked)
{ {
if(oppositedirection) if(oppositedirection)
@ -2209,8 +2208,7 @@ namespace CodeImp.DoomBuilder.Map
if(l1.Index == l2.Index) continue; if(l1.Index == l2.Index) continue;
// Sharing vertices? // Sharing vertices?
if((l1.Start == l2.End) || if(l1.Start == l2.End || l1.Start == l2.Start)
(l1.Start == l2.Start))
{ {
bool oppositedirection = (l1.Start == l2.End); bool oppositedirection = (l1.Start == l2.End);
bool l2marked = l2.Marked; bool l2marked = l2.Marked;
@ -2225,8 +2223,8 @@ namespace CodeImp.DoomBuilder.Map
{ {
l1.FrontInterior = l2.FrontInterior ^ oppositedirection; l1.FrontInterior = l2.FrontInterior ^ oppositedirection;
} }
// If l1 is marked as new geometry, we may need to flip it to preserve // If l1 is marked as new geometry, we may need to flip it to preserve
// orientation of the original geometry, and update its FrontInterior // orientation of the original geometry, and update its FrontInterior
else if(l1.Marked) else if(l1.Marked)
{ {
if(oppositedirection) if(oppositedirection)
@ -3098,17 +3096,6 @@ namespace CodeImp.DoomBuilder.Map
return null; 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 //mxd
/// <summary>This returns a sector if given coordinates are inside one.</summary> /// <summary>This returns a sector if given coordinates are inside one.</summary>
public Sector GetSectorByCoordinates(Vector2D pos, VisualBlockMap blockmap) public Sector GetSectorByCoordinates(Vector2D pos, VisualBlockMap blockmap)

View file

@ -568,7 +568,7 @@ namespace CodeImp.DoomBuilder.Map
// This requires the sector triangulation to be up-to-date! // This requires the sector triangulation to be up-to-date!
private RectangleF CreateBBox() private RectangleF CreateBBox()
{ {
if(sidedefs.Count == 0) return new RectangleF(); //mxd if(sidedefs.Count == 0) return new RectangleF(); //mxd
// Setup // Setup
float left = float.MaxValue; float left = float.MaxValue;
@ -576,29 +576,29 @@ namespace CodeImp.DoomBuilder.Map
float right = float.MinValue; float right = float.MinValue;
float bottom = 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) //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) foreach(Sidedef s in sidedefs)
{ {
//start... //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 < 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.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 < top) top = s.Line.Start.Position.y;
if(s.Line.Start.Position.y > bottom) bottom = 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... //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 < 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.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 < top) top = s.Line.End.Position.y;
if(s.Line.End.Position.y > bottom) bottom = 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 // String representation
public override string ToString() public override string ToString()
{ {
#if DEBUG
return "Sector " + listindex + (marked ? " (marked)" : ""); //mxd
#else
return "Sector " + listindex; return "Sector " + listindex;
#endif
} }
#endregion #endregion

View file

@ -633,6 +633,17 @@ namespace CodeImp.DoomBuilder.Map
General.Map.IsChanged = true; 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 #endregion

View file

@ -329,7 +329,11 @@ namespace CodeImp.DoomBuilder.Map
// String representation // String representation
public override string ToString() public override string ToString()
{ {
#if DEBUG
return "Vertex (" + pos + (marked ? "; marked" : "") + ")";
#else
return "Vertex (" + pos + ")"; return "Vertex (" + pos + ")";
#endif
} }
#endregion #endregion

View file

@ -419,8 +419,11 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Move selected geometry to final position // Move selected geometry to final position
MoveGeometryRelative(mousemappos - dragstartmappos, snaptogrid, snaptogridincrement, snaptonearest, snaptocardinaldirection); MoveGeometryRelative(mousemappos - dragstartmappos, snaptogrid, snaptogridincrement, snaptonearest, snaptocardinaldirection);
//mxd. Used in Linedef.Join()...
General.Map.Map.MarkSelectedSectors(true, true);
// Stitch geometry // Stitch geometry
if(snaptonearest) General.Map.Map.StitchGeometry(); General.Map.Map.StitchGeometry();
// Make corrections for backward linedefs // Make corrections for backward linedefs
MapSet.FlipBackwardLinedefs(General.Map.Map.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))); 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;
} }
} }

View file

@ -102,6 +102,10 @@ namespace CodeImp.DoomBuilder.BuilderModes
ICollection<Vertex> verts = General.Map.Map.GetVerticesFromLinesMarks(true); ICollection<Vertex> verts = General.Map.Map.GetVerticesFromLinesMarks(true);
foreach(Vertex v in verts) v.Selected = 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 // Perform normal disengage
base.OnDisengage(); base.OnDisengage();
@ -114,12 +118,21 @@ namespace CodeImp.DoomBuilder.BuilderModes
//mxd. Reattach/add/remove sidedefs only when there are no unstable lines in selection //mxd. Reattach/add/remove sidedefs only when there are no unstable lines in selection
if(unstablelines.Count == 0) if(unstablelines.Count == 0)
{ {
// Add sectors, which have all their linedefs selected // Get new lines from linedef marks...
// (otherwise those would be destroyed after moving the selection) HashSet<Linedef> newlines = new HashSet<Linedef>(General.Map.Map.GetMarkedLinedefs(true));
HashSet<Sector> toadjust = General.Map.Map.GetUnselectedSectorsFromLinedefs(selectedlines);
// 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 // 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 // If only a single linedef was selected, deselect it now

View file

@ -129,6 +129,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Process outer sidedefs // Process outer sidedefs
Tools.AdjustOuterSidedefs(toadjust, new HashSet<Linedef>(selectedlines)); Tools.AdjustOuterSidedefs(toadjust, new HashSet<Linedef>(selectedlines));
// Split outer sectors
Tools.SplitOuterSectors(selectedlines);
} }
// If only a single sector was selected, deselect it now // If only a single sector was selected, deselect it now

View file

@ -91,7 +91,15 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Select vertices from marks // Select vertices from marks
General.Map.Map.ClearSelectedVertices(); General.Map.Map.ClearSelectedVertices();
General.Map.Map.SelectMarkedVertices(true, true); 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 // Perform normal disengage
base.OnDisengage(); base.OnDisengage();
@ -99,15 +107,36 @@ namespace CodeImp.DoomBuilder.BuilderModes
if(!cancelled) if(!cancelled)
{ {
//mxd. Reattach/add/remove sidedefs only when there are no unstable lines in selection //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 // Get new lines from linedef marks...
// (otherwise those would be destroyed after moving the selection) HashSet<Linedef> newlines = new HashSet<Linedef>(General.Map.Map.GetMarkedLinedefs(true));
HashSet<Linedef> selectedlines = new HashSet<Linedef>(General.Map.Map.LinedefsFromMarkedVertices(false, true, false));
HashSet<Sector> toadjust = General.Map.Map.GetUnselectedSectorsFromLinedefs(selectedlines);
// Process outer sidedefs // Marked lines were created during linedef splitting
Tools.AdjustOuterSidedefs(toadjust, selectedlines); 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 // If only a single vertex was selected, deselect it now

View file

@ -248,6 +248,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update cached values // Update cached values
General.Map.Map.Update(); General.Map.Map.Update();
//mxd. Outer sectors may require some splittin...
Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true));
// Edit new sectors? // Edit new sectors?
List<Sector> newsectors = General.Map.Map.GetMarkedSectors(true); List<Sector> newsectors = General.Map.Map.GetMarkedSectors(true);
if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0)) if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0))

View file

@ -767,6 +767,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update cached values // Update cached values
General.Map.Map.Update(); General.Map.Map.Update();
//mxd. Outer sectors may require some splittin...
Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true));
// Edit new sectors? // Edit new sectors?
List<Sector> newsectors = General.Map.Map.GetMarkedSectors(true); List<Sector> newsectors = General.Map.Map.GetMarkedSectors(true);
if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0)) if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0))

View file

@ -92,7 +92,7 @@ namespace CodeImp.DoomBuilder.BuilderModes
General.Map.UndoRedo.CreateUndo("Grid draw"); General.Map.UndoRedo.CreateUndo("Grid draw");
// Make an analysis and show info // 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 word = adjectives[new Random().Next(adjectives.Length - 1)];
string a = (word[0] == 'u' ? "an " : "a "); string a = (word[0] == 'u' ? "an " : "a ");
@ -114,6 +114,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Clear selection // Clear selection
General.Map.Map.ClearAllSelected(); General.Map.Map.ClearAllSelected();
//mxd. Outer sectors may require some splittin...
Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true));
// Edit new sectors? // Edit new sectors?
if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0)) if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0))
General.Interface.ShowEditSectors(newsectors); General.Interface.ShowEditSectors(newsectors);

View file

@ -385,6 +385,9 @@ namespace CodeImp.DoomBuilder.BuilderModes
// Update cached values // Update cached values
General.Map.Map.Update(); General.Map.Map.Update();
//mxd. Outer sectors may require some splittin...
Tools.SplitOuterSectors(General.Map.Map.GetMarkedLinedefs(true));
// Edit new sectors? // Edit new sectors?
List<Sector> newsectors = General.Map.Map.GetMarkedSectors(true); List<Sector> newsectors = General.Map.Map.GetMarkedSectors(true);
if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0)) if(BuilderPlug.Me.EditNewSector && (newsectors.Count > 0))

View file

@ -1480,23 +1480,42 @@ namespace CodeImp.DoomBuilder.BuilderModes
} }
// Stitch geometry // Stitch geometry
if(snaptonearest) General.Map.Map.StitchGeometry(); General.Map.Map.StitchGeometry();
// Make corrections for backward linedefs // Make corrections for backward linedefs
MapSet.FlipBackwardLinedefs(General.Map.Map.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 //mxd. Reattach/add/remove sidedefs only when there are no unstable lines in selection
if(unstablelines.Count == 0) 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 // Update outer sides of the selection
HashSet<Sector> affectedsectors = new HashSet<Sector>(General.Map.Map.GetSelectedSectors(true)); if(changedlines.Count > 0)
affectedsectors.UnionWith(General.Map.Map.GetUnselectedSectorsFromLinedefs(selectedlines)); {
Tools.AdjustOuterSidedefs(affectedsectors, new HashSet<Linedef>(selectedlines)); // 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 // Update cached values
General.Map.Data.UpdateUsedTextures(); General.Map.Data.UpdateUsedTextures();
General.Map.Map.Update(); General.Map.Map.Update();