feat(presentation): 样式收敛批——全站色板与 StyleBox 单点化进 ui_kit + 顺带修复奖励徽章 action 键漏网

① ui_kit.gd 扩为全站取色/描边唯一出口:语义色板 6 族(墨/面板/金/旗朱/蓝紫/暖白灰石)+棋盘格底+深底+BBCode 十六进制+panel_flat 工厂(bg/border/corner/border_w/margin 一站式)——美术批换皮只改本文件
② 16 个视图/装配文件内联 Color8/StyleBoxFlat 字面量全部清零(含 4 个浮点字面色 toast 底/tooltip 底/遮罩灰收编;棋盘悬停高亮框保留 draw_center=false 特例挂点);battle_log_view 行级 BBCode 染色属文本标记层保留原地
③ 零视觉变化:layout_probe 布局转储与 master 逐字节一致;冒烟 355 项 0 失败
④ 顺带修复(master 既有缺陷,非本批引入):格面八型批 cell_type=action 无徽章键——board_view REWARD_BADGE 补「行」,ui_click_probe 91 次 fail-fast 断言清零(问题=0)
This commit is contained in:
DKChan committed 2026-09-20 14:24:13 +08:00
1 parent 2781cd170f
commit 648ad57a9b
20 files changed
+184 -183

No files matched your search

@@ -149,7 +149,7 @@ func _build_ui() -> void:
func _fatal_screen(msg: String) -> void:
var l := UiKit.label(msg, 20, true)
l.add_theme_color_override("font_color", Color8(200, 60, 48))
l.add_theme_color_override("font_color", UiKit.RED_ALERT)
l.set_anchors_preset(Control.PRESET_CENTER)
add_child(l)
@@ -18,9 +18,7 @@ static func build_battle_ui(root: Control, db) -> Dictionary:
# A 区:关卡进度条(全宽 × 28px 顶栏)
var strip_panel := PanelContainer.new()
strip_panel.custom_minimum_size = Vector2(0, 28)
var sb := StyleBoxFlat.new()
sb.bg_color = Color8(30, 25, 20)
sb.set_corner_radius_all(0)
var sb := UiKit.panel_flat(UiKit.BG_ROOT, UiKit.BG_ROOT, 0, 0)
strip_panel.add_theme_stylebox_override("panel", sb)
root.add_child(strip_panel)
var strip_view := LevelStripView.new()
@@ -85,13 +83,13 @@ static func build_overlays(host: Control, db, base_atk: int, base_hp: int) -> Di
# 开始覆盖层(返回 {overlay, box, seed_edit, lvbtn, tunebtn, dbgbtn}——按钮接线归组合根;
# 单场遭遇用户入口已删(2026-09-13 用户裁决——单场原语仅探针经 debug_session.start_single 使用))
static func build_start_overlay(host: Control, db = null) -> Dictionary:
var overlay := overlay_bg(host, Color8(28, 22, 18))
var overlay := overlay_bg(host, UiKit.BG_OVERLAY)
var box := overlay_box(overlay)
var title := UiKit.label("Dungeon Sweeper", 34, true)
title.add_theme_color_override("font_color", Color8(240, 226, 200))
title.add_theme_color_override("font_color", UiKit.WARM)
box.add_child(title)
var sub := UiKit.label("战斗屏战斗屏改造批 —— 扫雷的因,逐行兑现的果", 16, false)
sub.add_theme_color_override("font_color", Color8(200, 188, 166))
sub.add_theme_color_override("font_color", UiKit.WARM_SOFT)
box.add_child(sub)
box.add_child(HSeparator.new())
@@ -116,7 +114,7 @@ static func build_start_overlay(host: Control, db = null) -> Dictionary:
var help_text := "玩法:每轮 %d AP——挖开(1AP)/插旗(1AP)/移动(免费)/连锁(免费)。\n每个非封锁格都藏一种格面资源(增伤/护甲强化/回血/爆裂/削弱)。开安全格、标中雷 = 正向兑付;\n开雷格、标错安全格 = 负向兑付——全部在轮末结算逐行兑现;吃掷点的基础攻击按护甲等级判定,无 miss、最低保底 1 点。\n停手:剩余 AP 转存 RAP;弃图刷新:RAP−%d 当场换图继续挖(每轮剩 %d 次)。\n敌人全灭胜、主角倒下负。悬停可看三态光标与可挖域微光。" % [
int(db.action_economy.ap_per_round), int(db.action_economy.rap_refresh_cost), int(db.action_economy.refresh_cap_per_round)]
var help := UiKit.label(help_text, 13, false)
help.add_theme_color_override("font_color", Color8(178, 166, 146))
help.add_theme_color_override("font_color", UiKit.WARM_FAINT)
box.add_child(help)
return {"overlay": overlay, "box": box, "seed_edit": seed_edit,
@@ -128,7 +126,7 @@ static func build_inter_overlay(host: Control) -> Dictionary:
var overlay := overlay_bg(host, Color(0, 0, 0, 0.6))
var box := overlay_box(overlay)
var label := UiKit.label("", 24, true)
label.add_theme_color_override("font_color", Color8(240, 226, 200))
label.add_theme_color_override("font_color", UiKit.WARM)
box.add_child(label)
var next_btn := UiKit.button("进入下一层")
box.add_child(next_btn)
@@ -12,9 +12,9 @@ signal stop_pressed
signal refresh_confirmed
signal legend_toggled
const COL_GOLD := Color8(240, 168, 40)
const COL_DOT_OFF := Color8(120, 106, 88)
const COL_INK := Color8(51, 38, 27)
const COL_GOLD := UiKit.GOLD
const COL_DOT_OFF := UiKit.DOT_OFF
const COL_INK := UiKit.INK
var _dots: HBoxContainer
var _ap_label: Label
@@ -31,15 +31,7 @@ var _arm_tween: Tween
func _init() -> void:
custom_minimum_size = Vector2(0, 44)
var sb := StyleBoxFlat.new()
sb.bg_color = Color8(226, 210, 182)
sb.set_corner_radius_all(0)
sb.set_border_width_all(1)
sb.border_color = Color8(120, 106, 88)
sb.content_margin_left = 8.0
sb.content_margin_right = 8.0
sb.content_margin_top = 4.0
sb.content_margin_bottom = 4.0
var sb := UiKit.panel_flat(UiKit.PANEL_DATA, UiKit.PANEL_BORDER, 0, 1, Vector4(8, 4, 8, 4))
add_theme_stylebox_override("panel", sb)
var row := HBoxContainer.new()
@@ -9,9 +9,9 @@ extends Control
signal review_pressed
signal continue_pressed
const COL_GOLD := Color8(240, 168, 40)
const COL_DUSK := Color8(90, 108, 140) # 暮蓝 #5A6C8C(全作唯一暮蓝档)
const COL_WARM := Color8(240, 226, 200)
const COL_GOLD := UiKit.GOLD
const COL_DUSK := UiKit.DUSK # 暮蓝(全作唯一暮蓝档)
const COL_WARM := UiKit.WARM
var _dim: ColorRect
var _seal: Panel
@@ -45,11 +45,7 @@ func _init() -> void:
# 金蜡封占位(胜利):圆形色块落于扫雷图区中央——位置由 set_board_rect 注入
_seal = Panel.new()
_seal.mouse_filter = Control.MOUSE_FILTER_IGNORE
var sb := StyleBoxFlat.new()
sb.bg_color = COL_GOLD
sb.set_corner_radius_all(200)
sb.set_border_width_all(4)
sb.border_color = Color8(176, 122, 20)
var sb := UiKit.panel_flat(COL_GOLD, UiKit.GOLD_DEEP, 200, 4)
_seal.add_theme_stylebox_override("panel", sb)
_seal.size = Vector2(72, 72)
_seal.visible = false
@@ -62,7 +58,7 @@ func _init() -> void:
func open_victory(verdict_line: String, continue_label: String, board_rect: Rect2) -> void:
_dim.color = Color(COL_WARM, 0.28)
_verdict.text = verdict_line
_verdict.add_theme_color_override("font_color", Color8(60, 44, 20))
_verdict.add_theme_color_override("font_color", UiKit.INK_ON_GOLD)
_btn.text = continue_label
_board_rect = board_rect
visible = true
@@ -16,8 +16,8 @@ signal review_requested
const BAND_H_DIG := 24
const BAND_H_SETTLE := 84
const AGG_TYPES := ["reward_ineffective"]
const COL_GOLD := "#f0a828"
const COL_INK := "#33261b"
const COL_GOLD := UiKit.HEX_GOLD
const COL_INK := UiKit.HEX_INK
var _db
var _log: RichTextLabel
@@ -150,7 +150,7 @@ func _source_label(src_key: String) -> String:
func _gold_frame(text: String) -> String:
# highlight 金框强调(形状+色彩双通道:■ 前缀 + 金底)
return "[bgcolor=%s][color=#3a2a08]■ %s[/color][/bgcolor]" % [COL_GOLD, text]
return "[bgcolor=%s][color=#%s]■ %s[/color][/bgcolor]" % [COL_GOLD, UiKit.HEX_ON_GOLD, text]
func _format_row(row: Dictionary, agg_count := -1) -> String:
@@ -18,15 +18,7 @@ var _cards: Array = []
func _init(db_ref) -> void:
custom_minimum_size = Vector2(0, 252)
var sb := StyleBoxFlat.new()
sb.bg_color = Color8(216, 200, 172)
sb.set_corner_radius_all(0)
sb.set_border_width_all(1)
sb.border_color = Color8(120, 106, 88)
sb.content_margin_left = 6.0
sb.content_margin_right = 6.0
sb.content_margin_top = 4.0
sb.content_margin_bottom = 4.0
var sb := UiKit.panel_flat(UiKit.PANEL_STAGE, UiKit.PANEL_BORDER, 0, 1, Vector4(6, 4, 6, 4))
add_theme_stylebox_override("panel", sb)
var vb := VBoxContainer.new()
vb.add_theme_constant_override("separation", 4)
@@ -50,7 +42,7 @@ func _init(db_ref) -> void:
center_col.alignment = BoxContainer.ALIGNMENT_CENTER
center.add_child(center_col)
stage_center = UiKit.label("兑现演出区\n(结算期:光带 → 弹道 → 受击)", 13, false)
stage_center.add_theme_color_override("font_color", Color8(140, 124, 100))
stage_center.add_theme_color_override("font_color", UiKit.STONE_FAINT)
stage_center.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
center_col.add_child(stage_center)
row.add_child(center)
@@ -6,10 +6,10 @@
class_name BoardFxView
extends Control
const COL_GOLD := Color8(240, 168, 40)
const COL_BOSS := Color8(143, 47, 106) # 紫赤 #8F2F6A
const COL_FLAG := Color8(198, 61, 34) # 旗朱
const CONFETTI_COLS := [Color8(240, 168, 40), Color8(198, 61, 34), Color8(46, 110, 142), Color8(240, 226, 200)]
const COL_GOLD := UiKit.GOLD
const COL_BOSS := UiKit.BOSS_PURPLE # 紫赤 #8F2F6A
const COL_FLAG := UiKit.FLAG_RED # 旗朱
const CONFETTI_COLS := [UiKit.GOLD, UiKit.FLAG_RED, UiKit.HERO_BLUE, UiKit.WARM]
var _banner: Label
@@ -15,17 +15,18 @@ signal action_requested(cell: Vector2i, kind: String) # kind ∈ {dig, move, f
signal hover_forbidden(cell: Vector2i) # 非相邻未开格悬停(首遇 toast 归组合根去重)
signal chord_attempted(cell: Vector2i) # 双击快开尝试(chord 肌肉记忆提示锚)
const COL_BRICK := Color8(201, 175, 131) # 未开——掩尘完整地砖(色板原语 #C9AF83)
const COL_FLOOR := Color8(179, 154, 120) # 已开——裸土 #B39A78(碎裂裸露地面)
const COL_DIGIT := Color8(51, 38, 27) # 数字——墨族 #33261B(对格底 ≥4.5:1 硬指标)
const COL_HERO := Color8(46, 110, 142) # 小人边框——小人蓝 #2E6E8E
const COL_FLAG := Color8(198, 61, 34) # 旗朱 #C63D22
const COL_GOLD := Color8(240, 168, 40) # 奖励金 #F0A828
const COL_PATH := Color8(46, 110, 142) # 路径预览点迹——小人蓝细线
const COL_DIG_EDGE := Color8(120, 190, 120) # 可挖域呼吸微光基色(绿相,明度贴格底)
const COL_HL_TARGET := Color8(240, 168, 40) # 悬停目标格边框(金)
const REWARD_BADGE := { # 已开格格面资源身份 icon(cell_type 五型键;极性视觉归批 2)
const COL_BRICK := UiKit.BRICK # 未开——掩尘完整地砖(色板原语 #C9AF83)
const COL_FLOOR := UiKit.FLOOR # 已开——裸土 #B39A78(碎裂裸露地面)
const COL_DIGIT := UiKit.INK # 数字——墨族 #33261B(对格底 ≥4.5:1 硬指标)
const COL_HERO := UiKit.HERO_BLUE # 小人边框——小人蓝 #2E6E8E
const COL_FLAG := UiKit.FLAG_RED # 旗朱 #C63D22
const COL_GOLD := UiKit.GOLD # 奖励金 #F0A828
const COL_PATH := UiKit.HERO_BLUE # 路径预览点迹——小人蓝细线
const COL_DIG_EDGE := UiKit.DIG_EDGE # 可挖域呼吸微光基色(绿相,明度贴格底)
const COL_HL_TARGET := UiKit.GOLD # 悬停目标格边框(金)
const REWARD_BADGE := { # 已开格格面资源身份 icon(cell_type 八型键;极性视觉归批 2)
"attack": "攻", "defense": "守", "heal": "医", "blast": "爆", "weaken": "弱", "pierce": "穿", "magic": "魔", # 穿/魔 = 伤害道具批 2026-09-18
"action": "行", # 行 = 行动点型(八型批 2026-09-20——ap_up/ap_drain 两行;徽章键漏网补齐,ui_click_probe 91 断言修复)
}
const BADGE_PLACEHOLDER := "?" # 未知图标键占位纹样(HUD框架:禁静默空图标)
const CURSOR_DIG := Input.CURSOR_CROSS # 挖——镐形自绘纹理载体
@@ -237,7 +238,7 @@ func _apply_hover_visuals(c: Vector2i) -> void:
_set_cursor_shape(c, Input.CURSOR_FORBIDDEN)
else:
hl.visible = true
_set_hl_color(hl, Color8(120, 60, 50)) # 不可及域灰禁框(禁止光标+首遇 toast 双通道)
_set_hl_color(hl, UiKit.RED_FORBID) # 不可及域灰禁框(禁止光标+首遇 toast 双通道)
_set_cursor_shape(c, Input.CURSOR_FORBIDDEN)
hover_forbidden.emit(c)
@@ -315,7 +316,7 @@ func _paint_cell(c: Vector2i, hero: Vector2i) -> void:
if rec.get("kind", "") == "mine":
bg = COL_FLOOR
text = "雷"
digit_col = Color8(150, 44, 36)
digit_col = UiKit.RED_MINE
else:
bg = COL_FLOOR
var d: int = rec.get("digit", 0)
@@ -331,11 +332,7 @@ func _paint_cell(c: Vector2i, hero: Vector2i) -> void:
digit_col = COL_FLAG
else:
bg = COL_BRICK
var sb := StyleBoxFlat.new()
sb.bg_color = bg
sb.set_corner_radius_all(3)
sb.set_border_width_all(1)
sb.border_color = bg.darkened(0.15)
var sb := UiKit.panel_flat(bg, bg.darkened(0.15), 3)
if is_hero:
sb.set_border_width_all(3)
sb.border_color = COL_HERO
@@ -376,7 +373,7 @@ func _process(delta: float) -> void:
return
_breath_t += delta
var k := 0.5 + 0.5 * sin(_breath_t * 3.0) # 3 rad/s≈0.48Hz——无 >3 次/秒频闪(AC 基线)
var col := COL_DIG_EDGE.lerp(Color8(46, 80, 60), 0.55 - 0.35 * k)
var col := COL_DIG_EDGE.lerp(UiKit.DIG_EDGE_DEEP, 0.55 - 0.35 * k)
for c in _diggable:
if not _cell_sb.has(c):
continue
@@ -414,10 +411,8 @@ func _build_markers(btn: Button) -> Dictionary:
var hl := Panel.new()
hl.set_anchors_preset(Control.PRESET_FULL_RECT)
hl.mouse_filter = Control.MOUSE_FILTER_IGNORE
var hl_sb := StyleBoxFlat.new()
var hl_sb := UiKit.panel_flat(Color.TRANSPARENT, COL_HL_TARGET, 0, 2)
hl_sb.draw_center = false
hl_sb.set_border_width_all(2)
hl_sb.border_color = COL_HL_TARGET
hl.add_theme_stylebox_override("panel", hl_sb)
hl.visible = false
btn.add_child(hl)
@@ -10,16 +10,16 @@
class_name EnemyCardView
extends PanelContainer
const COL_INK := Color8(51, 38, 27)
const COL_INK := UiKit.INK
# 摇定动作呈现映射(敌人技能池批 §2.4 三档可见性;新效应词汇批 2026-09-19 扩四档):键 = pending_type(快照投影)。
# 普通攻击零表示("—" 中性色——完全不可预测);伤害特殊技 = 攻击系 ⚔(朱红);
# 增益特殊技 = 防御/增益系 ✦(蓝);妨害特殊技 = 妨害系 ☠(紫——对主角施减益,proposal-status-vocabulary §1.4)。
# nat20 暴击无前置表示(掷点层,与技能重击严格区分)。
const PENDING_STYLE := {
"basic": ["—", Color8(120, 106, 88)],
"damage": ["⚔", Color8(198, 61, 34)],
"buff": ["✦", Color8(46, 110, 142)],
"debuff": ["☠", Color8(122, 66, 148)],
"basic": ["—", UiKit.PANEL_BORDER],
"damage": ["⚔", UiKit.FLAG_RED],
"buff": ["✦", UiKit.HERO_BLUE],
"debuff": ["☠", UiKit.DEBUFF_PURPLE],
}
# 蓄力档技能集(2026-09-18 用户拍板:重击类独立蓄力提示——伤害技 ⚔ / 增益技 ✦ / 重击类 蓄力 三档占位)
const CHARGE_SKILL_IDS := ["heavy"]
@@ -39,21 +39,13 @@ var _dead := false
func _init() -> void:
custom_minimum_size = Vector2(190, 176)
var sb := StyleBoxFlat.new()
sb.bg_color = Color8(226, 212, 190)
sb.set_corner_radius_all(4)
sb.set_border_width_all(1)
sb.border_color = Color8(150, 60, 48)
sb.content_margin_left = 8.0
sb.content_margin_right = 8.0
sb.content_margin_top = 6.0
sb.content_margin_bottom = 6.0
var sb := UiKit.panel_flat(UiKit.PANEL_ENEMY, UiKit.RED_DEEP, 4, 1, Vector4(8, 6, 8, 6))
add_theme_stylebox_override("panel", sb)
var row := HBoxContainer.new()
row.add_theme_constant_override("separation", 8)
add_child(row)
_portrait = UiKit.label("敌", 34, true)
_portrait.add_theme_color_override("font_color", Color8(150, 60, 48))
_portrait.add_theme_color_override("font_color", UiKit.RED_DEEP)
_portrait.custom_minimum_size = Vector2(48, 0)
_portrait.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
_portrait.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
@@ -109,7 +101,7 @@ func _set_order(i: int) -> void:
func set_pending(ptype: String, pid: String) -> void:
if _dead:
return
var style: Array = PENDING_STYLE.get(ptype, ["—", Color8(120, 106, 88)])
var style: Array = PENDING_STYLE.get(ptype, ["—", UiKit.PANEL_BORDER])
_intent_badge.add_theme_color_override("font_color", style[1])
if ptype == "" or ptype == "basic":
_intent_badge.text = "意图:—" # 普通攻击零表示(不可预测——§2.4)
@@ -137,7 +129,7 @@ func mark_dead() -> void:
tw.tween_property(self, "rotation_degrees", 0.0, 0.08)
_portrait.text = "✕"
_intent_badge.text = "—— 击破 ——"
_intent_badge.add_theme_color_override("font_color", Color8(120, 110, 98))
_intent_badge.add_theme_color_override("font_color", UiKit.STONE)
_armor_line.text = ""
_status_label.text = ""
_hp_bar.value = 0
@@ -5,8 +5,8 @@
class_name HeroCardView
extends PanelContainer
const COL_INK := Color8(51, 38, 27)
const COL_HERO := Color8(46, 110, 142)
const COL_INK := UiKit.INK
const COL_HERO := UiKit.HERO_BLUE
var _portrait: Label
var _hp_bar: ProgressBar
@@ -18,15 +18,7 @@ var _status_label: Label
func _init() -> void:
custom_minimum_size = Vector2(216, 176)
var sb := StyleBoxFlat.new()
sb.bg_color = Color8(232, 220, 196)
sb.set_corner_radius_all(4)
sb.set_border_width_all(1)
sb.border_color = Color8(120, 106, 88)
sb.content_margin_left = 8.0
sb.content_margin_right = 8.0
sb.content_margin_top = 6.0
sb.content_margin_bottom = 6.0
var sb := UiKit.panel_flat(UiKit.PANEL_HERO, UiKit.PANEL_BORDER, 4, 1, Vector4(8, 6, 8, 6))
add_theme_stylebox_override("panel", sb)
var row := HBoxContainer.new()
row.add_theme_constant_override("separation", 8)
@@ -8,9 +8,9 @@
class_name HeroInfoPanelView
extends PanelContainer
const COL_INK := Color8(51, 38, 27)
const COL_GOLD := Color8(240, 168, 40)
const COL_DOT_OFF := Color8(120, 106, 88)
const COL_INK := UiKit.INK
const COL_GOLD := UiKit.GOLD
const COL_DOT_OFF := UiKit.DOT_OFF
var _hp_bar: ProgressBar
var _hp_label: Label
@@ -26,15 +26,7 @@ var _last_rap := 0 # 上次投影值(清零反馈判据——
func _init() -> void:
custom_minimum_size = Vector2(240, 0)
clip_contents = true
var sb := StyleBoxFlat.new()
sb.bg_color = Color8(232, 220, 196)
sb.set_corner_radius_all(0)
sb.set_border_width_all(1)
sb.border_color = Color8(120, 106, 88)
sb.content_margin_left = 8.0
sb.content_margin_right = 8.0
sb.content_margin_top = 6.0
sb.content_margin_bottom = 6.0
var sb := UiKit.panel_flat(UiKit.PANEL_HERO, UiKit.PANEL_BORDER, 0, 1, Vector4(8, 6, 8, 6))
add_theme_stylebox_override("panel", sb)
var col := VBoxContainer.new()
col.add_theme_constant_override("separation", 6)
@@ -60,19 +52,19 @@ func _init() -> void:
_rap_label = UiKit.label("RAP 0", 13, true)
rap_head.add_child(_rap_label)
_rap_feedback = UiKit.label("", 12, false)
_rap_feedback.add_theme_color_override("font_color", Color8(140, 124, 100))
_rap_feedback.add_theme_color_override("font_color", UiKit.STONE_FAINT)
col.add_child(_rap_feedback)
col.add_child(UiKit.label("状态效果", 14, true))
slot_row = StatusSlotRow.new()
col.add_child(slot_row)
_status_feedback = UiKit.label("", 12, false)
_status_feedback.add_theme_color_override("font_color", Color8(140, 124, 100))
_status_feedback.add_theme_color_override("font_color", UiKit.STONE_FAINT)
col.add_child(_status_feedback)
# 小人立绘占位(程序化色块——真实立绘归 战斗表现)
var portrait := ColorRect.new()
portrait.color = Color8(46, 110, 142, 56)
portrait.color = Color(UiKit.HERO_BLUE, 56.0 / 255.0) # 原 Color8(46, 110, 142, 56)
portrait.custom_minimum_size = Vector2(0, 120)
portrait.size_flags_vertical = Control.SIZE_EXPAND_FILL
col.add_child(portrait)
@@ -23,7 +23,7 @@ var _panel: PanelContainer
func _init() -> void:
var dim := ColorRect.new()
dim.color = Color(0.08, 0.06, 0.05, 0.55)
dim.color = Color(UiKit.DIM, 0.55)
dim.set_anchors_preset(Control.PRESET_FULL_RECT)
dim.gui_input.connect(func(ev: InputEvent):
if ev is InputEventMouseButton and ev.pressed:
@@ -7,11 +7,11 @@
class_name LevelStripView
extends HBoxContainer
const COL_DONE := Color8(140, 116, 60) # 已过——暗金
const COL_CURRENT := Color8(240, 168, 40) # 当前——奖励金高亮
const COL_UPCOMING := Color8(64, 58, 52)
const COL_CANDIDATE := Color8(230, 190, 90) # 候选下一跳——亮金边框
const COL_BOSS_BORDER := Color8(198, 61, 34) # Boss 边框——旗朱
const COL_DONE := UiKit.GOLD_DIM # 已过——暗金
const COL_CURRENT := UiKit.GOLD # 当前——奖励金高亮
const COL_UPCOMING := UiKit.DARK_UPCOMING
const COL_CANDIDATE := UiKit.GOLD_LIT # 候选下一跳——亮金边框
const COL_BOSS_BORDER := UiKit.FLAG_RED # Boss 边框——旗朱
const NODE_LABELS := {"battle": "战", "reward": "赏", "rest": "疗", "boss": "王"}
@@ -63,7 +63,7 @@ func refresh_graph(runner) -> void:
func _arrow() -> Label:
var arrow := UiKit.label("→", 13, false)
arrow.add_theme_color_override("font_color", Color8(120, 110, 98))
arrow.add_theme_color_override("font_color", UiKit.STONE)
return arrow
@@ -79,24 +79,20 @@ func _node_color(i: int, runner) -> Color:
func _node_chip(type: String, col: Color, candidate_border: bool, node_id: int = -1) -> PanelContainer:
var p := PanelContainer.new()
var sb := StyleBoxFlat.new()
sb.set_corner_radius_all(4)
sb.content_margin_left = 9.0
sb.content_margin_right = 9.0
sb.content_margin_top = 2.0
sb.content_margin_bottom = 2.0
sb.bg_color = col
var border := col
var border_w := 0
if type == "boss":
sb.set_border_width_all(2)
sb.border_color = COL_BOSS_BORDER
border = COL_BOSS_BORDER
border_w = 2
elif candidate_border:
sb.set_border_width_all(2)
sb.border_color = COL_CANDIDATE
border = COL_CANDIDATE
border_w = 2
var sb := UiKit.panel_flat(col, border, 4, border_w, Vector4(9, 2, 9, 2))
p.add_theme_stylebox_override("panel", sb)
var text := String(NODE_LABELS.get(type, "?"))
if node_id >= 0:
text += str(node_id)
var l := UiKit.label(text, 15, true)
l.add_theme_color_override("font_color", Color8(30, 26, 22) if col != COL_UPCOMING else Color8(160, 150, 138))
l.add_theme_color_override("font_color", UiKit.INK_TITLE if col != COL_UPCOMING else UiKit.DARK_TEXT_FAINT)
p.add_child(l)
return p
@@ -23,7 +23,7 @@ func _init() -> void:
box.add_theme_constant_override("separation", 12)
center.add_child(box)
_label = UiKit.label("", 20, true)
_label.add_theme_color_override("font_color", Color8(240, 226, 200))
_label.add_theme_color_override("font_color", UiKit.WARM)
_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(_label)
_btn = UiKit.button("继续")
@@ -10,12 +10,12 @@ extends Control
signal route_chosen(node_id: int)
const COL_ROOM_DONE := Color8(140, 116, 60) # 已到——暗金
const COL_ROOM_CURRENT := Color8(240, 168, 40) # 当前——奖励金
const COL_ROOM_FUTURE := Color8(64, 58, 52) # 未达——暗
const COL_PASSAGE := Color8(120, 110, 98) # 通道——石灰
const COL_PASSAGE_LIT := Color8(230, 190, 90) # 候选通道——亮金
const COL_BOSS_BORDER := Color8(198, 61, 34) # Boss 边框——旗朱
const COL_ROOM_DONE := UiKit.GOLD_DIM # 已到——暗金
const COL_ROOM_CURRENT := UiKit.GOLD # 当前——奖励金
const COL_ROOM_FUTURE := UiKit.DARK_UPCOMING # 未达——暗
const COL_PASSAGE := UiKit.STONE # 通道——石灰
const COL_PASSAGE_LIT := UiKit.GOLD_LIT # 候选通道——亮金
const COL_BOSS_BORDER := UiKit.FLAG_RED # Boss 边框——旗朱
const NODE_LABELS := {"battle": "战", "reward": "赏", "rest": "疗", "boss": "王"}
var _runner = null
@@ -35,7 +35,7 @@ func _init() -> void:
box.add_theme_constant_override("separation", 10)
center.add_child(box)
_title = UiKit.label("选择下一跳", 18, true)
_title.add_theme_color_override("font_color", Color8(240, 226, 200))
_title.add_theme_color_override("font_color", UiKit.WARM)
_title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(_title)
var canvas := Control.new()
@@ -131,8 +131,8 @@ func _draw_graph(canvas: Control) -> void:
canvas.draw_rect(rect, COL_PASSAGE_LIT, false, 2.0)
var font := ThemeDB.fallback_font
var label := String(NODE_LABELS.get(t, "?"))
canvas.draw_string(font, p + Vector2(-6, 2), label, HORIZONTAL_ALIGNMENT_LEFT, -1, 16, Color8(24, 20, 16))
canvas.draw_string(font, p + Vector2(10, 14), str(nid), HORIZONTAL_ALIGNMENT_LEFT, -1, 10, Color8(210, 196, 170))
canvas.draw_string(font, p + Vector2(-6, 2), label, HORIZONTAL_ALIGNMENT_LEFT, -1, 16, UiKit.INK_ROUTE)
canvas.draw_string(font, p + Vector2(10, 14), str(nid), HORIZONTAL_ALIGNMENT_LEFT, -1, 10, UiKit.WARM_ROUTE_SUB)
func _layout(nodes: Array, canvas: Control) -> Dictionary:
@@ -12,7 +12,7 @@ var _log: RichTextLabel
func _init() -> void:
var dim := ColorRect.new()
dim.color = Color(0.08, 0.06, 0.05, 0.62)
dim.color = Color(UiKit.DIM, 0.62)
dim.set_anchors_preset(Control.PRESET_FULL_RECT)
dim.gui_input.connect(func(ev: InputEvent):
if ev is InputEventMouseButton and ev.pressed:
@@ -16,15 +16,15 @@ const MAX_SLOTS := 4
# (2026-09-15 格面资源批补 sapped;2026-09-16 护甲等级掷点批 defense_up → ac_up 换装;
# 同日 敌人技能池批补 empower/fortify 敌方增益两键——敌方增益显示 = 敌卡状态行文本 + 本图标键词汇)。
const EFFECT_ICON := {
"attack_up": ["▲", Color8(176, 122, 20), "益"],
"ac_up": ["◇", Color8(46, 110, 142), "益"],
"weaken": ["▼", Color8(46, 110, 142), "益"],
"alert": ["◎", Color8(198, 61, 34), "害"],
"enrage": ["⚔", Color8(198, 61, 34), "害"],
"off_guard": ["✕", Color8(198, 61, 34), "害"],
"sapped": ["☾", Color8(198, 61, 34), "害"],
"empower": ["⇧", Color8(198, 61, 34), "害"],
"fortify": ["▣", Color8(120, 106, 88), "害"],
"attack_up": ["▲", UiKit.GOLD_DEEP, "益"],
"ac_up": ["◇", UiKit.HERO_BLUE, "益"],
"weaken": ["▼", UiKit.HERO_BLUE, "益"],
"alert": ["◎", UiKit.FLAG_RED, "害"],
"enrage": ["⚔", UiKit.FLAG_RED, "害"],
"off_guard": ["✕", UiKit.FLAG_RED, "害"],
"sapped": ["☾", UiKit.FLAG_RED, "害"],
"empower": ["⇧", UiKit.FLAG_RED, "害"],
"fortify": ["▣", UiKit.PANEL_BORDER, "害"],
}
const EFFECT_SEMANTIC := {
"attack_up": "主角攻击加成(hero_offense 池加算)",
@@ -39,7 +39,7 @@ const EFFECT_SEMANTIC := {
}
const SOURCE_NAMES := {"safe_cell": "安全格", "flag_hit": "标中旗", "mine_hit": "踩雷", "clear_reward": "清图奖励"}
# 未知图标键的占位纹样(HUD框架:占位也要可见,禁静默空图标)
const ICON_PLACEHOLDER := ["?", Color8(120, 106, 88), "?"]
const ICON_PLACEHOLDER := ["?", UiKit.PANEL_BORDER, "?"]
var _tip: PanelContainer
var _tip_label: Label
@@ -53,18 +53,10 @@ func _init() -> void:
_tip.z_index = 10
_tip.mouse_filter = Control.MOUSE_FILTER_IGNORE
_tip.visible = false
var sb := StyleBoxFlat.new()
sb.bg_color = Color(0.16, 0.12, 0.09, 0.96)
sb.set_corner_radius_all(2)
sb.set_border_width_all(1)
sb.border_color = Color8(240, 168, 40)
sb.content_margin_left = 6.0
sb.content_margin_right = 6.0
sb.content_margin_top = 3.0
sb.content_margin_bottom = 3.0
var sb := UiKit.panel_flat(UiKit.TIP_BG, UiKit.GOLD, 2, 1, Vector4(6, 3, 6, 3))
_tip.add_theme_stylebox_override("panel", sb)
_tip_label = UiKit.label("", 13, false)
_tip_label.add_theme_color_override("font_color", Color8(240, 226, 200))
_tip_label.add_theme_color_override("font_color", UiKit.WARM)
_tip_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
_tip_label.custom_minimum_size = Vector2(210, 0)
_tip.add_child(_tip_label)
@@ -106,11 +98,7 @@ func _sync_slots(n: int) -> void:
func _make_slot() -> PanelContainer:
var slot := PanelContainer.new()
slot.custom_minimum_size = Vector2(50, 46)
var sb := StyleBoxFlat.new()
sb.bg_color = Color8(226, 210, 182)
sb.set_corner_radius_all(0)
sb.set_border_width_all(1)
sb.border_color = Color8(120, 106, 88)
var sb := UiKit.panel_flat(UiKit.PANEL_DATA, UiKit.PANEL_BORDER)
slot.add_theme_stylebox_override("panel", sb)
slot.mouse_entered.connect(_on_slot_hover.bind(slot))
slot.mouse_exited.connect(func(): _tip.visible = false)
@@ -8,9 +8,9 @@ extends Control
const LIFE_SEC := 2.5
const MAX_SLOTS := 3
const COL_INFO := Color8(51, 38, 27)
const COL_WARN := Color8(198, 61, 34) # 旗朱族——拒绝/作废
const COL_GOLD := Color8(176, 122, 20) # 奖励金族——提示/达成
const COL_INFO := UiKit.INK
const COL_WARN := UiKit.FLAG_RED # 旗朱族——拒绝/作废
const COL_GOLD := UiKit.GOLD_DEEP # 奖励金族——提示/达成(深金档)
var _slot_box: VBoxContainer
@@ -35,14 +35,7 @@ func show_toast(text: String, tone: String = "info") -> void:
row.mouse_filter = Control.MOUSE_FILTER_IGNORE
row.clip_contents = true # 缺陷①约束:固定槽高裁剪,不回流布局
row.custom_minimum_size = Vector2(0, 24)
var sb := StyleBoxFlat.new()
sb.bg_color = Color(0.94, 0.91, 0.84, 0.95)
sb.set_corner_radius_all(2)
sb.set_border_width_all(1)
sb.content_margin_left = 8.0
sb.content_margin_right = 8.0
sb.content_margin_top = 2.0
sb.content_margin_bottom = 2.0
var sb := UiKit.panel_flat(UiKit.TOAST_BG, COL_INFO, 2, 1, Vector4(8, 2, 8, 2))
var col := COL_INFO
if tone == "warn":
col = COL_WARN
@@ -121,7 +121,7 @@ func effective_max_hp() -> int:
func _build() -> void:
var dim := ColorRect.new()
dim.color = Color8(28, 22, 18)
dim.color = UiKit.BG_OVERLAY
dim.set_anchors_preset(Control.PRESET_FULL_RECT)
add_child(dim)
var center := CenterContainer.new()
@@ -133,12 +133,12 @@ func _build() -> void:
center.add_child(box)
var title := UiKit.label("测试用 · 角色数值调整板", 26, true)
title.add_theme_color_override("font_color", Color8(240, 226, 200))
title.add_theme_color_override("font_color", UiKit.WARM)
box.add_child(title)
var desc := UiKit.label(
"模拟玩家在循环中解锁天赋获得的属性提升(仅测试工具,不落盘)。\n百分比叠加基础值:攻击 %d / 生命 %d。影响所有模式(手动与模拟)。" % [_base_atk, _base_hp],
13, false)
desc.add_theme_color_override("font_color", Color8(200, 188, 166))
desc.add_theme_color_override("font_color", UiKit.WARM_SOFT)
box.add_child(desc)
box.add_child(HSeparator.new())
@@ -1,16 +1,91 @@
# VERTICAL SLICE - NOT FOR PRODUCTION
# Date: 2026-09-11
# 呈现层共享小部件工厂(各视图视图复用;避免每个视图类重复六行工厂函数)。
# Date: 2026-09-11(2026-09-20 样式收敛批:全站色板与 StyleBox 工厂单点化)
# 呈现层共享小部件工厂 + 全站取色/描边唯一出口——各视图禁再内联 Color8/StyleBoxFlat
# 字面量;美术批换皮只改本文件(值 = 收敛时各视图现值快照,本批零视觉变化)。
class_name UiKit
extends RefCounted
# ── 色板(语义族;值 = 2026-09-20 收敛时现值) ──
const INK := Color8(51, 38, 27) # 墨族——正文/数字(对格底 ≥4.5:1)
const INK_LABEL := Color8(46, 34, 24) # 标签深墨
const INK_TITLE := Color8(30, 26, 22) # 亮底标题墨
const INK_ROUTE := Color8(24, 20, 16) # 节点图最深墨
const INK_ON_GOLD := Color8(60, 44, 20) # 金底上的深墨
const PANEL_HERO := Color8(232, 220, 196) # 面板底·主角侧(英雄卡/角色信息框)
const PANEL_ENEMY := Color8(226, 212, 190) # 面板底·敌方卡
const PANEL_DATA := Color8(226, 210, 182) # 面板底·数据框(AP 条/状态槽)
const PANEL_STAGE := Color8(216, 200, 172) # 面板底·战斗画面区
const PANEL_BORDER := Color8(120, 106, 88) # 面板细线框;兼熄灭点阵(DOT_OFF 别名)
const GOLD := Color8(240, 168, 40) # 奖励金
const GOLD_DEEP := Color8(176, 122, 20) # 深金(金框描边/达意金)
const GOLD_LIT := Color8(230, 190, 90) # 亮金(候选高亮)
const GOLD_DIM := Color8(140, 116, 60) # 暗金(已过节点)
const FLAG_RED := Color8(198, 61, 34) # 旗朱
const RED_DEEP := Color8(150, 60, 48) # 深朱(敌卡框/敌像)
const RED_MINE := Color8(150, 44, 36) # 引爆雷字朱(已开雷格"雷"字)
const RED_FORBID := Color8(120, 60, 50) # 禁止框朱
const RED_ALERT := Color8(200, 60, 48) # 报错朱
const HERO_BLUE := Color8(46, 110, 142) # 小人蓝
const BOSS_PURPLE := Color8(143, 47, 106) # 紫赤(Boss 专属)
const DEBUFF_PURPLE := Color8(122, 66, 148) # 妨害紫(意图 ☠)
const DUSK := Color8(90, 108, 140) # 暮蓝(全作唯一暮蓝档——失败终局)
const WARM := Color8(240, 226, 200) # 暖白(暗底正文)
const WARM_SOFT := Color8(200, 188, 166) # 暖白次级(说明文)
const WARM_FAINT := Color8(178, 166, 146) # 暖白弱化(帮助文)
const WARM_ROUTE_SUB := Color8(210, 196, 170) # 节点图编号暖白
const STONE := Color8(120, 110, 98) # 灰石(通道/箭头/失效)
const STONE_FAINT := Color8(140, 124, 100) # 灰石弱化(占位提示文)
const DARK_UPCOMING := Color8(64, 58, 52) # 未达暗字(底/文同值)
const DARK_TEXT_FAINT := Color8(160, 150, 138)# 未达节点文字
const BRICK := Color8(201, 175, 131) # 棋盘·未开掩尘地砖 #C9AF83
const FLOOR := Color8(179, 154, 120) # 棋盘·已开裸土 #B39A78
const DIG_EDGE := Color8(120, 190, 120) # 可挖域呼吸微光绿
const DIG_EDGE_DEEP := Color8(46, 80, 60) # 可挖域呼吸暗端(lerp 目标)
const BG_ROOT := Color8(30, 25, 20) # 屏幕根底
const BG_OVERLAY := Color8(28, 22, 18) # 模态遮罩底
const DIM := Color(0.08, 0.06, 0.05) # 遮罩基色(用时乘 alpha)
const TOAST_BG := Color(0.94, 0.91, 0.84, 0.95) # toast 面底
const TIP_BG := Color(0.16, 0.12, 0.09, 0.96) # tooltip 深底
# BBCode 十六进制(RichTextLabel 用;与上同值)
const HEX_GOLD := "f0a828"
const HEX_INK := "33261b"
const HEX_ON_GOLD := "3a2a08"
# 语义别名(同值异名——语义站点用别名,值仍单点)
const DOT_OFF := PANEL_BORDER
# ── StyleBox 工厂 ──
# margin = (左, 上, 右, 下);border_w = 0 即无边框(根底/遮罩用)
static func panel_flat(bg: Color, border: Color, corner: int = 0, border_w: int = 1, margin: Vector4 = Vector4.ZERO) -> StyleBoxFlat:
var sb := StyleBoxFlat.new()
sb.bg_color = bg
sb.set_corner_radius_all(corner)
sb.set_border_width_all(border_w)
sb.border_color = border
sb.content_margin_left = margin.x
sb.content_margin_top = margin.y
sb.content_margin_right = margin.z
sb.content_margin_bottom = margin.w
return sb
static func label(text: String, size: int, bold: bool) -> Label:
var l := Label.new()
l.text = text
l.add_theme_font_size_override("font_size", size)
if bold:
l.add_theme_color_override("font_color", Color8(46, 34, 24))
l.add_theme_color_override("font_color", INK_LABEL)
return l