Add operators for saving and loading blend metadata files

This commit is contained in:
falken10vdl
2025-11-21 17:24:10 +01:00
parent 71538455b4
commit 3d18aca2f2
3 changed files with 101 additions and 0 deletions
+2
View File
@@ -115,11 +115,13 @@ classes = [
operator.EditBlenderCollection,
operator.FileAssociate,
operator.FileUnassociate,
operator.LoadBlendMetadataAndIFC,
operator.OpenPath,
operator.OpenUpstream,
operator.OpenUri,
operator.ReloadIfcFile,
operator.RevertClippingPlaneCut,
operator.SaveBlendMetadataFile,
operator.SelectDir,
operator.SelectIfcFile,
operator.SelectURIAttribute,
@@ -331,6 +331,19 @@ class BIM_PT_project(Panel):
col.prop(props, "ifc_file", text="")
row.operator("bim.select_ifc_file", icon="FILE_FOLDER", text="")
# Blend metadata file UI
row = self.layout.row(align=True)
col = row.column()
col.enabled = False
# Show blend metadata file as a label, not editable
blendmetadata_path = ""
if props.ifc_file:
blendmetadata_path = props.ifc_file + ".blendmetadata"
col.label(text=blendmetadata_path)
row.operator("bim.save_blend_metadata_file", icon="FILE_TICK", text="")
row = self.layout.row(align=True)
row.operator("bim.load_blend_metadata_and_ifc", icon="FILE_REFRESH", text="Load Metadata + IFC")
class BIM_PT_new_project_wizard(Panel):
bl_label = "New Project Wizard"
+86
View File
@@ -236,6 +236,92 @@ class SelectIfcFile(bpy.types.Operator, IFCFileSelector, ImportHelper):
return res
return ImportHelper.invoke(self, context, event)
class SaveBlendMetadataFile(bpy.types.Operator):
bl_idname = "bim.save_blend_metadata_file"
bl_label = "Save Blend Metadata File"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
"""
Save the current blend file as a metadata-only file (no geometry), preserving settings, window arrangement, geometry nodes, etc.
"""
props = tool.Blender.get_bim_props()
ifc_file = getattr(props, "ifc_file", None)
if not ifc_file:
self.report({"WARNING"}, "No IFC file path set.")
return {"CANCELLED"}
blendmetadata_path = ifc_file + ".metadata.blend"
# Save a temporary copy of the current blend file
temp_path = bpy.path.abspath('//__temp_blendmetadata.blend')
bpy.ops.wm.save_as_mainfile(filepath=temp_path, copy=True)
# Prepare Python script to run in background Blender to remove geometry
cleanup_script = f"""
import bpy
# Remove all mesh objects and mesh collections
for obj in bpy.data.objects:
if obj.type == 'MESH':
bpy.data.objects.remove(obj, do_unlink=True)
for collection in bpy.data.collections:
# Remove collections that only contain mesh objects
if all(o.type == 'MESH' for o in collection.objects):
bpy.data.collections.remove(collection)
bpy.ops.wm.save_as_mainfile(filepath=r'{blendmetadata_path}')
"""
# Save cleanup script to temp file
import tempfile
with tempfile.NamedTemporaryFile('w', suffix='.py', delete=False) as script_file:
script_file.write(cleanup_script)
script_path = script_file.name
# Run Blender in background to clean and save metadata file
blender_exe = bpy.app.binary_path
import subprocess
result = subprocess.run([
blender_exe,
temp_path,
'--background',
'--python', script_path
], capture_output=True)
# Clean up temp files
try:
os.remove(temp_path)
os.remove(script_path)
except Exception:
pass
if result.returncode == 0:
self.report({"INFO"}, f"Blend metadata file saved to: {blendmetadata_path}")
else:
self.report({"ERROR"}, f"Failed to save blend metadata file: {result.stderr.decode()}")
return {"FINISHED"}
class LoadBlendMetadataAndIFC(bpy.types.Operator):
bl_idname = "bim.load_blend_metadata_and_ifc"
bl_label = "Load Blend Metadata and IFC"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
props = tool.Blender.get_bim_props()
ifc_file = getattr(props, "ifc_file", None)
if not ifc_file:
self.report({"WARNING"}, "No IFC file path set.")
return {"CANCELLED"}
metadata_path = ifc_file + ".metadata.blend"
# Open the metadata blend file
bpy.ops.wm.open_mainfile(filepath=metadata_path)
# After loading metadata, clear blend warning (no geometry loaded yet)
props = tool.Blender.get_bim_props()
props.has_blend_warning = False
# Load the IFC file into the current session (preserve layout)
bpy.ops.bim.load_project(filepath=ifc_file, should_start_fresh_session=False)
self.report({"INFO"}, f"Loaded metadata and IFC: {metadata_path}, {ifc_file}")
return {"FINISHED"}
# TODO: Unused operator.
# Is there a need for this or 'DIR_PATH' propety subtype does almost the same,