"""Re-execute the reviewed design and record matching geometry checkpoints. Existing Cycles images are explicitly imported from the reviewed source, not represented as renders performed during this recording. """ import bpy,sys,json,inspect,subprocess,runpy,hashlib from pathlib import Path sys.path.insert(0,str(Path(__file__).resolve().parent)) import build_warm_home as home from trace_recorder import TraceRecorder ROOT=Path(__file__).resolve().parents[1];OUT=ROOT/'assets/builds/blenderkit-interior' TEMP=ROOT/'tmp/blenderkit-recording';TEMP.mkdir(parents=True,exist_ok=True);home.OUT=TEMP original_source=inspect.getsource(home.main) marker=' architecture();kitchen();lounge();bedrooms();service_rooms()' initialization,lighting_source=original_source.split(marker,1) exec(initialization.replace('def main():','def initialize_materials():'),home.__dict__) exec('def assemble_daylight_and_cameras():\n'+lighting_source,home.__dict__) def architecture(): home.initialize_materials() home.architecture() return {'note':'Trace the supplied four-bedroom plan, cut real openings, lay individual oak boards and add full-height architecture. Width 18 m and height 2.9 m are explicit assumptions.'} def kitchen(): home.kitchen() return {'note':'Build the L-shaped kitchen with cabinet fronts, stone worktops, a recessed sink, tap, oven, cooktop and task lighting.'} def living_and_dining(): home.lounge() return {'note':'Load BlenderKit Taipei sofa, fluted coffee table, walnut dining table, six Netro chairs and ficus plants; add the rug, media wall, lamps and table settings.'} def bedrooms(): home.bedrooms() return {'note':'Furnish all four bedrooms with BlenderKit draped-linen beds, matching bedside cabinets, lamps, wardrobes and master-bedroom curtains.'} def bathrooms(): home.service_rooms() return {'note':'Fit the three service rooms with limestone floors, basins, taps, hollow baths and porcelain fixtures. The south bath alignment is corrected in the final review.'} def daylight(): home.assemble_daylight_and_cameras() return {'note':'Set the daylight sky, window-area lighting, ceiling bounce, four cameras, Cycles/CUDA and AgX. Pack the actual scene textures.'} def refine(): runpy.run_path(str(ROOT/'scripts/refine_warm_home.py'),run_name='__main__') runpy.run_path(str(ROOT/'scripts/finalize_warm_home.py'),run_name='__main__') return {'note':'Add the planted exterior, lower bright daylight, refine master-bedroom framing and lamp glow, and verify packed images and furniture instances.'} def final_review(): runpy.run_path(str(ROOT/'scripts/fix_warm_home_overview.py'),run_name='__main__') return {'note':'Union overlapping wall and window solids to remove black caps, rotate the south bath to match the plan and add stacked laundry appliances. This is the reviewed final design.'} STAGES=[('Trace the plan and build the shell','Full-height walls, openings, floors and curtains.',architecture), ('Fit the oak kitchen','Joinery, stone, appliances and task lighting.',kitchen), ('Furnish with BlenderKit','The living room and six-seat dining area.',living_and_dining), ('Dress the four bedrooms','Draped bedding, bedside lights and storage.',bedrooms), ('Fit the service rooms','Stone floors, baths, basins and fixtures.',bathrooms), ('Set daylight and cameras','Physical lighting and four owner-review views.',daylight), ('Refine light and framing','Garden views, exposure, lamps and bedroom composition.',refine), ('Review walls and room layout','Clean junctions, correct the bath and complete the laundry.',final_review)] OPERATIONS=[ ['Trace the footprint and room partitions','Raise 2.9 m exterior and interior walls','Cut door and window openings','Add jambs, headers and window frames','Lay staggered individual oak floorboards','Model pleated curtains, ceiling reveals and downlights'], ['Build base units and recessed plinths','Add oak fronts and finger rails','Cut the stone worktop and fit the sink','Model the brass faucet','Fit upper cabinets and task lighting','Add cooktop, oven and extractor','Fit the integrated refrigerator and accessories'], ['Import the BlenderKit Taipei sofa','Import the fluted coffee table','Place the walnut dining table and six Netro chairs','Add BlenderKit ficus plants','Lay the wool rug','Build the media wall and floating cabinet','Add pendants, side lamp and geometric wall relief','Set plates, glasses, linen and books'], ['Import four BlenderKit draped-linen beds','Orient beds to the supplied plan','Add rugs, bedside tables and lamps','Build fitted wardrobes','Add master-bedroom wall relief and curtains','Place the bedroom ficus'], ['Lay limestone wet-room floors','Build floating vanities and vessel basins','Add brass basin faucets','Cut hollow bathtub bowls','Fit toilets and bathroom lighting'], ['Set the sky and sun direction','Add north and south aperture lighting','Add master-window daylight and ceiling bounce','Position three interior cameras and the overview','Configure Cycles, CUDA and AgX','Pack textures and save the editable scene'], ['Add planted garden views','Balance exposure and aperture light levels','Reframe the master-bedroom camera','Add flush skirting','Refine bedside shade glow and room bounce','Validate texture packing and furniture instances'], ['Union overlapping architectural junctions','Rotate the south bathtub to match the plan','Fit stacked washer/dryer and laundry storage'] ] def snapshot(step_id): path=TEMP/f'checkpoint-{step_id}.blend' bpy.ops.wm.save_as_mainfile(filepath=str(path)) log=TEMP/f'export-{step_id}.log' with log.open('w',encoding='utf-8') as stream: subprocess.run([bpy.app.binary_path,'-b','--factory-startup','--python-exit-code','1','--python',str(ROOT/'scripts/integrate_blenderkit_journal.py'), '--','--checkpoint',str(path),'--step',step_id],stdout=stream,stderr=subprocess.STDOUT,check=True) return json.loads((TEMP/f'{step_id}-export.json').read_text()) def main(): prior=json.loads((OUT/'trace.json').read_text(encoding='utf-8')) metadata={key:prior[key] for key in ['title','reference','assumptions','renders','browserCameras','assetManifest','renderSamples','renderRunDurationMs']} metadata['assumptions']=[a for a in metadata['assumptions'] if not a.startswith(('Steps 1','These eight checkpoints'))] metadata['assumptions'].append('These eight checkpoints re-execute this BlenderKit design. The four reviewed Cycles renders are reused with checksums; their original rendering logs are retained separately.') trace=TraceRecorder(OUT,dict(**metadata,source='Recorded BlenderKit reconstruction',blenderVersion=bpy.app.version_string, script='/scripts/record_blenderkit_build.py',command='blender -b --factory-startup --python-exit-code 1 --python scripts/record_blenderkit_build.py', presentation=True,defaultMode='render',stageLabel='stage', provenance='Eight actual Blender executions/checkpoints of this BlenderKit design, recorded during reproducible reconstruction. The finished Cycles images and original packed Blender scene are the previously reviewed deliverables; imported images are identified by checksums, not claimed as newly rendered.'),STAGES) for step,operations in zip(trace.data['steps'],OPERATIONS):step['operations']=operations for i,(_,_,fn) in enumerate(STAGES): trace.run_step(i,fn,snapshot) original=OUT/'warm-modern-home.blend' for view in metadata['renders']: path=OUT/view['file'];trace.emit('render.imported',{'view':view['id'],'file':view['file'],'sha256':hashlib.sha256(path.read_bytes()).hexdigest(), 'sourceBlend':original.name,'sourceBlendSha256':hashlib.sha256(original.read_bytes()).hexdigest()}) trace.finish(model='step-08.glb',blend=original.name,preview='02-dining-living.png') if __name__=='__main__':main()