"""Critique 2: which parts carry the bright steel material (M_DoorArm_Steel), and how big they are. Read-only. blender -b --factory-startup "" --python previews/critique2/crit2_steelparts.py -- """ import json import sys import bpy import numpy as np OUT = sys.argv[sys.argv.index("--") + 1] R = {} for me in bpy.data.meshes: if not me.name.startswith("DoorArm |") or me.users == 0: continue slots = [m.name if m else None for m in me.materials] if "M_DoorArm_Steel" not in slots: continue si = slots.index("M_DoorArm_Steel") ids = list(me.get("parts", [])) lay = me.attributes.get("part") n = len(me.polygons) mi = np.empty(n, dtype=np.int64) me.polygons.foreach_get("material_index", mi) pv = np.full(n, -1, dtype=np.int64) if lay is not None: lay.data.foreach_get("value", pv) co = np.empty(len(me.vertices) * 3) me.vertices.foreach_get("co", co) co = co.reshape(-1, 3) rows = {} for k in np.unique(pv[mi == si]): fids = np.nonzero((mi == si) & (pv == k))[0] vs = set() for f in fids[:4000]: vs.update(me.polygons[int(f)].vertices) P = co[list(vs)] size = float(np.linalg.norm(P.max(0) - P.min(0))) name = ids[k] if 0 <= k < len(ids) else str(k) rows[name] = [int(len(fids)), round(size, 3)] R[me.name] = dict(sorted(rows.items(), key=lambda kv: -kv[1][1])[:25]) with open(OUT, "w") as fh: json.dump(R, fh, indent=1) print("[crit2] steel parts written", OUT, flush=True)