Files
gplan-2/game/presentation/modal_stack.gd
T
DKChan 8b9e55673f refactor(迭代27 T4): 波四 ModalFlow 抽取+互斥域 tags 化+双 context——对拍全同
P1-5/P2-7 组合根可测化+模态协议内聚(场景拆分后重估结论=抽取面收敛为模态编排域):
- modal_flow.gd 新纯逻辑类: 依赖仅 ModalStack+查询 Callable(审计处方)——开合编排
  (挂起兜底/排播排空/遮挡记账/开合同步)/棋盘输入锁谓词(三例外注入)/双形制角标谓词;
  V6 modal_flow_test 19 断言直接 new() 进 run_all(26→27 套)——测试抓出并修正
  挂起兜底 divergent return 一处(原 main 语义=先结挂起后继续开本层不短路)
- ModalStack 互斥域随层登记: register(m, tags) + TAG_NON_LOCKING/TAG_SCREEN_STATE
  封闭词表 + has_open_excluding_tags 组查询;原 has_open_excluding/_any 调用点拼装退役
  (main 五处判据迁移);main._modals=flow.stack(ui_struct _list 登记序断言缝保留)
- P1-5 控制器构造收拢 context: curio 16 参→CurioFlowContext/camp 13 参→CampFlowContext
  (字段逐一同名迁移,控制器可独立实例化)

验收: 对拍三变体全同;冒烟 1079/0+run_all 27 套+probe click+render golden 全绿
2026-10-15 00:31:36 +08:00

67 lines
2.8 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 = _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