# VERTICAL SLICE - NOT FOR PRODUCTION # 实现 GDD:design/ux/interaction-patterns.md(pattern 6 模态 overlay 层级纪律)。 # Date: 2026-09-12(code-review 修复批——自 main.gd 拆出,规范 1.1 状态装配独立成类) # 模态层级状态机:登记序 = 树序 = z 遮挡序;打开时显式隐藏树序在其上方的可见层、关闭恢复 # (缺陷⑤纪律载体:功能存在 ≠ 功能可达——遮挡关系不得靠树序巧合)。 # 纯逻辑零节点构建——组合根持有本类并喂入 Control;不持久化核心状态。 extends RefCounted var _list: Array[Control] = [] # 登记序 = z 遮挡序(低 → 高) var _occluded := {} # modal → 被其隐藏的上方层(关闭恢复) func register(m: Control) -> void: _list.append(m) func open(m: Control) -> void: var hidden: Array[Control] = [] var idx := _list.find(m) for i in range(idx + 1, _list.size()): var higher: Control = _list[i] if is_instance_valid(higher) and higher.visible: higher.visible = false hidden.append(higher) _occluded[m] = hidden m.visible = true func close(m: Control) -> void: m.visible = false for h in _occluded.get(m, []): if is_instance_valid(h): h.visible = true _occluded.erase(m) # 开态查询(T3 模态收口批 2026-10-02——组合根输入锁唯一判据:登记册上是否有任一层处于开态; # 可见性即开态,与 open/close 记账同源——组合根不再手工罗列各层) func has_open() -> bool: for m in _list: if is_instance_valid(m) and m.visible: return true return false # 排除式开态查询(迭代 17 卡③ 2026-10-06——暂停层入口守卫判据):skip 层自身的开态不计入 #(关卡地图屏系登记册模态成员=常态屏态,其上的地图屏角标必须可点;其余任一层开着=角标置灰)。 # 只读查询零副作用——登记序/开合记账语义零改动。 func has_open_excluding(skip: Control) -> bool: return has_open_excluding_any([skip]) # 多排除式开态查询(迭代 18 卡⑦ T2 防护——调试浮窗对局中可开后,棋盘输入锁与暂停角标置灰 # 判据须同时排除调试浮窗自身〔否则 DS_DEBUG 默认开×遮挡复活×has_open 组合=棋盘永久锁死—— # 审计🔴 S1+ 停机点防线〕;地图屏场景=地图屏+调试浮窗双排除)。语义同 has_open_excluding, # skip 集参数化;只读查询零副作用,登记序/开合记账语义零改动。 func has_open_excluding_any(skips: Array) -> bool: for m in _list: if skips.has(m): continue if is_instance_valid(m) and m.visible: return true return false