Files
gplan-2/game/smoke/ui_contrast_probe.gd
T
DKChan 5f9d8e7b77 chore(代码卫生): 文件头零工作日志红线落文+全仓头注变更叙事清偿(2026-10-15 用户令)
- CLAUDE.md 硬性红线新增「文件头零工作日志」;code-conventions.md 新增 §1.4.1(含反面案例)
- 全仓 .gd 文件头注清偿:删除全部带日期条目、批次叙事段与迁移退役叙述,保留并改写为
  现在时的职责、接口契约、GDD 锚内容(main.gd 头注 42→31 行、save_manager.gd 49→45 行)
- 纯注释改动零行为变更,按用户令免测试免冒烟
2026-10-15 04:08:38 +08:00

136 lines
9.9 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# VERTICAL SLICE - NOT FOR PRODUCTION
# UI 文字对比度机检(probe_gate 默认必跑)
# 断言面 = 文字墨对直背景 ≥4.5:1(art-bible §7.2 无区域例外;文字禁直压纹理底——垫牌后按牌色计)。
# 测点表:血数垫牌 / 意图徽标四墨(PANEL_DATA 垫牌)/ C区槽位两态墨 / RAP 标签 + 全站锚点组。
# 测点对一律取 UiKit 常量实时求值——代码侧换色即本闸红,禁只改注释不动值;α<1 墨先对背景混成再算。
# 运行:Godot_console.exe --headless --path . res://smoke/ui_contrast_probe.tscn
extends Node
const MIN_RATIO := 4.5
# R1 过渡白名单:呈现层(ui_kit.gd 之外)允许的裸 Color8( 在册处——file→恰计数。
# T4a 已把 T0 实测全量 25 处/10 文件全部原值搬运收 ui_kit(2026-10-06)——本表应为空表;
# 新增裸取色 = 本闸红(先立常量再消费)。
const BARE_COLOR8_WL := {}
# 测点表:[名称, 墨色, 直背景, 墨α](语义见行尾;新增文字位随批入表,白名单豁免须注理由)
func _pairs() -> Array:
return [
["站桩血数·垫牌", Color(1, 1, 1), UiKit.HP_BAR_BACK, 0.95], # N1-1/2 白 α.95 压 HP_BAR_BACK 素牌
["意图atk·垫牌", UiKit.RED_MINE, UiKit.PANEL_DATA, 1.0], # N1-3 ⚔ 攻击预告(零换墨)
["意图buf·垫牌", UiKit.HERO_BLUE_DEEP, UiKit.PANEL_DATA, 1.0], # N1-4 ✦ 增益(同族深档)
["意图debuff·垫牌", UiKit.DEBUFF_PURPLE, UiKit.PANEL_DATA, 1.0], # ☠ 妨害(零换墨随牌达标)
["意图charge·垫牌", UiKit.GOLD_INK, UiKit.PANEL_DATA, 1.0], # 蓄力重击(深金墨)
["C区槽·已用", UiKit.STONE_DEEP, UiKit.PANEL_DATA, 1.0], # N1-5 占位暗字(灰石深化)
["C区槽·不可用", UiKit.INK_LABEL, UiKit.PANEL_DATA, 1.0], # N1-6 置灰(标签深墨)
["RAP标签", UiKit.INK_LABEL, UiKit.PANEL_DATA, 1.0], # N1-7(T0 实测已合规,显式化)
["锚·正文墨/数据板", UiKit.INK, UiKit.PANEL_DATA, 1.0], # 全站锚点:正文墨对数据板
["锚·暖白/屏根", UiKit.WARM, UiKit.BG_ROOT, 1.0], # 全站锚点:暗底正文
["锚·暖白弱/舞台底", UiKit.WARM_FAINT, UiKit.STAGE_BG, 1.0], # 全站锚点:B区辅助墨
["钥石徽·深墨/烛光黄", UiKit.INK_ON_GOLD, UiKit.CANDLE, 1.0], # 迭代17卡③——badge 工厂件文字(营地徽+状态面板余额行同形制)
["生涯页·行名墨/暖亮页底", UiKit.WARM, UiKit.BG_BRIGHT, 1.0], # 迭代18卡④——生涯页行名列/提示文(WARM_SOFT 同族亮墨)
["生涯页·行值墨/暖亮页底", UiKit.CANDLE, UiKit.BG_BRIGHT, 1.0], # 迭代18卡④——生涯页数值列(烛光黄 bold)
["生涯页·组帽墨/暖亮页底", UiKit.INK_L_GOLD, UiKit.BG_BRIGHT, 1.0],# 迭代18卡④——生涯页分组小节头(金亮 bold)
# ---- 迭代19卡②旧界面呈现断言回补批(2026-10-08)——旧屏文字位追溯收测;石皮纹面板
# (panel_skinned)缺素材回退牌色 PANEL_DATA,机检按回退牌色计(素材不入 git 冒烟安全惯例)。
# 存量违例对首跑红=登记呈报不修(处置权归用户)→ 2026-10-08 尾裁微批a 用户裁甲另立修复批
# 回绿:7 对随代码侧换墨同步改指新常量(比率见各行尾注)。
["结算·判定墨/结算板", UiKit.INK_TITLE, UiKit.PANEL_DATA, 1.0], # 迭代19卡②——battle_end 判定行(INK_TITLE 亮底标题墨)
["结算·GP账行墨/结算板", UiKit.GOLD_INK, UiKit.PANEL_DATA, 1.0], # 迭代19卡②——battle_end 战利品 GP 行名/值(尾裁微批a 换深金墨 5.21:1;原 GOLD_DEEP 2.67 越带)
["结算·账行墨/结算板", UiKit.INK_LABEL, UiKit.PANEL_DATA, 1.0], # 迭代19卡②——battle_end 钥石/加成账行(标签深墨)
["商店·行卡名墨/暗底行卡", UiKit.WARM_SOFT, UiKit.BG_OVERLAY, 1.0], # 迭代19卡②——legacy 行卡商品名(尾裁微批a 显式传暖白次级 9.53:1;原 bold 缺省 INK_LABEL 1.12 越带)
["商店·行卡现价墨/暗底行卡", UiKit.WARM_SOFT, UiKit.BG_OVERLAY, 1.0],# 迭代19卡②——legacy 行卡「现价 N 金币」
["商店·行卡已购墨/暗底行卡", UiKit.WARM_FAINT, UiKit.BG_OVERLAY, 1.0],# 迭代19卡②——legacy 行卡「已购 N 档」
["商店·爬价规则墨/暖亮页底", UiKit.WARM_SOFT, UiKit.BG_BRIGHT, 1.0],# 迭代19卡②——货架面爬价规则行(page_shell 亮底)
["商店·货架卡名墨/货架板", UiKit.INK_TITLE, UiKit.PANEL_DATA, 1.0], # 迭代19卡②——bcard 货架卡商品名(iter16 换 TG 带后未机检位)
["商店·货架价签墨/货架板", UiKit.GOLD_INK, UiKit.PANEL_DATA, 1.0], # 迭代19卡②——bcard 价签「N ◈」(尾裁微批a 换深金墨 5.21:1;原 GOLD 1.46 越带)
["营地·等级章字/头带深棕", UiKit.INK_ON_DEEP, UiKit.CAMP_HEADER_BAND, 1.0],# 迭代19卡②——锻造行 Lv 章(木底小章亮墨)
["营地·柜台头带字/头带深棕", UiKit.WARM, UiKit.CAMP_HEADER_BAND, 1.0], # 迭代19卡②——三柜台头带标题(暖白 bold)
["营地·铭牌副题墨/铭牌板", UiKit.STONE_DEEP, UiKit.PANEL_DATA, 1.0],# 迭代19卡②——营地铭牌副题「跨局成长账本…」(尾裁微批a 换灰石深化 5.98:1;原 STONE 3.59 越带)
["营地·行名墨/行板", UiKit.INK, UiKit.CAMP_ROW_PLATE, 1.0], # 迭代19卡②——锻造/工坊行名(墨族压暖米行板)
["营地·行价格墨/行板", UiKit.STONE_DEEP, UiKit.CAMP_ROW_PLATE, 1.0],# 迭代19卡②——锻造行「N 钥石」价签/工坊进度行(尾裁微批a 换灰石深化 6.70:1;原 STONE 4.02 越带)
["营地·树分组头墨/柜台板", UiKit.GOLD_INK, UiKit.PANEL_DATA, 1.0],# 迭代19卡②——天赋树脉分组头「·锻造脉·」(尾裁微批a 换深金墨 5.21:1;原 GOLD_DEEP 2.67 越带)
["营地·树行名墨/柜台板", UiKit.INK_LABEL, UiKit.PANEL_DATA, 1.0], # 迭代19卡②——天赋树行「名 Lv0/1」(标签深墨)
["营地·工坊状态墨/行板", UiKit.GOLD_INK, UiKit.CAMP_ROW_PLATE, 1.0],# 迭代19卡②——工坊状态字「已解锁」(尾裁微批a 换深金墨 5.84:1;原 GOLD_DEEP 3.00 越带·最不利现役态)
["营地·最近冒险墨/暖亮底", UiKit.WARM_SOFT, UiKit.BG_BRIGHT, 1.0], # 迭代19卡②——底栏最近冒险条带(暖白次级)
["设置·警示文/设置板", UiKit.INK_HINT, UiKit.PANEL_DATA, 1.0], # 迭代19卡②——设置警示文/后果说明(暖棕提示墨)
["设置·选项标签/设置板", UiKit.INK_LABEL, UiKit.PANEL_DATA, 1.0], # 迭代19卡②——设置行标签/状态字(标签深墨)
["三选一·停点头部墨/暗页底", UiKit.WARM_SOFT, UiKit.BG_ROOT, 1.0], # 迭代19卡②——三选一停点头部/回血反馈行(page_shell 根底档)
["三选一·卡名墨/货架板", UiKit.INK_TITLE, UiKit.PANEL_DATA, 1.0], # 迭代19卡②——bcard 选项卡名(与商店货架同构卡)
["迷雾·记忆墨/灰罩合成底", UiKit.FOG_MEMORY_INK, # 迭代19卡②——fog_state2 记忆板 α.66 压 floor avg #453020
Color(UiKit.FOG_MEMORY_PLATE.r * 0.66 + 69.0 / 255.0 * 0.34, # 合成底(素材侧值无常量形态——取 art-bible §389 迭代16 T0 在册复算值,素材换装随批更新;
UiKit.FOG_MEMORY_PLATE.g * 0.66 + 48.0 / 255.0 * 0.34, # 三关逐关 avg 缺在册且素材不入 git 不可实查——最坏情况判据扩对归移交)
UiKit.FOG_MEMORY_PLATE.b * 0.66 + 32.0 / 255.0 * 0.34), 1.0],
]
func _lum(c: Color) -> float:
var f := func(x: float) -> float:
return x / 12.92 if x <= 0.03928 else pow((x + 0.055) / 1.055, 2.4)
return 0.2126 * f.call(c.r) + 0.7152 * f.call(c.g) + 0.0722 * f.call(c.b)
func _ratio(a: Color, b: Color) -> float:
var la := _lum(a)
var lb := _lum(b)
var hi := la if la >= lb else lb
var lo := lb if la >= lb else la
return (hi + 0.05) / (lo + 0.05)
func _ready() -> void:
var problems: Array = []
var pairs := _pairs()
for p in pairs:
var fg: Color = p[1]
var bg: Color = p[2]
var alpha: float = p[3]
if alpha < 1.0:
fg = Color(fg.r * alpha + bg.r * (1.0 - alpha),
fg.g * alpha + bg.g * (1.0 - alpha),
fg.b * alpha + bg.b * (1.0 - alpha))
var r := _ratio(fg, bg)
if r < MIN_RATIO:
problems.append("[contrast] %s = %.2f:1 < %.1f(测点对须垫牌或换墨)" % [p[0], r, MIN_RATIO])
problems.append_array(_scan_static())
if problems.is_empty():
print("[ui_contrast_probe] PASS — 对比度 %d 对测点全绿(≥%.1f:1 无区域例外)+ 裸色白名单/preload 红线静态段绿" % [pairs.size(), MIN_RATIO])
get_tree().quit(0)
else:
for msg in problems:
print(msg)
print("[ui_contrast_probe] FAIL — %d 项越带(含静态段)" % problems.size())
get_tree().quit(1)
# ---- 机检段②③(需求卡片 §7):呈现层裸 Color8( 计数 vs 白名单 + 素材 preload 计数 = 0 ----
func _scan_static() -> Array:
var problems: Array = []
var root := "res://presentation"
var dirs := [root]
while not dirs.is_empty():
var d: String = dirs.pop_front()
for f in DirAccess.get_files_at(d):
if not f.ends_with(".gd"):
continue
var path := d + "/" + f
var src := FileAccess.get_file_as_string(path)
var c8 := src.count("Color8(")
var pre := 0
for line in src.split("\n"):
if line.contains("preload(") and (line.contains("res://assets/") or line.contains(".png")):
pre += 1
if path.ends_with("/ui_kit.gd"):
if pre != 0:
problems.append("[static] ui_kit.gd 素材 preload=%d(红线=0)" % pre)
continue # ui_kit=色板工厂本体,Color8 定义面合法
var wl: int = BARE_COLOR8_WL.get(path, 0)
if c8 != wl:
problems.append("[static] %s 裸 Color8=%d 白名单=%d(R1 先立常量再消费)" % [path, c8, wl])
if pre != 0:
problems.append("[static] %s 素材 preload=%d(R2 红线=0)" % [path, pre])
for sub in DirAccess.get_directories_at(d):
dirs.append(d + "/" + sub)
return problems