#!/usr/bin/env python3 import hashlib,json,os,pathlib,sys,tempfile import bpy def report(): o=bpy.data.objects.get("WebGapCollisionObject") if o is None: raise RuntimeError("WebGapCollisionObject is missing") ms=[m for m in o.modifiers if m.type=="COLLISION"] if len(ms)!=1: raise RuntimeError(f"expected one COLLISION modifier, found {len(ms)}") m=ms[0] return {"meshId":"mesh:"+o.data.name,"modifier":{"name":m.name,"type":m.type,"typeCode":bpy.types.Modifier.bl_rna.properties["type"].enum_items[m.type].value,"showViewport":bool(m.show_viewport),"showRender":bool(m.show_render),"showEditMode":bool(m.show_in_editmode),"showOnCage":bool(m.show_on_cage)}} def main(): a=sys.argv[sys.argv.index("--")+1:] if len(a)!=2: raise SystemExit("usage: blender -b --python check-collision-modifier-desktop.py -- FIXTURE REPORT") f,out=(pathlib.Path(x).resolve() for x in a); bpy.ops.wm.open_mainfile(filepath=str(f),load_ui=False); before=report(); fd,t=tempfile.mkstemp(prefix="m16-collision-reopen-",suffix=".blend",dir=f.parent); os.close(fd) try: bpy.ops.wm.save_as_mainfile(filepath=t,check_existing=False,compress=True); bpy.ops.wm.open_mainfile(filepath=t,load_ui=False); after=report() finally: pathlib.Path(t).unlink(missing_ok=True) if before!=after: raise RuntimeError(f"collision modifier save/reopen drift: {before} != {after}") v={"schemaVersion":1,"task":"M16-GAP-00037","operation":"COLLISION_MODIFIER_DESKTOP","fixture":str(f),"fixtureSha256":hashlib.sha256(f.read_bytes()).hexdigest(),"modifier":after,"saveReopen":"EXACT","blenderVersion":bpy.app.version_string}; out.parent.mkdir(parents=True,exist_ok=True); out.write_text(json.dumps(v,indent=2,sort_keys=True)+"\n"); print(f"collision-modifier-desktop-ok mesh={after['meshId']} saveReopen=exact") if __name__=="__main__": main()