59 lines
2.1 KiB
GDScript
59 lines
2.1 KiB
GDScript
extends Node
|
||
|
||
# 统一处理 UI 的 Esc 退出。可关闭界面加入 whaletown_escape_dismissible 分组,
|
||
# 并实现 is_escape_dismissible / get_escape_priority / request_escape_close。
|
||
const ESCAPE_DISMISSIBLE_GROUP: StringName = &"whaletown_escape_dismissible"
|
||
|
||
func _ready() -> void:
|
||
# 公告、排行榜等界面会暂停场景树,Esc 仍必须有效。
|
||
process_mode = Node.PROCESS_MODE_ALWAYS
|
||
|
||
func _input(event: InputEvent) -> void:
|
||
if not (event is InputEventKey):
|
||
return
|
||
var key_event: InputEventKey = event as InputEventKey
|
||
if not key_event.pressed or key_event.echo or key_event.keycode != KEY_ESCAPE:
|
||
return
|
||
if _hide_open_popup_menu() or _close_topmost_dismissible() or _release_control_focus():
|
||
get_viewport().set_input_as_handled()
|
||
|
||
func _hide_open_popup_menu() -> bool:
|
||
var popup_nodes: Array[Node] = get_tree().root.find_children("*", "PopupMenu", true, false)
|
||
for popup_node: Node in popup_nodes:
|
||
var popup: PopupMenu = popup_node as PopupMenu
|
||
if popup != null and popup.visible:
|
||
popup.hide()
|
||
return true
|
||
return false
|
||
|
||
func _close_topmost_dismissible() -> bool:
|
||
var target: Node = null
|
||
var target_priority: int = -2147483648
|
||
var dismissibles: Array[Node] = get_tree().get_nodes_in_group(ESCAPE_DISMISSIBLE_GROUP)
|
||
for dismissible: Node in dismissibles:
|
||
if not is_instance_valid(dismissible):
|
||
continue
|
||
if not dismissible.has_method("is_escape_dismissible") or not dismissible.has_method("request_escape_close"):
|
||
continue
|
||
var is_dismissible_variant: Variant = dismissible.call("is_escape_dismissible")
|
||
if not bool(is_dismissible_variant):
|
||
continue
|
||
var priority: int = 0
|
||
if dismissible.has_method("get_escape_priority"):
|
||
var priority_variant: Variant = dismissible.call("get_escape_priority")
|
||
priority = int(priority_variant)
|
||
if target == null or priority > target_priority:
|
||
target = dismissible
|
||
target_priority = priority
|
||
if target == null:
|
||
return false
|
||
target.call("request_escape_close")
|
||
return true
|
||
|
||
func _release_control_focus() -> bool:
|
||
var focus_owner: Control = get_viewport().gui_get_focus_owner()
|
||
if focus_owner == null:
|
||
return false
|
||
focus_owner.release_focus()
|
||
return true
|