113 lines
5.6 KiB
GDScript
113 lines
5.6 KiB
GDScript
## 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()
|