"""Headless driver for the sliding pressure door (a Blender instance of its own, not the MCP's): "E:\\Steam\\steamapps\\common\\Blender\\blender.exe" -b --python sd_run.py -- stages: build new file: geometry (sd_build), rig (sd_rig), quick EEVEE pictures, save PressureDoorSliding.blend rig the rig alone on the saved file, save surfaces UV layers, baked masks, materials (sd_surfaces), save check the travel check (sd_check), writes build/check_report.json export UCX hulls, FBX files, layout JSON (sd_export), save render the Cycles pictures in previews/ verify re-import the FBX files (sd_verify_fbx) Several stages may be given in one call, in order.""" import bpy, sys, os, json, time, traceback BUILD = r"D:\HADAL - The Descent\models\pressure-door-sliding\build" FOLDER = os.path.dirname(BUILD) BLEND = os.path.join(FOLDER, "PressureDoorSliding.blend") PRE = os.path.join(FOLDER, "previews") def run(name, g=None): g = {} if g is None else g exec(open(os.path.join(BUILD, name), encoding="utf-8").read(), g) return g def save(): bpy.context.scene.frame_set(1) bpy.ops.wm.save_as_mainfile(filepath=BLEND, compress=False) print("SAVED", BLEND) def open_blend(): bpy.ops.wm.open_mainfile(filepath=BLEND) def main(): argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else ["build"] for stage in argv: t0 = time.time() print("=== STAGE", stage) if stage == "build": bpy.ops.wm.read_homefile(use_empty=True) g = run("sd_build.py", {"SD_NO_AUTORUN": False}) for a in g["RESULT"]["objects"]: print(" MESH", a) r = run("sd_rig.py") print(" RIG", r["rig"]()) s = run("sd_studio.py") s["setup"]() for view, f, name in (("front34", 1, "wip_01_shut"), ("front34", 60, "wip_02_open"), ("lock", 1, "wip_03_lock"), ("console", 1, "wip_04_console"), ("right", 1, "wip_05_right"), ("top", 1, "wip_06_top"), ("back", 60, "wip_07_back_open"), ("open34", 60, "wip_08_open34")): bpy.context.scene.frame_set(f) s["render"](view, os.path.join(PRE, name + ".png"), engine='BLENDER_EEVEE', samples=24, res=(1400, 900)) save() elif stage == "surfaces": open_blend() g = run("sd_surfaces.py") print(" SURFACES", g["run"]()) r = run("sd_rig.py") print(" LOCK DRIVER", r["rig_lock_material"]()) save() elif stage == "rig": # the rig alone on the saved file (sliders, their tooltips, drivers, timeline), then save open_blend() r = run("sd_rig.py") print(" RIG", r["rig"]()) save() elif stage == "materials": # the material node trees only (UVs and the bake kept), then the lock driver again open_blend() g = run("sd_surfaces.py") print(" MATERIALS", g["run"](bake=False, uvs=False)) r = run("sd_rig.py") print(" LOCK DRIVER", r["rig_lock_material"]()) save() elif stage == "check": open_blend() r = run("sd_rig.py") c = run("sd_check.py") rep = c["check"](set_open=r["set_open"], set_prop=r["set_prop"]) print(" CHECK", json.dumps(rep, indent=1)) with open(os.path.join(BUILD, "check_report.json"), "w", encoding="utf-8") as f: json.dump(rep, f, indent=1) elif stage == "export": open_blend() r = run("sd_rig.py") e = run("sd_export.py") print(" HULLS", e["make_hulls"](r["set_open"])) print(" FBX", e["export"](r["set_open"])) rp = os.path.join(BUILD, "check_report.json") chk = json.load(open(rp, encoding="utf-8")) if os.path.exists(rp) else None print(" LAYOUT", e["layout"](chk)) save() elif stage == "render": open_blend() s = run("sd_studio.py") s["setup"]() for view, f, name in (("front34", 1, "PressureDoorSliding_01_shut"), ("front", 1, "PressureDoorSliding_02_front"), ("open34", 60, "PressureDoorSliding_03_open"), ("front34", 42, "PressureDoorSliding_04_sliding"), ("lock", 1, "PressureDoorSliding_05_lock_shut"), ("lock", 10, "PressureDoorSliding_06_handle_turning"), ("lock", 20, "PressureDoorSliding_06b_lock_green"), ("leafL", 1, "PressureDoorSliding_06c_left_leaf"), ("console", 1, "PressureDoorSliding_07_console"), ("right", 1, "PressureDoorSliding_08_service_column"), ("top", 1, "PressureDoorSliding_09_cables_sign_camera"), ("back", 60, "PressureDoorSliding_10_back_open")): bpy.context.scene.frame_set(f) s["render"](view, os.path.join(PRE, name + ".png"), engine='CYCLES', samples=96, res=(1600, 1000)) elif stage.startswith("redo:"): # rebuild one part in the saved file and redo its UV layers and its square of the mask atlas part = stage.split(":", 1)[1] open_blend() g = run("sd_build.py", {"SD_NO_AUTORUN": True}) mats = g["get_mats"]() fn = {"camera": ("build_camera", "PDS | moving", "SM_PDSliding_Camera"), "monitor": ("build_monitor", "PDS | moving", "SM_PDSliding_Monitor"), "frame": ("build_frame", "PDS | static", "SM_PDSliding_Frame"), "wall": ("build_wall", "PDS | static", "SM_PDSliding_Wall"), "handle": ("build_handle", "PDS | moving", "SM_PDSliding_Handle")}[part] if part == "handle": ob = g[fn[0]](mats, bpy.data.collections[fn[1]], bpy.data.objects["SM_PDSliding_LeafL"]) else: ob = g[fn[0]](mats, bpy.data.collections[fn[1]]) print(" REBUILT", g["audit"](ob)) sf = run("sd_surfaces.py") sf["uv_tile_layer"](ob.data) sf["uv_atlas_layer"](ob, sf["ATLAS_RECT"][fn[2]]) sf["screen_uvs"](ob) masks = bpy.data.images["T_PDS_Masks"] print(" MASKS before", masks.source, masks.filepath, masks.is_dirty) print(" BAKE", sf["bake_masks"]([(fn[2], ob.data)], reset=False)[1]) save() elif stage == "verify": run("sd_verify_fbx.py") else: print("unknown stage", stage) print("=== DONE", stage, round(time.time() - t0, 1), "s") try: main() except Exception: traceback.print_exc() sys.exit(1)