Skip to content

Rebuild an open scene tab when a writer rewrites its scene - #1071

Merged
saworbit merged 3 commits into
mainfrom
fix/open-scene-tab-reload
Sep 29, 2026
Merged

saworbit merged 3 commits into
mainfrom
fix/open-scene-tab-reload

Conversation

@saworbit

Copy link
Copy Markdown
Owner

Fixes #1068

Problem

project_rename_references and project_apply_changes rewrite .tscn files. The refresh from #1047 reloads what the editor's resource cache holds, and an open tab is not in it. The tab is a node tree the editor built from the file, so it kept the old scene, and the next editor_save_scene wrote that back over the file. The writer said success and editor_copies_reloaded: [].

What changed

  • The bridge's resource.refreshCached now also rebuilds the tab of a path open in the editor, with EditorInterface.reload_scene_from_path, and says so per path. It checks the reload took by the tab's root: a reload that happened replaced it.
  • A new bridge read, editor.openScenes, answers the open tabs and the unsaved report editor.getState already carries.
  • Before writing, both writers ask it. A rewritten scene open with unsaved changes refuses with 409 unsaved_changes. Before Godot 4.7 the engine cannot say, so any open one refuses with 409 dirty_state_unavailable. Both name the scenes and carry discard_unsaved: true in retry_with. Nothing is written. The confirmation previews make the same check, so they refuse what the call would.
  • discard_unsaved is a new boolean on both tools. It is the caller accepting the loss of the tab's unsaved changes, the same word scene_close uses.
  • Answers gain editor_scenes_reloaded. A tab left stale is named in editor_copy_errors with the reason and the way out.
  • viewport_create_test_lab rebuilds an open lab tab on overwrite, the way scene_create already reloads the scene it overwrites.
  • Along the way: the rename's refusal of a new_name already in use named no fix. The new harness block was the first to reach it, and the remedy check failed on it. It now names new_name as the field.
  • The discard_unsaved description is one short sentence. The first draft put the full listing 380 bytes over the tools/list budget, and the refusal already explains the argument where an agent reads it.

Engine facts this rests on

Measured with a throwaway editor plugin on 4.5.1, 4.6.2 and 4.7.2:

  • reload_scene_from_path is synchronous. It returns with a new root holding the new file, keeps whichever tab was current, and drops the tab's unsaved changes and undo history. On 4.7 the scene leaves get_unsaved_scenes.
  • On 4.5 and 4.6 a second reload in the same frame does nothing and prints nothing. So the bridge rebuilds one tab a request and answers the rest pending, and the server asks again. Commands are taken off the queue before any runs, so each request lands on a later frame.
  • On 4.5 and 4.6 a reload of a path no tab holds clears the current scene's undo history, with no message. 4.7 prints an error instead. So the bridge only asks for paths get_open_scenes lists.

Tests

  • Native: a rename rebuilds two clean open tabs across the pending retry. A rename refuses an unsaved tab and an unknown one, writes nothing, and goes through with discard_unsaved. Apply refuses the same way before its check runs. A tab that could not be rebuilt is named. The check asks only when it can matter.
  • Live harness, tests/scene_tab_reload.ps1: the steps from the issue. A scene with a connection is opened and edited, the rename refuses, the scene is saved, and the rename runs (with discard_unsaved before 4.7). Then an edit and a save. The file keeps the new method name and the edit, on all three lines.

project_rename_references and project_apply_changes reloaded only the
editor's cached copies. An open tab is a node tree built from the file, so
it kept the old scene and the next editor_save_scene wrote it back over
the file (#1068).

The bridge now rebuilds the tab with reload_scene_from_path, one tab a
request because a second reload in the same frame does nothing on 4.5
and 4.6, and checks the root was replaced. Before writing, both tools ask
the new editor.openScenes read and refuse a rewritten scene whose tab has
unsaved changes, or any open one before 4.7, unless discard_unsaved is
passed. The previews make the same check. viewport_create_test_lab
rebuilds an open lab tab on overwrite.

The rename's refusal of a new_name already in use now names the field.
The first description put the full listing 380 bytes over its budget.
The refusal already explains the argument where an agent reads it, so
the schema says only what true allows. Contract snapshots regenerated.
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests Test suites and the contracts they assert addon The Godot addon and the in-engine GDExtension mcp-protocol The MCP wire surface: tools, schemas, annotations labels Sep 29, 2026
The rename writes files in scan order, which is alphabetical on NTFS and
not on APFS or ext4, so the test failed on macOS and the sanitizer job.
@saworbit
saworbit merged commit 20e163e into main Sep 29, 2026
28 checks passed
@saworbit
saworbit deleted the fix/open-scene-tab-reload branch September 29, 2026 22:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

addon The Godot addon and the in-engine GDExtension documentation Improvements or additions to documentation mcp-protocol The MCP wire surface: tools, schemas, annotations tests Test suites and the contracts they assert

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Editor sync] Reload an open scene tab when a file writer rewrites its scene

1 participant