46 lines
2.1 KiB
Python
46 lines
2.1 KiB
Python
"""原图变更后运行此脚本,更新七日活动的透明区域点击数据。需要 Pillow。"""
|
||
import json
|
||
from pathlib import Path
|
||
from PIL import Image
|
||
|
||
ROOT = Path(__file__).resolve().parents[1]
|
||
images = sorted((ROOT / "assets/seven_day_gift/texture").glob("*.png"))
|
||
for folder in ("huang", "lan"):
|
||
images.extend(sorted((ROOT / "assets/seven_day_gift/texture" / folder).glob("*.png")))
|
||
images.append(ROOT / "assets/UI/Cat/cat.png")
|
||
for name in ("hammer", "ice", "magic", "skyLine"):
|
||
images.append(ROOT / "assets/res/public" / (name + ".png"))
|
||
masks = {}
|
||
for path in images:
|
||
meta = json.loads(path.with_suffix(".png.meta").read_text(encoding="utf-8"))
|
||
alpha = Image.open(path).convert("RGBA").getchannel("A")
|
||
for frame in meta["subMetas"].values():
|
||
x, y, w, h = (frame[k] for k in ("trimX", "trimY", "width", "height"))
|
||
pixels = alpha.crop((x, y, x + w, y + h))
|
||
rows, spans, lookup = [], [], {}
|
||
for row in range(h):
|
||
runs, start = [], None
|
||
for col in range(w + 1):
|
||
solid = col < w and pixels.getpixel((col, row)) >= 16
|
||
if solid and start is None:
|
||
start = col
|
||
elif not solid and start is not None:
|
||
runs.extend((start, col))
|
||
start = None
|
||
key = tuple(runs)
|
||
if key not in lookup:
|
||
lookup[key] = len(spans)
|
||
spans.append(runs)
|
||
rows.append(lookup[key])
|
||
masks[frame["uuid"]] = dict(width=w, height=h, rows=rows, spans=spans)
|
||
|
||
output = ROOT / "assets/seven_day_gift/SevenDayHitMasks.ts"
|
||
output.write_text(
|
||
"// 自动生成的原图 Alpha 命中数据(阈值 16/255),勿手改;更新图片后运行 tools/generate-seven-hit-masks.py。\n"
|
||
"export interface SevenDayHitMask { width: number; height: number; rows: number[]; spans: number[][]; }\n"
|
||
"const masks: { [uuid: string]: SevenDayHitMask } = "
|
||
+ json.dumps(masks, separators=(",", ":")) + ";\nexport default masks;\n",
|
||
encoding="utf-8",
|
||
)
|
||
print(f"Generated {len(masks)} masks, {output.stat().st_size} bytes")
|