## 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[Variant] = [] slots.assign(data.get("slots", [])) # 元素为 Dictionary(喂入合同)——typed 容器过类型闸 R1 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()