From a24fab6d92b8b1c51697094e340b7e136ccb476a Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Tue, 3 Oct 2023 21:20:16 +1100 Subject: [PATCH] You can now select and bulk process multiple models using IfcFM in Blender. --- .../blenderbim/bim/module/fm/operator.py | 47 ++++++++++++++----- .../blenderbim/bim/module/fm/prop.py | 2 + src/blenderbim/blenderbim/bim/module/fm/ui.py | 5 +- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/fm/operator.py b/src/blenderbim/blenderbim/bim/module/fm/operator.py index d48502790a..a59fe1dc9a 100644 --- a/src/blenderbim/blenderbim/bim/module/fm/operator.py +++ b/src/blenderbim/blenderbim/bim/module/fm/operator.py @@ -32,9 +32,16 @@ class SelectFMIfcFile(bpy.types.Operator): filename_ext = ".ifc" filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"}) filepath: bpy.props.StringProperty(subtype="FILE_PATH") + files: bpy.props.CollectionProperty(name="File Path", type=bpy.types.OperatorFileListElement) def execute(self, context): - context.scene.BIMFMProperties.ifc_file = self.filepath + props = context.scene.BIMFMProperties + props.ifc_files.clear() + dirname = os.path.dirname(self.filepath) + for f in self.files: + new = props.ifc_files.add() + new.name = os.path.join(dirname, f.name) + props.ifc_file = self.filepath return {"FINISHED"} def invoke(self, context, event): @@ -42,6 +49,7 @@ class SelectFMIfcFile(bpy.types.Operator): return {"RUNNING_MODAL"} + class ExecuteIfcFM(bpy.types.Operator): bl_idname = "bim.execute_ifcfm" bl_label = "Execute IfcFM" @@ -66,17 +74,32 @@ class ExecuteIfcFM(bpy.types.Operator): props = context.scene.BIMFMProperties ifc_file = tool.Ifc.get() + filepaths = [] if not (ifc_file and props.should_load_from_memory): - ifc_file = ifcopenshell.open(props.ifc_file) + if len(props.ifc_files): + ifc_files = [ifcopenshell.open(f.name) for f in props.ifc_files] + filepaths = [f.name for f in props.ifc_files] + else: + ifc_files = [ifcopenshell.open(props.ifc_file)] + else: + ifc_files = [ifc_file] - parser = ifcfm.Parser(preset=props.engine) - parser.parse(ifc_file) - writer = ifcfm.Writer(parser) - writer.write() - if props.format == "csv": - writer.write_csv('tmp/') - elif props.format == "ods": - writer.write_ods(self.filepath) - elif props.format == "xlsx": - writer.write_xlsx(self.filepath) + for i, ifc_file in enumerate(ifc_files): + if filepaths: + dirname = os.path.dirname(self.filepath) + prefix, _ = os.path.splitext(os.path.basename(filepaths[i])) + basename = os.path.basename(self.filepath) + filepath = os.path.join(dirname, f"{prefix}-{basename}") + else: + filepath = self.filepath + parser = ifcfm.Parser(preset=props.engine) + parser.parse(ifc_file) + writer = ifcfm.Writer(parser) + writer.write() + if props.format == "csv": + writer.write_csv('tmp/') + elif props.format == "ods": + writer.write_ods(filepath) + elif props.format == "xlsx": + writer.write_xlsx(filepath) return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/fm/prop.py b/src/blenderbim/blenderbim/bim/module/fm/prop.py index f6a3074da3..c75ac52518 100644 --- a/src/blenderbim/blenderbim/bim/module/fm/prop.py +++ b/src/blenderbim/blenderbim/bim/module/fm/prop.py @@ -17,6 +17,7 @@ # along with BlenderBIM Add-on. If not, see . import bpy +from blenderbim.bim.prop import StrProperty from bpy.types import PropertyGroup from bpy.props import ( PointerProperty, @@ -32,6 +33,7 @@ from bpy.props import ( class BIMFMProperties(PropertyGroup): ifc_file: StringProperty(default="", name="IFC File") + ifc_files: CollectionProperty(name="IFC Files", type=StrProperty) should_load_from_memory: BoolProperty(default=False, name="Load from Memory") engine: EnumProperty( items=[ diff --git a/src/blenderbim/blenderbim/bim/module/fm/ui.py b/src/blenderbim/blenderbim/bim/module/fm/ui.py index 8ef8a4dd43..e838d72a0f 100644 --- a/src/blenderbim/blenderbim/bim/module/fm/ui.py +++ b/src/blenderbim/blenderbim/bim/module/fm/ui.py @@ -42,7 +42,10 @@ class BIM_PT_fm(Panel): if not IfcStore.get_file() or not props.should_load_from_memory: row = layout.row(align=True) - row.prop(props, "ifc_file") + if props.ifc_files: + row.label(text=f"{len(props.ifc_files)} Files Selected") + else: + row.prop(props, "ifc_file") row.operator("bim.select_fm_ifc_file", icon="FILE_FOLDER", text="") row = layout.row()