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.
This commit is contained in:
Andrej730
2025-02-04 13:31:47 +05:00
parent 56f0c19a85
commit 8f74f4d9f1
5 changed files with 55 additions and 0 deletions
@@ -118,6 +118,7 @@ class ProjectLibraryData:
cls.data["project_libraries"] = cls.project_libraries() cls.data["project_libraries"] = cls.project_libraries()
# After .project_libraries(). # After .project_libraries().
cls.data["project_libraries_enum"] = cls.project_libraries_enum() cls.data["project_libraries_enum"] = cls.project_libraries_enum()
cls.data["parent_libraries_enum"] = cls.parent_libraries_enum()
cls.is_loaded = True cls.is_loaded = True
@classmethod @classmethod
@@ -146,6 +147,18 @@ class ProjectLibraryData:
results += libs results += libs
return results 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: class LinksData:
linked_data = {} linked_data = {}
@@ -29,6 +29,7 @@ import ifcopenshell.api.attribute
import numpy as np import numpy as np
import ifcopenshell import ifcopenshell
import ifcopenshell.api import ifcopenshell.api
import ifcopenshell.api.nest
import ifcopenshell.api.project import ifcopenshell.api.project
import ifcopenshell.api.root import ifcopenshell.api.root
import ifcopenshell.geom import ifcopenshell.geom
@@ -631,6 +632,20 @@ class EditProjectLibrary(bpy.types.Operator):
project_library = library_file.by_id(props.editing_project_library_id) project_library = library_file.by_id(props.editing_project_library_id)
attributes = bonsai.bim.helper.export_attributes(props.project_library_attributes) attributes = bonsai.bim.helper.export_attributes(props.project_library_attributes)
ifcopenshell.api.attribute.edit_attributes(library_file, 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 props.is_editing_project_library = False
return {"FINISHED"} return {"FINISHED"}
@@ -98,15 +98,26 @@ def is_editing_project_library_update(self: "BIMProjectProperties", context: bpy
self.editing_project_library_id = int(self.selected_project_library) self.editing_project_library_id = int(self.selected_project_library)
project_library = library_file.by_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) 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. ProjectLibraryData.load() # Show edit icon in enum.
return return
del self["is_editing_project_library"] del self["is_editing_project_library"]
del self["editing_project_library_id"] del self["editing_project_library_id"]
self.project_library_attributes.clear() self.project_library_attributes.clear()
del self["parent_library"]
ProjectLibraryData.load() # Hide edit icon in enum. 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: def update_filter_mode(self: "BIMProjectProperties", context: bpy.types.Context) -> None:
self.filter_categories.clear() self.filter_categories.clear()
if self.filter_mode == "NONE": 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." 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) 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) use_relative_project_path: BoolProperty(name="Use Relative Project Path", default=False)
queried_obj: bpy.props.PointerProperty(type=bpy.types.Object) queried_obj: bpy.props.PointerProperty(type=bpy.types.Object)
@@ -398,6 +414,7 @@ class BIMProjectProperties(PropertyGroup):
is_editing_project_library: bool is_editing_project_library: bool
editing_project_library_id: int editing_project_library_id: int
project_library_attributes: bpy.types.bpy_prop_collection_idprop[Attribute] project_library_attributes: bpy.types.bpy_prop_collection_idprop[Attribute]
parent_library: str
use_relative_project_path: bool use_relative_project_path: bool
queried_obj: Union[bpy.types.Object, None] queried_obj: Union[bpy.types.Object, None]
@@ -389,6 +389,8 @@ class BIM_PT_project_library(Panel):
row.operator("bim.edit_project_library", text="Save Attributes", icon="GREASEPENCIL") row.operator("bim.edit_project_library", text="Save Attributes", icon="GREASEPENCIL")
row.prop(props, "is_editing_project_library", text="", icon="CANCEL") row.prop(props, "is_editing_project_library", text="", icon="CANCEL")
draw_attributes(props.project_library_attributes, layout) draw_attributes(props.project_library_attributes, layout)
row = layout.row()
row.prop(props, "parent_library", text="Parent Library")
layout.separator() layout.separator()
if not self.props.library_elements: if not self.props.library_elements:
+8
View File
@@ -344,3 +344,11 @@ class Project(bonsai.core.tool.Project):
element_name = props.active_library_element element_name = props.active_library_element
bpy.ops.bim.rewind_library() bpy.ops.bim.rewind_library()
bpy.ops.bim.change_library_element(element_name=element_name) 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