Files
UnheardCity/tools/screenshots.py

112 lines
5.0 KiB
Python

"""Render the user-guide screenshots headless (docs/img/*.png). Read-only: never applies anything.
python tools/screenshots.py [--game DIR] [--lang INT] [--only main,browse,settings,edit]
The app starts in the game's language as always; the screenshots then switch to --lang (default INT, the
game's English) the way a user does, through the Language list.
"""
import argparse
import os
import sys
import tempfile
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, ROOT)
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
if sys.platform == "win32":
os.environ.setdefault("QT_QPA_FONTDIR", os.path.join(os.environ.get("WINDIR", r"C:\Windows"), "Fonts"))
os.environ["ACKIT_NO_AUDIO"] = "1"
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--game")
ap.add_argument("--lang", default="INT", help="language shown in the screenshots (default: INT)")
ap.add_argument("--only", default="main,browse,settings,edit",
help="which screenshots (comma-separated): main, browse, settings, edit (editor.png)")
a = ap.parse_args()
only = set(a.only.split(","))
from PySide6.QtWidgets import QApplication
from ackit import audio
from app.dialogs import SettingsDialog
from app.mainwindow import MainWindow
from app.workers import Runner
import numpy as np
out = os.path.join(ROOT, "docs", "img")
os.makedirs(out, exist_ok=True)
from app import theme
app = QApplication([])
with tempfile.TemporaryDirectory() as td:
os.environ["ACKIT_HOME"] = td # do not touch the real settings/notes
# docs show no wallpaper (the app still shows it)
st = {"full_backup": True, "background_enabled": False}
theme.apply(app)
w = MainWindow(settings=st, runner=Runner(sync=True), game_dir=a.game)
w.resize(1500, 950)
w.show()
app.processEvents() # the game loads here (in the game's language)
if a.lang and w.ws and w.language != a.lang.upper():
w.cmb_lang.setCurrentText(a.lang.upper()) # what choosing it in the Language list does
w.load_game(w.ws.game.root, a.lang.upper())
app.processEvents()
# status bar: show the store where users have it, not this temporary folder (no local user names)
w.lbl_game.setText(w.lbl_game.text().replace(os.path.join(td, "data"), r"%APPDATA%\UnheardCity"))
# 1: browser filtered by character, a line selected (preview below the list)
from PySide6.QtTest import QTest
w.cmb_char.setCurrentText("Joker")
w._filters_changed()
w.search.setText("")
w._filter_text()
rows = [w.proxy.sound_at(w.proxy.index(r, 1)) for r in range(w.proxy.rowCount())]
with_sub = [s for s in rows if w.ws.texts.for_sound(s, w.language)] # show the subtitle too
target = max(with_sub or rows, key=lambda s: min(s.seconds, 6.0))
w.select_name(target.name)
app.processEvents()
if "main" in only:
w.grab().save(os.path.join(out, "main.png"))
# 2: category browsing
w.clear_filters()
w.cmb_group.setCurrentText("Speech")
w._group_changed(None)
w.cmb_cat.setCurrentText("Interview tapes")
w._filters_changed()
w.search.setText("joker")
w._filter_text()
app.processEvents()
if "browse" in only:
w.grab().save(os.path.join(out, "browse.png"))
# 3: settings
if "settings" in only:
d = SettingsDialog(w.settings, w)
d.bg_on.setChecked(True) # show the user's default (on), only the screenshots run without it
d.show()
app.processEvents()
d.grab().save(os.path.join(out, "settings.png"))
d.close()
# 4: the Edit tab: Mr. Freeze's lines on the edit list, one with a replacement (the original, reshaped,
# for display only) and the Mr. Freeze preset
if "edit" in only:
w.clear_filters()
w.cmb_char.setCurrentText("Mr. Freeze")
w._filters_changed()
freeze = [w.proxy.sound_at(w.proxy.index(r, 1)) for r in range(min(w.proxy.rowCount(), 12))]
target = max(freeze, key=lambda s: (bool(w.ws.texts.for_sound(s, w.language)), min(s.seconds, 4.0)))
w.edit_sounds([target] + [s for s in freeze if s is not target])
app.processEvents()
x, sr = w.editor.orig
t = np.arange(len(x)) / sr
new = (0.5 * x.mean(axis=1, keepdims=True) * (0.6 + 0.4 * np.sin(2 * np.pi * 0.7 * t))[:, None])
path = os.path.join(td, "new_line.wav")
audio.save_wav(path, new.astype(np.float32), sr)
w.editor.load_file(path)
w.edit.rack.apply_look("Mr. Freeze")
QTest.qWait(1500) # the effects render in the background, then the settings are saved
w.grab().save(os.path.join(out, "editor.png"))
w.close()
print("screenshots in", out)
if __name__ == "__main__":
main()