# ------------------------------------------------------------------ run O = bpy.data.objects parts = {o.name: o for o in O if o.type == 'MESH' and o.name.startswith("SM_Manta")} REPORT["uv"] = {} for atlas, spec in ATLASES.items(): for nm, rect in spec["rects"].items(): REPORT["uv"][nm] = uv_layers(parts[nm], rect, spec["size"]) screens = make_screens(os.path.join(TEX, "T_Manta_Screens.png")) REPORT["screen_faces"] = screen_uvs(parts["SM_Manta_Cabin"]) baked = {} for atlas, spec in ATLASES.items(): plist = [parts[n] for n in spec["rects"]] masks, bevel, info = bake_atlas(atlas, plist, spec["size"]) baked[atlas] = (masks, bevel) REPORT["bake_" + atlas] = info # materials: one per kind. The cabin reads its own atlas, so the kinds it shares with the outside (graphite, steel) get cabin copies cab = parts["SM_Manta_Cabin"] users = {} for o in parts.values(): for sl in o.material_slots: if sl.material: users.setdefault(sl.material.name, set()).add(o.name) KEY, ATL = {}, {} for sl in cab.material_slots: m = sl.material if m and m.name in SURF and users[m.name] - {cab.name}: cm = m.copy() cm.name = "MANTA | Cabin " + m.name.split("| ")[1].lower() sl.material = cm KEY[cm.name], ATL[cm.name] = m.name, "Cabin" for m in list(bpy.data.materials): if m.name in SURF: KEY[m.name] = m.name ATL[m.name] = "Cabin" if users.get(m.name) == {cab.name} else "Exterior" for m in bpy.data.materials: if m.name in KEY: masks, bevel = baked[ATL[m.name]] dress(m, SURF[KEY[m.name]], masks, bevel) elif m.name in GLOW: dress_glow(m, *GLOW[m.name]) elif m.name == "MANTA | Screen": dress_glow(m, SCREEN_INK, 2.2, screens) elif m.name in GLASSES: dress_glass(m, GLASSES[m.name]) REPORT["material_atlas"] = ATL REPORT["materials"] = sorted(m.name for m in bpy.data.materials if m.users and m.name.startswith("MANTA")) REPORT["seconds"] = round(time.time() - t0, 1) bpy.ops.file.make_paths_relative() bpy.ops.wm.save_mainfile() json.dump(REPORT, open(os.path.join(HERE, "surfaces_report.json"), "w"), indent=1) print("SURFACES OK", json.dumps(REPORT))