From 8ac8ad33b373491042e3a60b2843eb91ee859057 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Tue, 20 Apr 2021 12:45:20 +1000 Subject: [PATCH] You can now load and browse a tree of project library types products --- src/blenderbim/blenderbim/bim/ifc.py | 2 + .../blenderbim/bim/module/project/__init__.py | 7 ++ .../blenderbim/bim/module/project/operator.py | 83 +++++++++++++++++++ .../blenderbim/bim/module/project/prop.py | 10 +++ .../blenderbim/bim/module/project/ui.py | 49 ++++++++++- 5 files changed, 150 insertions(+), 1 deletion(-) diff --git a/src/blenderbim/blenderbim/bim/ifc.py b/src/blenderbim/blenderbim/bim/ifc.py index 371e05e51b..7a5833a852 100644 --- a/src/blenderbim/blenderbim/bim/ifc.py +++ b/src/blenderbim/blenderbim/bim/ifc.py @@ -12,6 +12,8 @@ class IfcStore: edited_objs = set() pset_template_path = "" pset_template_file = None + library_path = "" + library_file = None @staticmethod def get_file(): diff --git a/src/blenderbim/blenderbim/bim/module/project/__init__.py b/src/blenderbim/blenderbim/bim/module/project/__init__.py index fb41b6e9ed..d213d93f23 100644 --- a/src/blenderbim/blenderbim/bim/module/project/__init__.py +++ b/src/blenderbim/blenderbim/bim/module/project/__init__.py @@ -5,8 +5,15 @@ classes = ( operator.CreateProject, operator.CreateProjectLibrary, operator.ValidateIfcFile, + operator.SelectLibraryFile, + operator.ChangeLibraryElement, + operator.RefreshLibrary, + operator.RewindLibrary, + prop.LibraryElement, prop.BIMProjectProperties, ui.BIM_PT_project, + ui.BIM_PT_project_library, + ui.BIM_UL_library, ) diff --git a/src/blenderbim/blenderbim/bim/module/project/operator.py b/src/blenderbim/blenderbim/bim/module/project/operator.py index 60baeea3a0..70da02d928 100644 --- a/src/blenderbim/blenderbim/bim/module/project/operator.py +++ b/src/blenderbim/blenderbim/bim/module/project/operator.py @@ -88,3 +88,86 @@ class ValidateIfcFile(bpy.types.Operator): logger.setLevel(logging.DEBUG) ifcopenshell.validate.validate(IfcStore.get_file(), logger) return {"FINISHED"} + + +class SelectLibraryFile(bpy.types.Operator): + bl_idname = "bim.select_library_file" + bl_label = "Select Library File" + filepath: bpy.props.StringProperty(subtype="FILE_PATH") + filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"}) + + def execute(self, context): + IfcStore.library_path = self.filepath + IfcStore.library_file = ifcopenshell.open(self.filepath) + bpy.ops.bim.refresh_library() + return {"FINISHED"} + + def invoke(self, context, event): + context.window_manager.fileselect_add(self) + return {"RUNNING_MODAL"} + + +class RefreshLibrary(bpy.types.Operator): + bl_idname = "bim.refresh_library" + bl_label = "Refresh Library" + + def execute(self, context): + self.props = context.scene.BIMProjectProperties + + while len(self.props.library_elements) > 0: + self.props.library_elements.remove(0) + + while len(self.props.library_breadcrumb) > 0: + self.props.library_breadcrumb.remove(0) + + self.props.active_library_element = "" + + types = IfcStore.library_file.wrapped_data.types_with_super() + if "IfcTypeProduct" in types: + new = self.props.library_elements.add() + new.name = "IfcTypeProduct" + return {"FINISHED"} + + +class ChangeLibraryElement(bpy.types.Operator): + bl_idname = "bim.change_library_element" + bl_label = "Change Library Element" + element_name: bpy.props.StringProperty() + + def execute(self, context): + self.props = context.scene.BIMProjectProperties + ifc_classes = set() + self.props.active_library_element = self.element_name + crumb = self.props.library_breadcrumb.add() + crumb.name = self.element_name + elements = IfcStore.library_file.by_type(self.element_name) + [ifc_classes.add(e.is_a()) for e in elements] + while len(self.props.library_elements) > 0: + self.props.library_elements.remove(0) + if len(ifc_classes) == 1: + for element in elements: + new = self.props.library_elements.add() + new.name = element.Name or "Unnamed" + new.ifc_definition_id = element.id() + else: + for ifc_class in ifc_classes: + new = self.props.library_elements.add() + new.name = ifc_class + return {"FINISHED"} + + +class RewindLibrary(bpy.types.Operator): + bl_idname = "bim.rewind_library" + bl_label = "Rewind Library" + + def execute(self, context): + self.props = context.scene.BIMProjectProperties + total_breadcrumbs = len(self.props.library_breadcrumb) + if total_breadcrumbs < 2: + bpy.ops.bim.refresh_library() + return {"FINISHED"} + element_name = self.props.library_breadcrumb[total_breadcrumbs - 2].name + self.props.library_breadcrumb.remove(total_breadcrumbs - 1) + self.props.library_breadcrumb.remove(total_breadcrumbs - 2) + bpy.ops.bim.change_library_element(element_name = element_name) + return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/project/prop.py b/src/blenderbim/blenderbim/bim/module/project/prop.py index d90ceea623..503bed6388 100644 --- a/src/blenderbim/blenderbim/bim/module/project/prop.py +++ b/src/blenderbim/blenderbim/bim/module/project/prop.py @@ -1,4 +1,5 @@ import bpy +from blenderbim.bim.prop import StrProperty from bpy.types import PropertyGroup from bpy.props import ( PointerProperty, @@ -12,5 +13,14 @@ from bpy.props import ( ) +class LibraryElement(PropertyGroup): + name: StringProperty(name="Name") + ifc_definition_id: IntProperty(name="IFC Definition ID") + + class BIMProjectProperties(PropertyGroup): is_authoring: BoolProperty(name="Enable Authoring Mode", default=True) + active_library_element: StringProperty(name="Enable Authoring Mode", default="") + library_breadcrumb: CollectionProperty(name="Library Breadcrumb", type=StrProperty) + library_elements: CollectionProperty(name="Library Elements", type=LibraryElement) + active_library_element_index: IntProperty(name="Active Library Element Index") diff --git a/src/blenderbim/blenderbim/bim/module/project/ui.py b/src/blenderbim/blenderbim/bim/module/project/ui.py index 7e255ea0d3..c02685c3db 100644 --- a/src/blenderbim/blenderbim/bim/module/project/ui.py +++ b/src/blenderbim/blenderbim/bim/module/project/ui.py @@ -1,5 +1,5 @@ import os -from bpy.types import Panel +from bpy.types import Panel, UIList from blenderbim.bim.ifc import IfcStore @@ -66,3 +66,50 @@ class BIM_PT_project(Panel): if props.export_schema != "IFC2X3": row = self.layout.row() row.operator("bim.create_project_library") + + +class BIM_PT_project_library(Panel): + bl_label = "IFC Project Library" + bl_idname = "BIM_PT_project_library" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "scene" + + def draw(self, context): + self.layout.use_property_decorate = False + self.layout.use_property_split = True + self.props = context.scene.BIMProjectProperties + row = self.layout.row(align=True) + row.label(text=IfcStore.library_path or "No Library Loaded", icon="ASSET_MANAGER") + row.operator("bim.select_library_file", icon="FILE_FOLDER", text="") + if IfcStore.library_file: + self.draw_library_ul() + + def draw_library_ul(self): + if not self.props.library_elements: + row = self.layout.row() + row.label(text="No Assets Found", icon="ERROR") + return + row = self.layout.row(align=True) + row.label(text=self.props.active_library_element or "Top Level Assets") + if self.props.active_library_element: + row.operator("bim.rewind_library", icon="FRAME_PREV", text="") + row.operator("bim.refresh_library", icon="FILE_REFRESH", text="") + self.layout.template_list( + "BIM_UL_library", + "", + self.props, + "library_elements", + self.props, + "active_library_element_index", + ) + + +class BIM_UL_library(UIList): + def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + if item: + row = layout.row(align=True) + if not item.ifc_definition_id: + op = row.operator("bim.change_library_element", text="", icon="DISCLOSURE_TRI_RIGHT", emboss=False) + op.element_name = item.name + row.label(text=item.name)