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