From df493561040ad7685f668c0c0176b7828890389a Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 31 Jan 2025 14:35:22 +0500 Subject: [PATCH] Support adding a new IfcProjectLibrary from UI Example - https://imgur.com/a/NUQkvHf --- .../bonsai/bim/module/project/__init__.py | 1 + src/bonsai/bonsai/bim/module/project/data.py | 5 ++- .../bonsai/bim/module/project/operator.py | 39 ++++++++++++++++++- src/bonsai/bonsai/bim/module/project/ui.py | 16 +++++--- src/bonsai/bonsai/tool/project.py | 4 +- 5 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/project/__init__.py b/src/bonsai/bonsai/bim/module/project/__init__.py index ce77a0cd31..d87814c026 100644 --- a/src/bonsai/bonsai/bim/module/project/__init__.py +++ b/src/bonsai/bonsai/bim/module/project/__init__.py @@ -20,6 +20,7 @@ import bpy from . import ui, prop, operator, workspace, gizmo, decorator classes = ( + operator.AddProjectLibrary, operator.AppendEntireLibrary, operator.AppendInspectedLinkedElement, operator.AppendLibraryElement, diff --git a/src/bonsai/bonsai/bim/module/project/data.py b/src/bonsai/bonsai/bim/module/project/data.py index a4f2f6793c..3157eaf339 100644 --- a/src/bonsai/bonsai/bim/module/project/data.py +++ b/src/bonsai/bonsai/bim/module/project/data.py @@ -138,9 +138,12 @@ class ProjectLibraryData: ("-", "No Library", "Show elements without library assigned", "", 1), ] props = tool.Project.get_project_props() + libs = [] for i, data in enumerate(cls.data["project_libraries"].values(), len(results)): icon = "GREASEPENCIL" if props.editing_project_library_id == data["id"] else "" - results.append((str(data["id"]), data["Name"] or "", data["Description"] or "", icon, i)) + libs.append((str(data["id"]), data["Name"] or "Unnamed", data["Description"] or "", icon, i)) + libs.sort(key=lambda x: x[1]) + results += libs return results diff --git a/src/bonsai/bonsai/bim/module/project/operator.py b/src/bonsai/bonsai/bim/module/project/operator.py index 24aef44dfd..20eb4a1f5d 100644 --- a/src/bonsai/bonsai/bim/module/project/operator.py +++ b/src/bonsai/bonsai/bim/module/project/operator.py @@ -30,6 +30,7 @@ import numpy as np import ifcopenshell import ifcopenshell.api import ifcopenshell.api.project +import ifcopenshell.api.root import ifcopenshell.geom import ifcopenshell.ifcopenshell_wrapper as W import ifcopenshell.util.file @@ -55,7 +56,7 @@ from collections import defaultdict from mathutils import Vector, Matrix from bpy.app.handlers import persistent from ifcopenshell.geom import ShapeElementType -from bonsai.bim.module.project.data import LinksData +from bonsai.bim.module.project.data import LinksData, ProjectLibraryData from bonsai.bim.module.project.decorator import ProjectDecorator, ClippingPlaneDecorator, MeasureDecorator from bonsai.bim.module.model.decorator import PolylineDecorator from bonsai.bim.module.model.polyline import PolylineOperator @@ -639,6 +640,42 @@ class EditProjectLibrary(bpy.types.Operator): IfcStore.library_file.redo() +class AddProjectLibrary(bpy.types.Operator): + bl_idname = "bim.add_project_library" + bl_label = "Add Project Library" + bl_description = "Add new IfcProjectLibrary to the currently selected library." + bl_options = {"REGISTER", "UNDO"} + + def execute(self, context): + IfcStore.begin_transaction(self) + library_file = IfcStore.library_file + assert library_file + library_file.begin_transaction() + result = self._execute(context) + library_file.end_transaction() + IfcStore.add_transaction_operation(self) + IfcStore.end_transaction(self) + return result + + def _execute(self, context): + props = tool.Project.get_project_props() + library_file = IfcStore.library_file + assert library_file + project = library_file.by_type("IfcProject")[0] + project_library = ifcopenshell.api.root.create_entity(library_file, "IfcProjectLibrary") + ifcopenshell.api.project.assign_declaration(library_file, [project_library], project) + ProjectLibraryData.load() # Update enum. + props.selected_project_library = str(project_library.id()) + props.is_editing_project_library = True + return {"FINISHED"} + + def rollback(self, data): + IfcStore.library_file.undo() + + def commit(self, data): + IfcStore.library_file.redo() + + class EnableEditingHeader(bpy.types.Operator): bl_idname = "bim.enable_editing_header" bl_label = "Enable Editing Header" diff --git a/src/bonsai/bonsai/bim/module/project/ui.py b/src/bonsai/bonsai/bim/module/project/ui.py index 9c75d9b7cd..4c07ca7c57 100644 --- a/src/bonsai/bonsai/bim/module/project/ui.py +++ b/src/bonsai/bonsai/bim/module/project/ui.py @@ -366,15 +366,16 @@ class BIM_PT_project_library(Panel): layout = self.layout props = self.props - if not self.props.library_elements: - row = self.layout.row() - row.label(text="No Assets Found", icon="ERROR") - return - + library_file = IfcStore.library_file + assert library_file library_is_selected = props.selected_project_library not in ("*", "-") + row = layout.row(align=True) row.prop(self.props, "selected_project_library", text="") + if library_file.schema != "IFC2X3": + row.operator("bim.add_project_library", text="", icon="ADD") + if library_is_selected and not props.is_editing_project_library: row.prop(props, "is_editing_project_library", text="", icon="GREASEPENCIL") @@ -387,6 +388,11 @@ class BIM_PT_project_library(Panel): draw_attributes(props.project_library_attributes, layout) layout.separator() + 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: diff --git a/src/bonsai/bonsai/tool/project.py b/src/bonsai/bonsai/tool/project.py index 4f5ffa8744..033b1f3c61 100644 --- a/src/bonsai/bonsai/tool/project.py +++ b/src/bonsai/bonsai/tool/project.py @@ -332,7 +332,9 @@ class Project(bonsai.core.tool.Project): else: def condition(elements: list[ifcopenshell.entity_instance]): - pass + # Hacky way to create empty generator. + return + yield return condition