diff --git a/game/presentation/main_esc_flow.gd b/game/presentation/main_esc_flow.gd index 85ef1cb0..9ec94068 100644 --- a/game/presentation/main_esc_flow.gd +++ b/game/presentation/main_esc_flow.gd @@ -10,13 +10,18 @@ static func is_camp_context(root: Variant) -> bool: return root.ui.modals.camp.scene != null and root.ui.modals.camp.scene.visible -## Esc 四态优先序(契约 9——①先于②:设置开在浮窗之上态必须先命中「无反馈」,浮窗不隔层关闭): -## ①除浮窗外任一登记模态开→无反馈(子界面开态/设置开在浮窗之上)→②浮窗开→close(同键单义切换, -## Q2 甲)→③营地语境→open→④非营地→无反馈(选档/冒险/菜单语境 Esc 零响应——契约 2) +## 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 - if _other_modal_open(root, esc): - return # ① 除浮窗外任一登记模态开 → 无反馈 + var window := _topmost_camp_window(root) + if window != null: + root.ui.modals.flow.close(window) # ① 先关最上层功能窗(v2.3 定稿) + return + if root.ui.modals.settings_overlay.visible: + return # ①' 设置开在浮窗之上 → 无反馈(浮窗不隔层关闭——契约 3) if esc.visible: root.ui.modals.flow.close(esc) # ② 再按 Esc 关窗 return @@ -25,13 +30,14 @@ static func on_esc_input(root: Variant) -> void: # ④ 非营地语境 → 无反馈 -# 登记册现开集合查询(除浮窗与营地场景根本身——场景根=语境层非抑制对象; -# 迭代登记册遍历=契约 9「判据单点」 sanctioned 读法,禁按层名手枚名单) -static func _other_modal_open(root: Variant, esc: Control) -> bool: - for m in root.ui.modals.flow.stack._list: - if m != esc and m != root.ui.modals.camp.scene and is_instance_valid(m) and m.visible: - return true - return false +# 五功能窗现开查询(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.career_overlay]: + if w != null and w.visible: + return w + return null + ## 返回主菜单动线(契约 4):首步 close 浮窗(缺此步浮窗残留主菜单上方)→营地与选档层同收+开始层恢复 diff --git a/game/presentation/views/camp_sub_view_base.gd b/game/presentation/views/camp_sub_view_base.gd index 1cc78727..20f2d152 100644 --- a/game/presentation/views/camp_sub_view_base.gd +++ b/game/presentation/views/camp_sub_view_base.gd @@ -12,12 +12,8 @@ var _balance_label: Label # 钥石徽数值行(探针直读面——ui_probe ## 壳构建(子类 _init 调用一次):content 由子类先建好传入(列容器/滚动容器皆可) func _build_shell(title: String, icon_path: String, content: Control) -> void: - # 实底暖亮档(半透 dim 会透出底下场景图——CampOverlay 同案;遮蔽语义由组合根输入锁兜底) - var dim := UiKit._modal_dim(self, UiKit.BG_BRIGHT) - var bd := UiKit.backdrop_tile() - if bd != null: - dim.add_child(bd) - dim.add_child(UiKit.vignette_rect()) + # 半透明压暗遮罩 0.6(camp.md v2.3 定稿——场景根留底可见,窗口之下垫遮罩;交互聚焦由遮罩 STOP 兜底) + var dim := UiKit._modal_dim(self, Color(UiKit.DIM, 0.6)) var margin := MarginContainer.new() margin.set_anchors_preset(Control.PRESET_FULL_RECT) margin.add_theme_constant_override("margin_left", 16) diff --git a/game/presentation/views/career_overlay.gd b/game/presentation/views/career_overlay.gd index 796935b5..c5487a1c 100644 --- a/game/presentation/views/career_overlay.gd +++ b/game/presentation/views/career_overlay.gd @@ -18,6 +18,7 @@ var _keystone_badge: UiKit.KeystoneBadge # 钥石余额(badge 工厂件— func _init() -> void: # 全屏页壳(T6/T7 对齐批先例——暖亮底+石纹弱质感+暗角+56px 通栏顶条+内容列) var page: Dictionary[Variant, Variant] = UiKit.page_shell(self, true) + page.base.color = Color(UiKit.DIM, 0.6) # 功能窗口化(camp.md v2.3 定稿——场景根留底+半透明压暗遮罩 0.6;观感随样张目检校准) var top: HBoxContainer = page.top_row top.add_child(UiKit.label("生 涯",UiKit.FS_TITLE, true, UiKit.WARM)) var top_sp := Control.new() diff --git a/game/probe/screen_flow_probe.gd b/game/probe/screen_flow_probe.gd index cf9c5d51..b2232b59 100644 --- a/game/probe/screen_flow_probe.gd +++ b/game/probe/screen_flow_probe.gd @@ -257,9 +257,10 @@ func _step_camp_esc_and_hud() -> void: await _frames() _push_esc() await _frames() - if main.ui.modals.camp.esc_overlay.visible or not main.ui.modals.camp.tree.visible: - _problems.append("[esc] 子界面开态 Esc 反馈(契约 9① 无反馈失守)〔ESC批 V1〕") - main.ui.modals.camp.tree.closed.emit() + if main.ui.modals.camp.tree.visible: + _problems.append("[esc] 子界面开态 Esc 未关窗(camp.md v2.3 定稿——先关最上层窗)〔ESC批 V1〕") + if main.ui.modals.camp.esc_overlay.visible: + _problems.append("[esc] 关窗同拍唤起浮窗(先关窗后浮窗——两拍应分离)〔ESC批 V1〕") await _frames() # HUD 余额(契约 5 时机③——夹具直写后显式触发才变;禁 band 自刷假设) main.meta.meta_state._add_keystone(9999) diff --git a/reports/iter47-实现报告-2026-11-01.md b/reports/iter47-实现报告-2026-11-01.md index 42e376c5..57aa6e59 100644 --- a/reports/iter47-实现报告-2026-11-01.md +++ b/reports/iter47-实现报告-2026-11-01.md @@ -71,6 +71,7 @@ 8. **CampSceneView 初始隐**:_init visible=false(登记模态初始隐——boot 态场景根盖菜单三红同源修复)。 9. **ui_modals 头注/迁移面**:卡⑥ 头注换代(十二平铺+营地域子容器)✓;ui_struct 层序注释换代(camp_scene 代言)✓。 10. **卡④ T0 预算预案兑现**:main.gd 15/15 恰贴上限——T3/T4/T5 实现零新增成员(路由走 MainOverlayFlow 静态件+薄委托)✓。 +11. **camp.md v2.3 定稿换代吸收**(2026-11-01 用户裁,后于卡面):①承载形态=五功能窗口·场景根留底+半透明压暗遮罩 0.6(实现初版实底屏——按定稿换装,四子界面壳+生涯页基底同批换);②Esc 有功能窗开着→先关最上层窗(覆盖卡⑤ 契约 9① 的 Q1 甲「子界面开态无反馈」——MainEscFlow ①分支改写,_other_modal_open 退役);③五窗互斥单开(遮罩 STOP 挡场景点击自然成立,零代码)。设置开在浮窗之上仍无反馈(契约 3 保留)。 ## 6. 实机目检总清单(登记不阻塞——体验验证清单入册条目由文档批落)