Skip to content

Guard Level Settings static-mesh bindings against missing/stale merge entries#1212

Open
Copilot wants to merge 2 commits into
developfrom
copilot/fix-null-reference-exception-again
Open

Guard Level Settings static-mesh bindings against missing/stale merge entries#1212
Copilot wants to merge 2 commits into
developfrom
copilot/fix-null-reference-exception-again

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 20, 2026

Opening Level Settings could throw from DataGridView bindings when the Static Meshes tab evaluated merged static entries with no resolvable backing static mesh. The same failure mode could surface anywhere cloned merge entries retained a stale LevelSettings parent.

  • Problem

    • AutoStaticMeshMergeEntry.StaticMesh assumed WadTryGetStatic(...) always returned a mesh and immediately dereferenced it.
    • LevelSettings.Clone() preserved the original parent reference inside cloned merge entries, so bindings could resolve against outdated settings state.
  • Changes

    • Null-safe static mesh display
      • Replaced the direct dereference in AutoStaticMeshMergeEntry.StaticMesh with a guarded lookup.
      • When the mesh cannot be resolved, the binding now falls back to the static ID name for the current game version instead of throwing.
    • Correct clone reparenting
      • Added a clone path that rebinds AutoStaticMeshMergeEntry to the cloned LevelSettings.
      • Updated LevelSettings.Clone() to use the reparenting clone so merge entries no longer retain stale references.
  • Result

    • The Level Settings grids can render merged static mesh entries even when the source static is missing or the settings instance has been cloned.
    • This removes the TargetInvocationException/null-reference path from the Static Meshes tab and related bindings.
  • Example

    private string GetStaticMeshName()
    {
        var staticMeshId = new WadStaticId(meshId);
        var staticMesh = parent?.WadTryGetStatic(staticMeshId);
    
        if (staticMesh == null)
            return parent == null ? staticMeshId.ToString() : staticMeshId.ToString(parent.GameVersion);
    
        return staticMesh.ToString(parent.GameVersion);
    }

Copilot AI changed the title [WIP] Fix null reference exception in merged statics tab Guard Level Settings static-mesh bindings against missing/stale merge entries Apr 20, 2026
Copilot AI requested a review from Nickelony April 20, 2026 08:31
@Nickelony
Copy link
Copy Markdown
Collaborator

@copilot Would you be able to provide reproduction steps for the original issue? What do we have to do in order to get the original error before the fix was applied? Also, please double-check that the changes don't cause any regressions for other places in the code.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 20, 2026

@copilot Would you be able to provide reproduction steps for the original issue? What do we have to do in order to get the original error before the fix was applied? Also, please double-check ...

I re-checked this around 6dd15f0.

The easiest pre-fix repro is:

  1. Open a level that has at least one entry in AutoStaticMeshMerges.
  2. Make that entry unresolved in the current settings, e.g. remove/unload the WAD that contains the static mesh.
  3. Open Level Settings and go to Static Meshes.
  4. Before the fix, the grid evaluated AutoStaticMeshMergeEntry.StaticMesh, WadTryGetStatic(...) returned null, and the DataGridView surfaced it as a TargetInvocationException / null-reference.

There is also a clone-related variant: opening Level Settings clones LevelSettings, and before the fix the merge entries inside the clone still pointed at the original settings instance. If that old/new settings state diverged, the same binding path could blow up even though the dialog was working on the clone.

I have not been able to prove the exact "brand new empty level" sequence from the original report in this Linux sandbox, but the failure path above matches the stack/behavior and is what the fix addresses.

For regressions, I re-checked all AutoStaticMeshMergeEntry call sites and reran a targeted build of TombLib.Test with Windows targeting enabled in the sandbox. That build succeeds. The behavior change is limited to:

  • resolved statics still display exactly as before;
  • unresolved statics now fall back to the static ID/name instead of throwing;
  • cloned merge entries now point to the cloned LevelSettings, which is the intended behavior.

@Nickelony Nickelony added bug Something isn't working as intended. ready for review The Pull Request is finished and ready for review. labels Apr 20, 2026
@Nickelony Nickelony marked this pull request as ready for review April 20, 2026 17:01
@Nickelony Nickelony added this to the Version 2.1 milestone Apr 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working as intended. ready for review The Pull Request is finished and ready for review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TE: Null reference exception on merged statics tab in level settings

2 participants