Fix every button being permanently blocked after closing the build menu

The real cause of "the crafter buttons do nothing", reported three
times. IconButton._blocked_by_modal tested `menu.visible`, but hiding a
parent leaves a child's own `visible` flag true - and the build menu's
info popup is itself one of the modal panels. So opening any building's
info popup and then closing the build menu with the X left an invisible
popup still claiming to be open, and from that moment EVERY button in
the game was blocked, with no way for a player to get out of it.

It tests is_visible_in_tree() now, and closing the build menu also
closes its popup rather than leaving it half-open.

My earlier attempts kept missing it because the probes called the
handlers directly - they exercised the crafter logic, which was fine all
along, and never the input path in that state. The regression test
reproduces the exact sequence: open the build menu, show a building's
info, hide the menu, then check an unrelated button still fires.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Loïc Wisniewski 2026-08-11 23:41:00 +02:00
commit ee9d6ad9c6
3 changed files with 40 additions and 2 deletions

View file

@ -132,6 +132,30 @@ func _process(delta: float) -> bool:
quit(1)
return true
print("touch on the panel consumed, fleet target unchanged")
# --- 5. a hidden parent must not leave a panel "open" -------
# The build menu's info popup is itself a modal panel. Hiding the
# build menu leaves the popup's own `visible` flag true, so a
# guard testing `visible` rather than `is_visible_in_tree()`
# blocked EVERY button in the game from then on - with no way for
# a player to get out of it. Reported three times as "the buttons
# do nothing".
skill_menu.visible = false
var controller2: Node = scene.get_node("BuildController")
controller2._on_build_pressed()
controller2._show_building_info(GameState.BUILDING_SHIP_CRAFTER)
scene.get_node("UI/BuildMenu").visible = false
var info: Control = scene.get_node("UI/BuildMenu/InfoPopup")
print("popup after hiding its parent: visible=%s in_tree=%s" % [
info.visible, info.is_visible_in_tree()
])
outside_fired = false
_tap(map_button)
if not outside_fired:
print("TEST_MODAL_BLOCKS_INPUT: FAIL (a panel hidden with its parent still blocks every button)")
quit(1)
return true
print("hidden-with-parent panel no longer blocks anything")
print("TEST_MODAL_BLOCKS_INPUT: PASS")
quit(0)
return true