43 lines
2.4 KiB
Python
43 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
# Renders README images into docs/images/: python3 tools/screenshots/make.py [scene ...]
|
|
# Stills -> PNG (zlib, stdlib only); the "plot" scene -> GIF via ffmpeg (palette).
|
|
import os, struct, subprocess, sys, tempfile, zlib
|
|
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
OUT = os.path.join(ROOT, "docs", "images")
|
|
STILLS = ["debug", "tool", "hello", "demo", "tables", "style", "metrics", "docking", "drawlist"]
|
|
|
|
def png(path, w, h, rows):
|
|
raw = b"".join(b"\x00" + r for r in rows)
|
|
def chunk(t, d): return struct.pack(">I", len(d)) + t + d + struct.pack(">I", zlib.crc32(t + d) & 0xffffffff)
|
|
open(path, "wb").write(b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", w, h, 8, 2, 0, 0, 0))
|
|
+ chunk(b"IDAT", zlib.compress(raw, 9)) + chunk(b"IEND", b""))
|
|
|
|
def run(scene):
|
|
src = open(os.path.join(ROOT, "tools", "screenshots", "capture.luau")).read()
|
|
tmp = os.path.join(tempfile.mkdtemp(), "scene.luau")
|
|
open(tmp, "w").write('SCENE = "%s"\n' % scene + src)
|
|
frames = 152 if scene == "plot" else 42
|
|
p = subprocess.run([sys.executable, os.path.join(ROOT, "tools", "test", "run.py"), "--main", tmp, "--frames", str(frames),
|
|
"--quiet", "--roblox", "--timeout", "1200"], capture_output=True, text=True, env=dict(os.environ, FULL_OUTPUT="1"))
|
|
shots, size = {}, None
|
|
for l in p.stdout.splitlines():
|
|
if l.startswith("SIZE"): size = tuple(map(int, l.split()[1:]))
|
|
elif l.startswith("PX"):
|
|
_, f, y, hx = l.split(); shots.setdefault(int(f), {})[int(y)] = bytes.fromhex(hx)
|
|
if not shots: sys.exit("scene %s failed:\n%s" % (scene, p.stdout[-3000:]))
|
|
w, h = size
|
|
return w, h, [[rows[y] for y in range(h)] for _, rows in sorted(shots.items())]
|
|
|
|
os.makedirs(OUT, exist_ok=True)
|
|
for scene in sys.argv[1:] or STILLS + ["plot"]:
|
|
w, h, frames = run(scene)
|
|
if scene == "plot":
|
|
d = tempfile.mkdtemp()
|
|
for i, rows in enumerate(frames): png(os.path.join(d, "f%04d.png" % i), w, h, rows)
|
|
subprocess.run(["ffmpeg", "-loglevel", "error", "-y", "-framerate", "30", "-i", os.path.join(d, "f%04d.png"), "-vf",
|
|
"split[a][b];[a]palettegen=stats_mode=diff[p];[b][p]paletteuse=dither=none", "-loop", "0",
|
|
os.path.join(OUT, "plot.gif")], check=True)
|
|
else:
|
|
png(os.path.join(OUT, scene + ".png"), w, h, frames[-1])
|
|
print("wrote", scene)
|