mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2025-01-18 22:41:46 +00:00
Changed drawing behavior so that drawn lines are not corrected to clockwise orientation
This commit is contained in:
parent
65521d1ea6
commit
91b76bcb5b
5 changed files with 92 additions and 44 deletions
|
@ -76,6 +76,27 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
foreach(EarClipVertex v in p) base.AddLast(v);
|
foreach(EarClipVertex v in p) base.AddLast(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This calculates the area
|
||||||
|
public float CalculateArea()
|
||||||
|
{
|
||||||
|
// Multiply the x coordinate of each vertex by the y coordinate of the next vertex.
|
||||||
|
// Multiply the y coordinate of each vertex by the x coordinate of the next vertex.
|
||||||
|
// Subtract these.
|
||||||
|
float result = 0.0f;
|
||||||
|
int firstcalculated = 0;
|
||||||
|
LinkedListNode<EarClipVertex> n1 = base.First;
|
||||||
|
while(firstcalculated < 2)
|
||||||
|
{
|
||||||
|
LinkedListNode<EarClipVertex> n2 = n1.Next ?? base.First;
|
||||||
|
float a = n1.Value.Position.x * n2.Value.Position.y;
|
||||||
|
float b = n1.Value.Position.y * n2.Value.Position.x;
|
||||||
|
result += a - b;
|
||||||
|
n1 = n2;
|
||||||
|
if(n2 == base.First) firstcalculated++;
|
||||||
|
}
|
||||||
|
return Math.Abs(result / 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
// This creates a bounding box from the outer polygon
|
// This creates a bounding box from the outer polygon
|
||||||
public RectangleF CreateBBox()
|
public RectangleF CreateBBox()
|
||||||
{
|
{
|
||||||
|
|
|
@ -827,6 +827,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
List<Vertex> newverts = new List<Vertex>();
|
List<Vertex> newverts = new List<Vertex>();
|
||||||
List<Vertex> intersectverts = new List<Vertex>();
|
List<Vertex> intersectverts = new List<Vertex>();
|
||||||
List<Linedef> newlines = new List<Linedef>();
|
List<Linedef> newlines = new List<Linedef>();
|
||||||
|
List<bool> newlinescw = new List<bool>();
|
||||||
List<Linedef> oldlines = new List<Linedef>(General.Map.Map.Linedefs);
|
List<Linedef> oldlines = new List<Linedef>(General.Map.Map.Linedefs);
|
||||||
List<Sidedef> insidesides = new List<Sidedef>();
|
List<Sidedef> insidesides = new List<Sidedef>();
|
||||||
List<Vertex> mergeverts = new List<Vertex>();
|
List<Vertex> mergeverts = new List<Vertex>();
|
||||||
|
@ -839,7 +840,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
if(points.Count > 0)
|
if(points.Count > 0)
|
||||||
{
|
{
|
||||||
/***************************************************\
|
/***************************************************\
|
||||||
STEP 1: Create the new geometry
|
Create the drawing
|
||||||
\***************************************************/
|
\***************************************************/
|
||||||
|
|
||||||
// Make first vertex
|
// Make first vertex
|
||||||
|
@ -923,6 +924,10 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
// Join merge vertices so that overlapping vertices in the draw become one.
|
// Join merge vertices so that overlapping vertices in the draw become one.
|
||||||
MapSet.JoinVertices(mergeverts, mergeverts, false, MapSet.STITCH_DISTANCE);
|
MapSet.JoinVertices(mergeverts, mergeverts, false, MapSet.STITCH_DISTANCE);
|
||||||
|
|
||||||
|
/***************************************************\
|
||||||
|
Find a way to close the drawing
|
||||||
|
\***************************************************/
|
||||||
|
|
||||||
// We prefer a closed polygon, because then we can determine the interior properly
|
// We prefer a closed polygon, because then we can determine the interior properly
|
||||||
// Check if the two ends of the polygon are closed
|
// Check if the two ends of the polygon are closed
|
||||||
bool drawingclosed = false;
|
bool drawingclosed = false;
|
||||||
|
@ -1089,14 +1094,13 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
MapSet.SplitLinesByVertices(newlines, mergeverts, MapSet.STITCH_DISTANCE, null);
|
MapSet.SplitLinesByVertices(newlines, mergeverts, MapSet.STITCH_DISTANCE, null);
|
||||||
|
|
||||||
/***************************************************\
|
/***************************************************\
|
||||||
STEP 2: Merge the new geometry
|
Determine drawing interior
|
||||||
\***************************************************/
|
\***************************************************/
|
||||||
|
|
||||||
// In step 3 we will make sectors on the front sides and join sectors on the
|
// In step 3 we will make sectors on the interior sides and join sectors on the
|
||||||
// back sides, but because the user could have drawn counterclockwise or just
|
// exterior sides, but because the user could have drawn counterclockwise or just
|
||||||
// some weird polygon this could result in problems. The following code adjusts
|
// some weird polygon. The following code figures out the interior side of all
|
||||||
// the direction of all new lines so that their front (right) side is facing
|
// new lines.
|
||||||
// the interior of the new drawn polygon.
|
|
||||||
map.Update(true, false);
|
map.Update(true, false);
|
||||||
foreach(Linedef ld in newlines)
|
foreach(Linedef ld in newlines)
|
||||||
{
|
{
|
||||||
|
@ -1109,7 +1113,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
EarClipPolygon pathpoly = tracepath.MakePolygon(true);
|
EarClipPolygon pathpoly = tracepath.MakePolygon(true);
|
||||||
|
|
||||||
// Check if the front of the line is outside the polygon
|
// Check if the front of the line is outside the polygon
|
||||||
if(!pathpoly.Intersect(ld.GetSidePoint(true)))
|
if((pathpoly.CalculateArea() > 0.001f) && !pathpoly.Intersect(ld.GetSidePoint(true)))
|
||||||
{
|
{
|
||||||
// Now trace from the back side of the line to see if
|
// Now trace from the back side of the line to see if
|
||||||
// the back side lies in the interior. I don't want to
|
// the back side lies in the interior. I don't want to
|
||||||
|
@ -1123,19 +1127,29 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
tracepath = new LinedefTracePath(pathlines);
|
tracepath = new LinedefTracePath(pathlines);
|
||||||
pathpoly = tracepath.MakePolygon(true);
|
pathpoly = tracepath.MakePolygon(true);
|
||||||
|
|
||||||
// Check if the back of the line is inside the polygon
|
// Check if the front of the line is inside the polygon
|
||||||
if(pathpoly.Intersect(ld.GetSidePoint(false)))
|
ld.FrontInterior = (pathpoly.CalculateArea() < 0.001f) || pathpoly.Intersect(ld.GetSidePoint(true));
|
||||||
{
|
}
|
||||||
// We must flip this linedef to face the interior
|
else
|
||||||
ld.FlipVertices();
|
{
|
||||||
ld.FlipSidedefs();
|
ld.FrontInterior = true;
|
||||||
ld.UpdateCache();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ld.FrontInterior = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ld.FrontInterior = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************\
|
||||||
|
Merge the new geometry
|
||||||
|
\***************************************************/
|
||||||
|
|
||||||
// Mark only the vertices that should be merged
|
// Mark only the vertices that should be merged
|
||||||
map.ClearMarkedVertices(false);
|
map.ClearMarkedVertices(false);
|
||||||
foreach(Vertex v in mergeverts) v.Marked = true;
|
foreach(Vertex v in mergeverts) v.Marked = true;
|
||||||
|
@ -1157,11 +1171,11 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
if(!ld.IsDisposed) oldlines.Add(ld);
|
if(!ld.IsDisposed) oldlines.Add(ld);
|
||||||
|
|
||||||
/***************************************************\
|
/***************************************************\
|
||||||
STEP 3: Join and create new sectors
|
Join and create new sectors
|
||||||
\***************************************************/
|
\***************************************************/
|
||||||
|
|
||||||
// The code below atempts to create sectors on the front sides of the drawn
|
// The code below atempts to create sectors on the interior sides of the drawn
|
||||||
// geometry and joins sectors on the back sides of the drawn geometry.
|
// geometry and joins sectors on the other sides of the drawn geometry.
|
||||||
// This code does not change any geometry, it only makes/updates sidedefs.
|
// This code does not change any geometry, it only makes/updates sidedefs.
|
||||||
bool sidescreated = false;
|
bool sidescreated = false;
|
||||||
bool[] frontsdone = new bool[newlines.Count];
|
bool[] frontsdone = new bool[newlines.Count];
|
||||||
|
@ -1170,11 +1184,11 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
{
|
{
|
||||||
Linedef ld = newlines[i];
|
Linedef ld = newlines[i];
|
||||||
|
|
||||||
// Front not marked as done?
|
// Interior not done yet?
|
||||||
if(!frontsdone[i])
|
if((ld.FrontInterior && !frontsdone[i]) || (!ld.FrontInterior && !backsdone[i]))
|
||||||
{
|
{
|
||||||
// Find a way to create a sector here
|
// Find a way to create a sector here
|
||||||
List<LinedefSide> sectorlines = Tools.FindPotentialSectorAt(ld, true);
|
List<LinedefSide> sectorlines = Tools.FindPotentialSectorAt(ld, ld.FrontInterior);
|
||||||
if(sectorlines != null)
|
if(sectorlines != null)
|
||||||
{
|
{
|
||||||
sidescreated = true;
|
sidescreated = true;
|
||||||
|
@ -1216,15 +1230,14 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Back not marked as done?
|
// Exterior not done yet?
|
||||||
if(!backsdone[i])
|
if((ld.FrontInterior && !backsdone[i]) || (!ld.FrontInterior && !frontsdone[i]))
|
||||||
{
|
{
|
||||||
// Find a way to create a sector here
|
// Find a way to create a sector here
|
||||||
List<LinedefSide> sectorlines = Tools.FindPotentialSectorAt(ld, false);
|
List<LinedefSide> sectorlines = Tools.FindPotentialSectorAt(ld, !ld.FrontInterior);
|
||||||
if(sectorlines != null)
|
if(sectorlines != null)
|
||||||
{
|
{
|
||||||
// We don't always want to create a new sector on the back sides
|
// Check if any of the surrounding lines originally have sidedefs we can join
|
||||||
// So first check if any of the surrounding lines originally have sidedefs
|
|
||||||
Sidedef joinsidedef = null;
|
Sidedef joinsidedef = null;
|
||||||
foreach(LinedefSide ls in sectorlines)
|
foreach(LinedefSide ls in sectorlines)
|
||||||
{
|
{
|
||||||
|
@ -1267,6 +1280,10 @@ namespace CodeImp.DoomBuilder.Geometry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***************************************************\
|
||||||
|
Corrections and clean up
|
||||||
|
\***************************************************/
|
||||||
|
|
||||||
// Make corrections for backward linedefs
|
// Make corrections for backward linedefs
|
||||||
MapSet.FlipBackwardLinedefs(newlines);
|
MapSet.FlipBackwardLinedefs(newlines);
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
private int activate;
|
private int activate;
|
||||||
private int tag;
|
private int tag;
|
||||||
private int[] args;
|
private int[] args;
|
||||||
|
private bool frontinterior; // for drawing only
|
||||||
|
|
||||||
// Clone
|
// Clone
|
||||||
private int serializedindex;
|
private int serializedindex;
|
||||||
|
@ -101,6 +102,7 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
public RectangleF Rect { get { return rect; } }
|
public RectangleF Rect { get { return rect; } }
|
||||||
public int[] Args { get { return args; } }
|
public int[] Args { get { return args; } }
|
||||||
internal int SerializedIndex { get { return serializedindex; } set { serializedindex = value; } }
|
internal int SerializedIndex { get { return serializedindex; } set { serializedindex = value; } }
|
||||||
|
internal bool FrontInterior { get { return frontinterior; } set { frontinterior = value; } }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -489,6 +491,9 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
startvertexlistitem = endvertexlistitem;
|
startvertexlistitem = endvertexlistitem;
|
||||||
endvertexlistitem = vn;
|
endvertexlistitem = vn;
|
||||||
|
|
||||||
|
// For drawing, the interior now lies on the other side
|
||||||
|
frontinterior = !frontinterior;
|
||||||
|
|
||||||
// Update required (angle changed)
|
// Update required (angle changed)
|
||||||
NeedUpdate();
|
NeedUpdate();
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
|
|
|
@ -1886,22 +1886,24 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Not the same line?
|
// Not the same line?
|
||||||
if(l1 != l2)
|
if(l1 != l2)
|
||||||
{
|
{
|
||||||
bool flipresult = (l1.End == l2.Start);
|
bool oppositedirection = (l1.End == l2.Start);
|
||||||
|
|
||||||
// Merge these two linedefs
|
// Merge these two linedefs
|
||||||
//while(lines.Remove(l1));
|
|
||||||
//l1.Join(l2);
|
|
||||||
while(lines.Remove(l2)) ;
|
while(lines.Remove(l2)) ;
|
||||||
l2.Join(l1);
|
l2.Join(l1);
|
||||||
|
|
||||||
// The flipping is purely a cosmetic to preserve orientation
|
// The flipping is purely a cosmetic to preserve orientation
|
||||||
// when drawing new lines over older lines
|
// when drawing new lines over older lines
|
||||||
if(flipresult)
|
if(oppositedirection)
|
||||||
{
|
{
|
||||||
l1.FlipVertices();
|
l1.FlipVertices();
|
||||||
l1.FlipSidedefs();
|
l1.FlipSidedefs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Direction is now the same, so the interior side is also the same
|
||||||
|
// We have to copy the interior side to preserve this for drawing
|
||||||
|
l1.FrontInterior = l2.FrontInterior;
|
||||||
|
|
||||||
joinsdone++;
|
joinsdone++;
|
||||||
joined = true;
|
joined = true;
|
||||||
break;
|
break;
|
||||||
|
@ -1922,22 +1924,24 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// Not the same line?
|
// Not the same line?
|
||||||
if(l1 != l2)
|
if(l1 != l2)
|
||||||
{
|
{
|
||||||
bool flipresult = (l1.End == l2.Start);
|
bool oppositedirection = (l1.Start == l2.End);
|
||||||
|
|
||||||
// Merge these two linedefs
|
// Merge these two linedefs
|
||||||
//while(lines.Remove(l1));
|
|
||||||
//l1.Join(l2);
|
|
||||||
while(lines.Remove(l2)) ;
|
while(lines.Remove(l2)) ;
|
||||||
l2.Join(l1);
|
l2.Join(l1);
|
||||||
|
|
||||||
// The flipping is purely a cosmetic to preserve orientation
|
// The flipping is purely a cosmetic to preserve orientation
|
||||||
// when drawing new lines over older lines
|
// when drawing new lines over older lines
|
||||||
if(flipresult)
|
if(oppositedirection)
|
||||||
{
|
{
|
||||||
l1.FlipVertices();
|
l1.FlipVertices();
|
||||||
l1.FlipSidedefs();
|
l1.FlipSidedefs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Direction is now the same, so the interior side is also the same
|
||||||
|
// We have to copy the interior side to preserve this for drawing
|
||||||
|
l1.FrontInterior = l2.FrontInterior;
|
||||||
|
|
||||||
joinsdone++;
|
joinsdone++;
|
||||||
joined = true;
|
joined = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -291,6 +291,14 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
// This removes textures that are not required
|
// This removes textures that are not required
|
||||||
public void RemoveUnneededTextures(bool removemiddle, bool force)
|
public void RemoveUnneededTextures(bool removemiddle, bool force)
|
||||||
{
|
{
|
||||||
|
// The middle texture can be removed regardless of any sector tag or linedef action
|
||||||
|
if(!MiddleRequired() && removemiddle)
|
||||||
|
{
|
||||||
|
this.texnamemid = "-";
|
||||||
|
this.longtexnamemid = MapSet.EmptyLongName;
|
||||||
|
General.Map.IsChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the line or sectors have no action or tags because
|
// Check if the line or sectors have no action or tags because
|
||||||
// if they do, any texture on this side could be needed
|
// if they do, any texture on this side could be needed
|
||||||
if(((linedef.Tag <= 0) && (linedef.Action == 0) && (sector.Tag <= 0) &&
|
if(((linedef.Tag <= 0) && (linedef.Action == 0) && (sector.Tag <= 0) &&
|
||||||
|
@ -304,13 +312,6 @@ namespace CodeImp.DoomBuilder.Map
|
||||||
General.Map.IsChanged = true;
|
General.Map.IsChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!MiddleRequired() && removemiddle)
|
|
||||||
{
|
|
||||||
this.texnamemid = "-";
|
|
||||||
this.longtexnamemid = MapSet.EmptyLongName;
|
|
||||||
General.Map.IsChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!LowRequired())
|
if(!LowRequired())
|
||||||
{
|
{
|
||||||
this.texnamelow = "-";
|
this.texnamelow = "-";
|
||||||
|
|
Loading…
Reference in a new issue