## 营地子界面功能窗口基类(锻造工坊/秘宝匣/天赋树/奖励格图鉴四子界面公共形态): ## 居中定尺寸窗壳(石板皮窗板+半透明压暗遮罩)+顶栏(铭牌+钥石徽)+内容列+底栏返回钮。 ## 窗几何单点=WINDOW_SIZE(camp.md v2.5 起点 720×640);窗内滚动=内容体超高由子类滚动容器承载(窗不随内容涨)。 ## 开合可见性归模态栈(登记层开合一律走栈);返回钮只发 closed——关层编排归 presenter(组合根单口)。 ## 余额徽随子类 refresh_camp 刷新(钥石读数=投影单口,禁第二账本)。 class_name CampSubViewBase extends Control signal closed const WINDOW_SIZE := Vector2(720, 640) # 功能窗口起点定值单点(camp.md v2.5——生涯页经本常量引用,禁第二处字面值) var _balance_label: Label # 钥石徽数值行(探针直读面——ui_probe 余额文案断言改指新界面) ## 壳构建(子类 _init 调用一次):content 由子类先建好传入(列容器/滚动容器皆可)。 ## 窗壳骨架=UiKit.modal_shell(dim 全屏压暗+CenterContainer 居中+石板皮窗板;min_size 参数保持 ZERO ## 使窗板尺寸经 custom_minimum_size 精确可钉 720×640——panel_skinned 边距被 PANEL_SLICE 钳到 16 为既有工厂行为) func _build_shell(title: String, icon_path: String, content: Control) -> void: # 半透明压暗遮罩 0.6(camp.md v2.5——场景根留底可见,窗口之下垫遮罩;交互聚焦由遮罩 STOP 兜底) var shell := UiKit.modal_shell(self, Color(UiKit.DIM, 0.6), Vector2.ZERO, 8, UiKit.panel_skinned(Vector4(14, 12, 14, 12))) shell.panel.custom_minimum_size = WINDOW_SIZE _build_top_bar(shell.box, title, icon_path) content.size_flags_vertical = Control.SIZE_EXPAND_FILL # 内容米板身(柜台行板对比底=PanelData——旧柜台面板形态延续,行板墨色对比表不脱锚) var body := PanelContainer.new() body.add_theme_stylebox_override("panel", UiKit.panel_flat(UiKit.PANEL_DATA, UiKit.PANEL_BORDER, UiKit.RADIUS_OBJECT, 1, Vector4(10, 10, 10, 10))) body.size_flags_vertical = Control.SIZE_EXPAND_FILL body.add_child(content) shell.box.add_child(body) _build_bottom_bar(shell.box) visible = false # 登记模态初始隐(开合走栈) ## 顶栏域:铭牌(标题)+钥石徽(余额徽单点——子类 refresh_camp 刷新数值行) func _build_top_bar(col: VBoxContainer, title: String, icon_path: String) -> void: var top := HBoxContainer.new() top.add_theme_constant_override("separation", 10) col.add_child(top) var plaque := PanelContainer.new() plaque.add_theme_stylebox_override("panel", UiKit.panel_flat(UiKit.PANEL_DATA, UiKit.PANEL_BORDER, UiKit.RADIUS_OBJECT, 1, Vector4(14, 8, 14, 8))) top.add_child(plaque) var head := HBoxContainer.new() head.add_theme_constant_override("separation", 6) plaque.add_child(head) if icon_path != "": var ic := UiKit.icon_rect(icon_path, 32) # 头带图标缺位 null → 纯文本回退 if ic != null: head.add_child(ic) head.add_child(UiKit.label(title, UiKit.FS_TITLE, true, UiKit.INK_TITLE)) var spacer := Control.new() spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL top.add_child(spacer) var badge := UiKit.keystone_badge("钥石 0") # UiKit 工厂单点(烛光黄底深墨字) top.add_child(badge) _balance_label = badge.value_label ## 底栏域:返回营地钮(closed 信号——关层编排归 presenter) func _build_bottom_bar(col: VBoxContainer) -> void: var bottom := HBoxContainer.new() bottom.add_theme_constant_override("separation", 10) col.add_child(bottom) var back := UiKit.button("返回营地") back.pressed.connect(_emit_closed) bottom.add_child(back) var spacer2 := Control.new() spacer2.size_flags_horizontal = Control.SIZE_EXPAND_FILL bottom.add_child(spacer2) func open_camp(data: Dictionary) -> void: refresh_camp(data) visible = true # 开可见性由栈承载(本行为开层数据投喂的收尾拍) func refresh_camp(data: Dictionary) -> void: pass # 子类覆写(余额徽刷新+各自行板/门判据) func _emit_closed() -> void: closed.emit()