# lena_leafbikini lane, stage 06: open a lane mesh in the Blender GUI, framed and shaded. # # blender --python 06_open_in_blender.py -- # # Runs inside a GUI session, NOT --background, and deliberately NOT --factory-startup: the # TinqsBlenderBridge autostarts from scripts/startup (tools/install_blender_bridge.ps1), and # factory startup would skip it, leaving the session undriveable from the terminal afterwards. # # TWO THINGS THIS SCRIPT LEARNED THE HARD WAY, both consequences of `--python` running BEFORE # Blender's window exists: # 1. `bpy.context.screen` is None at this point, so any viewport setup here dies with # AttributeError. All of it is deferred onto an app timer, which first fires once the UI # is up and can therefore see the 3D View. # 2. `bpy.ops.wm.read_homefile()` kills the bridge — the startup module has already # registered its socket server by now, and reloading the file takes it down with no # autostart to bring it back. The default cube/light/camera are removed by hand instead. # # Material Preview, not Solid: the point of looking at this file is the boundary between the # holes and her skin, and in Solid shading the baked leaf contact shadows in the albedo are # invisible — which is half of what makes the rim read the way it does. import bpy, sys, os GLB = os.path.abspath(sys.argv[sys.argv.index("--") + 1:][0]) for o in list(bpy.data.objects): if o.name in {"Cube", "Light", "Camera"}: bpy.data.objects.remove(o, do_unlink=True) bpy.ops.import_scene.gltf(filepath=GLB) body = max([o for o in bpy.data.objects if o.type == 'MESH'], key=lambda o: len(o.data.vertices)) bpy.context.view_layer.objects.active = body for o in bpy.data.objects: o.select_set(o is body) print(f"[open] {os.path.basename(GLB)}: {len(body.data.vertices)}v {len(body.data.polygons)}f", flush=True) def setup_viewport(): """Fires once, after the window exists.""" screen = getattr(bpy.context, "screen", None) if screen is None: return 0.25 # UI not up yet — ask the timer to call again for area in screen.areas: if area.type != 'VIEW_3D': continue sp = area.spaces.active sp.shading.type = 'MATERIAL' sp.shading.use_scene_lights = False sp.shading.use_scene_world = False sp.overlay.show_floor = False sp.overlay.show_axis_x = sp.overlay.show_axis_y = False sp.overlay.show_relationship_lines = False sp.clip_start = 0.001 sp.clip_end = 100.0 region = next((r for r in area.regions if r.type == 'WINDOW'), None) if region: with bpy.context.temp_override(area=area, region=region, space_data=sp): # BACK, not FRONT. These lane GLBs are exported with export_yup=True and come # back in facing +Y, so Blender's FRONT view (looking from -Y) puts you behind # her — which is the wrong side for judging a cut that is mostly on her front. bpy.ops.view3d.view_axis(type='BACK') bpy.ops.view3d.view_selected() print("[open] viewport ready — Material Preview, framed on her front", flush=True) return None # done; unregister bpy.app.timers.register(setup_viewport, first_interval=0.5)