From 36ed618adf22a041aa165aa0d8d37b8d14983137 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Mon, 9 Oct 2023 17:26:27 +1100 Subject: [PATCH] You can now federate FM spreadsheets using the Blender UI --- .../blenderbim/bim/module/fm/__init__.py | 4 +- .../blenderbim/bim/module/fm/operator.py | 60 +++++++++++++++++-- .../blenderbim/bim/module/fm/prop.py | 1 + src/blenderbim/blenderbim/bim/module/fm/ui.py | 9 ++- 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/module/fm/__init__.py b/src/blenderbim/blenderbim/bim/module/fm/__init__.py index de3f0f9448..bae513a98f 100644 --- a/src/blenderbim/blenderbim/bim/module/fm/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/fm/__init__.py @@ -20,8 +20,10 @@ import bpy from . import ui, prop, operator classes = ( - operator.SelectFMIfcFile, operator.ExecuteIfcFM, + operator.ExecuteIfcFMFederate, + operator.SelectFMIfcFile, + operator.SelectFMSpreadsheetFiles, prop.BIMFMProperties, ui.BIM_PT_fm, ) diff --git a/src/blenderbim/blenderbim/bim/module/fm/operator.py b/src/blenderbim/blenderbim/bim/module/fm/operator.py index a59fe1dc9a..813ceae37a 100644 --- a/src/blenderbim/blenderbim/bim/module/fm/operator.py +++ b/src/blenderbim/blenderbim/bim/module/fm/operator.py @@ -19,6 +19,7 @@ import os import bpy import json +import ifcfm import logging import tempfile import ifcopenshell @@ -49,7 +50,6 @@ class SelectFMIfcFile(bpy.types.Operator): return {"RUNNING_MODAL"} - class ExecuteIfcFM(bpy.types.Operator): bl_idname = "bim.execute_ifcfm" bl_label = "Execute IfcFM" @@ -70,8 +70,6 @@ class ExecuteIfcFM(bpy.types.Operator): return {"RUNNING_MODAL"} def execute(self, context): - import ifcfm - props = context.scene.BIMFMProperties ifc_file = tool.Ifc.get() filepaths = [] @@ -97,9 +95,63 @@ class ExecuteIfcFM(bpy.types.Operator): writer = ifcfm.Writer(parser) writer.write() if props.format == "csv": - writer.write_csv('tmp/') + writer.write_csv("tmp/") elif props.format == "ods": writer.write_ods(filepath) elif props.format == "xlsx": writer.write_xlsx(filepath) return {"FINISHED"} + + +class SelectFMSpreadsheetFiles(bpy.types.Operator): + bl_idname = "bim.select_fm_spreadsheet_files" + bl_label = "Select FM Spreadsheet Files" + bl_options = {"REGISTER", "UNDO"} + filter_glob: bpy.props.StringProperty(default="*.ods;*.xlsx", options={"HIDDEN"}) + filepath: bpy.props.StringProperty(subtype="FILE_PATH") + files: bpy.props.CollectionProperty(name="File Path", type=bpy.types.OperatorFileListElement) + + def execute(self, context): + props = context.scene.BIMFMProperties + props.spreadsheet_files.clear() + dirname = os.path.dirname(self.filepath) + for f in self.files: + new = props.spreadsheet_files.add() + new.name = os.path.join(dirname, f.name) + return {"FINISHED"} + + def invoke(self, context, event): + context.window_manager.fileselect_add(self) + return {"RUNNING_MODAL"} + + +class ExecuteIfcFMFederate(bpy.types.Operator): + bl_idname = "bim.execute_ifcfm_federate" + bl_label = "Execute IfcFM" + file_format: bpy.props.StringProperty() + filter_glob: bpy.props.StringProperty(default="*.ods;*.xlsx", options={"HIDDEN"}) + filepath: bpy.props.StringProperty(subtype="FILE_PATH") + + @classmethod + def poll(cls, context): + props = context.scene.BIMFMProperties + return props.spreadsheet_files + + def invoke(self, context, event): + props = context.scene.BIMFMProperties + self.filepath = bpy.path.ensure_ext(bpy.data.filepath, f".{props.format}") + WindowManager = context.window_manager + WindowManager.fileselect_add(self) + return {"RUNNING_MODAL"} + + def execute(self, context): + props = context.scene.BIMFMProperties + parser = ifcfm.Parser(preset=props.engine) + parser.federate([f.name for f in props.spreadsheet_files]) + writer = ifcfm.Writer(parser) + writer.write() + if props.format == "ods": + writer.write_ods(self.filepath) + elif props.format == "xlsx": + writer.write_xlsx(self.filepath) + return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/fm/prop.py b/src/blenderbim/blenderbim/bim/module/fm/prop.py index c75ac52518..696c27a084 100644 --- a/src/blenderbim/blenderbim/bim/module/fm/prop.py +++ b/src/blenderbim/blenderbim/bim/module/fm/prop.py @@ -34,6 +34,7 @@ from bpy.props import ( class BIMFMProperties(PropertyGroup): ifc_file: StringProperty(default="", name="IFC File") ifc_files: CollectionProperty(name="IFC Files", type=StrProperty) + spreadsheet_files: CollectionProperty(name="Spreadsheets", 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 e838d72a0f..502e463e19 100644 --- a/src/blenderbim/blenderbim/bim/module/fm/ui.py +++ b/src/blenderbim/blenderbim/bim/module/fm/ui.py @@ -42,7 +42,7 @@ class BIM_PT_fm(Panel): if not IfcStore.get_file() or not props.should_load_from_memory: row = layout.row(align=True) - if props.ifc_files: + if len(props.ifc_files) > 1: row.label(text=f"{len(props.ifc_files)} Files Selected") else: row.prop(props, "ifc_file") @@ -55,3 +55,10 @@ class BIM_PT_fm(Panel): row = layout.row() op = row.operator("bim.execute_ifcfm", text="Convert To Spreadsheet") + + row = layout.row(align=True) + row.label(text=f"{len(props.spreadsheet_files)} Spreadsheets Selected") + row.operator("bim.select_fm_spreadsheet_files", icon="FILE_FOLDER", text="") + + row = layout.row() + op = row.operator("bim.execute_ifcfm_federate", text="Merge Spreadsheets")