Nothing under ui/ or vfx/ was marked @tool, so every hand-drawn control
rendered as an empty rect in the editor. BuildMenu.tscn positions its
buttons with hand-tuned pixel offsets (offset_left = -204) around a glyph
identified only as `icon = 8` - laying out invisible boxes by number.
@tool on the three scene-placed components that are safe to run in the
editor, covering 23 of the 34 placements: IconButton (20 scenes),
TouchJoystick (2), NeonPanel (1).
Two of them mutate persisted properties on _ready, which under @tool
would write computed values back into the .tscn every time the scene was
opened, so both are guarded with Engine.is_editor_hint():
NeonPanel._fit_to_screen() rewrites all four offsets
TouchJoystick._relayout() overwrites max_radius, which is @export
IconButton's _gui_input is guarded too, so clicking a button on the
editor canvas does not emit `pressed`.
The autoload-heavy drawers (ResourceBar, PriceTag, QuestPanel,
ResourceTransferList, SkillTreeView, FormationEditor - 6 to 16
GameState./Quests. references each) are left alone; they need their call
sites guarded first.
Verified: 172/172 headless, and a --headless --editor pass loads the
project with no script errors. That pass only proves the scripts parse
under @tool - it never opens a scene, so it does not exercise the
in-editor _draw.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019AJMdB7iuHuLFZM1aBu3GD