From 8f74f4d9f1a0a4a9ca6e2925ce67293862a326d4 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Tue, 4 Feb 2025 13:31:47 +0500 Subject: [PATCH] Change IfcProjectLibrary's parent library from UI Example - https://imgur.com/a/4PZr0px It's very clunky and mainly exposed just to be available in some way, it will all make more sense when we display project libraries as trees in project library ui. --- src/bonsai/bonsai/bim/module/project/data.py | 13 +++++++++++++ .../bonsai/bim/module/project/operator.py | 15 +++++++++++++++ src/bonsai/bonsai/bim/module/project/prop.py | 17 +++++++++++++++++ src/bonsai/bonsai/bim/module/project/ui.py | 2 ++ src/bonsai/bonsai/tool/project.py | 8 ++++++++ 5 files changed, 55 insertions(+) diff --git a/src/bonsai/bonsai/bim/module/project/data.py b/src/bonsai/bonsai/bim/module/project/data.py index 3157eaf339..fe9d5a8d47 100644 --- a/src/bonsai/bonsai/bim/module/project/data.py +++ b/src/bonsai/bonsai/bim/module/project/data.py @@ -118,6 +118,7 @@ class ProjectLibraryData: cls.data["project_libraries"] = cls.project_libraries() # After .project_libraries(). cls.data["project_libraries_enum"] = cls.project_libraries_enum() + cls.data["parent_libraries_enum"] = cls.parent_libraries_enum() cls.is_loaded = True @classmethod @@ -146,6 +147,18 @@ class ProjectLibraryData: results += libs return results + @classmethod + def parent_libraries_enum(cls) -> list[tuple[str, str, str]]: + results: list[tuple[str, str, str]] = [] + library_file = IfcStore.library_file + if library_file is None or library_file.schema == "IFC2X3": + return results + project = library_file.by_type("IfcProject")[0] + results.append((str(project.id()), f"IfcProject {project.Name or 'Unnamed'}", project.Description or "")) + for library_id, data in cls.data["project_libraries"].items(): + results.append((str(library_id), data["Name"] or "Unnamed", data["Description"] or "")) + return results + class LinksData: linked_data = {} diff --git a/src/bonsai/bonsai/bim/module/project/operator.py b/src/bonsai/bonsai/bim/module/project/operator.py index faa93914dd..81091d466e 100644 --- a/src/bonsai/bonsai/bim/module/project/operator.py +++ b/src/bonsai/bonsai/bim/module/project/operator.py @@ -29,6 +29,7 @@ import ifcopenshell.api.attribute import numpy as np import ifcopenshell import ifcopenshell.api +import ifcopenshell.api.nest import ifcopenshell.api.project import ifcopenshell.api.root import ifcopenshell.geom @@ -631,6 +632,20 @@ class EditProjectLibrary(bpy.types.Operator): project_library = library_file.by_id(props.editing_project_library_id) attributes = bonsai.bim.helper.export_attributes(props.project_library_attributes) ifcopenshell.api.attribute.edit_attributes(library_file, project_library, attributes) + + # Update parent library. + previous_parent_library = tool.Project.get_parent_library(project_library) + new_parent_library = library_file.by_id(int(props.parent_library)) + if previous_parent_library != new_parent_library: + if previous_parent_library.is_a("IfcProject"): + # Then new one is IfcProjectLibrary. + ifcopenshell.api.nest.assign_object(library_file, [project_library], new_parent_library) + else: # Previous is IfcProjectLibrary. + ifcopenshell.api.nest.unassign_object(library_file, [project_library]) + # If new one is IfcProject, then it's already assigned by default. + if new_parent_library.is_a("IfcProjectLibrary"): + ifcopenshell.api.nest.assign_object(library_file, [project_library], new_parent_library) + props.is_editing_project_library = False return {"FINISHED"} diff --git a/src/bonsai/bonsai/bim/module/project/prop.py b/src/bonsai/bonsai/bim/module/project/prop.py index 77ad8facc1..9f61c2aeab 100644 --- a/src/bonsai/bonsai/bim/module/project/prop.py +++ b/src/bonsai/bonsai/bim/module/project/prop.py @@ -98,15 +98,26 @@ def is_editing_project_library_update(self: "BIMProjectProperties", context: bpy self.editing_project_library_id = int(self.selected_project_library) project_library = library_file.by_id(int(self.selected_project_library)) bonsai.bim.helper.import_attributes2(project_library, self.project_library_attributes) + self.parent_library = str(tool.Project.get_parent_library(project_library).id()) ProjectLibraryData.load() # Show edit icon in enum. return del self["is_editing_project_library"] del self["editing_project_library_id"] self.project_library_attributes.clear() + del self["parent_library"] ProjectLibraryData.load() # Hide edit icon in enum. +def get_parent_libaries(self: "BIMProjectProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]: + if not ProjectLibraryData.is_loaded: + ProjectLibraryData.load() + edited_library = str(self.editing_project_library_id) + # Prevent assigning library to itself. + enum_items = [i for i in ProjectLibraryData.data["parent_libraries_enum"] if i[0] != edited_library] + return enum_items + + def update_filter_mode(self: "BIMProjectProperties", context: bpy.types.Context) -> None: self.filter_categories.clear() if self.filter_mode == "NONE": @@ -328,6 +339,11 @@ class BIMProjectProperties(PropertyGroup): description="Needed to keep track of currently edited library when user changes currently selected library in dropdown." ) project_library_attributes: CollectionProperty(name="Project Library Attributes", type=Attribute) + parent_library: EnumProperty( + name="Parent Library", + description="Parent library that library is assigned to (either IfcProject or IfcProjectLibrary).", + items=get_parent_libaries, + ) use_relative_project_path: BoolProperty(name="Use Relative Project Path", default=False) queried_obj: bpy.props.PointerProperty(type=bpy.types.Object) @@ -398,6 +414,7 @@ class BIMProjectProperties(PropertyGroup): is_editing_project_library: bool editing_project_library_id: int project_library_attributes: bpy.types.bpy_prop_collection_idprop[Attribute] + parent_library: str use_relative_project_path: bool queried_obj: Union[bpy.types.Object, None] diff --git a/src/bonsai/bonsai/bim/module/project/ui.py b/src/bonsai/bonsai/bim/module/project/ui.py index 8a45518ce8..4b4b5dcad9 100644 --- a/src/bonsai/bonsai/bim/module/project/ui.py +++ b/src/bonsai/bonsai/bim/module/project/ui.py @@ -389,6 +389,8 @@ class BIM_PT_project_library(Panel): row.operator("bim.edit_project_library", text="Save Attributes", icon="GREASEPENCIL") row.prop(props, "is_editing_project_library", text="", icon="CANCEL") draw_attributes(props.project_library_attributes, layout) + row = layout.row() + row.prop(props, "parent_library", text="Parent Library") layout.separator() if not self.props.library_elements: diff --git a/src/bonsai/bonsai/tool/project.py b/src/bonsai/bonsai/tool/project.py index 033b1f3c61..33312a0e76 100644 --- a/src/bonsai/bonsai/tool/project.py +++ b/src/bonsai/bonsai/tool/project.py @@ -344,3 +344,11 @@ class Project(bonsai.core.tool.Project): element_name = props.active_library_element bpy.ops.bim.rewind_library() bpy.ops.bim.change_library_element(element_name=element_name) + + @classmethod + def get_parent_library(cls, project_library: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance: + if nests := project_library.Nests: + # IfcProjectLibrary. + return nests[0].RelatingObject + # IfcProject. + return project_library.HasContext[0].RelatingContext