Files
gplan-2/game/presentation/main_esc_flow.gd
T

57 lines
2.8 KiB
GDScript

## 组合根 Esc 流程承接件(产品码首个键盘输入入口——main._unhandled_input 同名薄委托落地):
## Esc 四态路由(契约 9 判据单点=ModalStack 登记册现开集合,禁手枚名单)+三出口动线。
## 静态承接件零成员态(仿 main_overlay_flow 形态——main 侧留同名薄委托,探针 main.X 路径零改动)。
class_name MainEscFlow
extends RefCounted
## 营地语境判据(Q1 甲——场景根 visible;子界面开态抑制由契约 9① 现开集合承载,不并入本谓词)
static func is_camp_context(root: Variant) -> bool:
return root.ui.modals.camp.scene != null and root.ui.modals.camp.scene.visible
## Esc 优先序(camp.md v2.3 定稿 2026-11-01 用户裁——有功能窗开着→先关最上层窗,覆盖卡⑤ 契约 9①
## 的 Q1 甲无反馈;设置开在浮窗之上仍无反馈=契约 3 保留):
## ①功能窗开着→close 最上层窗→①'设置开在浮窗之上→无反馈→②浮窗开→close(Q2 同键单义)→
## ③营地语境→open→④非营地→无反馈
static func on_esc_input(root: Variant) -> void:
var esc: Control = root.ui.modals.camp.esc_overlay
var window := _topmost_camp_window(root)
if window != null:
root.ui.flow.close(window) # ① 先关最上层功能窗(v2.3 定稿)
return
if root.ui.modals.menu.settings_overlay.visible:
return # ①' 设置开在浮窗之上 → 无反馈(浮窗不隔层关闭——契约 3)
if esc.visible:
root.ui.flow.close(esc) # ② 再按 Esc 关窗
return
if is_camp_context(root):
root.ui.flow.open(esc) # ③ 营地语境唤起
# ④ 非营地语境 → 无反馈
# 五功能窗现开查询(camp.md v2.3 五窗互斥单开——模态栈深恒 1,至多一窗在开;生涯页入窗集)
static func _topmost_camp_window(root: Variant) -> Control:
for w: Control in [root.ui.modals.camp.forge, root.ui.modals.camp.treasure, root.ui.modals.camp.tree,
root.ui.modals.camp.codex, root.ui.modals.menu.career_overlay]:
if w != null and w.visible:
return w
return null
## 返回主菜单动线(契约 4):首步 close 浮窗(缺此步浮窗残留主菜单上方)→营地与选档层同收+开始层恢复
static func _on_return_to_menu(root: Variant) -> void:
root.ui.flow.close(root.ui.modals.camp.esc_overlay)
root._camp_pres.on_camp_closed() # 关层收闭单口(卡④ T3——营地层与选档层同收+开始层恢复)
## 设置出口(浮窗登记在设置层之下——open 只隐上方层,浮窗由树序遮挡非属性隐藏;关后重现=栈语义)
static func _on_settings(root: Variant) -> void:
root.ui.flow.open(root.ui.modals.menu.settings_overlay)
## 退出出口(_quit_game 原样复用——settings_store.save_settings+quit,零语义副作用)
static func _on_quit(root: Variant) -> void:
root._quit_game()