64 lines
2.2 KiB
Python
64 lines
2.2 KiB
Python
# Blender headless: probe a folder of FBX models for fighter-readiness.
|
|
# Emits one JSON line per file: rig, bones, namespace, meshes, verts,
|
|
# height, textures, action count. Re-runnable (skips nothing, cheap).
|
|
#
|
|
# Usage: Blender -b --python tools/assess_fbx.py -- --dir ~/Documents/fbxes --out report.jsonl
|
|
import argparse
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import bpy
|
|
|
|
|
|
def parse_args():
|
|
argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--dir", required=True)
|
|
ap.add_argument("--out", required=True)
|
|
return ap.parse_args(argv)
|
|
|
|
|
|
args = parse_args()
|
|
src = Path(args.dir).expanduser()
|
|
out = Path(args.out).expanduser()
|
|
results = []
|
|
|
|
for f in sorted(src.glob("*.fbx")):
|
|
rec = {"file": f.name, "mb": round(f.stat().st_size / 1e6, 1)}
|
|
bpy.ops.wm.read_factory_settings(use_empty=True)
|
|
try:
|
|
bpy.ops.import_scene.fbx(filepath=str(f))
|
|
except Exception as e:
|
|
rec["error"] = str(e)[:80]
|
|
results.append(rec)
|
|
continue
|
|
arms = [o for o in bpy.data.objects if o.type == "ARMATURE"]
|
|
meshes = [o for o in bpy.data.objects if o.type == "MESH"]
|
|
rec["arms"] = len(arms)
|
|
rec["meshes"] = len(meshes)
|
|
rec["verts"] = sum(len(m.data.vertices) for m in meshes)
|
|
if arms:
|
|
bones = arms[0].data.bones
|
|
rec["bones"] = len(bones)
|
|
rec["ns"] = ""
|
|
for b in bones:
|
|
if ":" in b.name:
|
|
rec["ns"] = b.name.split(":")[0]
|
|
break
|
|
# world height
|
|
import mathutils
|
|
pts = [o.matrix_world @ mathutils.Vector(c) for o in meshes for c in o.bound_box]
|
|
if pts:
|
|
rec["h"] = round(max(p[2] for p in pts) - min(p[2] for p in pts), 2)
|
|
rec["textured"] = any(
|
|
n.type == "TEX_IMAGE" and n.image is not None
|
|
for m in meshes for s in m.material_slots if s.material and s.material.use_nodes
|
|
for n in s.material.node_tree.nodes)
|
|
rec["actions"] = len(bpy.data.actions)
|
|
results.append(rec)
|
|
print("PROBED", f.name, "rig" if arms else "NORIG", flush=True)
|
|
|
|
out.write_text("\n".join(json.dumps(r) for r in results))
|
|
print("WROTE", out, len(results), "records")
|