106 lines
3.9 KiB
Python
106 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""色板基线生成器——palette_check 双门②基线的建档与刷新件。
|
||
|
||
产出两张 1×N 条带 PNG 落 game/tests/golden/palette_baseline/(图像白名单在册目录):
|
||
ui_tokens.png = ui_kit.gd 全量 Color8 常量唯一色值(token 板现役值快照)
|
||
art_snapshot.png = 现役素材(game/assets/art 递归)全量唯一色快照(像素板+各屏环境子板)
|
||
|
||
palette_check --baseline 取目录下全部 PNG 的唯一色并集为「既有色板」;基线缺一张
|
||
即漏判——基线刷新必须重生成全套。维护纪律:素材批收尾跑一次本器刷新并随批提交
|
||
(新色过门②后须入基线,否则下批扫描把已过门的新色再报新增)。
|
||
|
||
用法:
|
||
python tools/gen_palette_baseline.py [--repo <仓库根>]
|
||
退出码: 0 成功 / 2 前置缺位(ui_kit.gd 或素材目录缺 / 素材零 PNG)
|
||
"""
|
||
import argparse
|
||
import os
|
||
import re
|
||
import sys
|
||
|
||
from PIL import Image
|
||
|
||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||
from palette_check import palette_of # 排除全透明的唯一色提取——与检查器同口径
|
||
|
||
|
||
def strip_comments(text):
|
||
"""剔 GDScript 行注释与字符串字面量,防注释里举的色值被误收进 token 快照。"""
|
||
out = []
|
||
for line in text.split("\n"):
|
||
i = line.find("#")
|
||
if i != -1:
|
||
line = line[:i]
|
||
out.append(line)
|
||
return "\n".join(out)
|
||
|
||
|
||
def token_cols(ui_kit_path):
|
||
"""ui_kit.gd 全量 Color8 唯一色值集合。"""
|
||
text = strip_comments(open(ui_kit_path, encoding="utf-8").read())
|
||
vals = re.findall(r"Color8\((\d+),\s*(\d+),\s*(\d+)\)", text)
|
||
return sorted(set((int(r), int(g), int(b)) for r, g, b in vals))
|
||
|
||
|
||
def scan_dirs(roots):
|
||
"""递归扫 PNG,唯一色并集(含像素位置首见序不保——并集无序)。"""
|
||
cols = set()
|
||
count = 0
|
||
for root in roots:
|
||
for dirpath, _, names in os.walk(root):
|
||
for fn in sorted(names):
|
||
if fn.lower().endswith(".png"):
|
||
c, _n = palette_of(os.path.join(dirpath, fn))
|
||
cols |= c
|
||
count += 1
|
||
return cols, count
|
||
|
||
|
||
def write_strip(cols, out_path):
|
||
"""1×N 条带 PNG(一色一像素列)。"""
|
||
cols = sorted(cols)
|
||
im = Image.new("RGB", (len(cols), 1))
|
||
for i, c in enumerate(cols):
|
||
im.putpixel((i, 0), c)
|
||
im.save(out_path)
|
||
return len(cols)
|
||
|
||
|
||
def main():
|
||
if hasattr(sys.stdout, "reconfigure"):
|
||
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
||
ap = argparse.ArgumentParser(description="色板基线生成器(token∪素材快照)")
|
||
ap.add_argument("--repo", default=".", help="仓库根(含 game/ 与 tools/)")
|
||
args = ap.parse_args()
|
||
|
||
ui_kit = os.path.join(args.repo, "game", "presentation", "views", "ui_kit.gd")
|
||
artdir = os.path.join(args.repo, "game", "assets", "art")
|
||
outdir = os.path.join(args.repo, "game", "tests", "golden", "palette_baseline")
|
||
if not os.path.isfile(ui_kit):
|
||
print("[gen_palette_baseline] FAIL:ui_kit.gd 缺:%s" % ui_kit)
|
||
return 2
|
||
if not os.path.isdir(artdir):
|
||
print("[gen_palette_baseline] FAIL:素材目录缺:%s" % artdir)
|
||
return 2
|
||
os.makedirs(outdir, exist_ok=True)
|
||
|
||
tcols = token_cols(ui_kit)
|
||
n_t = write_strip(tcols, os.path.join(outdir, "ui_tokens.png"))
|
||
|
||
acols, npng = scan_dirs([artdir])
|
||
if npng == 0:
|
||
print("[gen_palette_baseline] FAIL:素材目录零 PNG(素材未同步)——拒绝生成空快照")
|
||
return 2
|
||
n_a = write_strip(acols, os.path.join(outdir, "art_snapshot.png"))
|
||
|
||
union = set(tcols) | set(acols)
|
||
print("[gen_palette_baseline] 已生成:ui_tokens.png %d 色 / art_snapshot.png %d 色"
|
||
"(素材 %d 张 PNG);基线并集 %d 色 → %s"
|
||
% (n_t, n_a, npng, len(union), outdir))
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|