From 58e8903a3ca1d8aadc9d9d21095a82cf6f47ef9d Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Tue, 6 Oct 2026 06:56:14 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20=E5=AE=A1=E8=AE=A1=E5=B7=AE=E8=B7=9D?= =?UTF-8?q?=E2=91=A0=E2=91=A3=E2=91=A4=E2=91=A6=E5=9B=9B=E4=BB=B6=E8=90=BD?= =?UTF-8?q?=E5=9C=B0=EF=BC=88=E5=BA=95=E6=A0=8F85=E5=AE=9A=E9=AB=98+?= =?UTF-8?q?=E7=89=B9=E6=80=A7=E8=A1=8C=E9=99=90=E5=AE=BD=E6=88=AA=E6=96=AD?= =?UTF-8?q?/=E7=BB=93=E7=AE=97=E4=B8=A4=E5=88=97=E8=B4=A6=E8=A1=8C+DIM=5FN?= =?UTF-8?q?IGHT=E5=8E=8B=E6=9A=970.62/0.6+=E7=B4=A7=E5=87=91=E9=92=AE/?= =?UTF-8?q?=E6=A0=87=E9=A2=98=E5=B1=8F=E4=B8=BB=E6=93=8D=E4=BD=9C=E8=AF=AD?= =?UTF-8?q?=E4=B9=89=E5=AF=B9=E9=BD=90demo/E5=E7=88=86=E7=A0=B4=E5=B8=A6?= =?UTF-8?q?=E5=9B=9E=E6=BB=9Amagic=E6=97=8F=EF=BC=89+danger=5Fbutton=20min?= =?UTF-8?q?=5Fw=E5=8F=82=E6=95=B0=E5=8C=96=EF=BC=88=E6=94=BE=E5=BC=8390?= =?UTF-8?q?=E5=AE=BD=EF=BC=89=E2=80=94=E2=80=94=E8=BD=BB=E9=97=B8=E5=86=92?= =?UTF-8?q?=E7=83=9F782/0+probe=5Fgate=20--click=E5=85=A8=E7=BB=BF?= =?UTF-8?q?=EF=BC=9B=E4=B8=A4=E6=8E=A2=E9=92=88=E9=80=82=E9=85=8D=E4=B8=A4?= =?UTF-8?q?=E5=88=97=E8=B4=A6=E8=A1=8C=EF=BC=88ui=5Fprobe=20=5Fgp=5Fval/ui?= =?UTF-8?q?=5Fclick=5Fprobe=20=E5=90=8D=E5=80=BC=E6=8B=BC=E4=B8=B2?= =?UTF-8?q?=EF=BC=89=EF=BC=9Bui=5Faudit=5Fprobe.gd.uid=20=E4=BE=A7?= =?UTF-8?q?=E8=BD=A6=E8=A1=A5=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/presentation/ui_assembler.gd | 7 +- game/presentation/views/battle_end_overlay.gd | 87 +++++++++++++++---- game/presentation/views/level_map_screen.gd | 19 ++-- game/presentation/views/ui_kit.gd | 14 +-- game/smoke/ui_audit_probe.gd.uid | 1 + game/smoke/ui_click_probe.gd | 2 +- game/smoke/ui_probe.gd | 4 +- 7 files changed, 101 insertions(+), 33 deletions(-) create mode 100644 game/smoke/ui_audit_probe.gd.uid diff --git a/game/presentation/ui_assembler.gd b/game/presentation/ui_assembler.gd index 602f2d21..b2efcfba 100644 --- a/game/presentation/ui_assembler.gd +++ b/game/presentation/ui_assembler.gd @@ -138,11 +138,14 @@ static func build_start_overlay(host: Control, db = null) -> Dictionary: # 组帽·冒险(M2 分组) box.add_child(UiKit.label("── 冒 险 ──",UiKit.FS_CAPTION, false, UiKit.WARM_FAINT)) # 唯一试玩入口 = 正式「开始冒险」(三关序列);单关测试直入口(L2/L3)退役(2026-09-23 用户拍板) - var resumebtn := UiKit.button("▶ 继续上局") # 迭代 8 卡②——有断点才亮(可见性与关数文案归组合根刷新) + var resumebtn := UiKit.primary_button("▶ 继续上局") # 迭代 8 卡②——有断点才亮(可见性与关数文案归组合根刷新);主操作钮=审计差距⑤对齐 demo resumebtn.tooltip_text = "自最近停点恢复" resumebtn.visible = false box.add_child(resumebtn) - var lvbtn := UiKit.primary_button("▶ 开始冒险", "三关连探:地精洞窟 → 幽暗地域 → 灰矮人矿城") + # 主操作语义对齐 demo(2026-10-06 审计差距⑤——有档时「继续上局」才是首动作=主黄钮, + # 「开始冒险」=常规石钮;tooltip 保留) + var lvbtn := UiKit.button("▶ 开始冒险") + lvbtn.tooltip_text = "三关连探:地精洞窟 → 幽暗地域 → 灰矮人矿城" box.add_child(lvbtn) # 组帽·营地与系统 diff --git a/game/presentation/views/battle_end_overlay.gd b/game/presentation/views/battle_end_overlay.gd index 445873cf..978631ef 100644 --- a/game/presentation/views/battle_end_overlay.gd +++ b/game/presentation/views/battle_end_overlay.gd @@ -15,10 +15,16 @@ const COL_WARM := UiKit.WARM var _dim: ColorRect var _seal: Panel var _verdict: Label -var _rows_box: VBoxContainer # M9 三行账(GP/钥石/本关加成——demo ⑧;失败侧整行隐藏=P-C4 维持 OQ14) -var _gp_row: Label -var _ks_row: Label -var _bonus_row_l: Label +var _rows_box: VBoxContainer # M9 三行账(GP/钥石/本关加成——demo ⑧两列对齐 2026-10-06 审计差距④;失败侧整行隐藏=P-C4 维持 OQ14) +var _gp_row: HBoxContainer +var _gp_name: Label +var _gp_val: Label +var _ks_row: HBoxContainer +var _ks_name: Label +var _ks_val: Label +var _bonus_row_l: HBoxContainer +var _bonus_name: Label +var _bonus_val: Label var _cele: TextureRect # M9 庆祝立绘(idle 占位浮动——正式帧待资产批) var _btn: Button var _board_rect := Rect2() @@ -75,20 +81,32 @@ func _init() -> void: _rows_box.add_theme_constant_override("separation", 6) _rows_box.visible = false box.add_child(_rows_box) - _gp_row = UiKit.label("",UiKit.FS_SUB, true, UiKit.GOLD_DEEP) - _gp_row.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + # 两列对齐账行(审计差距④对齐 demo ⑧——项目名左/数值右,定宽 360) + _gp_row = _ledger_row() + _gp_name = _ledger_name(UiKit.FS_SUB, UiKit.GOLD_DEEP, true) + _gp_val = _ledger_value(UiKit.FS_SUB, UiKit.GOLD_DEEP, true) + _gp_row.add_child(_gp_name) + _gp_row.add_child(_gp_val) _rows_box.add_child(_gp_row) - _ks_row = UiKit.label("",UiKit.FS_BODY, true, UiKit.INK_LABEL) - _ks_row.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + _ks_row = _ledger_row() + _ks_name = _ledger_name(UiKit.FS_BODY, UiKit.INK_LABEL, false) + _ks_val = _ledger_value(UiKit.FS_BODY, UiKit.INK_LABEL, true) + _ks_row.add_child(_ks_name) + _ks_row.add_child(_ks_val) _ks_row.visible = false _rows_box.add_child(_ks_row) - _bonus_row_l = UiKit.label("",UiKit.FS_HINT, false, UiKit.INK_LABEL) - _bonus_row_l.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + _bonus_row_l = _ledger_row() + _bonus_name = _ledger_name(UiKit.FS_HINT, UiKit.INK_LABEL, false) + _bonus_val = _ledger_value(UiKit.FS_HINT, UiKit.INK_LABEL, true) + _bonus_row_l.add_child(_bonus_name) + _bonus_row_l.add_child(_bonus_val) _bonus_row_l.visible = false _rows_box.add_child(_bonus_row_l) box.add_child(HSeparator.new()) # M9:明细回看钮退役(P-C7——冒险中回看归「生涯」) _btn = UiKit.primary_button("继续") + _btn.size_flags_horizontal = Control.SIZE_SHRINK_CENTER # 审计差距④——紧凑钮(原全宽) + _btn.custom_minimum_size.x = 150 _btn.pressed.connect(_emit_continue_pressed) box.add_child(_btn) visible = false @@ -99,14 +117,14 @@ func _init() -> void: # 传入(入账次序 = LevelRunner 入账先于组合根 handler,runner.gp 即战后总量);空串 = 不显示(失败侧恒空)。 func open_victory(verdict_line: String, continue_label: String, board_rect: Rect2, gp_summary: String = "", ks_summary: String = "", bonus_summary: String = "", gp_gain := -1, gp_total := -1) -> void: - _dim.color = Color(COL_WARM, 0.28) + _dim.color = Color(UiKit.DIM_NIGHT, 0.62) # 审计差距④——全屏压暗对齐 demo(原 0.28 暖纱透底) _verdict.text = verdict_line _seal.visible = true # 胜利徽记(面板头部静态) _seal.modulate = Color.WHITE - _gp_row.text = gp_summary - _ks_row.text = ks_summary + _set_ledger_row(_gp_name, _gp_val, gp_summary, true) # GP 行=固定名「战利品 GP」(滚动/整串均只入值列) + _set_ledger_row(_ks_name, _ks_val, ks_summary) _ks_row.visible = ks_summary != "" - _bonus_row_l.text = bonus_summary + _set_ledger_row(_bonus_name, _bonus_val, bonus_summary) _bonus_row_l.visible = bonus_summary != "" _rows_box.visible = gp_summary != "" or ks_summary != "" or bonus_summary != "" _btn.text = continue_label @@ -125,7 +143,7 @@ func open_victory(verdict_line: String, continue_label: String, board_rect: Rect func open_defeat(verdict_line: String, continue_label: String, board_rect: Rect2) -> void: # 明度不变的暮蓝色相氛围(全屏唯一暮蓝档——§2.5 最静一拍) - _dim.color = Color(COL_DUSK, 0.45) + _dim.color = Color(COL_DUSK, 0.6) # 审计差距④同族压暗(原 0.45) _verdict.text = verdict_line _board_rect = board_rect visible = true @@ -153,6 +171,41 @@ func verdict_text() -> String: return _verdict.text +# 两列账行工厂(审计差距④——名左/值右,定宽 360) +func _ledger_row() -> HBoxContainer: + var r := HBoxContainer.new() + r.custom_minimum_size = Vector2(360, 0) + return r + + +func _ledger_name(size: int, col: Color, _bold: bool) -> Label: + var l := UiKit.label("", size, true, col) + l.size_flags_horizontal = Control.SIZE_EXPAND_FILL + return l + + +func _ledger_value(size: int, col: Color, bold: bool) -> Label: + return UiKit.label("", size, bold, col) + + +# 拆名/值(组合根传入整串):gp_shape=固定名「战利品 GP」值取余串;其余行按「:」或「 · 」切; +# 无分隔符=整串入值列、名空 +func _set_ledger_row(name_l: Label, val_l: Label, s: String, gp_shape := false) -> void: + if gp_shape and s.begins_with("战利品 GP"): + name_l.text = "战利品 GP" + val_l.text = s.substr(6).strip_edges() + return + var sep := s.find(":") + if sep < 0: + sep = s.find(" · ") + if sep >= 0: + name_l.text = s.substr(0, sep) + val_l.text = s.substr(sep).strip_edges() + else: + name_l.text = "" + val_l.text = s + + func _fx_center() -> Vector2: return get_viewport_rect().size * 0.5 @@ -254,11 +307,11 @@ func _play_victory_dust() -> void: # M9 GP 行数字滚动(demo ⑧——0.8s 三次缓出;减动效直出终值) func _roll_gp(gp_gain: int, gp_total: int) -> void: if UiKit.motion_scale < 1.0: - _gp_row.text = "战利品 GP +%d · 合计 %d" % [gp_gain, gp_total] + _gp_val.text = "+%d · 合计 %d" % [gp_gain, gp_total] return var tw := create_tween() tw.tween_method(func(v: float) -> void: - _gp_row.text = "战利品 GP +%d · 合计 %d" % [roundi(gp_gain * v), gp_total], + _gp_val.text = "+%d · 合计 %d" % [roundi(gp_gain * v), gp_total], 0.0, 1.0, UiKit.motion(0.8)).set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) diff --git a/game/presentation/views/level_map_screen.gd b/game/presentation/views/level_map_screen.gd index 4f6bbdc3..fd9e31de 100644 --- a/game/presentation/views/level_map_screen.gd +++ b/game/presentation/views/level_map_screen.gd @@ -121,7 +121,11 @@ func _init() -> void: # 底部状态栏(M5 合并单条:亮米面板一站读齐=头像+生命+属性+本关加成/流派件——demo ④; # 道具槽不摆=道具读数无关卡画面成文出口(读快照私域越权),随 runner 出口批补——台账 352 注记; # _hp_value/_attr_value/_bonus_value/_feat_value 投喂键全部保留) + # 底栏定高纪律(2026-10-06 审计差距①对齐 demo——单条 ~85px 紧凑亮条;任何子件不再能把栏撑爆: + # 特性持有行限宽截断+tooltip 全文,旧「autowrap 无限宽→最小高度逐字竖排爆栏」形态根除) var bottom := PanelContainer.new() + bottom.custom_minimum_size = Vector2(0, 85) + bottom.size_flags_vertical = Control.SIZE_SHRINK_END bottom.add_theme_stylebox_override("panel", UiKit.panel_flat(UiKit.MAP_BAR_PLATE, UiKit.CAMP_HEADER_BAND, 0, 2, Vector4(12, 6, 12, 6))) box.add_child(bottom) @@ -165,18 +169,22 @@ func _init() -> void: _bonus_row.add_child(bonus_box) var bonus_inner := VBoxContainer.new() bonus_box.add_child(bonus_inner) - var bonus_cap := UiKit.label("特性",UiKit.FS_CAPTION, false, UiKit.WARM_SOFT) + var bonus_cap := UiKit.label("特性",UiKit.FS_CAPTION, false, UiKit.INK_HINT) # 淡墨→深墨(亮板可读,审计差距①) bonus_inner.add_child(bonus_cap) - _bonus_value = UiKit.label("",UiKit.FS_BODY, true, UiKit.WARM) + _bonus_value = UiKit.label("",UiKit.FS_BODY, true, UiKit.INK_TITLE) # 淡墨→深墨(同上) bonus_inner.add_child(_bonus_value) # 特性持有行(迭代 12 呈现补齐 2026-10-04——用户反馈关卡选择页看不到局内奖励;组合根投喂) - _feat_value = UiKit.label("",UiKit.FS_HINT, false, UiKit.WARM_SOFT) - _feat_value.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART + # 审计差距①修(2026-10-06):限宽单行截断+tooltip 全文(旧 autowrap 无限宽=爆栏元凶); + # 墨色 WARM_SOFT→INK_HINT(暖白系对亮板 ≈1:1 不可读——§7.2 违例修复) + _feat_value = UiKit.label("",UiKit.FS_HINT, false, UiKit.INK_HINT) + _feat_value.custom_minimum_size = Vector2(240, 0) + _feat_value.clip_text = true + _feat_value.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS bonus_box.add_child(_feat_value) var spacer := Control.new() spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL strip.add_child(spacer) - abandon_btn = UiKit.danger_button("放弃") # 打磨包 2026-09-29 文案 + M5 危险钮皮(M10 公共件) + abandon_btn = UiKit.danger_button("放弃", "", 90.0) # 审计差距①对齐 demo:小号危险钮 ~90×38(原 216 宽砖);打磨包 2026-09-29 文案 + M5 危险钮皮 abandon_btn.pressed.connect(_on_abandon_pressed) abandon_btn.visible = false strip.add_child(abandon_btn) @@ -211,6 +219,7 @@ func _draw_hp_bar(bar: Control) -> void: # 特性持有投影(迭代 12 呈现补齐——组合根投喂聚合文案;空文案=行隐藏) func set_feat_holdings(text: String) -> void: _feat_value.text = text + _feat_value.tooltip_text = text # 截断全量兜底(限宽单行省略——悬停看全文) func set_abandon_available(v: bool) -> void: diff --git a/game/presentation/views/ui_kit.gd b/game/presentation/views/ui_kit.gd index 82973d64..48995cd2 100644 --- a/game/presentation/views/ui_kit.gd +++ b/game/presentation/views/ui_kit.gd @@ -52,14 +52,15 @@ const TG_MAGIC := Color8(138, 114, 196) # 魔法 const TG_PIERCE := Color8(87, 160, 160) # 穿甲 const TG_AOE := Color8(226, 86, 118) # 群伤/AOE #E25676(demo --tg-aoe) -# 类型色带分族判定(N4c/Q4 甲——三选一与商店货架同源同判:id/kind 小写子串匹配,默认=通用增益带; -# blast=爆裂群伤归 TG_AOE(reward.tres 现成 clear_blast/spark_aoe 消费面);max_hp 含 hp 归回复族) +# 类型色带分族判定(N4c/Q4 甲——三选一与商店货架同源同判:id/kind 小写子串匹配,默认=通用增益带。 +# E5 回滚 2026-10-06:审计实证 demo「工兵爆破」卡=紫带(magic 族)——blast 归回 TG_MAGIC, +# TG_AOE 只接 aoe 键(spark_aoe 消费面保留);max_hp 含 hp 归回复族) static func tg_band(id_lower: String) -> Color: if id_lower.contains("heal") or id_lower.contains("hp"): return TG_HEAL - if id_lower.contains("aoe") or id_lower.contains("blast"): + if id_lower.contains("aoe"): return TG_AOE - if id_lower.contains("magic"): + if id_lower.contains("blast") or id_lower.contains("magic"): return TG_MAGIC if id_lower.contains("pierce"): return TG_PIERCE @@ -83,6 +84,7 @@ const FOG_OUTLINE := Color8(30, 24, 18) # 雾面轮廓墨(原 board_ const ICON_TINT_ON_GOLD := Color(24.0 / 240.0, 20.0 / 226.0, 16.0 / 200.0) # 当前金底图标墨 = WARM 分量乘法调制(双色墨制——原 level_map_screen 局部) const DUSK := Color8(90, 108, 140) # 暮蓝(全作唯一暮蓝档——失败终局) +const DIM_NIGHT := Color8(24, 18, 12) # 终局压暗底 #18120C(demo 结算仪式暗纱——胜利侧 dim 基色) const WARM := Color8(240, 226, 200) # 暖白(暗底正文) const WARM_SOFT := Color8(232, 213, 168) # 暖白次级(说明文)#E8D5A8(M0 换代——灰米 #C8BCA6 退役,配色总纲「米色去灰」) @@ -435,8 +437,8 @@ static func primary_button(text: String, tip := "") -> Button: # 危险钮(深红平涂——放弃/删除类;破坏性确认位置纪律=不得与常规确认同位) -static func danger_button(text: String, tip := "") -> Button: - var b := button(text) +static func danger_button(text: String, tip := "", min_w := 216.0) -> Button: + var b := button(text, min_w) var sb := panel_flat(Color8(180, 78, 54), Color8(110, 42, 28),RADIUS_OBJECT, 2, Vector4(10, 2, 10, 2)) b.add_theme_stylebox_override("normal", sb) b.add_theme_stylebox_override("hover", panel_flat(Color8(196, 90, 62), Color8(110, 42, 28),RADIUS_OBJECT, 2, Vector4(10, 2, 10, 2))) diff --git a/game/smoke/ui_audit_probe.gd.uid b/game/smoke/ui_audit_probe.gd.uid new file mode 100644 index 00000000..d90c0c00 --- /dev/null +++ b/game/smoke/ui_audit_probe.gd.uid @@ -0,0 +1 @@ +uid://ddqhkbsad4wno diff --git a/game/smoke/ui_click_probe.gd b/game/smoke/ui_click_probe.gd index ceb060c1..0fa541e2 100644 --- a/game/smoke/ui_click_probe.gd +++ b/game/smoke/ui_click_probe.gd @@ -249,7 +249,7 @@ func _ready() -> void: # 卡⑥ 战斗胜利总结结算框(真实信号路径——每场普通胜利到达):断言已拍板面后点「下一节点」 if not main._input_locked(): _problems.append("胜利结算框打开时输入未锁定") - var gp_line: String = main._end_overlay._gp_row.text + var gp_line: String = "%s %s" % [main._end_overlay._gp_name.text, main._end_overlay._gp_val.text] # 两列账行(审计差距④)——名/值列拼回整串断言 if not gp_line.contains("GP +%d" % main._last_gain_amount) or not gp_line.contains("合计 %d" % int(main.runner.gp)): _problems.append("胜利结算框 GP 增量/总量与钱包实态不符(%s|实态 +%d/%d)" % [gp_line, main._last_gain_amount, int(main.runner.gp)]) if main._end_overlay.verdict_text() == "": diff --git a/game/smoke/ui_probe.gd b/game/smoke/ui_probe.gd index f09dab87..eed02c8a 100644 --- a/game/smoke/ui_probe.gd +++ b/game/smoke/ui_probe.gd @@ -222,8 +222,8 @@ func _ready() -> void: main.meta = meta_saved if not main._end_overlay.is_open(): problems.append("冒险终局面板未开(合成摘要路径)") - elif not main._end_overlay._gp_row.visible or not main._end_overlay._gp_row.text.contains("57"): - problems.append("终局面板 GP 行缺失或取数不对(%s)" % main._end_overlay._gp_row.text) + elif not main._end_overlay._gp_row.visible or not main._end_overlay._gp_val.text.contains("57"): + problems.append("终局面板 GP 行缺失或取数不对(%s)" % main._end_overlay._gp_val.text) main._end_overlay.close() main._close_modal(main._end_overlay) if problems.is_empty(): From 5e2fa8bb8716b1c64fb585da942c7569e6fa270c Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Tue, 6 Oct 2026 07:15:49 +0800 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=E5=AE=A1=E8=AE=A1=E5=B7=AE?= =?UTF-8?q?=E8=B7=9D=E2=91=A1=E2=91=A2=E8=83=8C=E6=99=AF/=E5=BD=A2?= =?UTF-8?q?=E6=80=81=E4=B8=89=E4=BB=B6=EF=BC=88T5-T8=EF=BC=89=E2=80=94?= =?UTF-8?q?=E2=80=94T5=20=E5=B1=8F=E5=BA=95=E6=B0=9B=E5=9B=B4=E5=B1=82?= =?UTF-8?q?=E5=8D=95=E7=82=B9=EF=BC=88backdrop=5Ftile=200.14/vignette/beam?= =?UTF-8?q?s/=E5=9C=B0=E5=9B=BE=E6=B8=90=E5=8F=98=20#4A3B2A=E2=86=92#3A2E2?= =?UTF-8?q?2@40%=EF=BC=9Bstart/map/camp=20=E4=B8=89=E9=9D=A2=E6=97=A7?= =?UTF-8?q?=E6=BB=A1=E9=93=BA=E7=9F=B3=E7=BA=B9=E9=80=80=E5=BD=B9=EF=BC=8C?= =?UTF-8?q?=E5=9C=B0=E5=9B=BE=E6=8D=A2=E5=B1=82=20tint=20=E4=BF=9D=200.14?= =?UTF-8?q?=20=E6=A1=A3=EF=BC=89+T6=20=E5=95=86=E5=BA=97=E5=85=A8=E5=B1=8F?= =?UTF-8?q?=E9=A1=B5=E5=A3=B3=EF=BC=88page=5Fshell=2056px=20=E9=80=9A?= =?UTF-8?q?=E6=A0=8F=E9=A1=B6=E6=9D=A1+=E7=88=AC=E4=BB=B7=E8=A7=84?= =?UTF-8?q?=E5=88=99=E8=A1=8C=20set=5Fvisit=5Finfo=E3=80=94shop=5Fbp=5Fvis?= =?UTF-8?q?it=5Fbuys=C3=97shop=5Fprice=5Fa=20=E6=8A=95=E5=96=82=E4=B8=89?= =?UTF-8?q?=E5=8F=A3=E3=80=95+=E5=BA=95=E6=B3=A8=E6=B1=A0=E6=BA=90?= =?UTF-8?q?=EF=BC=9Bbcard=20D1=3D232=C3=97352+=E5=9B=BE=E6=A0=87=E6=A7=BD?= =?UTF-8?q?=2076/60=EF=BC=89+T7=20=E4=B8=89=E9=80=89=E4=B8=80=E5=90=8C?= =?UTF-8?q?=E5=A3=B3=E5=85=A8=E5=B1=8F=EF=BC=88GP=20=E6=B1=87=E6=80=BB?= =?UTF-8?q?=E8=A1=8C+=E5=BA=95=E9=83=A8=E7=A1=AE=E8=AE=A4=E9=92=AE+?= =?UTF-8?q?=E5=85=8D=E8=B4=B9=E6=B3=A8=E8=AE=B0=EF=BC=89+T8=20=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E4=B8=A4=E5=88=97=E5=AF=B9=E9=BD=90=EF=BC=88label=20?= =?UTF-8?q?=E5=AE=9A=E5=AE=BD=20140/why=20=E5=86=85=E8=81=94/=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=2090=20=E7=B4=A7=E5=87=91=EF=BC=9B=E5=87=8F=E5=8A=A8?= =?UTF-8?q?=E6=95=88=E8=A1=8C=E6=A0=B8=E8=AF=81=3Dreduced=5Fmotion=20?= =?UTF-8?q?=E5=8D=95=E8=AE=BE=E7=BD=AE=E5=90=8C=E9=A9=B1=20motion=5Fscale+?= =?UTF-8?q?=E7=BB=93=E7=AE=97=E6=BC=94=E6=92=AD=EF=BC=8Cdemo=20=E4=B8=A4?= =?UTF-8?q?=E8=A1=8C=E7=B3=BB=E5=90=8C=E4=B8=80=E8=AE=BE=E7=BD=AE=E4=B8=8D?= =?UTF-8?q?=E6=8B=86=EF=BC=89=E2=80=94=E2=80=94=E5=86=92=E7=83=9F782/0+pro?= =?UTF-8?q?be=5Fgate=20--click=E5=85=A8=E7=BB=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/presentation/camp_shop_presenter.gd | 2 + game/presentation/main.gd | 2 + game/presentation/ui_assembler.gd | 15 +- game/presentation/views/camp_overlay_view.gd | 14 +- game/presentation/views/curio_pick_overlay.gd | 40 ++++-- game/presentation/views/level_map_screen.gd | 21 ++- game/presentation/views/settings_overlay.gd | 26 ++-- game/presentation/views/shop_overlay_view.gd | 48 +++++-- game/presentation/views/ui_kit.gd | 130 +++++++++++++++++- 9 files changed, 231 insertions(+), 67 deletions(-) diff --git a/game/presentation/camp_shop_presenter.gd b/game/presentation/camp_shop_presenter.gd index cf799bec..e4f3ced4 100644 --- a/game/presentation/camp_shop_presenter.gd +++ b/game/presentation/camp_shop_presenter.gd @@ -153,6 +153,7 @@ func on_shop_buy(product_id: String) -> void: toast.show_toast("金币不足——买不起这件商品", "warn") return shop_overlay.open_shelf(runner.shop_shelf(), int(runner.gp)) + shop_overlay.set_visit_info(int(runner.shop_bp_visit_buys()), float(db.shop_price_a())) # T6 爬价规则行 shop_overlay.set_refresh_display(runner.shop_refresh_free_left(), runner.shop_refresh_cost(), int(runner.gp) >= runner.shop_refresh_cost()) _refresh_presentations.call() return @@ -174,6 +175,7 @@ func on_shop_refresh() -> void: toast.show_toast("金币不足——刷新失败", "warn") return shop_overlay.open_shelf(runner.shop_shelf(), int(runner.gp)) + shop_overlay.set_visit_info(int(runner.shop_bp_visit_buys()), float(db.shop_price_a())) # T6 爬价规则行 shop_overlay.set_refresh_display(runner.shop_refresh_free_left(), runner.shop_refresh_cost(), int(runner.gp) >= runner.shop_refresh_cost()) _refresh_presentations.call() diff --git a/game/presentation/main.gd b/game/presentation/main.gd index b48e27a2..30b47ccb 100644 --- a/game/presentation/main.gd +++ b/game/presentation/main.gd @@ -521,9 +521,11 @@ func _on_runner_node(node: Dictionary, info: Dictionary) -> void: _open_modal(shop_overlay) if runner.is_shop_pool(): shop_overlay.open_shelf(runner.shop_shelf(), int(runner.gp)) + shop_overlay.set_visit_info(int(runner.shop_bp_visit_buys()), float(db.shop_price_a())) # T6 爬价规则行 shop_overlay.set_refresh_display(runner.shop_refresh_free_left(), runner.shop_refresh_cost(), int(runner.gp) >= runner.shop_refresh_cost()) # MC-1 else: shop_overlay.open_shop(runner.shop_products(), int(runner.gp)) + shop_overlay.set_visit_info(-1, 1.0) # legacy 面无爬价行(off 对照承载) log_view.append_bb(Narrator.shop_line(int(runner.gp))) logger.log_node(node, info, runner.node_index) _refresh_presentations() diff --git a/game/presentation/ui_assembler.gd b/game/presentation/ui_assembler.gd index b2efcfba..8c0dbfac 100644 --- a/game/presentation/ui_assembler.gd +++ b/game/presentation/ui_assembler.gd @@ -102,16 +102,13 @@ static func build_overlays(host: Control, db) -> Dictionary: static func build_start_overlay(host: Control, db = null) -> Dictionary: var overlay := overlay_bg(host, UiKit.BG_BRIGHT) overlay.theme = UiKit.tooltip_theme() - # 石纹底噪底层(样张 v2 冻结批 T2——z 序=dim 之上/内容之下;缺位不挂即回退平色) - var bd_tex := UiKit.load_tex(UiKit.TEX_BACKDROP_STONE) - if bd_tex != null: - var bd := TextureRect.new() - bd.texture = bd_tex - bd.stretch_mode = TextureRect.STRETCH_TILE - bd.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST - bd.set_anchors_preset(Control.PRESET_FULL_RECT) - bd.mouse_filter = Control.MOUSE_FILTER_IGNORE + # 石纹弱质感+斜光带+暗角(UI 对齐批 T5 2026-10-06——demo .tilebg 0.14/.beams/.vignette 三层; + # 旧满铺石纹不透退役。缺位不挂即回退平色) + var bd := UiKit.backdrop_tile() + if bd != null: overlay.add_child(bd) + overlay.add_child(UiKit.beams_rect()) + overlay.add_child(UiKit.vignette_rect()) # 双列骨架(M2):左=操作列 56% / 右=舞台+速览 var cols := HBoxContainer.new() cols.set_anchors_preset(Control.PRESET_FULL_RECT) diff --git a/game/presentation/views/camp_overlay_view.gd b/game/presentation/views/camp_overlay_view.gd index 1feeb813..a9a097a7 100644 --- a/game/presentation/views/camp_overlay_view.gd +++ b/game/presentation/views/camp_overlay_view.gd @@ -39,16 +39,12 @@ var _recent_list: Label # 最近冒险(逐行拼接 label——只读 func _init() -> void: var dim := UiKit.modal_dim(self, Color(0, 0, 0, 0.45)) # 方向稿=石纹底透出(浅 dim——石纹全屏底担当氛围) - # 石纹底噪(样张 v2 冻结件——start overlay 同款;缺位不挂即回退平 dim) - var bd_tex := UiKit.load_tex(UiKit.TEX_BACKDROP_STONE) - if bd_tex != null: - var bd := TextureRect.new() - bd.texture = bd_tex - bd.stretch_mode = TextureRect.STRETCH_TILE - bd.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST - bd.set_anchors_preset(Control.PRESET_FULL_RECT) - bd.mouse_filter = Control.MOUSE_FILTER_IGNORE + # 石纹弱质感+暗角(UI 对齐批 T5 2026-10-06——demo .tilebg 0.14/.vignette;旧满铺石纹不透退役; + # 缺位不挂即回退平 dim) + var bd := UiKit.backdrop_tile() + if bd != null: dim.add_child(bd) + dim.add_child(UiKit.vignette_rect()) var root := MarginContainer.new() root.set_anchors_preset(Control.PRESET_FULL_RECT) diff --git a/game/presentation/views/curio_pick_overlay.gd b/game/presentation/views/curio_pick_overlay.gd index a60a7b19..3acf8cc2 100644 --- a/game/presentation/views/curio_pick_overlay.gd +++ b/game/presentation/views/curio_pick_overlay.gd @@ -20,6 +20,7 @@ var _continue_btn: Button # 继续钮(兑付反馈态唯一 var _refresh_btn: Button # 刷新钮(迭代 11 第①批 T5b——余量>0 才显示;M7 升顶条图标钮) var _refresh_badge: Label # M7 余量角标(图标钮右上——demo ⑥ 同构) var _refresh_l: Label # 刷新余量读数(X 优先 + Y 冒险池) +var _foot_hint: Label # T7 底注(demo .bonus-foot .hint——pick 态显隐) var _refresh_allowance := 0 # 组合根投喂余量(本视图零核心引用) var _selected := "" # 点选暂存(确认前可改选) var _header := "" # 停点头部文案(选择态保持显示) @@ -28,12 +29,12 @@ var _bcards: Array = [] # M7 bcard 引用列(select 高亮 func _init() -> void: - # M7(UI 落码批):与商店同构(demo ⑥ 用户令两屏一致)——通栏顶条(标题+刷新图标钮/角标)+ - # 居中入账信息行 + bcard 三竖卡 + 底部唯一主钮「确认选择」;差异白名单=免费选择/✓章/无价签 - var box: VBoxContainer = UiKit.modal_shell(self, Color(0, 0, 0, 0.6)).box - var top := HBoxContainer.new() - top.add_theme_constant_override("separation", 12) - box.add_child(top) + # T7(UI 设计对齐批 2026-10-06):全屏页形态(demo ⑥ #v-bonus——与商店 T6 同壳 page_shell, + # 根底暗档)——56px 通栏顶条(标题+刷新图标钮/角标)+ 居中入账信息行(GP 汇总行承载)+ + # bcard 三竖卡(D1 232×352)+ 底部确认主钮与免费选择注记。差异白名单=免费选择/✓章/无价签。 + # 状态机不变:pick→[replace]→result。M7 同构裁决遗产保留。 + var page: Dictionary = UiKit.page_shell(self, false) + 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 @@ -54,25 +55,34 @@ func _init() -> void: _refresh_l = UiKit.label("",UiKit.FS_CAPTION, false, UiKit.WARM_SOFT) _refresh_l.visible = false top.add_child(_refresh_l) + var box: VBoxContainer = page.box _label = UiKit.label("",UiKit.FS_BODY, false, UiKit.WARM_SOFT) _label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER box.add_child(_label) _choice_box = HBoxContainer.new() - _choice_box.add_theme_constant_override("separation", 20) + _choice_box.add_theme_constant_override("separation", 26) # demo .cards gap 26(T7 对齐) _choice_box.alignment = BoxContainer.ALIGNMENT_CENTER + _choice_box.size_flags_vertical = Control.SIZE_EXPAND_FILL box.add_child(_choice_box) + var foot := HBoxContainer.new() + foot.alignment = BoxContainer.ALIGNMENT_CENTER + foot.add_theme_constant_override("separation", 16) + box.add_child(foot) _confirm_btn = UiKit.primary_button("确认选择") _confirm_btn.pressed.connect(_on_confirm_pressed) _confirm_btn.visible = false - box.add_child(_confirm_btn) - _replace_box = VBoxContainer.new() - _replace_box.add_theme_constant_override("separation", 8) - _replace_box.alignment = BoxContainer.ALIGNMENT_CENTER - box.add_child(_replace_box) + foot.add_child(_confirm_btn) _continue_btn = UiKit.button("继续") _continue_btn.pressed.connect(_emit_continue_pressed) _continue_btn.visible = false - box.add_child(_continue_btn) + foot.add_child(_continue_btn) + _foot_hint = UiKit.label("免费选择 · 刷新不消耗 AP",UiKit.FS_HINT, false, UiKit.WARM_FAINT) + foot.add_child(_foot_hint) + _replace_box = VBoxContainer.new() + _replace_box.add_theme_constant_override("separation", 8) + _replace_box.alignment = BoxContainer.ALIGNMENT_CENTER + _replace_box.size_flags_vertical = Control.SIZE_EXPAND_FILL + box.add_child(_replace_box) visible = false @@ -105,6 +115,7 @@ func open_pick(header: String, cards: Array) -> void: _confirm_btn.visible = false _replace_box.visible = false _continue_btn.visible = false + _foot_hint.visible = true # T7 底注=pick 态专属(replace/result 态让位) _refresh_btn.visible = false # 刷新余量随 set_refresh_info 投喂后现形(open 先归零防残留) _refresh_l.text = "" visible = true @@ -163,6 +174,7 @@ func show_result(text: String) -> void: _confirm_btn.visible = false _replace_box.visible = false _continue_btn.visible = true + _foot_hint.visible = false visible = true @@ -184,6 +196,7 @@ func open_replace(items: Array, incoming_name: String, holding: int, slots: int) _confirm_btn.visible = false _replace_box.visible = true _continue_btn.visible = false + _foot_hint.visible = false visible = true @@ -193,6 +206,7 @@ func close_pick() -> void: _replace_box.visible = false _continue_btn.visible = false _confirm_btn.visible = false + _foot_hint.visible = false visible = false diff --git a/game/presentation/views/level_map_screen.gd b/game/presentation/views/level_map_screen.gd index fd9e31de..c0b9f0d3 100644 --- a/game/presentation/views/level_map_screen.gd +++ b/game/presentation/views/level_map_screen.gd @@ -72,21 +72,15 @@ func _init() -> void: # 节点图标贴图装载(样张 v1 冻结形制——load_tex 守卫,缺位回退现行字形) for t in TEX_NODE_ICONS: _node_icons[t] = UiKit.load_tex(TEX_NODE_ICONS[t]) - # 独立屏底(形态升格 2026-09-28——spec Layout:深底+石纹底噪铺满;底纹缺位回退纯色——load_tex 守卫) - var base := ColorRect.new() - base.color = UiKit.BG_ROOT - base.set_anchors_preset(Control.PRESET_FULL_RECT) + # 独立屏底(形态升格 2026-09-28——spec Layout;UI 对齐批 T5 2026-10-06:demo #v-map 暖棕竖向 + # 渐变(#4A3B2A 0%→#3A2E22 40%)+石纹弱质感 0.14+暗角聚焦;旧满铺石纹不透退役;底纹缺位回退纯色) + var base := UiKit.gradient_base(UiKit.BG_MAP_TOP, UiKit.BG_ROOT) add_child(base) - var noise := UiKit.load_tex(UiKit.TEX_BACKDROP_STONE) - if noise != null: - var tex := TextureRect.new() - tex.texture = noise - tex.stretch_mode = TextureRect.STRETCH_TILE - tex.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST - tex.set_anchors_preset(Control.PRESET_FULL_RECT) - tex.mouse_filter = Control.MOUSE_FILTER_IGNORE + var tex := UiKit.backdrop_tile() + if tex != null: base.add_child(tex) _noise_rect = tex # 世界侧 tint 承载面(换层色板渐变挂点——§2.7 切片档) + base.add_child(UiKit.vignette_rect()) var center := CenterContainer.new() center.set_anchors_preset(Control.PRESET_FULL_RECT) base.add_child(center) @@ -322,7 +316,8 @@ func _apply_level_tint(level_index: int) -> void: _tint_level = level_index var target: Color = BOARD_TINTS.get(level_index, Color(1, 1, 1)) var tw := create_tween() - tw.tween_property(_noise_rect, "modulate", target, UiKit.motion(0.45)) + tw.tween_property(_noise_rect, "modulate", + Color(target.r, target.g, target.b, UiKit.BACKDROP_TILE_ALPHA), UiKit.motion(0.45)) # 0.14 弱质感档随 tint 保持(T5) # 状态栏刷新(命令式纪律——组合根打开本屏/兑付确认回执后重查;零推送信号订阅) diff --git a/game/presentation/views/settings_overlay.gd b/game/presentation/views/settings_overlay.gd index eb485886..96733f8a 100644 --- a/game/presentation/views/settings_overlay.gd +++ b/game/presentation/views/settings_overlay.gd @@ -34,7 +34,9 @@ func retarget(store) -> void: func _build() -> void: # M4(UI 落码批):石板面板化(demo ③)+行牌化(标签+拨杆+状态字+后果说明行); # 设置项零增减(P-C6:只有主音量——demo 音效音量行系原型发明已撤); - # 减动效与结算演出动画=同一设置(语义命名批合并),一行承载 + # 减动效与结算演出动画=同一设置(语义命名批合并),一行承载。 + # T8(UI 设计对齐批 2026-10-06):两列对齐(label 列定宽 140——demo .setrow label/控制两列)+ + # 后果说明内联随行(demo .why 同排)+返回钮紧凑化(demo .btn9 紧凑——原 216 宽砖)。 var shell: Dictionary = UiKit.modal_shell(self, UiKit.BG_BRIGHT, Vector2(560, 0), 8, true, UiKit.panel_skinned(Vector4(20, 16, 20, 16))) var box: VBoxContainer = shell.box @@ -51,9 +53,12 @@ func _build() -> void: var vol_row := HBoxContainer.new() vol_row.add_theme_constant_override("separation", 14) box.add_child(vol_row) - vol_row.add_child(UiKit.label("主音量",UiKit.FS_BODY, false, UiKit.INK_LABEL)) + var vol_lab := UiKit.label("主音量",UiKit.FS_BODY, false, UiKit.INK_LABEL) + vol_lab.custom_minimum_size = Vector2(140, 0) # T8 label 列定宽(两列对齐) + vol_row.add_child(vol_lab) _volume = UiKit.styled_slider(100.0, 0.0, 100.0) _volume.step = 1 + _volume.size_flags_horizontal = Control.SIZE_EXPAND_FILL _volume.value_changed.connect(_on_volume_changed) vol_row.add_child(_volume) _volume_val = UiKit.label("100%",UiKit.FS_BODY, true, UiKit.INK_TITLE) @@ -64,33 +69,38 @@ func _build() -> void: var fs_row := HBoxContainer.new() fs_row.add_theme_constant_override("separation", 14) box.add_child(fs_row) - fs_row.add_child(UiKit.label("全屏",UiKit.FS_BODY, false, UiKit.INK_LABEL)) + var fs_lab := UiKit.label("全屏",UiKit.FS_BODY, false, UiKit.INK_LABEL) + fs_lab.custom_minimum_size = Vector2(140, 0) # T8 同上 + fs_row.add_child(fs_lab) _fs_btn = UiKit.switch_toggle(false) _fs_btn.toggled.connect(_on_fullscreen_toggled) fs_row.add_child(_fs_btn) _fs_st = UiKit.label("关",UiKit.FS_HINT, true, UiKit.INK_LABEL) fs_row.add_child(_fs_st) - # 结算演出动画(=减动效实称——语义命名批 T17;拨杆 on=完整,off=快速时长减半) + # 结算演出动画(=减动效实称——语义命名批 T17;拨杆 on=完整,off=快速时长减半。 + # T8 核证:reduced_motion 单设置同驱 UiKit.motion_scale 与结算演播——demo「减动效」行与 + # 本行系同一设置,不另立行(拆两行=一设置双行重复,违语义命名批裁决) var motion_row := HBoxContainer.new() motion_row.add_theme_constant_override("separation", 14) box.add_child(motion_row) - motion_row.add_child(UiKit.label("结算演出动画",UiKit.FS_BODY, false, UiKit.INK_LABEL)) + var motion_lab := UiKit.label("结算演出动画",UiKit.FS_BODY, false, UiKit.INK_LABEL) + motion_lab.custom_minimum_size = Vector2(140, 0) # T8 同上 + motion_row.add_child(motion_lab) _motion_btn = UiKit.switch_toggle(true) _motion_btn.toggled.connect(_on_motion_toggled) motion_row.add_child(_motion_btn) _motion_st = UiKit.label("完整",UiKit.FS_HINT, true, UiKit.INK_LABEL) motion_row.add_child(_motion_st) var why := UiKit.label("快速 = 时长减半(运动敏感 / 演示用)",UiKit.FS_CAPTION, false, UiKit.INK_HINT) - why.position.y = 0 - box.add_child(why) + motion_row.add_child(why) # T8 内联随行(demo .why 同排;原独立行换排) box.add_child(HSeparator.new()) # 退出游戏已提级开始菜单(D1——设置面不再承载,用户裁决「退出只在一级菜单出现」) var close_row := HBoxContainer.new() close_row.alignment = BoxContainer.ALIGNMENT_CENTER box.add_child(close_row) - var close_btn := UiKit.button("返回") + var close_btn := UiKit.button("返回", 90.0) # T8 紧凑返回钮(demo 紧凑形;原 216 宽砖) close_btn.pressed.connect(_emit_closed) close_row.add_child(close_btn) diff --git a/game/presentation/views/shop_overlay_view.gd b/game/presentation/views/shop_overlay_view.gd index 54cf60aa..635dbe1f 100644 --- a/game/presentation/views/shop_overlay_view.gd +++ b/game/presentation/views/shop_overlay_view.gd @@ -20,21 +20,22 @@ const KIND_LABELS := {"attack": "攻击", "max_hp": "生命上限", "armor": " var _gp_label: Label var _refresh_btn: Button # M6 呈现位——MC-1 起由 set_refresh_display 投喂启用 signal refresh_requested # MC-1:刷新意图(pool 面;组合根接 presenter.on_shop_refresh) +var _visit_label: Label # T6 爬价规则行(demo .svisit——已购件数/现价倍数由 presenter 投喂) var _cards_box: VBoxContainer +var _foot_hint: Label # T6 底注(demo .shop-foot .hint) var _card_rows: Array[Dictionary] = [] # [{product_id, price, bought, btn}]——refresh_state 就地重刷(零重建回流) var _shelf_rows: Array[Dictionary] = [] # [{kind_id, btn}]——pool 面卡片(买后整架重建=重抽反馈) func _init() -> void: - # M6(UI 落码批):pool 面卡面 bcard 三竖卡同构化(demo ⑤/2026-10-02 同构裁决呈现侧闭环)—— - # 库存余量退役(关卡节点地图 v1.5-a 用户裁);刷新钮呈现位照摆(机制=MC-1 核心批投喂,占位禁用); - # 爬价总览行不摆=已购次数无成文出口(随 MC-1 shop_draw 投影补)。legacy 面(open_shop)原样保留。 - var box: VBoxContainer = UiKit.modal_shell(self, Color(0, 0, 0, 0.6)).box - var top := HBoxContainer.new() - top.add_theme_constant_override("separation", 12) - box.add_child(top) - var title := UiKit.label("商 店",UiKit.FS_TITLE, true, UiKit.WARM) - top.add_child(title) + # T6(UI 设计对齐批 2026-10-06):全屏页形态(demo ⑤ #v-shop——06 在册 D2 商店全屏化/D1 竖卡 + # 232×352 落地)——暖亮底+石纹弱质感+暗角(UiKit.page_shell)+56px 通栏顶条(标题+刷新图标钮/ + # 角标+GP 框)+ 爬价规则行 + bcard 三竖卡居中 + 底部离开钮与池源注记。 + # M6 遗产:库存余量退役(关卡节点地图 v1.5-a 用户裁);刷新钮呈现位照摆(机制=MC-1 投喂)。 + # legacy 面(open_shop)行卡同壳呈现(shop=off 对照承载原样)。高内聚边界不变:纯视图 setter 面。 + var page: Dictionary = 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) @@ -56,15 +57,40 @@ func _init() -> void: top.add_child(gp_chip) _gp_label = UiKit.label("金币 0",UiKit.FS_BODY, true, UiKit.INK_ON_GOLD) gp_chip.add_child(_gp_label) + var box: VBoxContainer = page.box + _visit_label = UiKit.label("",UiKit.FS_BODY, false, UiKit.WARM_SOFT) + _visit_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + box.add_child(_visit_label) _cards_box = VBoxContainer.new() + _cards_box.size_flags_vertical = Control.SIZE_EXPAND_FILL _cards_box.add_theme_constant_override("separation", 8) box.add_child(_cards_box) + var foot := HBoxContainer.new() + foot.alignment = BoxContainer.ALIGNMENT_CENTER + foot.add_theme_constant_override("separation", 16) + box.add_child(foot) var leave_btn := UiKit.button("离开商店") leave_btn.pressed.connect(_emit_leave_pressed) - box.add_child(leave_btn) + foot.add_child(leave_btn) + _foot_hint = UiKit.label("货架与奖励三选一同一池 · 池空即空架关店",UiKit.FS_HINT, false, UiKit.WARM_FAINT) + foot.add_child(_foot_hint) visible = false +# 爬价规则行投喂(demo .svisit——buys<0 = legacy 面隐藏行;mult=pow(price_a, buys) 由 presenter 算) +func set_visit_info(buys: int, price_a: float) -> void: + if buys < 0: + _visit_label.text = "" + return + var mult := pow(price_a, float(buys)) + _visit_label.text = "本次进店已购 %d 件 · 现价 %s | 买 1 件 → 三件全换新 · 全场涨价 ×%s" % [ + buys, _xnum(mult), _xnum(price_a)] + + +func _xnum(v: float) -> String: + return "×%d" % int(round(v)) if absf(v - roundf(v)) < 0.005 else "×%.2f" % v + + # 打开商店(products = runner.shop_products() 投影——[{product_id, display_name, attr, flat_value, price, purchased}]) func open_shop(products: Array, gp: int) -> void: for child in _cards_box.get_children(): @@ -137,7 +163,7 @@ func open_shelf(cards: Array, gp: int) -> void: _shelf_rows.clear() var row := HBoxContainer.new() row.alignment = BoxContainer.ALIGNMENT_CENTER - row.add_theme_constant_override("separation", 20) + row.add_theme_constant_override("separation", 26) # demo .cards gap 26(T6 对齐) _cards_box.add_child(row) for c in cards: _shelf_rows.append(_build_shelf_card(row, c)) diff --git a/game/presentation/views/ui_kit.gd b/game/presentation/views/ui_kit.gd index 48995cd2..bf5558db 100644 --- a/game/presentation/views/ui_kit.gd +++ b/game/presentation/views/ui_kit.gd @@ -217,6 +217,85 @@ static func load_tex(path: String) -> Texture2D: return null +# ── 屏底氛围层(UI 设计对齐批 T5 2026-10-06——demo .tilebg opacity .14/.vignette/.beams 对齐; +# 旧「石纹全屏满铺不透」退役——demo 石纹只作弱质感,聚焦靠暗角)── +const BACKDROP_TILE_ALPHA := 0.14 # demo .tilebg{opacity:.14} +const BG_MAP_TOP := Color8(74, 59, 42) # 地图屏渐变顶 #4A3B2A(demo #v-map 180deg 0%;低点 40% = BG_ROOT #3A2E22) + + +# 石纹弱质感全屏片(0.14;缺素材返回 null = 调用侧回退平色) +static func backdrop_tile() -> TextureRect: + var bd_tex := load_tex(TEX_BACKDROP_STONE) + if bd_tex == null: + return null + var bd := TextureRect.new() + bd.texture = bd_tex + bd.stretch_mode = TextureRect.STRETCH_TILE + bd.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST + bd.modulate = Color(1, 1, 1, BACKDROP_TILE_ALPHA) + bd.set_anchors_preset(Control.PRESET_FULL_RECT) + bd.mouse_filter = Control.MOUSE_FILTER_IGNORE + return bd + + +# 径向暗角(demo .vignette——ellipse 90%×80% at 50% 42%,透明 58% → 黑 0.30 满角) +static func vignette_rect() -> TextureRect: + var g := Gradient.new() + g.offsets = PackedFloat32Array([0.0, 0.58, 1.0]) + g.colors = PackedColorArray([Color(0, 0, 0, 0), Color(0, 0, 0, 0), Color(0, 0, 0, 0.30)]) + var t := GradientTexture2D.new() + t.gradient = g + t.fill = GradientTexture2D.FILL_RADIAL + t.fill_from = Vector2(0.5, 0.42) + t.fill_to = Vector2(1.4, 0.42) + t.width = 256 + t.height = 256 + var tr := TextureRect.new() + tr.texture = t + tr.stretch_mode = TextureRect.STRETCH_SCALE + tr.set_anchors_preset(Control.PRESET_FULL_RECT) + tr.mouse_filter = Control.MOUSE_FILTER_IGNORE + return tr + + +# 斜光带(demo #v-start .beams——repeating-linear-gradient 102deg,暖白 5% 窄带 240-340/560px; +# 程序纹理循环带,确定性生成零随机) +static func beams_rect() -> TextureRect: + var img := Image.create(560, 560, false, Image.FORMAT_RGBA8) + var ca := cos(0.2094) # 12°(102deg 带轴的垂直倾角) + var sa := sin(0.2094) + for y in 560: + for x in 560: + var d := fposmod(x * ca + y * sa, 560.0) + if d >= 240.0 and d < 340.0: + img.set_pixel(x, y, Color(1.0, 236.0 / 255.0, 200.0 / 255.0, 0.05)) + var tr := TextureRect.new() + tr.texture = ImageTexture.create_from_image(img) + tr.stretch_mode = TextureRect.STRETCH_TILE + tr.set_anchors_preset(Control.PRESET_FULL_RECT) + tr.mouse_filter = Control.MOUSE_FILTER_IGNORE + return tr + + +# 竖向渐变底(demo #v-map linear-gradient(180deg, top 0%, low 40%)——stop 后恒 low) +static func gradient_base(top: Color, low: Color, stop := 0.4) -> TextureRect: + var g := Gradient.new() + g.offsets = PackedFloat32Array([0.0, stop]) + g.colors = PackedColorArray([top, low]) + var t := GradientTexture2D.new() + t.gradient = g + t.fill_from = Vector2(0.5, 0.0) + t.fill_to = Vector2(0.5, 1.0) + t.width = 64 + t.height = 256 + var tr := TextureRect.new() + tr.texture = t + tr.stretch_mode = TextureRect.STRETCH_SCALE + tr.set_anchors_preset(Control.PRESET_FULL_RECT) + tr.mouse_filter = Control.MOUSE_FILTER_IGNORE + return tr + + # CJK 随包字体(2026-09-27 用户拍板 Fusion Pixel OFL——CJK 覆盖+授权干净;命名遵 art-bible §8.3 # 全小写 snake_case 域前缀)。守卫装载同 load_tex 纪律:缺位返回 null(引擎回退字体接手,不炸)。 const FONT_UI := "res://assets/fonts/ui_font_fusion_pixel_zh_hans.ttf" @@ -307,6 +386,44 @@ static func modal_shell(parent: Control, dim_color: Color, min_size := Vector2.Z return {"dim": dim, "center": center, "panel": panel, "box": box} +# ── 全屏页壳(UI 设计对齐批 T6/T7 2026-10-06——demo #v-shop/#v-bonus 全屏页形态落地: +# 06 在册 D2 商店全屏化/D1 竖卡 232×352。暖底+石纹弱质感+暗角+56px 通栏顶条+内容列; +# 商店=暖亮底、三选一=根底,两屏同构差异仅底色与顶条工具件)── +const PAGE_TOP_H := 56.0 + +static func page_shell(host: Control, bright := true) -> Dictionary: + var page := Control.new() + page.set_anchors_preset(Control.PRESET_FULL_RECT) + host.add_child(page) + var base := ColorRect.new() + base.color = BG_BRIGHT if bright else BG_ROOT + base.set_anchors_preset(Control.PRESET_FULL_RECT) + base.mouse_filter = Control.MOUSE_FILTER_STOP # 页底挡点击——模态语义由组合根输入锁兜底 + page.add_child(base) + var tile := backdrop_tile() + if tile != null: + page.add_child(tile) + page.add_child(vignette_rect()) + var top := PanelContainer.new() + top.set_anchors_preset(Control.PRESET_TOP_WIDE) + top.custom_minimum_size = Vector2(0, PAGE_TOP_H) + top.add_theme_stylebox_override("panel", + panel_flat(Color8(38, 29, 20), Color8(85, 72, 58), 0, 1, Vector4(26, 6, 26, 6))) + page.add_child(top) + var top_row := HBoxContainer.new() + top_row.add_theme_constant_override("separation", 12) + top.add_child(top_row) + var box := VBoxContainer.new() + box.set_anchors_preset(Control.PRESET_FULL_RECT) + box.offset_top = PAGE_TOP_H + 20 + box.offset_left = 26 + box.offset_right = -26 + box.offset_bottom = -22 + box.add_theme_constant_override("separation", 10) + page.add_child(box) + return {"page": page, "base": base, "top_row": top_row, "box": box} + + # 属性百分比合成(main._debug_hero_override 与调试浮窗生效值预览共用单点——两处同式实现收口) static func scaled(base: int, pct: int) -> int: return maxi(1, int(round(float(base) * (100.0 + float(pct)) / 100.0))) @@ -492,7 +609,7 @@ class BCard: _sb_normal = UiKit.panel_skinned(Vector4(12, 10, 12, 10)) if tex != null else UiKit.panel_flat(PANEL_DATA, PANEL_BORDER,RADIUS_OBJECT, 1, Vector4(12, 10, 12, 10)) # 回退=数据板单点(P7 乙后同值,字面量退役) _sb_sel = UiKit.panel_flat(PANEL_DATA, Color8(138, 90, 52), RADIUS_OBJECT, 2, Vector4(12, 10, 12, 10)) # 选中底=数据板单点(P7 乙后同值) add_theme_stylebox_override("panel", _sb_normal) - custom_minimum_size = Vector2(216, 300) + custom_minimum_size = Vector2(232, 352) # D1(UI 设计对齐批 T6 2026-10-06——demo .bcard 232×352;原 216×300) var box := VBoxContainer.new() box.add_theme_constant_override("separation", 8) add_child(box) @@ -503,16 +620,21 @@ class BCard: mark.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT mark.visible = false box.add_child(mark) + # 图标槽(demo .ic 76×76 槽底+图标 60=20px 源 3 整数倍——P6 甲④ 2× 档升 3× 随 D1 对齐) + var slot := PanelContainer.new() + slot.add_theme_stylebox_override("panel", UiKit.panel_flat(SLOT_BACKDROP, PANEL_BORDER, 0, 1)) + slot.custom_minimum_size = Vector2(76, 76) + slot.size_flags_horizontal = Control.SIZE_SHRINK_CENTER + box.add_child(slot) icon_tr = TextureRect.new() var itex := UiKit.load_tex(icon_path) if itex != null: icon_tr.texture = itex - icon_tr.custom_minimum_size = Vector2(40, 40) # P6 甲④(2026-10-06):20×20 源 2× 档(原 56=2.8× 违 §8.2) + icon_tr.custom_minimum_size = Vector2(60, 60) icon_tr.expand_mode = TextureRect.EXPAND_IGNORE_SIZE icon_tr.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED icon_tr.texture_filter = CanvasItem.TEXTURE_FILTER_NEAREST - icon_tr.size_flags_horizontal = Control.SIZE_SHRINK_CENTER - box.add_child(icon_tr) + slot.add_child(icon_tr) name_l = UiKit.label(title,FS_SUB, true, INK_TITLE) name_l.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER box.add_child(name_l) From 463c5b178cc97d15d1107751e8255116f16b6f64 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Tue, 6 Oct 2026 07:23:09 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20T6/T7=20=E5=AE=9E=E6=B5=8B=E4=B8=A4?= =?UTF-8?q?=E4=BF=AE=E2=80=94=E2=80=94bcard=20=E8=A1=8C=E5=AE=B9=E5=99=A8?= =?UTF-8?q?=E7=BA=B5=E5=90=91=E6=8B=89=E4=BC=B8=E4=BF=AE=EF=BC=88SHRINK=5F?= =?UTF-8?q?CENTER=20=E6=81=92=20352=20=E9=AB=98=E5=B1=85=E4=B8=AD=EF=BC=8C?= =?UTF-8?q?HBox=20fill=20=E6=8B=89=E5=88=B0=20~536=20=E5=AE=9E=E6=B5=8B?= =?UTF-8?q?=EF=BC=89+=E7=BB=93=E7=AE=97=E8=B4=A6=E8=A1=8C=E5=85=A8?= =?UTF-8?q?=E8=A7=92=E5=86=92=E5=8F=B7=E4=B8=8D=E5=85=A5=E5=80=BC=E5=88=97?= =?UTF-8?q?=EF=BC=88=E5=AE=9E=E6=9C=BA=E3=80=8C=EF=BC=9A=E6=94=BB=E5=87=BB?= =?UTF-8?q?=20+1=E3=80=8D=E7=BC=A9=E8=BF=9B=E4=BF=AE=EF=BC=89=EF=BC=9B?= =?UTF-8?q?=E5=AE=A1=E8=AE=A1=E6=8E=A2=E9=92=88=E5=95=86=E5=BA=97=E5=B1=8F?= =?UTF-8?q?=E6=94=B9=E6=8A=95=E5=96=82=20pool=20=E8=B4=A7=E6=9E=B6?= =?UTF-8?q?=E9=9D=A2=EF=BC=88=E7=8E=A9=E5=AE=B6=E6=AD=A3=E4=B8=BB=E5=BD=A2?= =?UTF-8?q?=E6=80=81=3Ddemo=20#v-shop=20=E5=AF=B9=E6=AF=94=E5=9F=BA?= =?UTF-8?q?=E7=BA=BF=EF=BC=89+=E7=88=AC=E4=BB=B7=E8=A1=8C=E6=8A=95?= =?UTF-8?q?=E5=96=82=E2=80=94=E2=80=94=E5=86=92=E7=83=9F782/0+probe=5Fgate?= =?UTF-8?q?=20--click=E5=85=A8=E7=BB=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/presentation/views/battle_end_overlay.gd | 11 +++++++---- game/presentation/views/ui_kit.gd | 1 + game/smoke/ui_audit_probe.gd | 11 ++++++----- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/game/presentation/views/battle_end_overlay.gd b/game/presentation/views/battle_end_overlay.gd index 978631ef..71a2b6ff 100644 --- a/game/presentation/views/battle_end_overlay.gd +++ b/game/presentation/views/battle_end_overlay.gd @@ -188,16 +188,19 @@ func _ledger_value(size: int, col: Color, bold: bool) -> Label: return UiKit.label("", size, bold, col) -# 拆名/值(组合根传入整串):gp_shape=固定名「战利品 GP」值取余串;其余行按「:」或「 · 」切; -# 无分隔符=整串入值列、名空 +# 拆名/值(组合根传入整串):gp_shape=固定名「战利品 GP」值取余串;其余行按「:」或「 · 」切 +#(全角冒号不入值列——T7 实机「:攻击 +1」缩进 Corrections);无分隔符=整串入值列、名空 func _set_ledger_row(name_l: Label, val_l: Label, s: String, gp_shape := false) -> void: if gp_shape and s.begins_with("战利品 GP"): name_l.text = "战利品 GP" val_l.text = s.substr(6).strip_edges() return var sep := s.find(":") - if sep < 0: - sep = s.find(" · ") + if sep >= 0: + name_l.text = s.substr(0, sep) + val_l.text = s.substr(sep + 1).strip_edges() + return + sep = s.find(" · ") if sep >= 0: name_l.text = s.substr(0, sep) val_l.text = s.substr(sep).strip_edges() diff --git a/game/presentation/views/ui_kit.gd b/game/presentation/views/ui_kit.gd index bf5558db..97c9b652 100644 --- a/game/presentation/views/ui_kit.gd +++ b/game/presentation/views/ui_kit.gd @@ -610,6 +610,7 @@ class BCard: _sb_sel = UiKit.panel_flat(PANEL_DATA, Color8(138, 90, 52), RADIUS_OBJECT, 2, Vector4(12, 10, 12, 10)) # 选中底=数据板单点(P7 乙后同值) add_theme_stylebox_override("panel", _sb_normal) custom_minimum_size = Vector2(232, 352) # D1(UI 设计对齐批 T6 2026-10-06——demo .bcard 232×352;原 216×300) + size_flags_vertical = Control.SIZE_SHRINK_CENTER # 行容器不纵向拉伸(卡恒 352 高居中——T7 实测 HBox fill 拉到 ~536 修) var box := VBoxContainer.new() box.add_theme_constant_override("separation", 8) add_child(box) diff --git a/game/smoke/ui_audit_probe.gd b/game/smoke/ui_audit_probe.gd index 9e5f538c..699f55c3 100644 --- a/game/smoke/ui_audit_probe.gd +++ b/game/smoke/ui_audit_probe.gd @@ -94,12 +94,13 @@ func _ready() -> void: await _snap("6_bonus") main.curio_overlay.visible = false await _settle() - # 10 商店(买前态) - main.shop_overlay.open_shop([ - {"product_id": "attack", "display_name": "攻击强化", "attr": "atk", "flat_value": 1, "price": 12, "purchased": 0}, - {"product_id": "max_hp", "display_name": "生命强化", "attr": "hp", "flat_value": 3, "price": 12, "purchased": 0}, - {"product_id": "armor", "display_name": "护甲强化", "attr": "armor", "flat_value": 1, "price": 15, "purchased": 0}, + # 10 商店(买前态——pool 货架面=玩家正主形态,demo #v-shop 对比基线;T6 全屏页) + main.shop_overlay.open_shelf([ + {"kind_id": "attack", "display_name": "攻击强化", "value": 1, "price": 12}, + {"kind_id": "max_hp", "display_name": "生命强化", "value": 3, "price": 12}, + {"kind_id": "armor", "display_name": "护甲片", "value": 1, "price": 15}, ], 27) + main.shop_overlay.set_visit_info(0, 1.8) # 爬价规则行(T6——presenter 同款投喂) await _settle() await _snap("7_shop") main.shop_overlay.visible = false