From 143129c6bafcfb3ceaf135f9108a3ffbbcb7808f Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Mon, 5 Oct 2026 02:26:06 +0800 Subject: [PATCH] =?UTF-8?q?M7=20=E4=B8=89=E9=80=89=E4=B8=80bcard=E5=8C=96+?= =?UTF-8?q?=E5=95=86=E5=BA=97=E5=90=8C=E6=9E=84=EF=BC=88UI=E8=90=BD?= =?UTF-8?q?=E7=A0=81=E7=AC=AC=E4=BA=8C=E6=B3=A2=EF=BC=89=E2=80=94=E2=80=94?= =?UTF-8?q?=E6=8C=89=E9=92=AE170=C3=9788=E2=86=92bcard=E4=B8=89=E7=AB=96?= =?UTF-8?q?=E5=8D=A1(=E7=B1=BB=E5=9E=8B=E8=89=B2=E5=B8=A6=E6=9F=A5?= =?UTF-8?q?=E8=A1=A8/=E6=89=8B=E7=BB=98=E5=9B=BE=E6=A0=87/=E2=9C=93?= =?UTF-8?q?=E7=AB=A0+=E6=9C=A8=E6=8F=8F=E8=BE=B9=E9=80=89=E4=B8=AD?= =?UTF-8?q?=E6=80=81)+=E9=80=9A=E6=A0=8F=E9=A1=B6=E6=9D=A1(=E6=A0=87?= =?UTF-8?q?=E9=A2=98+=E5=88=B7=E6=96=B0=E5=9B=BE=E6=A0=87=E9=92=AE/?= =?UTF-8?q?=E4=BD=99=E9=87=8F=E8=A7=92=E6=A0=87)+=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E5=8D=87CANDLE=E4=B8=BB=E9=92=AE=EF=BC=9Bpress=5Fcard/selected?= =?UTF-8?q?=5Fid=E6=8E=A2=E9=92=88=E8=AF=AD=E4=B9=89=E4=BF=9D=E6=8C=81(?= =?UTF-8?q?=E5=90=8C=E4=B8=80=5Fselect=5Fcard=E7=9C=9F=E5=AE=9E=E8=B7=AF?= =?UTF-8?q?=E5=BE=84)=EF=BC=9B=E5=B7=AE=E5=BC=82=E7=99=BD=E5=90=8D?= =?UTF-8?q?=E5=8D=95=3D=E5=85=8D=E8=B4=B9/=E2=9C=93/=E6=97=A0=E4=BB=B7?= =?UTF-8?q?=E7=AD=BE=E3=80=82=E9=97=B8=3D=E5=86=92=E7=83=9F747/0+probe=5Fg?= =?UTF-8?q?ate=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/bonus_pick_overlay.gd | 101 ++++++++++++++---- 1 file changed, 78 insertions(+), 23 deletions(-) diff --git a/game/presentation/views/bonus_pick_overlay.gd b/game/presentation/views/bonus_pick_overlay.gd index 88e8a1c0..1001ebe2 100644 --- a/game/presentation/views/bonus_pick_overlay.gd +++ b/game/presentation/views/bonus_pick_overlay.gd @@ -13,38 +13,58 @@ signal continue_pressed signal refresh_requested # 三选一刷新意图(迭代 11 第①批 T5b——P1 甲 X/Y 双源;重抽归组合根) var _label: Label -var _choice_box: HBoxContainer # 三卡按钮区(pick 态) +var _choice_box: HBoxContainer # 三卡区(pick 态——M7 bcard 竖卡) var _replace_box: VBoxContainer # 替换子面板(replace 态) var _confirm_btn: Button # 确认钮(点选后点亮——两段式第二拍) var _continue_btn: Button # 继续钮(兑付反馈态唯一出口) -var _refresh_btn: Button # 刷新钮(迭代 11 第①批 T5b——余量>0 才显示) +var _refresh_btn: Button # 刷新钮(迭代 11 第①批 T5b——余量>0 才显示;M7 升顶条图标钮) +var _refresh_badge: Label # M7 余量角标(图标钮右上——demo ⑥ 同构) var _refresh_l: Label # 刷新余量读数(X 优先 + Y 冒险池) var _refresh_allowance := 0 # 组合根投喂余量(本视图零核心引用) var _selected := "" # 点选暂存(确认前可改选) var _header := "" # 停点头部文案(选择态保持显示) var _card_meta: Array = [] # open_pick 缓存 [{id, text}]——高亮还原读面 +var _bcards: Array = [] # M7 bcard 引用列(select 高亮=set_selected) func _init() -> void: + # M7(UI 落码批):与商店同构(demo ⑥ 用户令两屏一致)——通栏顶条(标题+刷新图标钮/角标)+ + # 居中入账信息行 + bcard 三竖卡 + 底部唯一主钮「确认选择」;差异白名单=免费选择/✓章/无价签 var box: VBoxContainer = UiKit.modal_shell(self, Color(0, 0, 0, 0.6)).box - _label = UiKit.label("", 20, true, UiKit.WARM) + var top := HBoxContainer.new() + top.add_theme_constant_override("separation", 12) + box.add_child(top) + top.add_child(UiKit.label("战利品三选一", 22, true, UiKit.WARM)) + 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 = "刷新候选——装配刷新件 X 优先,Y 为冒险池;不消耗 AP" + _refresh_btn.pressed.connect(_emit_refresh_requested) + _refresh_btn.visible = false + top.add_child(_refresh_btn) + _refresh_badge = UiKit.label("0", 12, true, UiKit.INK_ON_GOLD) + _refresh_badge.mouse_filter = Control.MOUSE_FILTER_IGNORE + _refresh_badge.set_anchors_preset(Control.PRESET_TOP_RIGHT) + _refresh_badge.offset_left = -22.0 + _refresh_badge.offset_top = -6.0 + _refresh_btn.add_child(_refresh_badge) + _refresh_l = UiKit.label("", 12, false, UiKit.WARM_SOFT) + _refresh_l.visible = false + top.add_child(_refresh_l) + _label = UiKit.label("", 15, 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", 12) + _choice_box.add_theme_constant_override("separation", 20) _choice_box.alignment = BoxContainer.ALIGNMENT_CENTER box.add_child(_choice_box) - _confirm_btn = UiKit.button("确认选择") + _confirm_btn = UiKit.primary_button("确认选择") _confirm_btn.pressed.connect(_on_confirm_pressed) _confirm_btn.visible = false box.add_child(_confirm_btn) - # 三选一刷新面(迭代 11 第①批 T5b——程序占位用 UiKit 既有件;余量 0 = 隐藏) - _refresh_btn = UiKit.button("刷新候选") - _refresh_btn.pressed.connect(_emit_refresh_requested) - _refresh_btn.visible = false - box.add_child(_refresh_btn) - _refresh_l = UiKit.label("", 13, false, UiKit.STONE) - box.add_child(_refresh_l) _replace_box = VBoxContainer.new() _replace_box.add_theme_constant_override("separation", 8) _replace_box.alignment = BoxContainer.ALIGNMENT_CENTER @@ -65,12 +85,28 @@ func open_pick(header: String, cards: Array) -> void: _card_meta = (cards as Array).duplicate(true) for c in _choice_box.get_children(): c.queue_free() + _bcards.clear() for ch in cards: var cid := String(ch.get("id", "")) - var btn := UiKit.button(String(ch.get("text", ""))) - btn.custom_minimum_size = Vector2(170, 88) - btn.pressed.connect(_select_card.bind(cid)) # 具名方法 bind(仓内惯例——内联 lambda 退役) - _choice_box.add_child(btn) + var full := String(ch.get("text", "")) + var lines := full.split("\n") + var title := lines[0] + var desc := "\n".join(lines.slice(1)) if lines.size() > 1 else "" + var idl := cid.to_lower() + var band := Color8(194, 178, 100) # 通用增益(默认——§4.2 类型微光族色) + if idl.contains("heal"): + band = Color8(102, 164, 87) + elif idl.contains("magic") or idl.contains("blast"): + band = Color8(138, 114, 196) + elif idl.contains("pierce"): + band = Color8(87, 160, 160) + var card := UiKit.bcard(title, desc, band, _icon_for_id(idl)) + card.gui_input.connect(func(ev: InputEvent) -> void: + if ev is InputEventMouseButton and ev.pressed and ev.button_index == MOUSE_BUTTON_LEFT: + _select_card(cid)) + card.mouse_filter = Control.MOUSE_FILTER_STOP + _choice_box.add_child(card) + _bcards.append(card) _choice_box.visible = true _confirm_btn.visible = false _replace_box.visible = false @@ -84,7 +120,9 @@ func open_pick(header: String, cards: Array) -> void: func set_refresh_info(allowance: int) -> void: _refresh_allowance = maxi(0, int(allowance)) _refresh_btn.visible = _refresh_allowance > 0 - _refresh_l.text = "可刷新 %d 次(装配刷新件 X 优先消耗,Y 为冒险池)" % _refresh_allowance if _refresh_allowance > 0 else "" + _refresh_badge.text = str(_refresh_allowance) + _refresh_l.text = "免费 · 不消耗 AP" if _refresh_allowance > 0 else "" + _refresh_l.visible = _refresh_allowance > 0 func _emit_refresh_requested() -> void: @@ -93,11 +131,10 @@ func _emit_refresh_requested() -> void: func _select_card(id: String) -> void: _selected = id - for i in _choice_box.get_child_count(): - var btn := _choice_box.get_child(i) as Button + # 选中态=木描边+✓章(demo ⑥;set_selected 逐卡置真值防改选残留) + for i in _bcards.size(): var meta: Dictionary = _card_meta[i] if i < _card_meta.size() else {} - var base_text := String(meta.get("text", "")) - btn.text = ("✓ " + base_text) if String(meta.get("id", "")) == id else base_text + (_bcards[i] as UiKit.BCard).set_selected(String(meta.get("id", "")) == id) _confirm_btn.visible = true @@ -108,8 +145,9 @@ func _on_confirm_pressed() -> void: # 探针/测试复用:以真实按钮路径触发点选、确认与继续(树序遮挡纪律——断言走真实信号路径) func press_card(index: int) -> void: - if index >= 0 and index < _choice_box.get_child_count(): - (_choice_box.get_child(index) as Button).pressed.emit() + # M7:卡载体 Button→bcard(gui_input 点选)——真实路径=同一 _select_card 处理器,探针语义不变 + if index >= 0 and index < _card_meta.size(): + _select_card(String(_card_meta[index].get("id", ""))) func press_confirm() -> void: @@ -170,3 +208,20 @@ func _emit_continue_pressed() -> void: func _emit_replace_chosen(tag: int) -> void: replace_chosen.emit(tag) + + +# M7:id → 手绘图标键(子串映射容错 id 词表演进;缺位=BCard 空图标槽不炸) +func _icon_for_id(idl: String) -> String: + if idl.contains("heal"): + return UiKit.TEX_ICON_MEDKIT + if idl.contains("blast") or idl.contains("magic"): + return UiKit.TEX_ICON_BLAST + if idl.contains("gp") or idl.contains("coin"): + return UiKit.TEX_ICON_COINBAG + if idl.contains("attack"): + return UiKit.TEX_ICON_SWORD + if idl.contains("armor"): + return UiKit.TEX_ICON_SHIELD + if idl.contains("ap") or idl.contains("action"): + return UiKit.TEX_ICON_POUCH + return UiKit.TEX_ICON_COINBAG