Draw the neon components in the editor, not just at runtime

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
This commit is contained in:
Claude 2026-09-08 14:13:51 +02:00
commit 9872cb9930
3 changed files with 19 additions and 0 deletions

View file

@ -1,3 +1,4 @@
@tool
class_name NeonPanel
extends Control
@ -39,6 +40,12 @@ var design_centre: Vector2 = Vector2.ZERO
func _ready() -> void:
# _fit_to_screen() below rewrites offset_left/right/top/bottom. Under
# @tool that runs against the editor viewport, overwriting the authored
# layout and dirtying the scene, so the card previews at its authored
# size and is only ever fitted at runtime.
if Engine.is_editor_hint():
return
# Fitting adjusts the four offsets around a fixed centre, which is only
# meaningful for a card pinned to a point - both anchor pairs collapsed,
# as a centred dialog's are. A panel stretched between different anchors