from __future__ import annotations import json from pathlib import Path from PIL import Image, ImageDraw, ImageFont def _load_cfg(path: Path) -> dict: return json.loads(path.read_text(encoding="utf-8")) def _is_zero(pt) -> bool: try: return int(pt[0]) == 0 and int(pt[1]) == 0 except Exception: return True def main() -> int: root = Path(__file__).resolve().parents[1] img_path = root / "outputs" / "bluestacks" / "validate_base.png" cfg_path = root / "config" / "bluestacks_gameplay.local.json" out_path = root / "outputs" / "bluestacks" / "validate_overlay.png" if not img_path.exists(): raise SystemExit(f"missing screenshot: {img_path}") if not cfg_path.exists(): raise SystemExit(f"missing calibration: {cfg_path}") cfg = _load_cfg(cfg_path) img = Image.open(img_path).convert("RGBA") draw = ImageDraw.Draw(img) try: font = ImageFont.truetype("Arial.ttf", 18) except Exception: font = ImageFont.load_default() points: list[tuple[str, tuple[int, int], str]] = [] # Card slots for k in ("1", "2", "3", "4"): pt = cfg.get("card_slots", {}).get(k, [0, 0]) points.append((f"S{k}", (int(pt[0]), int(pt[1])), "yellow")) # Key grid cells for cell in ("A1", "A8", "H1", "H8", "E2", "E7", "D2", "D7"): pt = cfg.get("grid", {}).get(cell, [0, 0]) points.append((cell, (int(pt[0]), int(pt[1])), "cyan")) # Draw points for label, (x, y), color in points: r = 10 fill = (255, 0, 0, 180) if (x == 0 and y == 0) else (0, 0, 0, 0) outline = (255, 64, 64, 255) if (x == 0 and y == 0) else (0, 255, 255, 255) if color == "cyan" else (255, 255, 0, 255) draw.ellipse([x - r, y - r, x + r, y + r], fill=fill, outline=outline, width=3) draw.rectangle([x + 12, y - 12, x + 12 + 46, y + 12], fill=(0, 0, 0, 160)) draw.text((x + 16, y - 10), label, fill=(255, 255, 255, 255), font=font) # Header header = f"Calibration overlay | cfg={cfg_path.name} | red = (0,0) invalid" draw.rectangle([0, 0, img.size[0], 34], fill=(0, 0, 0, 200)) draw.text((10, 8), header, fill=(255, 255, 255, 255), font=font) img.save(out_path) print(out_path) return 0 if __name__ == "__main__": raise SystemExit(main())