From b6ae74e28874cbbabfab3c103f6649e1a815c4ff Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Mon, 5 Oct 2026 02:18:43 +0800 Subject: [PATCH] =?UTF-8?q?M6=20=E5=95=86=E5=BA=97bcard=E5=90=8C=E6=9E=84?= =?UTF-8?q?=E5=8C=96=EF=BC=88UI=E8=90=BD=E7=A0=81=E7=AC=AC=E4=BA=8C?= =?UTF-8?q?=E6=B3=A2=EF=BC=89=E2=80=94=E2=80=94pool=E8=B4=A7=E6=9E=B6?= =?UTF-8?q?=E6=A8=AA=E6=8E=92=E8=A1=8C=E5=8D=A1=E2=86=92bcard=E4=B8=89?= =?UTF-8?q?=E7=AB=96=E5=8D=A1(=E7=B1=BB=E5=9E=8B=E8=89=B2=E5=B8=A6/?= =?UTF-8?q?=E5=9B=BE=E6=A0=87/=E5=90=8D/=E4=BB=B6=E5=80=BC/=E4=BB=B7?= =?UTF-8?q?=E7=AD=BE=E9=87=91/=E5=BA=95=E6=B3=A8/=E8=B4=AD=E4=B9=B0?= =?UTF-8?q?=E9=92=AEfooter)+=E9=A1=B6=E6=A0=8F(=E6=A0=87=E9=A2=98+?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E5=8D=A0=E4=BD=8D=E9=92=AE=E7=A6=81=E7=94=A8?= =?UTF-8?q?+GP=E7=83=9B=E5=85=89=E7=AB=A0)+=E5=BA=93=E5=AD=98=E4=BD=99?= =?UTF-8?q?=E9=87=8F=E9=80=80=E5=BD=B9(v1.5-a=E7=94=A8=E6=88=B7=E8=A3=81,?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=B1=82stock=5Fleft=E4=B8=8D=E5=8A=A8)+?= =?UTF-8?q?=E7=88=AC=E4=BB=B7=E8=A1=8C=E6=8C=82MC-1(=E6=97=A0=E6=88=90?= =?UTF-8?q?=E6=96=87=E5=87=BA=E5=8F=A3)=EF=BC=9BBCard=E5=BE=AE=E6=89=A9bod?= =?UTF-8?q?y/add=5Ffooter(=E4=B8=B2=E8=A1=8C=E6=97=A0=E6=92=9E)=EF=BC=9Ble?= =?UTF-8?q?gacy=E9=9D=A2=E5=8E=9F=E6=A0=B7=E3=80=82=E9=97=B8=3D=E5=86=92?= =?UTF-8?q?=E7=83=9F747/0+probe=5Fgate=E5=85=A8=E7=BB=BF+layout=200?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/presentation/views/shop_overlay_view.gd | 81 +++++++++++++------- game/presentation/views/ui_kit.gd | 6 ++ 2 files changed, 61 insertions(+), 26 deletions(-) diff --git a/game/presentation/views/shop_overlay_view.gd b/game/presentation/views/shop_overlay_view.gd index e7b43538..84873258 100644 --- a/game/presentation/views/shop_overlay_view.gd +++ b/game/presentation/views/shop_overlay_view.gd @@ -18,19 +18,43 @@ const ATTR_LABELS := {"atk": "攻击", "max_hp": "生命上限", "armor_class": const KIND_LABELS := {"attack": "攻击", "max_hp": "生命上限", "armor": "护甲", "ap": "行动点"} # 货架件值文案轴(共享池 kind 词表——迭代 11 第②批) var _gp_label: Label +var _refresh_btn: Button # M6 刷新呈现位(禁用占位——机制由 MC-1 核心批接线) var _cards_box: VBoxContainer 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 title := UiKit.label("商店", 26, true, UiKit.WARM) - title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER - box.add_child(title) - _gp_label = UiKit.label("金币 0", 18, true, UiKit.GOLD) - _gp_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER - box.add_child(_gp_label) + var top := HBoxContainer.new() + top.add_theme_constant_override("separation", 12) + box.add_child(top) + var title := UiKit.label("商 店", 26, true, UiKit.WARM) + top.add_child(title) + var top_sp := Control.new() + top_sp.size_flags_horizontal = Control.SIZE_EXPAND_FILL + top.add_child(top_sp) + _refresh_btn = UiKit.button("") + _refresh_btn.icon = UiKit.load_tex(UiKit.TEX_ICON_REFRESH) + _refresh_btn.custom_minimum_size = Vector2(44, 44) + _refresh_btn.tooltip_text = "刷新货架(机制接入中——商店刷新核心批 MC-1)" + _refresh_btn.disabled = true + top.add_child(_refresh_btn) + var stock_badge := UiKit.label("0", 12, true, UiKit.INK_ON_GOLD) + stock_badge.mouse_filter = Control.MOUSE_FILTER_IGNORE + stock_badge.set_anchors_preset(Control.PRESET_TOP_RIGHT) + stock_badge.offset_left = -22.0 + stock_badge.offset_top = -6.0 + _refresh_btn.add_child(stock_badge) + var gp_chip := PanelContainer.new() + gp_chip.add_theme_stylebox_override("panel", + UiKit.panel_flat(UiKit.CANDLE, UiKit.CAMP_HEADER_BAND, 2, 1, Vector4(12, 4, 12, 4))) + top.add_child(gp_chip) + _gp_label = UiKit.label("金币 0", 16, true, UiKit.INK_ON_GOLD) + gp_chip.add_child(_gp_label) _cards_box = VBoxContainer.new() _cards_box.add_theme_constant_override("separation", 8) box.add_child(_cards_box) @@ -110,12 +134,16 @@ func open_shelf(cards: Array, gp: int) -> void: for child in _cards_box.get_children(): child.queue_free() _shelf_rows.clear() + var row := HBoxContainer.new() + row.alignment = BoxContainer.ALIGNMENT_CENTER + row.add_theme_constant_override("separation", 20) + _cards_box.add_child(row) for c in cards: - _shelf_rows.append(_build_shelf_card(c)) + _shelf_rows.append(_build_shelf_card(row, c)) if cards.is_empty(): var empty := UiKit.label("货架售罄——共享池已买空(属性件全冒险共 3+3+3 份 / AP 件 2 份)", 14, false, UiKit.WARM_FAINT) empty.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER - _cards_box.add_child(empty) + row.add_child(empty) refresh_shelf_state(gp) visible = true @@ -125,29 +153,30 @@ func refresh_shelf_state(gp: int) -> void: _gp_label.text = "金币 %d" % gp for card in _shelf_rows: card.btn.disabled = gp < int(card.price) + card.card.modulate = Color(1, 1, 1, 1) if gp >= int(card.price) else Color(1, 1, 1, 0.55) -# 货架卡(显示名+件值文案 | 现价 | 库存余量 | 购买钮)——三选一同构语言:买 1 = 一次真实购买 -func _build_shelf_card(c: Dictionary) -> Dictionary: +# 货架卡(bcard 竖卡:类型色带+图标+名+件值描述+价签+购买钮——M6 同构卡;demo ⑤) +# 库存余量退役=关卡节点地图 v1.5-a 用户裁(2026-10-04)——数据层 stock_left 仍投喂断点,仅呈现不摆 +func _build_shelf_card(holder: Control, c: Dictionary) -> Dictionary: var kind := String(c.get("kind_id", "")) - var card := PanelContainer.new() - card.add_theme_stylebox_override("panel", UiKit.panel_flat(UiKit.BG_OVERLAY, UiKit.GOLD_DIM, 4, 1, Vector4(12, 6, 12, 6))) - var row := HBoxContainer.new() - row.add_theme_constant_override("separation", 14) - card.add_child(row) - var name_l := UiKit.label("%s(%s %+d)" % [String(c.get("display_name", kind)), String(KIND_LABELS.get(kind, kind)), int(c.get("value", 0))], 15, true) - name_l.custom_minimum_size = Vector2(190, 0) - row.add_child(name_l) - var price_l := UiKit.label("现价 %d 金币" % int(c.get("price", 0)), 14, false, UiKit.WARM_SOFT) - price_l.custom_minimum_size = Vector2(110, 0) - row.add_child(price_l) - var stock_l := UiKit.label("库存余 %s" % str(int(c.get("stock_left", 0))) if int(c.get("stock_left", 0)) < (1 << 20) else "库存余 ∞", 14, false, UiKit.WARM_FAINT) - row.add_child(stock_l) + var icon_key := UiKit.TEX_ICON_SWORD + var kl := kind.to_lower() + if kl.contains("hp") or kl.contains("heal"): + icon_key = UiKit.TEX_ICON_HEART + elif kl.contains("armor") or kl.contains("shield"): + icon_key = UiKit.TEX_ICON_SHIELD + elif kl.contains("ap") or kl.contains("action") or kl.contains("pouch"): + icon_key = UiKit.TEX_ICON_POUCH + var card := UiKit.bcard(String(c.get("display_name", kind)), + "%s %+d(本冒险)" % [String(KIND_LABELS.get(kind, kind)), int(c.get("value", 0))], + Color8(194, 178, 100), icon_key, + "%d ◈" % int(c.get("price", 0)), String(KIND_LABELS.get(kind, kind))) var btn := UiKit.button("购买") btn.pressed.connect(_emit_shelf_buy.bind(kind)) - row.add_child(btn) - _cards_box.add_child(card) - return {"kind_id": kind, "price": int(c.get("price", 0)), "btn": btn} + card.add_footer(btn) + holder.add_child(card) + return {"kind_id": kind, "price": int(c.get("price", 0)), "btn": btn, "card": card} func _emit_shelf_buy(kind: String) -> void: diff --git a/game/presentation/views/ui_kit.gd b/game/presentation/views/ui_kit.gd index 2c387f24..a0e704c2 100644 --- a/game/presentation/views/ui_kit.gd +++ b/game/presentation/views/ui_kit.gd @@ -386,6 +386,7 @@ class BCard: var desc_l: Label var price_l: Label var foot_l: Label + var body: VBoxContainer # 内容列(消费方经 add_footer 插件到底注前——M6 购买钮挂位) var _sb_normal: StyleBox var _sb_sel: StyleBox @@ -398,6 +399,7 @@ class BCard: var box := VBoxContainer.new() box.add_theme_constant_override("separation", 8) add_child(box) + body = box var band_r := ColorRect.new() band_r.color = band band_r.custom_minimum_size = Vector2(0, 6) @@ -439,6 +441,10 @@ class BCard: add_theme_stylebox_override("panel", _sb_sel if v else _sb_normal) mark.visible = v + func add_footer(c: Control) -> void: + body.add_child(c) + body.move_child(c, body.get_child_index(foot_l)) + static func bcard(title: String, desc: String, band: Color, icon_path: String, price := "", footnote := "") -> BCard: return BCard.new(title, desc, band, icon_path, price, footnote)