Unveränderter Ausgangsstand inklusive Masterprompt und Konzeptbildern unter assets/. .godot/ und docs/screenshots/ bleiben laut .gitignore unversioniert; letztere sind unter ../backups gesichert. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
39 lines
2.6 KiB
Python
39 lines
2.6 KiB
Python
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')
|