Let a dialog opened over another dialog be closed
The "no research data" explainer is the only dialog in the game that opens ON TOP of another one - the skill tree or the ship lab, from the button that was just refused. IconButton._blocked_by_modal() refuses input to any button sitting behind an open panel, and it had no notion of stacking order: it saw the lab still visible, saw it was not an ancestor of the popup's close button, and killed the touch. Every button in the explainer was dead, including the only way out of it. Reported from the game. The check now compares draw order. A panel that this button's own panel is drawn on top of is behind it, not over it, and is ignored; a panel drawn above it still blocks, so the lab's own buttons stay dead while the popup covers them. Buttons belonging to no panel - the HUD - are unchanged and still blocked by anything open. The existing test missed this because it dismissed the popup by calling close_menu() directly, which is not what a player can do. Case D presses the button, and asserts the reverse too. Verified in both directions: with the fix reverted it fails with "the explainer close button is blocked by the lab behind it - the dialog is inescapable". 172/172. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019AJMdB7iuHuLFZM1aBu3GD
This commit is contained in:
parent
9872cb9930
commit
693919dadb
2 changed files with 62 additions and 2 deletions
|
|
@ -130,6 +130,7 @@ func _blocked_by_modal() -> bool:
|
|||
# touches through the GUI system swallows them before they ever get
|
||||
# there. So the panels stay transparent to input and the buttons check
|
||||
# instead.
|
||||
var own_modal: Node = _own_modal()
|
||||
for menu in get_tree().get_nodes_in_group("modal_menus"):
|
||||
# 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
|
||||
|
|
@ -137,11 +138,42 @@ func _blocked_by_modal() -> bool:
|
|||
# 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
|
||||
if not menu.is_visible_in_tree():
|
||||
continue
|
||||
if menu.is_ancestor_of(self):
|
||||
continue
|
||||
# Stacking order matters, and used not to be considered at all. A
|
||||
# panel that this button's own panel is drawn ON TOP OF sits behind
|
||||
# it, not over it, so it must not swallow the input. The research
|
||||
# shortfall popup opens over the skill tree and the ship lab, and
|
||||
# without this every button in it - its close button included - was
|
||||
# dead, leaving the player no way out of the dialog.
|
||||
if own_modal != null and not _covers(menu, own_modal):
|
||||
continue
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
# The modal panel this button lives inside, or null for a HUD button that
|
||||
# belongs to no panel (those stay blocked by any open panel, as before).
|
||||
func _own_modal() -> Node:
|
||||
var node: Node = get_parent()
|
||||
while node != null:
|
||||
if node.is_in_group("modal_menus"):
|
||||
return node
|
||||
node = node.get_parent()
|
||||
return null
|
||||
|
||||
|
||||
func _covers(other: Node, own: Node) -> bool:
|
||||
# Later siblings draw on top. Different parents means one of them is
|
||||
# nested inside something else - the build menu's info popup is a child
|
||||
# of the build menu - and there the conservative answer is "covered".
|
||||
if other.get_parent() != own.get_parent():
|
||||
return true
|
||||
return other.get_index() > own.get_index()
|
||||
|
||||
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in a new issue