Add Ifc Document information element to decide if blend metadata info should be used in this project file

This commit is contained in:
falken10vdl
2026-01-06 22:14:08 +01:00
parent 831c3190cc
commit 321878e1bb
4 changed files with 116 additions and 16 deletions
@@ -1062,18 +1062,34 @@ class LoadProject(bpy.types.Operator, IFCFileSelector, ImportHelper):
and not self.is_advanced
):
filepath = self.get_filepath()
suffix = tool.Blender.get_addon_preferences().metadata_blend_file_suffix
if str(filepath).lower().endswith(".ifc"):
metadata_path = Path(str(filepath)[:-4] + suffix)
else:
metadata_path = Path(str(filepath) + suffix)
if metadata_path.exists() and metadata_path.is_file():
try:
bpy.ops.bim.load_blend_metadata_and_ifc(filepath=filepath)
self.report({"INFO"}, f"Loaded metadata file: {metadata_path.name}")
return {"FINISHED"}
except Exception as e:
self.report({"WARNING"}, f"Failed to load metadata file, using regular load: {e}")
# First, load the IFC file temporarily to check for metadata document
temp_ifc = None
has_metadata_doc = False
try:
temp_ifc = ifcopenshell.open(str(filepath))
for doc in temp_ifc.by_type("IfcDocumentInformation"):
if getattr(doc, "Scope", None) == "BLEND_METADATA":
has_metadata_doc = True
break
except:
pass
finally:
temp_ifc = None
if has_metadata_doc:
suffix = tool.Blender.get_addon_preferences().metadata_blend_file_suffix
if str(filepath).lower().endswith(".ifc"):
metadata_path = Path(str(filepath)[:-4] + suffix)
else:
metadata_path = Path(str(filepath) + suffix)
if metadata_path.exists() and metadata_path.is_file():
try:
bpy.ops.bim.load_blend_metadata_and_ifc(filepath=filepath)
self.report({"INFO"}, f"Loaded metadata file: {metadata_path.name}")
return {"FINISHED"}
except Exception as e:
self.report({"WARNING"}, f"Failed to load metadata file, using regular load: {e}")
@persistent
def load_handler(*args):
@@ -1121,6 +1137,10 @@ class LoadProject(bpy.types.Operator, IFCFileSelector, ImportHelper):
props.is_loading = True
props.total_elements = len(tool.Ifc.get().by_type("IfcElement"))
props.use_relative_project_path = self.use_relative_path
metadata_doc = tool.Project.get_metadata_document_information()
props.should_save_metadata_for_this_file = metadata_doc is not None
tool.Blender.register_toolbar()
tool.Project.add_recent_ifc_project(self.get_filepath_abs())
@@ -1749,6 +1769,22 @@ class ExportIFC(bpy.types.Operator, ExportHelper):
settings.json_version = self.json_version
settings.json_compact = self.json_compact
pprops = tool.Project.get_project_props()
if tool.Blender.get_addon_preferences().save_metadata_blend_file and pprops.should_save_metadata_for_this_file:
suffix = tool.Blender.get_addon_preferences().metadata_blend_file_suffix
if output_file.lower().endswith(".ifc"):
metadata_filename = os.path.basename(output_file)[:-4] + suffix
else:
metadata_filename = os.path.basename(output_file) + suffix
if not tool.Project.get_metadata_document_information():
tool.Project.create_metadata_document_information(metadata_filename)
else:
tool.Project.update_metadata_document_information(metadata_filename)
else:
if not pprops.should_save_metadata_for_this_file:
tool.Project.remove_metadata_document_information()
ifc_exporter = export_ifc.IfcExporter(settings)
print("Starting export")
settings.logger.info("Starting export")
@@ -1765,7 +1801,8 @@ class ExportIFC(bpy.types.Operator, ExportHelper):
tool.Ifc.set_path(output_file)
bim_props.is_dirty = False
if tool.Blender.get_addon_preferences().save_metadata_blend_file:
pprops = tool.Project.get_project_props()
if tool.Blender.get_addon_preferences().save_metadata_blend_file and pprops.should_save_metadata_for_this_file:
try:
bpy.ops.bim.save_blend_metadata_file()
suffix = tool.Blender.get_addon_preferences().metadata_blend_file_suffix
@@ -411,6 +411,11 @@ class BIMProjectProperties(PropertyGroup):
)
use_relative_project_path: BoolProperty(name="Use Relative Project Path", default=False)
should_save_metadata_for_this_file: BoolProperty(
name="Save Session Data for This File",
description="Enable saving session data (window layout, settings) to a metadata blend file for this specific IFC file",
default=False,
)
queried_obj: bpy.props.PointerProperty(type=bpy.types.Object)
queried_obj_root: bpy.props.PointerProperty(type=bpy.types.Object)
clipping_planes: bpy.props.CollectionProperty(type=ObjProperty)
@@ -504,6 +509,7 @@ class BIMProjectProperties(PropertyGroup):
parent_library: str
use_relative_project_path: bool
should_save_metadata_for_this_file: bool
queried_obj: Union[bpy.types.Object, None]
queried_obj_root: Union[bpy.types.Object, None]
clipping_planes: bpy.types.bpy_prop_collection_idprop[ObjProperty]
+3 -3
View File
@@ -338,9 +338,9 @@ class BIM_PT_project(Panel):
else:
metadata_filename = os.path.basename(props.ifc_file) + suffix
row = self.layout.row(align=True)
col = row.column()
col.enabled = False
col.label(text=f"Saving session data to: {metadata_filename}")
row.use_property_split = False
pprops = tool.Project.get_project_props()
row.prop(pprops, "should_save_metadata_for_this_file", text=f"Save session data to: {metadata_filename}")
class BIM_PT_new_project_wizard(Panel):
+57
View File
@@ -513,3 +513,60 @@ class Project(bonsai.core.tool.Project):
if tmp.exists():
shutil.rmtree(tmp)
bpy.ops.bim.save_project(filepath=cls.TEMP_PROJECT_PATH.__str__(), should_save_as=True)
@classmethod
def get_metadata_document_information(cls) -> Optional[ifcopenshell.entity_instance]:
ifc_file = tool.Ifc.get()
if not ifc_file:
return None
for doc in ifc_file.by_type("IfcDocumentInformation"):
if getattr(doc, "Scope", None) == "BLEND_METADATA":
return doc
return None
@classmethod
def create_metadata_document_information(cls, metadata_filename: str) -> ifcopenshell.entity_instance:
ifc_file = tool.Ifc.get()
if not ifc_file:
raise Exception("No IFC file loaded")
doc = tool.Ifc.run("document.add_information", parent=None)
if ifc_file.schema == "IFC2X3":
tool.Ifc.run("document.edit_information", information=doc, attributes={
"DocumentId": "BLEND_METADATA",
"Name": "Blend Metadata",
"Scope": "BLEND_METADATA",
"Description": "References to blend metadata file for this IFC project",
"Location": metadata_filename
})
else:
tool.Ifc.run("document.edit_information", information=doc, attributes={
"Identification": "BLEND_METADATA",
"Name": "Blend Metadata",
"Scope": "BLEND_METADATA",
"Description": "References to blend metadata file for this IFC project",
"Location": metadata_filename
})
return doc
@classmethod
def update_metadata_document_information(cls, metadata_filename: str) -> None:
doc = cls.get_metadata_document_information()
if not doc:
return
ifc_file = tool.Ifc.get()
if not ifc_file:
return
tool.Ifc.run("document.edit_information", information=doc, attributes={
"Location": metadata_filename
})
@classmethod
def remove_metadata_document_information(cls) -> None:
doc = cls.get_metadata_document_information()
if doc:
tool.Ifc.run("document.remove_information", information=doc)