From e5d2e1653cef883d30f3dc6a4850fa72ee3ef713 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 08:19:09 +0000 Subject: [PATCH 1/2] Initial plan From 6dd15f074db96c9dbd2e3bb08cc92026fe82a15e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 20 Apr 2026 08:29:12 +0000 Subject: [PATCH 2/2] Guard static mesh merge grid against missing statics Agent-Logs-Url: https://github.com/TombEngine/Tomb-Editor/sessions/8e9f590f-8231-4541-ab43-ad4af3742a46 Co-authored-by: Nickelony <20436882+Nickelony@users.noreply.github.com> --- TombLib/TombLib.Test/LevelSettingsTests.cs | 36 ++++++++++++++++++++++ TombLib/TombLib/LevelData/LevelSettings.cs | 29 +++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 TombLib/TombLib.Test/LevelSettingsTests.cs diff --git a/TombLib/TombLib.Test/LevelSettingsTests.cs b/TombLib/TombLib.Test/LevelSettingsTests.cs new file mode 100644 index 000000000..c9420852e --- /dev/null +++ b/TombLib/TombLib.Test/LevelSettingsTests.cs @@ -0,0 +1,36 @@ +using System.Linq; +using System.Reflection; +using TombLib.LevelData; +using TombLib.Wad; + +namespace TombLib.Test; + +[TestClass] +public class LevelSettingsTests +{ + [TestMethod] + public void AutoStaticMeshMergeEntry_StaticMesh_FallsBackToStaticIdNameWhenMissing() + { + var settings = new LevelSettings + { + GameVersion = TRVersion.Game.TR4 + }; + + var entry = new AutoStaticMeshMergeEntry(123u, false, false, false, false, settings); + + Assert.AreEqual(new WadStaticId(123u).ToString(settings.GameVersion), entry.StaticMesh); + } + + [TestMethod] + public void Clone_ReparentsAutoStaticMeshMergeEntries() + { + var settings = new LevelSettings(); + settings.AutoStaticMeshMerges.Add(new AutoStaticMeshMergeEntry(321u, true, false, false, false, settings)); + + var clonedSettings = settings.Clone(); + var parentField = typeof(AutoStaticMeshMergeEntry).GetField("parent", BindingFlags.Instance | BindingFlags.NonPublic); + + Assert.IsNotNull(parentField); + Assert.AreSame(clonedSettings, parentField.GetValue(clonedSettings.AutoStaticMeshMerges.Single())); + } +} diff --git a/TombLib/TombLib/LevelData/LevelSettings.cs b/TombLib/TombLib/LevelData/LevelSettings.cs index 97fa8545f..fa6702809 100644 --- a/TombLib/TombLib/LevelData/LevelSettings.cs +++ b/TombLib/TombLib/LevelData/LevelSettings.cs @@ -35,7 +35,7 @@ public enum VariableType public class AutoStaticMeshMergeEntry : ICloneable, IEquatable { - public string StaticMesh => parent.WadTryGetStatic(new WadStaticId(meshId)).ToString(parent.GameVersion); + public string StaticMesh => GetStaticMeshName(); private readonly LevelSettings parent; public uint meshId; @@ -53,9 +53,32 @@ public AutoStaticMeshMergeEntry(uint staticMesh, bool merge, bool interpretShade ClearShades = clearShades; } + private string GetStaticMeshName() + { + var staticMeshId = new WadStaticId(meshId); + var staticMesh = parent?.WadTryGetStatic(staticMeshId); + + if (staticMesh == null) + { + if (parent == null) + { + return staticMeshId.ToString(); + } + + return staticMeshId.ToString(parent.GameVersion); + } + + return staticMesh.ToString(parent.GameVersion); + } + + public AutoStaticMeshMergeEntry Clone(LevelSettings newParent) + { + return new AutoStaticMeshMergeEntry(meshId, Merge, InterpretShadesAsEffect, TintAsAmbient, ClearShades, newParent); + } + public AutoStaticMeshMergeEntry Clone() { - return (AutoStaticMeshMergeEntry)MemberwiseClone(); + return Clone(parent); } object ICloneable.Clone() @@ -242,7 +265,7 @@ public LevelSettings Clone() result.Textures = Textures.ConvertAll(texture => (LevelTexture)texture.Clone()); result.AnimatedTextureSets = AnimatedTextureSets.ConvertAll(set => set.Clone()); result.ImportedGeometries = ImportedGeometries.ConvertAll(geometry => geometry.Clone()); - result.AutoStaticMeshMerges = AutoStaticMeshMerges.ConvertAll(entry => entry.Clone()); + result.AutoStaticMeshMerges = AutoStaticMeshMerges.ConvertAll(entry => entry.Clone(result)); return result; }