Project library UI - make filter optional and allow assigning to different libraries

This commit is contained in:
Andrej730
2025-01-31 12:17:43 +05:00
parent 87cbc66c99
commit 8469d10c85
4 changed files with 79 additions and 27 deletions
@@ -288,11 +288,17 @@ class ChangeLibraryElement(bpy.types.Operator):
is_declarable = project_libraries_exist and element.is_a("IfcObjectDefinition")
new.is_declarable = is_declarable
selected_library = self.props.selected_project_library
# is_declared.
if not is_declarable:
new.is_declared = False
elif (has_context := element.HasContext) and has_context[0].RelatingContext.is_a("IfcProjectLibrary"):
new.is_declared = True
elif has_context := element.HasContext:
relating_context: ifcopenshell.entity_instance
relating_context = has_context[0].RelatingContext
if selected_library in ("-", "*"):
new.is_declared = relating_context.is_a("IfcProjectLibrary")
else:
new.is_declared = relating_context == self.library_file.by_id(int(selected_library))
# is_appended.
try:
@@ -328,9 +334,13 @@ class RewindLibrary(bpy.types.Operator):
class AssignLibraryDeclaration(bpy.types.Operator):
bl_idname = "bim.assign_library_declaration"
bl_label = "Assign Library Declaration"
bl_description = "Assign element to the active library. If no specific library selected, will assign it to the first library in the file."
bl_options = {"REGISTER", "UNDO"}
definition: bpy.props.IntProperty()
if TYPE_CHECKING:
definition: int
def execute(self, context):
IfcStore.begin_transaction(self)
IfcStore.library_file.begin_transaction()
@@ -341,17 +351,22 @@ class AssignLibraryDeclaration(bpy.types.Operator):
return result
def _execute(self, context):
self.props = context.scene.BIMProjectProperties
self.file = IfcStore.library_file
ifcopenshell.api.run(
"project.assign_declaration",
self.file,
definitions=[self.file.by_id(self.definition)],
relating_context=self.file.by_type("IfcProjectLibrary")[0],
props = tool.Project.get_project_props()
library_file = IfcStore.library_file
assert library_file
if props.selected_project_library in ("*", "-"):
project_library = library_file.by_type("IfcProjectLibrary")[0]
else:
project_library = library_file.by_id(int(props.selected_project_library))
ifcopenshell.api.project.assign_declaration(
library_file,
definitions=[library_file.by_id(self.definition)],
relating_context=project_library,
)
element_name = self.props.active_library_element
bpy.ops.bim.rewind_library()
bpy.ops.bim.change_library_element(element_name=element_name)
tool.Project.update_current_library_page()
return {"FINISHED"}
def rollback(self, data):
@@ -367,6 +382,9 @@ class UnassignLibraryDeclaration(bpy.types.Operator):
bl_options = {"REGISTER", "UNDO"}
definition: bpy.props.IntProperty()
if TYPE_CHECKING:
definition: int
def execute(self, context):
IfcStore.begin_transaction(self)
IfcStore.library_file.begin_transaction()
@@ -377,17 +395,18 @@ class UnassignLibraryDeclaration(bpy.types.Operator):
return result
def _execute(self, context):
self.props = context.scene.BIMProjectProperties
self.file = IfcStore.library_file
ifcopenshell.api.run(
"project.unassign_declaration",
self.file,
definitions=[self.file.by_id(self.definition)],
relating_context=self.file.by_type("IfcProjectLibrary")[0],
props = tool.Project.get_project_props()
library_file = IfcStore.library_file
assert library_file
element = library_file.by_id(self.definition)
ifcopenshell.api.project.unassign_declaration(
library_file,
definitions=[library_file.by_id(self.definition)],
relating_context=element.HasContext[0].RelatingContext,
)
element_name = self.props.active_library_element
bpy.ops.bim.rewind_library()
bpy.ops.bim.change_library_element(element_name=element_name)
tool.Project.update_current_library_page()
return {"FINISHED"}
def rollback(self, data):
+19 -1
View File
@@ -67,7 +67,11 @@ def update_library_file(self: "BIMProjectProperties", context: bpy.types.Context
def update_selected_project_library(self: "BIMProjectProperties", context: bpy.types.Context) -> None:
bpy.ops.bim.refresh_library()
if self.filter_by_library:
bpy.ops.bim.refresh_library()
else:
# Ensure `.is_declared` up to date.
tool.Project.update_current_library_page()
def get_project_libaries(self: "BIMProjectProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]:
@@ -76,6 +80,13 @@ def get_project_libaries(self: "BIMProjectProperties", context: bpy.types.Contex
return ProjectLibraryData.data["project_libraries_enum"]
def filter_by_library_update(self: "BIMProjectProperties", context: bpy.types.Context) -> None:
if self.filter_by_library and self.selected_project_library == "*":
# Filter is toggled from OFF to ON, so it was showing all elements previously either way.
return
bpy.ops.bim.refresh_library()
def update_filter_mode(self: "BIMProjectProperties", context: bpy.types.Context) -> None:
self.filter_categories.clear()
if self.filter_mode == "NONE":
@@ -282,6 +293,12 @@ class BIMProjectProperties(PropertyGroup):
description="Project library to display elements from",
update=update_selected_project_library,
)
filter_by_library: BoolProperty(
name="Filter by Library",
description="Filter library elements based on selected library. If unselected can be used to assign selected library to library elements.",
default=True,
update=filter_by_library_update,
)
use_relative_project_path: BoolProperty(name="Use Relative Project Path", default=False)
queried_obj: bpy.props.PointerProperty(type=bpy.types.Object)
@@ -348,6 +365,7 @@ class BIMProjectProperties(PropertyGroup):
library_file: str
selected_project_library: Union[Literal["*", "-"], str]
filter_by_library: bool
use_relative_project_path: bool
queried_obj: Union[bpy.types.Object, None]
+7 -1
View File
@@ -363,11 +363,17 @@ class BIM_PT_project_library(Panel):
row.label(text="No Library Loaded", icon="ASSET_MANAGER")
def draw_library_ul(self):
layout = self.layout
if not self.props.library_elements:
row = self.layout.row()
row.label(text="No Assets Found", icon="ERROR")
return
self.layout.prop(self.props, "selected_project_library", text="")
row = layout.row(align=True)
row.prop(self.props, "selected_project_library", text="")
row.prop(self.props, "filter_by_library", text="", icon="FILTER")
row = self.layout.row(align=True)
row.label(text=self.props.active_library_element or "Top Level Assets")
if self.props.active_library_element:
+12 -3
View File
@@ -303,12 +303,14 @@ class Project(bonsai.core.tool.Project):
library_file = IfcStore.library_file
assert library_file
if props.selected_project_library == "*":
selected_project_library = props.selected_project_library if props.filter_by_library else "*"
if selected_project_library == "*":
def condition(elements: list[ifcopenshell.entity_instance]):
yield from elements
elif props.selected_project_library == "-":
elif selected_project_library == "-":
def condition(elements: list[ifcopenshell.entity_instance]):
for element in elements:
@@ -316,7 +318,7 @@ class Project(bonsai.core.tool.Project):
yield element
else:
project_library = library_file.by_id(int(props.selected_project_library))
project_library = library_file.by_id(int(selected_project_library))
project_library_rels = set(project_library.Declares)
if project_library_rels:
@@ -333,3 +335,10 @@ class Project(bonsai.core.tool.Project):
pass
return condition
@classmethod
def update_current_library_page(cls):
props = cls.get_project_props()
element_name = props.active_library_element
bpy.ops.bim.rewind_library()
bpy.ops.bim.change_library_element(element_name=element_name)