import bpy import os import pathlib # Ensure blend file is saved blend_filepath = bpy.data.filepath if not blend_filepath: raise Exception("Blend file is not saved") assert bpy.context.scene is not None def clean_blend_path(blend_path: str) -> str: return os.path.join(os.path.dirname(blend_path), bpy.path.clean_name(os.path.basename(blend_path))) # Directory setup abs_filepath = bpy.path.abspath(blend_filepath) src_assets_path = os.path.dirname(abs_filepath) project_path = os.path.dirname(src_assets_path) assets_path = os.path.join(project_path, "assets") rel_blend_path = os.path.relpath(abs_filepath, src_assets_path) clean_rel_path = clean_blend_path(rel_blend_path) scene_name = bpy.context.scene.name instance_output_path = os.path.join(assets_path, "blender", clean_rel_path, f"{scene_name}.scn") # Utility: returns path to store the glb def get_model_export_path(obj: bpy.types.Object) -> str: if obj.instance_type == 'COLLECTION' and obj.instance_collection: lib_path = obj.instance_collection.library.filepath collection_name = bpy.path.clean_name(obj.instance_collection.name) rel_lib_path = os.path.relpath(bpy.path.abspath(lib_path), src_assets_path) rel_lib_path = clean_blend_path(rel_lib_path) return os.path.join("blender", rel_lib_path, f"{collection_name}.glb") else: obj_name = bpy.path.clean_name(obj.name) return os.path.join("blender", clean_rel_path, f"{obj_name}.glb") # Utility: writes an object to glb def export_object_as_glb(obj: bpy.types.Object, export_path: str): full_export_path = os.path.join(assets_path, export_path) pathlib.Path(os.path.dirname(full_export_path)).mkdir(parents=True, exist_ok=True) bpy.ops.object.select_all(action='DESELECT') obj.select_set(True) assert bpy.context.view_layer is not None bpy.context.view_layer.objects.active = obj bpy.ops.export_scene.gltf(filepath=full_export_path, use_selection=True, export_apply=True) print(f"Exported {obj.name} -> {export_path}") # Collect all visible, non-hidden objects in the scene visible_objects = [ obj for obj in bpy.context.scene.objects if obj.visible_get() ] exported = set() instances = [] for obj in visible_objects: model_path = get_model_export_path(obj) if model_path not in exported: export_object_as_glb(obj, model_path) exported.add(model_path) loc = obj.location rot = obj.rotation_quaternion scale = obj.scale instance_sexpr = ( '(inst' f'\n\t:model "assets/{model_path}"' f'\n\t:pos ({loc.x:.6f} {loc.y:.6f} {loc.z:.6f}) ' f'\n\t:rot ({rot.x:.6f} {rot.y:.6f} {rot.z:.6f} {rot.w:.6f}) ' f'\n\t:scale ({scale.x:.6f} {scale.y:.6f} {scale.z:.6f}))' ) instances.append(instance_sexpr) # Save instances to scene file instance_output_abs = os.path.join(project_path, instance_output_path) pathlib.Path(os.path.dirname(instance_output_abs)).mkdir(parents=True, exist_ok=True) with open(instance_output_abs, "w", encoding="utf-8") as f: for line in instances: f.write(line + "\n") print(f"Written instances to {instance_output_abs}")