From 11600f736454ef031457461da9aeea5a6ff7e130 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 22 Mar 2026 12:58:19 +0000 Subject: [PATCH 1/7] Fix numerous TE memory problems --- .../Controls/ImportedGeometryManager.cs | 5 +++- TombEditor/Controls/Panel3D/Panel3D.cs | 2 ++ TombEditor/Controls/Panel3D/Panel3DDraw.cs | 5 ++-- .../Controls/Panel3D/Panel3DDrawCollector.cs | 8 ++++--- TombLib/TombLib/LevelData/ImportedGeometry.cs | 20 +++++++++++++++- TombLib/TombLib/LevelData/RoomGeometry.cs | 17 +++++++++++++ TombLib/TombLib/Wad/WadTexture.cs | 24 ++++++++++++------- 7 files changed, 66 insertions(+), 15 deletions(-) diff --git a/TombEditor/Controls/ImportedGeometryManager.cs b/TombEditor/Controls/ImportedGeometryManager.cs index b7bf2afb75..077ff93b43 100644 --- a/TombEditor/Controls/ImportedGeometryManager.cs +++ b/TombEditor/Controls/ImportedGeometryManager.cs @@ -139,6 +139,7 @@ public void Set(SetValue setValue) private readonly Color _correctColor; private readonly Color _wrongColor; + private ListChangedEventHandler _listChangedHandler; public ImportedGeometryManager() { @@ -193,7 +194,7 @@ public ImportedGeometryManager() }; dataGridView.DataSource = _dataGridViewDataSource; dataGridViewControls.DeleteRowCheckIfCancel = MessageUserAboutHimDeletingRows; - _dataGridViewDataSource.ListChanged += delegate (object sender, ListChangedEventArgs e) + _listChangedHandler = delegate (object sender, ListChangedEventArgs e) { switch (e.ListChangedType) { @@ -203,6 +204,7 @@ public ImportedGeometryManager() break; } }; + _dataGridViewDataSource.ListChanged += _listChangedHandler; Enabled = true; @@ -214,6 +216,7 @@ protected override void Dispose(bool disposing) { if (disposing) { + _dataGridViewDataSource.ListChanged -= _listChangedHandler; components?.Dispose(); Editor.Instance.EditorEventRaised -= EditorEventRaised; } diff --git a/TombEditor/Controls/Panel3D/Panel3D.cs b/TombEditor/Controls/Panel3D/Panel3D.cs index 667653af35..5b8c626971 100644 --- a/TombEditor/Controls/Panel3D/Panel3D.cs +++ b/TombEditor/Controls/Panel3D/Panel3D.cs @@ -135,6 +135,8 @@ public bool DisablePickingForHiddenRooms private Buffer _objectHeightLineVertexBuffer; private Buffer _flybyPathVertexBuffer; private Buffer _ghostBlockVertexBuffer; + private SolidVertex[] _ghostBlockVertices = new SolidVertex[84]; + private float[] _roomsDistanceCache; private Buffer _boxVertexBuffer; // Flyby stuff diff --git a/TombEditor/Controls/Panel3D/Panel3DDraw.cs b/TombEditor/Controls/Panel3D/Panel3DDraw.cs index 8e148d1701..ec6698e8d5 100644 --- a/TombEditor/Controls/Panel3D/Panel3DDraw.cs +++ b/TombEditor/Controls/Panel3D/Panel3DDraw.cs @@ -668,8 +668,9 @@ private void DrawGhostBlockBodies(Effect effect, List ghostB if (!instance.Valid) continue; - // Create a vertex array - SolidVertex[] vtxs = new SolidVertex[84]; // 78 with diagonal steps + // Reuse cached vertex array + SolidVertex[] vtxs = _ghostBlockVertices; + Array.Clear(vtxs, 0, vtxs.Length); // Derive base sector colours var p1c = new Vector4(baseColor.To3() * (selected ? 0.8f : 0.4f), selected ? 0.7f : 0.5f); diff --git a/TombEditor/Controls/Panel3D/Panel3DDrawCollector.cs b/TombEditor/Controls/Panel3D/Panel3DDrawCollector.cs index 94e79dc803..1e6320aab9 100644 --- a/TombEditor/Controls/Panel3D/Panel3DDrawCollector.cs +++ b/TombEditor/Controls/Panel3D/Panel3DDrawCollector.cs @@ -144,12 +144,14 @@ Room[] CollectRoomsToDraw() // Collect rooms to draw var camPos = Camera.GetPosition(); var roomsToDraw = CollectRoomsToDraw(_editor.SelectedRoom).ToArray(); - var roomsToDrawDistanceSquared = new float[roomsToDraw.Length]; + + if (_roomsDistanceCache == null || _roomsDistanceCache.Length < roomsToDraw.Length) + _roomsDistanceCache = new float[roomsToDraw.Length]; for (int i = 0; i < roomsToDraw.Length; ++i) - roomsToDrawDistanceSquared[i] = Vector3.DistanceSquared(camPos, roomsToDraw[i].WorldPos + roomsToDraw[i].GetLocalCenter()); + _roomsDistanceCache[i] = Vector3.DistanceSquared(camPos, roomsToDraw[i].WorldPos + roomsToDraw[i].GetLocalCenter()); - Array.Sort(roomsToDrawDistanceSquared, roomsToDraw); + Array.Sort(_roomsDistanceCache, roomsToDraw, 0, roomsToDraw.Length); Array.Reverse(roomsToDraw); return roomsToDraw; diff --git a/TombLib/TombLib/LevelData/ImportedGeometry.cs b/TombLib/TombLib/LevelData/ImportedGeometry.cs index 2aef2029a5..3daa6b9de0 100644 --- a/TombLib/TombLib/LevelData/ImportedGeometry.cs +++ b/TombLib/TombLib/LevelData/ImportedGeometry.cs @@ -16,7 +16,7 @@ namespace TombLib.LevelData { - public class ImportedGeometryTexture : Texture + public class ImportedGeometryTexture : Texture, IDisposable { public Texture2D DirectXTexture { get; private set; } @@ -44,11 +44,21 @@ private ImportedGeometryTexture(ImportedGeometryTexture other) public void Assign(ImportedGeometryTexture other) { + // Dispose old GPU texture if it differs from the new one. + if (DirectXTexture != null && DirectXTexture != other.DirectXTexture) + DirectXTexture.Dispose(); + AbsolutePath = other.AbsolutePath; Image = other.Image; DirectXTexture = other.DirectXTexture; } + public void Dispose() + { + DirectXTexture?.Dispose(); + DirectXTexture = null; + } + public override Texture Clone() => new ImportedGeometryTexture(this); public override int GetHashCode() => AbsolutePath.GetHashCode(); @@ -215,6 +225,14 @@ public void Update(LevelSettings settings, Dictionary absoluteP Info = info; LoadException = null; DirectXModel = null; + + // Dispose GPU textures that are exclusive to this geometry and won't be reused. + foreach (var texture in Textures) + { + if (!absolutePathTextureLookup.ContainsKey(texture.AbsolutePath)) + texture.Dispose(); + } + Textures.Clear(); try diff --git a/TombLib/TombLib/LevelData/RoomGeometry.cs b/TombLib/TombLib/LevelData/RoomGeometry.cs index 5276002643..448f62bd5a 100644 --- a/TombLib/TombLib/LevelData/RoomGeometry.cs +++ b/TombLib/TombLib/LevelData/RoomGeometry.cs @@ -93,6 +93,10 @@ public void Build(Room room, bool useLegacyCode = false) private void ClearGeometryData() { + // Preserve previous capacity to avoid repeated internal array resizing. + int prevVertexCount = VertexPositions.Count; + int prevTriangleCount = TriangleTextureAreas.Count; + VertexPositions.Clear(); VertexEditorUVs.Clear(); VertexColors.Clear(); @@ -101,6 +105,19 @@ private void ClearGeometryData() SharedVertices.Clear(); VertexRangeLookup.Clear(); DoubleSidedTriangleCount = 0; + + if (prevVertexCount > 0) + { + VertexPositions.EnsureCapacity(prevVertexCount); + VertexEditorUVs.EnsureCapacity(prevVertexCount); + VertexColors.EnsureCapacity(prevVertexCount); + } + + if (prevTriangleCount > 0) + { + TriangleTextureAreas.EnsureCapacity(prevTriangleCount); + TriangleSectorInfo.EnsureCapacity(prevTriangleCount); + } } private static bool IsCornerSector(int x, int z, int xMax, int zMax) diff --git a/TombLib/TombLib/Wad/WadTexture.cs b/TombLib/TombLib/Wad/WadTexture.cs index 678a4e5eac..e5b5739c6f 100644 --- a/TombLib/TombLib/Wad/WadTexture.cs +++ b/TombLib/TombLib/Wad/WadTexture.cs @@ -1,7 +1,9 @@ using System; +using System.Buffers.Binary; using System.IO; using TombLib.Graphics; using TombLib.Utils; +using Blake3Hasher = Blake3.Hasher; namespace TombLib.Wad { @@ -20,14 +22,20 @@ public WadTexture(ImageC image) { Image = image; - using (var ms = new MemoryStream()) - { - var writer = new BinaryWriter(ms); - writer.Write(Image.Size.X); - writer.Write(Image.Size.Y); - Image.WriteToStreamRaw(ms); - Hash = Hash.FromByteArray(ms.ToArray()); - } + // Hash image dimensions and pixel data directly without intermediate copies. + using var hasher = Blake3Hasher.New(); + Span header = stackalloc byte[8]; + BinaryPrimitives.WriteInt32LittleEndian(header, Image.Size.X); + BinaryPrimitives.WriteInt32LittleEndian(header.Slice(4), Image.Size.Y); + hasher.Update(header); + hasher.Update(Image.ToByteArray()); + + Span digest = stackalloc byte[32]; + hasher.Finalize(digest); + + ulong low = BinaryPrimitives.ReadUInt64LittleEndian(digest.Slice(0, 8)); + ulong high = BinaryPrimitives.ReadUInt64LittleEndian(digest.Slice(8, 8)); + Hash = new Hash { HashLow = low, HashHigh = high }; } public override Texture Clone() => this; From 6b765a0b386907586312de09459975b29ec59150 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 22 Mar 2026 14:24:32 +0000 Subject: [PATCH 2/7] Fix finalizers not being suppressed and a font renderer memory leak --- TombLib/TombLib.Rendering/Rendering/RenderingFont.cs | 4 +++- TombLib/TombLib/IO/BinaryWriterFast.cs | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/TombLib/TombLib.Rendering/Rendering/RenderingFont.cs b/TombLib/TombLib.Rendering/Rendering/RenderingFont.cs index e85dc1d8c8..0723ef676b 100644 --- a/TombLib/TombLib.Rendering/Rendering/RenderingFont.cs +++ b/TombLib/TombLib.Rendering/Rendering/RenderingFont.cs @@ -315,7 +315,7 @@ public class GlyphRenderInfo public void Dispose() { - if (!_disposed) + if (_disposed) return; _disposed = true; @@ -325,6 +325,8 @@ public void Dispose() Marshal.FreeHGlobal(_gdiGetCharacterPlacementOrder); Marshal.FreeHGlobal(_gdiGetCharacterPlacementDx); Marshal.FreeHGlobal(_gdiGetCharacterPlacementGlpyhs); + + GC.SuppressFinalize(this); } ~RenderingFont() diff --git a/TombLib/TombLib/IO/BinaryWriterFast.cs b/TombLib/TombLib/IO/BinaryWriterFast.cs index 850221b13e..ef0c55bab4 100644 --- a/TombLib/TombLib/IO/BinaryWriterFast.cs +++ b/TombLib/TombLib/IO/BinaryWriterFast.cs @@ -52,6 +52,8 @@ public void Dispose() _ptr = null; _startPtr = null; _baseStream = null; + + GC.SuppressFinalize(this); } public Stream BaseStream From 3d502641056f3848688901d7a14e438680707f64 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 22 Mar 2026 14:42:00 +0000 Subject: [PATCH 3/7] Apply Copilot fixes --- TombLib/TombLib/LevelData/ImportedGeometry.cs | 1 - TombLib/TombLib/LevelData/RoomGeometry.cs | 17 ----------------- 2 files changed, 18 deletions(-) diff --git a/TombLib/TombLib/LevelData/ImportedGeometry.cs b/TombLib/TombLib/LevelData/ImportedGeometry.cs index 3daa6b9de0..941e652ed6 100644 --- a/TombLib/TombLib/LevelData/ImportedGeometry.cs +++ b/TombLib/TombLib/LevelData/ImportedGeometry.cs @@ -37,7 +37,6 @@ public ImportedGeometryTexture(string absolutePath) private ImportedGeometryTexture(ImportedGeometryTexture other) { - DirectXTexture = other.DirectXTexture; AbsolutePath = other.AbsolutePath; Image = other.Image; } diff --git a/TombLib/TombLib/LevelData/RoomGeometry.cs b/TombLib/TombLib/LevelData/RoomGeometry.cs index 448f62bd5a..5276002643 100644 --- a/TombLib/TombLib/LevelData/RoomGeometry.cs +++ b/TombLib/TombLib/LevelData/RoomGeometry.cs @@ -93,10 +93,6 @@ public void Build(Room room, bool useLegacyCode = false) private void ClearGeometryData() { - // Preserve previous capacity to avoid repeated internal array resizing. - int prevVertexCount = VertexPositions.Count; - int prevTriangleCount = TriangleTextureAreas.Count; - VertexPositions.Clear(); VertexEditorUVs.Clear(); VertexColors.Clear(); @@ -105,19 +101,6 @@ private void ClearGeometryData() SharedVertices.Clear(); VertexRangeLookup.Clear(); DoubleSidedTriangleCount = 0; - - if (prevVertexCount > 0) - { - VertexPositions.EnsureCapacity(prevVertexCount); - VertexEditorUVs.EnsureCapacity(prevVertexCount); - VertexColors.EnsureCapacity(prevVertexCount); - } - - if (prevTriangleCount > 0) - { - TriangleTextureAreas.EnsureCapacity(prevTriangleCount); - TriangleSectorInfo.EnsureCapacity(prevTriangleCount); - } } private static bool IsCornerSector(int x, int z, int xMax, int zMax) From bf342b191ba5351c366b81a6f7faea4519492da1 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 22 Mar 2026 15:03:02 +0000 Subject: [PATCH 4/7] Fix more disposability issues --- DarkUI/DarkUI/Collections/ObservableList.cs | 19 ++----------------- .../Rendering/RenderingFont.cs | 17 +++++++++++------ TombLib/TombLib/LevelData/ImportedGeometry.cs | 14 ++++++++++++-- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/DarkUI/DarkUI/Collections/ObservableList.cs b/DarkUI/DarkUI/Collections/ObservableList.cs index fce7f9a9e9..16764d0d49 100644 --- a/DarkUI/DarkUI/Collections/ObservableList.cs +++ b/DarkUI/DarkUI/Collections/ObservableList.cs @@ -19,28 +19,13 @@ public class ObservableList : List, IDisposable #endregion - #region Destructor Region - - ~ObservableList() - { - Dispose(false); - } - - #endregion - #region Dispose Region - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) + public virtual void Dispose() { if (_disposed) return; - + ItemsAdded = null; ItemsRemoved = null; diff --git a/TombLib/TombLib.Rendering/Rendering/RenderingFont.cs b/TombLib/TombLib.Rendering/Rendering/RenderingFont.cs index 0723ef676b..9ef006f2e2 100644 --- a/TombLib/TombLib.Rendering/Rendering/RenderingFont.cs +++ b/TombLib/TombLib.Rendering/Rendering/RenderingFont.cs @@ -320,18 +320,23 @@ public void Dispose() _disposed = true; TextureAllocator?.Dispose(); - GDI.DeleteObject(_gdiFont); - GDI.DeleteDC(_gdiHdc); - Marshal.FreeHGlobal(_gdiGetCharacterPlacementOrder); - Marshal.FreeHGlobal(_gdiGetCharacterPlacementDx); - Marshal.FreeHGlobal(_gdiGetCharacterPlacementGlpyhs); + ReleaseUnmanagedResources(); GC.SuppressFinalize(this); } ~RenderingFont() { - Dispose(); + ReleaseUnmanagedResources(); + } + + private void ReleaseUnmanagedResources() + { + GDI.DeleteObject(_gdiFont); + GDI.DeleteDC(_gdiHdc); + Marshal.FreeHGlobal(_gdiGetCharacterPlacementOrder); + Marshal.FreeHGlobal(_gdiGetCharacterPlacementDx); + Marshal.FreeHGlobal(_gdiGetCharacterPlacementGlpyhs); } private static class GDI diff --git a/TombLib/TombLib/LevelData/ImportedGeometry.cs b/TombLib/TombLib/LevelData/ImportedGeometry.cs index 941e652ed6..63e1482c57 100644 --- a/TombLib/TombLib/LevelData/ImportedGeometry.cs +++ b/TombLib/TombLib/LevelData/ImportedGeometry.cs @@ -20,6 +20,8 @@ public class ImportedGeometryTexture : Texture, IDisposable { public Texture2D DirectXTexture { get; private set; } + private bool _disposed; + public ImportedGeometryTexture(string absolutePath) { AbsolutePath = absolutePath; @@ -31,8 +33,12 @@ public ImportedGeometryTexture(string absolutePath) if (SynchronizationContext.Current == null) DirectXTexture = TextureLoad.Load(ImportedGeometry.Device, Image); else - SynchronizationContext.Current.Post(unused => // Synchronize DirectX, we can't 'send' because that may deadlock with the level settings reloader - DirectXTexture = TextureLoad.Load(ImportedGeometry.Device, Image), null); + SynchronizationContext.Current.Post(unused => { + if (_disposed) + return; + + DirectXTexture = TextureLoad.Load(ImportedGeometry.Device, Image); + }, null); } private ImportedGeometryTexture(ImportedGeometryTexture other) @@ -50,10 +56,14 @@ public void Assign(ImportedGeometryTexture other) AbsolutePath = other.AbsolutePath; Image = other.Image; DirectXTexture = other.DirectXTexture; + + _disposed = false; } public void Dispose() { + _disposed = true; + DirectXTexture?.Dispose(); DirectXTexture = null; } From f70582fda06bd2c76102ccb2790de183a6606184 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 22 Mar 2026 15:28:00 +0000 Subject: [PATCH 5/7] Apply Copilot suggestion --- TombLib/TombLib/LevelData/LevelSettings.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/TombLib/TombLib/LevelData/LevelSettings.cs b/TombLib/TombLib/LevelData/LevelSettings.cs index 97fa8545fa..9fad3916b9 100644 --- a/TombLib/TombLib/LevelData/LevelSettings.cs +++ b/TombLib/TombLib/LevelData/LevelSettings.cs @@ -755,23 +755,25 @@ public bool LoadDefaultSoundCatalog() public void ImportedGeometryUpdate(IEnumerable geometriesToUpdate) { - Dictionary absolutePathTextureLookup = new Dictionary(); + var updateList = geometriesToUpdate.ToList(); + var geometriesBeingUpdated = new HashSet(updateList.Select(g => g.Key)); + var absolutePathTextureLookup = new Dictionary(); - // Add other imported geometry textures to lookup + // Add textures from geometries not being updated, so shared textures are preserved foreach (ImportedGeometry importedGeometry in ImportedGeometries) { + if (geometriesBeingUpdated.Contains(importedGeometry)) + continue; + foreach (ImportedGeometryTexture importedGeometryTexture in importedGeometry.Textures) { if (!absolutePathTextureLookup.ContainsKey(importedGeometryTexture.AbsolutePath)) - { absolutePathTextureLookup.Add(importedGeometryTexture.AbsolutePath, importedGeometryTexture); - } } } // TODO Ideally we could load these concurrently - // Load geometries - foreach (ImportedGeometryUpdateInfo geometryToUpdate in geometriesToUpdate) + foreach (ImportedGeometryUpdateInfo geometryToUpdate in updateList) { geometryToUpdate.Key.Update(this, absolutePathTextureLookup, geometryToUpdate.Value); } From 4480972fcfec1cda473b7f55a3cb656d0521acd7 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 22 Mar 2026 15:49:20 +0000 Subject: [PATCH 6/7] Revert loop disposal entirely --- TombLib/TombLib/LevelData/ImportedGeometry.cs | 8 -------- TombLib/TombLib/LevelData/LevelSettings.cs | 14 ++++++-------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/TombLib/TombLib/LevelData/ImportedGeometry.cs b/TombLib/TombLib/LevelData/ImportedGeometry.cs index 63e1482c57..e5c606c86a 100644 --- a/TombLib/TombLib/LevelData/ImportedGeometry.cs +++ b/TombLib/TombLib/LevelData/ImportedGeometry.cs @@ -234,14 +234,6 @@ public void Update(LevelSettings settings, Dictionary absoluteP Info = info; LoadException = null; DirectXModel = null; - - // Dispose GPU textures that are exclusive to this geometry and won't be reused. - foreach (var texture in Textures) - { - if (!absolutePathTextureLookup.ContainsKey(texture.AbsolutePath)) - texture.Dispose(); - } - Textures.Clear(); try diff --git a/TombLib/TombLib/LevelData/LevelSettings.cs b/TombLib/TombLib/LevelData/LevelSettings.cs index 9fad3916b9..97fa8545fa 100644 --- a/TombLib/TombLib/LevelData/LevelSettings.cs +++ b/TombLib/TombLib/LevelData/LevelSettings.cs @@ -755,25 +755,23 @@ public bool LoadDefaultSoundCatalog() public void ImportedGeometryUpdate(IEnumerable geometriesToUpdate) { - var updateList = geometriesToUpdate.ToList(); - var geometriesBeingUpdated = new HashSet(updateList.Select(g => g.Key)); - var absolutePathTextureLookup = new Dictionary(); + Dictionary absolutePathTextureLookup = new Dictionary(); - // Add textures from geometries not being updated, so shared textures are preserved + // Add other imported geometry textures to lookup foreach (ImportedGeometry importedGeometry in ImportedGeometries) { - if (geometriesBeingUpdated.Contains(importedGeometry)) - continue; - foreach (ImportedGeometryTexture importedGeometryTexture in importedGeometry.Textures) { if (!absolutePathTextureLookup.ContainsKey(importedGeometryTexture.AbsolutePath)) + { absolutePathTextureLookup.Add(importedGeometryTexture.AbsolutePath, importedGeometryTexture); + } } } // TODO Ideally we could load these concurrently - foreach (ImportedGeometryUpdateInfo geometryToUpdate in updateList) + // Load geometries + foreach (ImportedGeometryUpdateInfo geometryToUpdate in geometriesToUpdate) { geometryToUpdate.Key.Update(this, absolutePathTextureLookup, geometryToUpdate.Value); } From e453a48857f0933748b1c12d3837473e773f6eeb Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 22 Mar 2026 16:12:07 +0000 Subject: [PATCH 7/7] Fix double-dispose issues --- TombEditor/Controls/Panel3D/Panel3D.cs | 1 + WadTool/Controls/PanelRenderingAnimationEditor.cs | 1 - WadTool/Controls/PanelRenderingMesh.cs | 1 + WadTool/Controls/PanelRenderingSkeleton.cs | 1 - WadTool/Controls/PanelRenderingStaticEditor.cs | 1 - 5 files changed, 2 insertions(+), 3 deletions(-) diff --git a/TombEditor/Controls/Panel3D/Panel3D.cs b/TombEditor/Controls/Panel3D/Panel3D.cs index 5b8c626971..63407eabc5 100644 --- a/TombEditor/Controls/Panel3D/Panel3D.cs +++ b/TombEditor/Controls/Panel3D/Panel3D.cs @@ -230,6 +230,7 @@ protected override void Dispose(bool disposing) _rasterizerStateDepthBias?.Dispose(); _currentContextMenu?.Dispose(); _wadRenderer?.Dispose(); + _fontDefault?.Dispose(); } base.Dispose(disposing); } diff --git a/WadTool/Controls/PanelRenderingAnimationEditor.cs b/WadTool/Controls/PanelRenderingAnimationEditor.cs index c4a935a4c6..8a9ecc5654 100644 --- a/WadTool/Controls/PanelRenderingAnimationEditor.cs +++ b/WadTool/Controls/PanelRenderingAnimationEditor.cs @@ -141,7 +141,6 @@ protected override void Dispose(bool disposing) { if (disposing) { - _fontTexture?.Dispose(); _fontDefault?.Dispose(); _gizmo?.Dispose(); _plane?.Dispose(); diff --git a/WadTool/Controls/PanelRenderingMesh.cs b/WadTool/Controls/PanelRenderingMesh.cs index 5ff525876f..b457fde211 100644 --- a/WadTool/Controls/PanelRenderingMesh.cs +++ b/WadTool/Controls/PanelRenderingMesh.cs @@ -353,6 +353,7 @@ protected override void Dispose(bool disposing) _bigSphere?.Dispose(); _plane?.Dispose(); _wadRenderer?.Dispose(); + _fontDefault?.Dispose(); } base.Dispose(disposing); } diff --git a/WadTool/Controls/PanelRenderingSkeleton.cs b/WadTool/Controls/PanelRenderingSkeleton.cs index 1fb687f80a..81221f69b4 100644 --- a/WadTool/Controls/PanelRenderingSkeleton.cs +++ b/WadTool/Controls/PanelRenderingSkeleton.cs @@ -114,7 +114,6 @@ protected override void Dispose(bool disposing) { if (disposing) { - _fontTexture?.Dispose(); _fontDefault?.Dispose(); _rasterizerWireframe?.Dispose(); _vertexBufferVisibility?.Dispose(); diff --git a/WadTool/Controls/PanelRenderingStaticEditor.cs b/WadTool/Controls/PanelRenderingStaticEditor.cs index d6d34f94c5..9f8acc8489 100644 --- a/WadTool/Controls/PanelRenderingStaticEditor.cs +++ b/WadTool/Controls/PanelRenderingStaticEditor.cs @@ -139,7 +139,6 @@ protected override void Dispose(bool disposing) { if (disposing) { - _fontTexture?.Dispose(); _fontDefault?.Dispose(); _gizmo?.Dispose(); _gizmoLight?.Dispose();