Files
gplan-2/game/presentation/views/save_select_overlay.gd
T
DKChan a6614a3b8e iter33 卡③ T1+T2+T3: 选档界面新建(3 存档位 新档/进档/删档)+组合根接线+断言批
视图 save_select_overlay.gd:页壳先例(career 同款)纵列三行槽卡;摘要三项(钥石徽/通关局/总局——
裁决 4 零断点读数);操作集二分(空/坏槽=仅新档,有档=进档+删档——Q2 甲坏槽按空呈现);删档只发
意图信号(二次确认归组合根);零预选(Q1 甲零选中态字段);零新素材零新色值(契约 7)。
组合根:LAYER_CONTRACT 加行(生涯同档)+_open_save_select 开层+_save_select_data 窥视取数
(occupied=has_file∧readable)+三回调;暂行落点 CampOverlay(Q3 乙,动线序=先落点开层不关选档);
ConfirmDialog 消费方编排(静态常驻接线→open 前设消费方按量分派——sl8,_start_adventure_from_menu
同步设消费方)。窥视读器补 has_file 位(T0 对齐结论:空/有档二分判定来处,非摘要第四项)。
断言批:struct 段(sl1 计数/禁滚动+sl2 逐槽读数+sl3 禁词+sl4 二分+sl9 不预选);click 段
(sl5 新档链+sl6 进档链+sl7 确认双路径+sl8 分派单口+sl12 动线序逐帧采样);flow 步(sl10
返回路径+ESC 不响应)。开层探针=函数直调中间态(「进入存档」钮归卡② mn3)。
2026-10-22 05:07:51 +08:00

112 lines
5.5 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
## 选档界面·全屏页:3 存档位(新档/进档/删档)+ 槽摘要三项(钥石余额/通关局数/冒险总局数)。
## 结构树层级:选档 → 进档 → 营地(本面零存档内功能入口——禁营地/冒险/生涯跳转与购买/查看入口);
## 删档必经二次确认(确认弹窗与分派归组合根消费方编排——本面只发意图信号)。
## 槽数与槽态(空/有档)唯一来自组合根喂入数据(open_save_select 每开重建——组合根经卡① 窥视 API
## 取数;视图禁自数文件/禁自拼槽名/禁硬编码槽判定);Q1 甲=零预选(视图零选中态字段、零持久化)。
## 摘要面仅三项,零断点/未完冒险读数(裁决 4——槽卡只消费喂入三键)。
## 构成件全部经 UiKit 工厂产出——零新素材/新色值(契约 7)。
class_name SaveSelectOverlay
extends Control
signal closed
signal new_slot_requested(slot: int)
signal load_slot_requested(slot: int)
signal delete_slot_requested(slot: int)
var _rows_box: VBoxContainer
var _summary_labels: Dictionary[int, Label] = {} # 槽号→摘要读数 label(通关/冒险两值——探针取值缝)
var _occupied_flags: Dictionary[int, bool] = {} # 槽号→有档态(操作集二分断言缝;判定源=喂入数据)
var _new_btns: Dictionary[int, Button] = {} # 槽号→新档钮(空/坏槽——操作集断言与点击链驱动缝)
var _load_btns: Dictionary[int, Button] = {} # 槽号→进档钮(有档槽)
var _delete_btns: Dictionary[int, Button] = {} # 槽号→删档钮(有档槽——确认链驱动缝)
func _init() -> void:
# 全屏页壳(career_overlay 同款先例——暖亮底+石纹+暗角+56px 通栏顶条+内容列)
var page: Dictionary[Variant, Variant] = UiKit.page_shell(self, true)
var top: HBoxContainer = page.top_row
top.add_child(UiKit.label("存 档",UiKit.FS_TITLE, true, UiKit.WARM))
var top_sp := Control.new()
top_sp.size_flags_horizontal = Control.SIZE_EXPAND_FILL
top.add_child(top_sp)
var close_btn := UiKit.button("返回", 90.0) # 紧凑返回钮(生涯/设置先例形制)
close_btn.tooltip_text = "关闭选档界面,返回主菜单(进入存档位前不发生任何进度读写)"
close_btn.pressed.connect(_emit_closed)
top.add_child(close_btn)
var box: VBoxContainer = page.box
# 对比度口径:亮底页用亮墨族 token(career_overlay 同款——深墨族禁用)
box.add_child(UiKit.label("选择一个存档位进入。空存档位可新开档;删档需二次确认。",
UiKit.FS_HINT, false, UiKit.WARM_SOFT))
_rows_box = VBoxContainer.new()
_rows_box.add_theme_constant_override("separation", 10)
box.add_child(_rows_box)
visible = false # 显式初始化——不靠树序巧合(缺陷⑤家族纪律)
# ---- 开层(组合根唯一调用口——槽数据随开重建;删档确认后就地重喂刷新)----
# data = {"slots": [{"slot": int, "occupied": bool, "keystone": int, "cleared": int, "total": int}, ...]}
# 槽数=数组长度(位数唯一在卡① 承载面 SLOT_COUNT);occupied=组合根经窥视 API 判定
# (has_file∧readable——坏槽/高版本槽按空槽呈现,Q2 裁甲);摘要仅消费三键(裁决 4)。
func open_save_select(data: Dictionary) -> void:
for c in _rows_box.get_children():
_rows_box.remove_child(c)
c.queue_free() # 先摘树后释放——重建无同帧叠影
_slot_labels_clear()
var slots: Array = data.get("slots", []) as Array
for sd: Dictionary in slots:
_build_slot_row(sd)
visible = true
func _slot_labels_clear() -> void:
_summary_labels.clear()
_occupied_flags.clear()
_new_btns.clear()
_load_btns.clear()
_delete_btns.clear()
func _build_slot_row(sd: Dictionary) -> void:
var slot := int(sd.get("slot", 0))
var occupied := bool(sd.get("occupied", false))
_occupied_flags[slot] = occupied
var row := HBoxContainer.new()
row.add_theme_constant_override("separation", 14)
_rows_box.add_child(row)
var name_l := UiKit.label("存档位 %d" % slot,UiKit.FS_SUB, true, UiKit.WARM)
name_l.custom_minimum_size = Vector2(110, 0)
row.add_child(name_l)
var sp := Control.new()
sp.size_flags_horizontal = Control.SIZE_EXPAND_FILL
if occupied:
row.add_child(UiKit.keystone_badge("钥石 %d" % int(sd.get("keystone", 0))))
var summary_l := UiKit.label("通关 %d 局 · 冒险 %d 局" % [int(sd.get("cleared", 0)), int(sd.get("total", 0))],
UiKit.FS_BODY, false, UiKit.CANDLE)
_summary_labels[slot] = summary_l # 摘要读数缝(禁词断言枚举 Label 全集时含此件)
row.add_child(summary_l)
row.add_child(sp)
var load_btn := UiKit.primary_button("进档")
load_btn.tooltip_text = "激活存档位 %d 并进入营地" % slot
load_btn.pressed.connect(func() -> void: load_slot_requested.emit(slot))
row.add_child(load_btn)
_load_btns[slot] = load_btn
var del_btn := UiKit.danger_button("删档", "删除存档位 %d(需二次确认——删除后该档不可恢复)" % slot)
del_btn.pressed.connect(func() -> void: delete_slot_requested.emit(slot))
row.add_child(del_btn)
_delete_btns[slot] = del_btn
else:
row.add_child(UiKit.label("空存档位",UiKit.FS_BODY, false, UiKit.WARM_FAINT))
row.add_child(sp)
var new_btn := UiKit.primary_button("新档")
new_btn.tooltip_text = "在存档位 %d 新开一档(初始白板)" % slot
new_btn.pressed.connect(func() -> void: new_slot_requested.emit(slot))
row.add_child(new_btn)
_new_btns[slot] = new_btn
func _emit_closed() -> void:
closed.emit()