mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-26 22:01:45 +00:00
Increased performance when creating new map geometry (for example, when applying changes made by "Draw Line", "Draw Rectangle" etc. actions).
This commit is contained in:
parent
9df67e8b22
commit
b1b3dda28b
8 changed files with 163 additions and 100 deletions
|
@ -130,15 +130,14 @@ namespace CodeImp.DoomBuilder.Actions
|
|||
public static string GetShortcutKeyDesc(int key)
|
||||
{
|
||||
KeysConverter conv = new KeysConverter();
|
||||
int ctrl, button;
|
||||
string ctrlprefix = "";
|
||||
|
||||
// When key is 0, then return an empty string
|
||||
if(key == 0) return "";
|
||||
|
||||
// Split the key in Control and Button
|
||||
ctrl = key & ((int)Keys.Control | (int)Keys.Shift | (int)Keys.Alt);
|
||||
button = key & ~((int)Keys.Control | (int)Keys.Shift | (int)Keys.Alt);
|
||||
int ctrl = key & ((int)Keys.Control | (int)Keys.Shift | (int)Keys.Alt);
|
||||
int button = key & ~((int)Keys.Control | (int)Keys.Shift | (int)Keys.Alt);
|
||||
|
||||
// When the button is a control key, then remove the control itsself
|
||||
if((button == (int)Keys.ControlKey) ||
|
||||
|
|
|
@ -1540,9 +1540,10 @@ namespace CodeImp.DoomBuilder
|
|||
// This outputs log information
|
||||
public static void WriteLogLine(string line)
|
||||
{
|
||||
#if DEBUG
|
||||
// Output to console
|
||||
Console.WriteLine(line);
|
||||
|
||||
#endif
|
||||
// Write to log file
|
||||
try { File.AppendAllText(logfile, line + Environment.NewLine); }
|
||||
catch(Exception) { }
|
||||
|
@ -1551,8 +1552,10 @@ namespace CodeImp.DoomBuilder
|
|||
// This outputs log information
|
||||
public static void WriteLog(string text)
|
||||
{
|
||||
#if DEBUG
|
||||
// Output to console
|
||||
Console.Write(text);
|
||||
#endif
|
||||
|
||||
// Write to log file
|
||||
try { File.AppendAllText(logfile, text); }
|
||||
|
|
|
@ -125,7 +125,8 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
u_ray = ((v2.x - v1.x) * (v1.y - y3) - (v2.y - v1.y) * (v1.x - x3)) / div;
|
||||
|
||||
// Return if intersecting
|
||||
return (u_ray >= 0.0f) && (u_ray <= 1.0f) && (u_line >= 0.0f) && (u_line <= 1.0f);
|
||||
if (u_ray <= 0.0f || u_ray >= 1.0f || u_line <= 0.0f || u_line >= 1.0f) return false; //mxd
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -910,17 +910,25 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
// Check if any other lines intersect this line
|
||||
List<float> intersections = new List<float>();
|
||||
Line2D measureline = ld.Line;
|
||||
foreach(Linedef ld2 in map.Linedefs)
|
||||
{
|
||||
// Intersecting?
|
||||
// We only keep the unit length from the start of the line and
|
||||
// do the real splitting later, when all intersections are known
|
||||
Dictionary<Linedef, bool> processed = new Dictionary<Linedef, bool>(); //mxd
|
||||
|
||||
//mxd
|
||||
foreach (Sector s in map.Sectors) {
|
||||
//line intersects with sector's bounding box?
|
||||
if((MapSet.GetCSFieldBits(measureline.v1, s.BBox) & MapSet.GetCSFieldBits(measureline.v2, s.BBox)) == 0) {
|
||||
foreach (Sidedef side in s.Sidedefs) {
|
||||
if(processed.ContainsKey(side.Line)) continue;
|
||||
if(side.Line == ld) continue;
|
||||
|
||||
float u;
|
||||
if(ld2.Line.GetIntersection(measureline, out u))
|
||||
{
|
||||
if(!float.IsNaN(u) && (u > 0.0f) && (u < 1.0f) && (ld2 != ld))
|
||||
if(side.Line.Line.GetIntersection(measureline, out u)) {
|
||||
if(float.IsNaN(u) || (u < 0.0f) || (u > 1.0f)) continue;
|
||||
intersections.Add(u);
|
||||
}
|
||||
|
||||
processed.Add(side.Line, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the intersections
|
||||
|
@ -960,7 +968,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
|
||||
// Join merge vertices so that overlapping vertices in the draw become one.
|
||||
map.BeginAddRemove();
|
||||
MapSet.JoinVertices(mergeverts, mergeverts, false, MapSet.STITCH_DISTANCE);
|
||||
MapSet.JoinVertices(mergeverts, MapSet.STITCH_DISTANCE); //mxd
|
||||
map.EndAddRemove();
|
||||
|
||||
/***************************************************\
|
||||
|
@ -1187,7 +1195,7 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
drawingclosed = true;
|
||||
|
||||
// Join merge vertices so that overlapping vertices in the draw become one.
|
||||
MapSet.JoinVertices(mergeverts, mergeverts, false, MapSet.STITCH_DISTANCE);
|
||||
MapSet.JoinVertices(mergeverts, MapSet.STITCH_DISTANCE); //mxd
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1417,7 +1425,8 @@ namespace CodeImp.DoomBuilder.Geometry
|
|||
for(int i = newlines.Count - 1; i >= 0; i--)
|
||||
{
|
||||
// Remove the line if it has no sides
|
||||
if((newlines[i].Front == null) && (newlines[i].Back == null)) newlines[i].Dispose();
|
||||
if((newlines[i].Front != null) || (newlines[i].Back != null)) continue;
|
||||
newlines[i].Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace CodeImp.DoomBuilder.Map
|
|||
public Size Size { get { return size; } }
|
||||
public RectangleF Range { get { return range; } }
|
||||
public int BlockSize { get { return blocksize; } }
|
||||
internal BE[,] Map { get { return blockmap; } }
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#region ================== Namespaces
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using CodeImp.DoomBuilder.Geometry;
|
||||
using CodeImp.DoomBuilder.Windows;
|
||||
|
@ -1907,7 +1906,7 @@ namespace CodeImp.DoomBuilder.Map
|
|||
foreach(Linedef l in lines)
|
||||
{
|
||||
// Check the cs field bits
|
||||
if ((GetCSFieldBits(l.Start, ref area) & GetCSFieldBits(l.End, ref area)) == 0)
|
||||
if ((GetCSFieldBits(l.Start.Position, area) & GetCSFieldBits(l.End.Position, area)) == 0)
|
||||
{
|
||||
// The line could be in the area
|
||||
newlines.Add(l);
|
||||
|
@ -1918,14 +1917,14 @@ namespace CodeImp.DoomBuilder.Map
|
|||
return newlines;
|
||||
}
|
||||
|
||||
// This returns the cohen-sutherland field bits for a vertex in a rectangle area
|
||||
private static int GetCSFieldBits(Vertex v, ref RectangleF area)
|
||||
/// <summary> This returns the cohen-sutherland field bits for a vector in a rectangle area</summary>
|
||||
public static int GetCSFieldBits(Vector2D v, RectangleF area)
|
||||
{
|
||||
int bits = 0;
|
||||
if(v.Position.y < area.Top) bits |= 0x01;
|
||||
if(v.Position.y > area.Bottom) bits |= 0x02;
|
||||
if(v.Position.x < area.Left) bits |= 0x04;
|
||||
if(v.Position.x > area.Right) bits |= 0x08;
|
||||
if(v.y < area.Top) bits |= 0x01;
|
||||
if(v.y > area.Bottom) bits |= 0x02;
|
||||
if(v.x < area.Left) bits |= 0x04;
|
||||
if(v.x > area.Right) bits |= 0x08;
|
||||
return bits;
|
||||
}
|
||||
|
||||
|
@ -2270,6 +2269,48 @@ namespace CodeImp.DoomBuilder.Map
|
|||
return joinsdone;
|
||||
}
|
||||
|
||||
/// <summary>This joins nearby vertices in the same collection </summary>
|
||||
public static int JoinVertices(List<Vertex> set, float joindist) {
|
||||
float joindist2 = joindist * joindist;
|
||||
int joinsdone = 0;
|
||||
bool joined;
|
||||
Vertex v1, v2;
|
||||
|
||||
do {
|
||||
// No joins yet
|
||||
joined = false;
|
||||
|
||||
// Go for all vertices in the first set
|
||||
for(int i = 0; i < set.Count - 1; i++) {
|
||||
for(int c = i + 1; c < set.Count; c++) {
|
||||
v1 = set[i];
|
||||
v2 = set[c];
|
||||
|
||||
// Check if vertices are close enough
|
||||
if (v1.DistanceToSq(v2.Position) <= joindist2) {
|
||||
// Check if not the same vertex
|
||||
if (v1.Index != v2.Index) {
|
||||
// Move the second vertex to match the first
|
||||
v2.Move(v1.Position);
|
||||
|
||||
// Join the second into the first
|
||||
v2.Join(v1);
|
||||
set.Remove(v2);
|
||||
|
||||
// Count the join
|
||||
joinsdone++;
|
||||
joined = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(joined);
|
||||
|
||||
// Return result
|
||||
return joinsdone;
|
||||
}
|
||||
|
||||
/// <summary>This corrects lines that have a back sidedef but no front sidedef by flipping them. Returns the number of flips made.</summary>
|
||||
public static int FlipBackwardLinedefs(ICollection<Linedef> lines)
|
||||
{
|
||||
|
@ -2299,28 +2340,38 @@ namespace CodeImp.DoomBuilder.Map
|
|||
float splitdist2 = splitdist * splitdist;
|
||||
bool splitted;
|
||||
|
||||
//mxd. Create blockmap
|
||||
RectangleF area = CreateArea(verts);
|
||||
BlockMap<BlockEntry> blockmap = new BlockMap<BlockEntry>(area);
|
||||
blockmap.AddVerticesSet(verts);
|
||||
blockmap.AddLinedefsSet(lines);
|
||||
int bmWidth = blockmap.Size.Width;
|
||||
int bmHeight = blockmap.Size.Height;
|
||||
BlockEntry[,] bmap = blockmap.Map;
|
||||
BlockEntry block;
|
||||
int w, h;
|
||||
|
||||
do
|
||||
{
|
||||
// No split yet
|
||||
splitted = false;
|
||||
|
||||
for(w = 0; w < bmWidth; w++) {
|
||||
for(h = 0; h < bmHeight; h++) {
|
||||
block = bmap[w, h];
|
||||
if(block.Vertices.Count == 0 || block.Lines.Count == 0) continue;
|
||||
|
||||
// Go for all the lines
|
||||
foreach(Linedef l in lines)
|
||||
{
|
||||
foreach(Linedef l in block.Lines) {
|
||||
// Go for all the vertices
|
||||
foreach(Vertex v in verts)
|
||||
{
|
||||
foreach(Vertex v in block.Vertices) {
|
||||
// Check if v is close enough to l for splitting
|
||||
if(l.DistanceToSq(v.Position, true) <= splitdist2)
|
||||
{
|
||||
if(l.DistanceToSq(v.Position, true) <= splitdist2) {
|
||||
// Line is not already referencing v?
|
||||
Vector2D deltastart = l.Start.Position - v.Position;
|
||||
Vector2D deltaend = l.End.Position - v.Position;
|
||||
if(((Math.Abs(deltastart.x) > 0.001f) ||
|
||||
(Math.Abs(deltastart.y) > 0.001f)) &&
|
||||
((Math.Abs(deltaend.x) > 0.001f) ||
|
||||
(Math.Abs(deltaend.y) > 0.001f)))
|
||||
{
|
||||
if(((Math.Abs(deltastart.x) > 0.001f) || (Math.Abs(deltastart.y) > 0.001f)) &&
|
||||
((Math.Abs(deltaend.x) > 0.001f) || (Math.Abs(deltaend.y) > 0.001f))) {
|
||||
// Split line l with vertex v
|
||||
Linedef nl = l.Split(v);
|
||||
if(nl == null) return false;
|
||||
|
@ -2334,8 +2385,7 @@ namespace CodeImp.DoomBuilder.Map
|
|||
nl.UpdateCache();
|
||||
|
||||
// Add both lines to changedlines
|
||||
if(changedlines != null)
|
||||
{
|
||||
if(changedlines != null) {
|
||||
changedlines.Add(l);
|
||||
changedlines.Add(nl);
|
||||
}
|
||||
|
@ -2353,6 +2403,8 @@ namespace CodeImp.DoomBuilder.Map
|
|||
if(splitted) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while(splitted);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -269,31 +269,30 @@ namespace CodeImp.DoomBuilder.Map
|
|||
#region ================== Methods
|
||||
|
||||
// This checks and returns a flag without creating it
|
||||
public bool IsFlagSet(string flagname) {
|
||||
if(flags.ContainsKey(flagname))
|
||||
return flags[flagname];
|
||||
else
|
||||
return false;
|
||||
public bool IsFlagSet(string flagname)
|
||||
{
|
||||
return (flags.ContainsKey(flagname) && flags[flagname]);
|
||||
}
|
||||
|
||||
// This sets a flag
|
||||
public void SetFlag(string flagname, bool value) {
|
||||
public void SetFlag(string flagname, bool value)
|
||||
{
|
||||
if(!flags.ContainsKey(flagname) || (IsFlagSet(flagname) != value)) {
|
||||
BeforePropsChange();
|
||||
|
||||
flags[flagname] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// This returns a copy of the flags dictionary
|
||||
public Dictionary<string, bool> GetFlags() {
|
||||
public Dictionary<string, bool> GetFlags()
|
||||
{
|
||||
return new Dictionary<string, bool>(flags);
|
||||
}
|
||||
|
||||
// This clears all flags
|
||||
public void ClearFlags() {
|
||||
public void ClearFlags()
|
||||
{
|
||||
BeforePropsChange();
|
||||
|
||||
flags.Clear();
|
||||
}
|
||||
|
||||
|
@ -306,11 +305,13 @@ namespace CodeImp.DoomBuilder.Map
|
|||
// This removes textures that are not required
|
||||
public void RemoveUnneededTextures(bool removemiddle, bool force)
|
||||
{
|
||||
BeforePropsChange();
|
||||
bool changed = false; //mxd
|
||||
|
||||
// The middle texture can be removed regardless of any sector tag or linedef action
|
||||
if(!MiddleRequired() && removemiddle)
|
||||
{
|
||||
BeforePropsChange(); //mxd
|
||||
changed = true; //mxd
|
||||
this.texnamemid = "-";
|
||||
this.longtexnamemid = MapSet.EmptyLongName;
|
||||
General.Map.IsChanged = true;
|
||||
|
@ -324,6 +325,10 @@ namespace CodeImp.DoomBuilder.Map
|
|||
{
|
||||
if(!HighRequired())
|
||||
{
|
||||
if(!changed) { //mxd
|
||||
BeforePropsChange();
|
||||
changed = true;
|
||||
}
|
||||
this.texnamehigh = "-";
|
||||
this.longtexnamehigh = MapSet.EmptyLongName;
|
||||
General.Map.IsChanged = true;
|
||||
|
@ -331,6 +336,7 @@ namespace CodeImp.DoomBuilder.Map
|
|||
|
||||
if(!LowRequired())
|
||||
{
|
||||
if(!changed) BeforePropsChange(); //mxd
|
||||
this.texnamelow = "-";
|
||||
this.longtexnamelow = MapSet.EmptyLongName;
|
||||
General.Map.IsChanged = true;
|
||||
|
@ -349,11 +355,9 @@ namespace CodeImp.DoomBuilder.Map
|
|||
// Texture is required when ceiling of other side is lower
|
||||
return (Other.sector.CeilHeight < this.sector.CeilHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This checks if a texture is required
|
||||
|
@ -375,11 +379,9 @@ namespace CodeImp.DoomBuilder.Map
|
|||
// Texture is required when floor of other side is higher
|
||||
return (Other.sector.FloorHeight > this.sector.FloorHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This returns the height of the upper wall part. Returns 0 when no upper part exists.
|
||||
|
@ -394,11 +396,9 @@ namespace CodeImp.DoomBuilder.Map
|
|||
int height = top - bottom;
|
||||
return (height > 0) ? height : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This returns the height of the middle wall part.
|
||||
|
@ -435,11 +435,9 @@ namespace CodeImp.DoomBuilder.Map
|
|||
int height = top - bottom;
|
||||
return (height > 0) ? height : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// This creates a checksum from the sidedef properties
|
||||
// Used for faster sidedefs compression
|
||||
|
|
|
@ -81,14 +81,14 @@ namespace CodeImp.DoomBuilder.BuilderModes.ClassicModes
|
|||
if (block == null) continue;
|
||||
|
||||
foreach (Vertex blockVert in block.Vertices) {
|
||||
if(!blockVert.IsDisposed && blockVert.Index != v.Index && blockVert.Position == v.Position) {
|
||||
if(blockVert.IsDisposed || blockVert.Index == v.Index || blockVert.Position != v.Position) continue;
|
||||
|
||||
foreach(Linedef l in blockVert.Linedefs)
|
||||
if(!movedLines.Contains(l)) movedLines.Add(l);
|
||||
v.Join(blockVert);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update cached values of lines because we may need their length/angle
|
||||
General.Map.Map.Update(true, false);
|
||||
|
|
Loading…
Reference in a new issue