import bpy,json,sys from pathlib import Path p=Path(__file__).resolve().parents[2];source=p/'assets-source/phase4' sys.path.insert(0,str(source/'blender')) from reference_sculpt_detail import add_offline_materials for path in sorted((source/'records').glob('*.json')): record=json.loads(path.read_text()) if record['faction'] not in ['wurzelbund','glutpakt','rift'] and record['role'] not in ['worker','core']:continue with bpy.data.libraries.load(record['blend_path'],link=False) as (frm,to):to.scenes=frm.scenes objects=[o for scene in to.scenes for o in scene.objects if o.type=='MESH'] add_offline_materials(objects,p) # Keep source image references relative to the .blend location. bpy.data.libraries.write(record['blend_path'],set(to.scenes),path_remap='RELATIVE_ALL',fake_user=True,compress=True) record['offline_sculpt_parts']=sum(bool(o.get('sculpt_surface')) for o in objects) record['offline_render_triangles']=0 for obj in objects: obj.data.calc_loop_triangles();record['offline_render_triangles']+=len(obj.data.loop_triangles)*(16 if obj.get('sculpt_surface') else 1) path.write_text(json.dumps(record,ensure_ascii=False,indent=2)+'\n') for scene in to.scenes:bpy.data.scenes.remove(scene) for obj in objects: if not obj.users:bpy.data.objects.remove(obj) from pipeline import write_manifest write_manifest() print('BLENDER_PBR_SOURCE_PASS: 33 independent scenes with editable high-resolution geometry and material nodes.') # Environment source keeps its original 2586 independently editable objects. map_path=p/'assets-source/phase10/verdant-rift.blend' with bpy.data.libraries.load(str(map_path),link=False) as (frm,to):to.scenes=frm.scenes materials={m for scene in to.scenes for obj in scene.objects if obj.type=='MESH' for m in obj.data.materials if m} for mat in materials: if mat.get('phase10_pbr') or not any(k in mat.name for k in ['limestone','cliff','paving']):continue nodes=mat.node_tree.nodes;links=mat.node_tree.links;bsdf=nodes.get('Principled BSDF') texture=nodes.new('ShaderNodeTexImage');texture.image=bpy.data.images.load(str(p/'assets/materials/phase10/limestone-albedo.png'),check_existing=True);texture.projection='BOX';texture.projection_blend=.3 coord=nodes.new('ShaderNodeTexCoord');links.new(coord.outputs['Object'],texture.inputs['Vector']) bump=nodes.new('ShaderNodeBump');bump.inputs['Strength'].default_value=.3;bump.inputs['Distance'].default_value=.04 links.new(texture.outputs['Color'],bump.inputs['Height']);links.new(bump.outputs['Normal'],bsdf.inputs['Normal']) mat['phase10_pbr']=True bpy.data.libraries.write(str(map_path),set(to.scenes),path_remap='RELATIVE_ALL',fake_user=True,compress=True) print('ENVIRONMENT_PBR_SOURCE_PASS')