"""Lists how a demo map places its pieces (per kit mesh: count, world bounds and the positions / headings used). python build/study_layout.py [name filter] [--pos] Works on the exported map JSON, no Blender needed. Positions are Blender metres: (x, -y, z) / 100 of Unreal's. """ import collections import json import math import os import sys HERE = os.path.dirname(os.path.abspath(__file__)) KIT = os.path.join(os.path.dirname(HERE), "kit_export") name = sys.argv[1] filt = [a for a in sys.argv[2:] if not a.startswith("--")] show_pos = "--pos" in sys.argv meshes = json.load(open(os.path.join(KIT, "meshes.json"), encoding="utf-8")) data = json.load(open(os.path.join(KIT, "maps", name + ".json"), encoding="utf-8")) def to_bl(rows): X, Y, Z, W = rows return [(X[0], -Y[0], Z[0], W[0] / 100.0), (-X[1], Y[1], -Z[1], -W[1] / 100.0), (X[2], -Y[2], Z[2], W[2] / 100.0)] def bounds(path, m): rec = meshes.get(path) if rec is None: return None mn, mx = rec["min"], rec["max"] lo = [1e9] * 3 hi = [-1e9] * 3 for cx in (mn[0], mx[0]): for cy in (mn[1], mx[1]): for cz in (mn[2], mx[2]): p = (cx / 100.0, -cy / 100.0, cz / 100.0) for i in range(3): v = m[i][0] * p[0] + m[i][1] * p[1] + m[i][2] * p[2] + m[i][3] lo[i] = min(lo[i], v) hi[i] = max(hi[i], v) return lo, hi groups = collections.defaultdict(list) for a in data["actors"]: if a.get("hidden") or a.get("hidden_in_game"): continue for mc in a.get("meshes", []): path = mc["mesh"] for rows in (mc.get("instances") or [mc["matrix"]]): m = to_bl(rows) yaw = math.degrees(math.atan2(m[1][0], m[0][0])) sc = math.sqrt(m[0][0] ** 2 + m[1][0] ** 2 + m[2][0] ** 2) groups[path].append((m, yaw, sc, a["label"], [x.split("/")[-1] if x else None for x in mc.get("materials", [])])) for path in sorted(groups, key=lambda p: (p.split("/")[2], p.split("/")[-1])): short = path.split("/")[2][-9:] + "/" + path.split("/")[-1] if filt and not any(f.lower() in short.lower() for f in filt): continue items = groups[path] lo = [1e9] * 3 hi = [-1e9] * 3 for m, yaw, sc, lab, mats in items: b = bounds(path, m) if b: for i in range(3): lo[i] = min(lo[i], b[0][i]) hi[i] = max(hi[i], b[1][i]) print("%-42s x%-3d x %7.2f..%7.2f y %7.2f..%7.2f z %6.2f..%6.2f" % (short, len(items), lo[0], hi[0], lo[1], hi[1], lo[2], hi[2])) if show_pos: for m, yaw, sc, lab, mats in sorted(items, key=lambda t: (round(t[0][1][3], 1), round(t[0][0][3], 1))): print(" (%7.2f, %7.2f, %6.2f) yaw %6.1f%s %s" % (m[0][3], m[1][3], m[2][3], yaw, "" if abs(sc - 1) < 1e-3 else " s%.2f" % sc, lab))