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 IconButton
extends Control
@ -142,6 +143,11 @@ func _blocked_by_modal() -> bool:
func _gui_input(event: InputEvent) -> void:
# @tool runs this in the editor too, where a click on the canvas would
# emit `pressed` at whatever it is wired to. The glyph is what we want
# visible there, not the behaviour.
if Engine.is_editor_hint():
return
if _blocked_by_modal():
return
if event is InputEventScreenTouch: