P1-6 类型闸(须 T1-T4 全落后——本波按执行顺序锁殿后): - tools/audit_type_hints.py 新机器闸(V7): R1 无类型容器注解/R2 有值返回缺返回类型/ R3 参数缺类型三规则+行级 # type-hint: ignore 显式白名单通道;产品码 core/data/presentation - 存量收口: 368 处显式 Array/Dictionary 非参数化注解→机械参数化(Array[Variant]/ Dictionary[Variant, Variant] 零行为面);13 处参数真类型(SaveManagerCore/ConfigDb/ BattleOrchestrator/MinesweeperRules/LevelRunner/SettingsStore 等) - 白名单豁免四处: board_generator generate/_attempt/legality/_finalize 的 db 参—— 测量面 _BoardRowStub 冒烟夹具鸭子型注入(typed 参拒 stub) - project.godot 拉起 gdscript/warnings/untyped_declaration=1(V7 源码断言在 smoke _smoke_type_gate) - static_scan 新 S9 类型闸规则;顺修历史 cd 错位(9-24 布局迁移后 /.. 落 game/ 致守卫 恒跳过静默空转——修复后 S1-S4/S9 首次实跑全绿)+S1/S2 增 ADR-0007-exempt 标记豁免通道 (main _seed_value 引擎熵源=文档化豁免面) 验收: 冒烟 1081/0(+V7×2)+run_all 27 套+static_scan 全绿+probe click+render golden+对拍三变体全同
67 lines
2.8 KiB
GDScript
67 lines
2.8 KiB
GDScript
# 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 → 被其隐藏的上方层(关闭恢复)
|
||
var _tags := {} # modal → 排除组标签集(迭代 27 T4——互斥域随层登记;P2-7 开态谓词收口)
|
||
|
||
# 排除组封闭词表(组合根登记用——新标签=改此处+评审,防调用点拼装回潮)
|
||
const TAG_NON_LOCKING := "non_locking" # 开态不计入棋盘输入锁与角标置灰(调试浮窗——迭代 18 卡⑦ T2 防线:DS_DEBUG 默认开×遮挡复活×has_open 组合=棋盘永久锁死)
|
||
const TAG_SCREEN_STATE := "screen_state" # 常驻屏态(关卡地图屏——自身开态不计入本屏角标判据)
|
||
|
||
|
||
func register(m: Control, tags: Array = []) -> void:
|
||
_list.append(m)
|
||
_tags[m] = tags
|
||
|
||
|
||
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
|
||
|
||
|
||
# 排除组开态查询(迭代 27 T4——P2-7 模态协议内聚:原「调用点排除式拼装」has_open_excluding/
|
||
# has_open_excluding_any 退役,排除语义随层登记(register tags),查询按组名集合表达。
|
||
# 只读查询零副作用——登记序/开合记账语义零改动;空标签集=全计(与旧 has_open 同形)。
|
||
func has_open_excluding_tags(exclude_tags: Array) -> bool:
|
||
for m in _list:
|
||
if is_instance_valid(m) and m.visible:
|
||
var mt: Array[Variant] = _tags.get(m, [])
|
||
var excluded := false
|
||
for t in exclude_tags:
|
||
if mt.has(t):
|
||
excluded = true
|
||
break
|
||
if not excluded:
|
||
return true
|
||
return false
|