diff --git a/Source/Core/General/MapManager.cs b/Source/Core/General/MapManager.cs index efeadcd7038f6f8da7e8e12300b7d1727301289e..b5ccadf9a3a37bfca560338a0d6b4036c41e4d79 100644 --- a/Source/Core/General/MapManager.cs +++ b/Source/Core/General/MapManager.cs @@ -788,6 +788,9 @@ namespace CodeImp.DoomBuilder General.MainWindow.DisplayStatus(StatusType.Busy, "Building map nodes..."); includenodes = (!string.IsNullOrEmpty(nodebuildername) && BuildNodes(nodebuildername, true)); General.MainWindow.DisplayStatus(oldstatus); + + //mxd. Compress temp file... + tempwadreader.WadFile.Compress(); } else { @@ -1152,6 +1155,9 @@ namespace CodeImp.DoomBuilder result = false; General.MainWindow.DisplayStatus(oldstatus); + //mxd. Compress temp file... + tempwadreader.WadFile.Compress(); + return result; } diff --git a/Source/Core/IO/WAD.cs b/Source/Core/IO/WAD.cs index 9720279dc58ecbc21b073bb19b1697207924a83b..99d2dc81a8bde23641cd4f742e9a2424346c0f7c 100644 --- a/Source/Core/IO/WAD.cs +++ b/Source/Core/IO/WAD.cs @@ -85,6 +85,17 @@ namespace CodeImp.DoomBuilder.IO #endregion + #region ================== Structs (mxd) + + private struct LumpCopyData + { + public byte[] Data; + public byte[] FixedName; + public int Index; + } + + #endregion + #region ================== Variables // File objects @@ -333,6 +344,66 @@ namespace CodeImp.DoomBuilder.IO fs.Dispose(); } } + + //mxd. This rebuilds the WAD file, removing all "dead" entries + // Tech info: WAD.Remove() doesn't remove lump data, so MapManager.TemporaryMapFile slowly gets bigger + // with every map save/test, which leads to lumpsoffset overflowing when TemporaryMapFile size reaches + // int.MaxValue bytes in size (that's ~2Gb). + internal void Compress() + { + // No can't do... + if(isreadonly) return; + + // Gather existing data + int totaldatalength = 0; + List<LumpCopyData> copydata = new List<LumpCopyData>(lumps.Count); + for(int i = 0; i < lumps.Count; i++) + { + // Copy lump... + LumpCopyData lcd = new LumpCopyData(); + Lump l = lumps[i]; + + lcd.FixedName = l.FixedName; + lcd.Index = i; + lcd.Data = l.Stream.ReadAllBytes(); + + // Store data + copydata.Add(lcd); + + // Track total length + totaldatalength += l.Length; + + // Dispose lump + l.Dispose(); + } + + // Compression required? + if(totaldatalength >= lumpsoffset + 12) return; + + // Set new file length + file.SetLength(totaldatalength + lumps.Count * 16); + + // Reset lumpsoffset + lumpsoffset = 12; + + // Reset lumps collection + lumps = new List<Lump>(copydata.Count); + numlumps = copydata.Count; + + // Recreate all lumps + foreach(LumpCopyData lcd in copydata) + { + Lump l = new Lump(file, this, lcd.FixedName, lumpsoffset, lcd.Data.Length); + l.Stream.Write(lcd.Data, 0, lcd.Data.Length); + l.Stream.Seek(0, SeekOrigin.Begin); + lumps.Insert(lcd.Index, l); + + lumpsoffset += lcd.Data.Length; + } + + // Write new headers + WriteHeaders(); + } // This flushes writing changes /*public void Flush() @@ -363,19 +434,10 @@ namespace CodeImp.DoomBuilder.IO // Create the lump Lump lump = new Lump(file, this, Lump.MakeFixedName(name, ENCODING), lumpsoffset, datalength); lumps.Insert(position, lump); - - //dbg - int oldlumpoffset = lumpsoffset; // Advance lumps table offset lumpsoffset += datalength; - //dbg - if(lumpsoffset < 0) - { - throw new InvalidOperationException("Invalid lumpsoffset (" + lumpsoffset + ") after inserting lump \"" + name + "\" at position " + position + ", datalength=" + datalength + ". Previous lumpoffset was " + oldlumpoffset); - } - // Write the new headers if(writeheaders) WriteHeaders(); diff --git a/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs b/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs index d90164e34e1339a9edf10d343187e1549dc6647b..21ace362cf04c311929884571eb82d7daa532bb3 100644 --- a/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs +++ b/Source/Plugins/BuilderModes/ClassicModes/DrawGeometryMode.cs @@ -377,20 +377,23 @@ namespace CodeImp.DoomBuilder.BuilderModes //mxd. Line angle must stay the same if(snaptocardinal) { - Line2D ourline = new Line2D(points[points.Count - 1].pos, vm); - Line2D nearestline = new Line2D(nl.Start.Position, nl.End.Position); - Vector2D intersection = Line2D.GetIntersectionPoint(nearestline, ourline, false); - if(!float.IsNaN(intersection.x)) + if(points.Count > 0) { - // Intersection is on nearestline? - float u = Line2D.GetNearestOnLine(nearestline.v1, nearestline.v2, intersection); - - if(u < 0f || u > 1f){} - else + Line2D ourline = new Line2D(points[points.Count - 1].pos, vm); + Line2D nearestline = new Line2D(nl.Start.Position, nl.End.Position); + Vector2D intersection = Line2D.GetIntersectionPoint(nearestline, ourline, false); + if(!float.IsNaN(intersection.x)) { - p.pos = new Vector2D((float)Math.Round(intersection.x, General.Map.FormatInterface.VertexDecimals), - (float)Math.Round(intersection.y, General.Map.FormatInterface.VertexDecimals)); - return p; + // Intersection is on nearestline? + float u = Line2D.GetNearestOnLine(nearestline.v1, nearestline.v2, intersection); + + if(u < 0f || u > 1f) { } + else + { + p.pos = new Vector2D((float)Math.Round(intersection.x, General.Map.FormatInterface.VertexDecimals), + (float)Math.Round(intersection.y, General.Map.FormatInterface.VertexDecimals)); + return p; + } } } }