class_name PopupBackdrop extends ColorRect ## Dims everything behind an open popup and keeps clicks from reaching the buttons ## under it. ## ## The backdrop sits above the rest of its parent and below the popups it belongs to. ## Popups close themselves when clicked outside, and the backdrop keeps that click from ## reaching the buttons behind them. var _popups: Array[BasePopup] = [] ## Adds a backdrop to [param parent] and moves [param popups] above it. The backdrop ## shows while any of them is open. static func add_to(parent: Control, popups: Array[BasePopup]) -> PopupBackdrop: var backdrop: PopupBackdrop = PopupBackdrop.new() backdrop.name = "PopupBackdrop" backdrop.mouse_filter = Control.MOUSE_FILTER_STOP backdrop._popups = popups parent.add_child(backdrop) backdrop.color = backdrop.get_theme_color(&"backdrop", &"Palette") backdrop.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) for popup: BasePopup in popups: parent.move_child(popup, -1) popup.visibility_changed.connect(backdrop._update) popup.closing.connect(backdrop._on_popup_closing) popup.opening.connect(backdrop._on_popup_opening) backdrop._update() return backdrop func _notification(what: int) -> void: # The dimming colour comes from the theme, which can be switched in Settings if what == NOTIFICATION_THEME_CHANGED: color = get_theme_color(&"backdrop", &"Palette") func _update() -> void: var was_visible: bool = visible visible = _popups.any(func(popup: BasePopup) -> bool: return popup.visible) if visible && !was_visible: Anim.fade_in(self) # A popup opened again while closing stops the backdrop fading out func _on_popup_opening() -> void: var fade_tween: Tween = Anim.tween(self, &"fade") if fade_tween == null || modulate.a >= 1.0: modulate.a = 1.0 return fade_tween.tween_property(self, "modulate:a", 1.0, Anim.FAST) # Fades out with the last open popup, which hides the backdrop when it has closed func _on_popup_closing() -> void: if _popups.any(func(popup: BasePopup) -> bool: return popup.visible && !popup.is_closing): return var fade_tween: Tween = Anim.tween(self, &"fade") if fade_tween != null: fade_tween.tween_property(self, "modulate:a", 0.0, Anim.FAST)