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

@ -61,7 +61,13 @@ func _blocked_by_modal() -> bool:
# there. So the panels stay transparent to input and the buttons check
# instead.
for menu in get_tree().get_nodes_in_group("modal_menus"):
if menu.visible and not menu.is_ancestor_of(self):
# is_visible_in_tree(), NOT visible. Hiding a parent leaves the
# child's own `visible` flag true, and the build menu's info popup is
# itself a modal panel - so closing the build menu with the X left an
# invisible popup still claiming to be open, and every button in the
# game was blocked from then on. That is not a state a player can
# get out of.
if menu.is_visible_in_tree() and not menu.is_ancestor_of(self):
return true
return false