Select IfcProjectLibrary to display for the loaded library

Example - https://imgur.com/a/14LOL0J
This commit is contained in:
Andrej730
2025-01-29 16:52:04 +05:00
parent 8bddde49a2
commit 83d7cda26b
5 changed files with 85 additions and 4 deletions
@@ -116,6 +116,8 @@ class ProjectLibraryData:
def load(cls): def load(cls):
cls.data = {} cls.data = {}
cls.data["project_libraries"] = cls.project_libraries() cls.data["project_libraries"] = cls.project_libraries()
# After .project_libraries().
cls.data["project_libraries_enum"] = cls.project_libraries_enum()
cls.is_loaded = True cls.is_loaded = True
@classmethod @classmethod
@@ -129,6 +131,16 @@ class ProjectLibraryData:
results[l.id()] = {k: v for k, v in l.get_info().items() if k in KEEP_ATTRS} results[l.id()] = {k: v for k, v in l.get_info().items() if k in KEEP_ATTRS}
return results return results
@classmethod
def project_libraries_enum(cls) -> list[tuple[str, str, str]]:
results = [
("*", "All Libraries", "Show all elements"),
("-", "No Library", "Show elements without library assigned"),
]
for data in cls.data["project_libraries"].values():
results.append((str(data["id"]), data["Name"] or "", data["Description"] or ""))
return results
class LinksData: class LinksData:
linked_data = {} linked_data = {}
@@ -214,10 +214,15 @@ class RefreshLibrary(bpy.types.Operator):
self.props.active_library_element = "" self.props.active_library_element = ""
library_file = IfcStore.library_file
assert library_file
condition = tool.Project.get_filter_for_active_library()
for importable_type in sorted(tool.Project.get_appendable_asset_types()): for importable_type in sorted(tool.Project.get_appendable_asset_types()):
if IfcStore.library_file.by_type(importable_type): if (elements := library_file.by_type(importable_type)) and next(condition(elements), None):
new = self.props.library_elements.add() new = self.props.library_elements.add()
new.name = importable_type new.name = importable_type
return {"FINISHED"} return {"FINISHED"}
@@ -225,7 +230,7 @@ class ChangeLibraryElement(bpy.types.Operator):
bl_idname = "bim.change_library_element" bl_idname = "bim.change_library_element"
bl_label = "Change Library Element" bl_label = "Change Library Element"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
element_name: bpy.props.StringProperty() element_name: bpy.props.StringProperty(description="IFC class to select")
if TYPE_CHECKING: if TYPE_CHECKING:
element_name: str element_name: str
@@ -242,7 +247,9 @@ class ChangeLibraryElement(bpy.types.Operator):
crumb = self.props.library_breadcrumb.add() crumb = self.props.library_breadcrumb.add()
crumb.name = self.element_name crumb.name = self.element_name
filter_elements = tool.Project.get_filter_for_active_library()
elements = self.library_file.by_type(self.element_name) elements = self.library_file.by_type(self.element_name)
elements = list(filter_elements(elements))
[ifc_classes.add(e.is_a()) for e in elements] [ifc_classes.add(e.is_a()) for e in elements]
self.props.library_elements.clear() self.props.library_elements.clear()
+23 -1
View File
@@ -21,7 +21,7 @@ import bpy
import ifcopenshell.util.element import ifcopenshell.util.element
import ifcopenshell.util.placement import ifcopenshell.util.placement
import bonsai.tool as tool import bonsai.tool as tool
from bonsai.bim.module.project.data import ProjectData from bonsai.bim.module.project.data import ProjectData, ProjectLibraryData
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
from bonsai.bim.prop import StrProperty, ObjProperty from bonsai.bim.prop import StrProperty, ObjProperty
from bpy.types import PropertyGroup from bpy.types import PropertyGroup
@@ -66,6 +66,16 @@ def update_library_file(self: "BIMProjectProperties", context: bpy.types.Context
bpy.ops.bim.select_library_file(filepath=filepath.__str__()) bpy.ops.bim.select_library_file(filepath=filepath.__str__())
def update_selected_project_library(self: "BIMProjectProperties", context: bpy.types.Context) -> None:
bpy.ops.bim.refresh_library()
def get_project_libaries(self: "BIMProjectProperties", context: bpy.types.Context) -> list[tuple[str, str, str]]:
if not ProjectLibraryData.is_loaded:
ProjectLibraryData.load()
return ProjectLibraryData.data["project_libraries_enum"]
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":
@@ -260,7 +270,16 @@ class BIMProjectProperties(PropertyGroup):
active_link_index: IntProperty(name="Active Link Index") active_link_index: IntProperty(name="Active Link Index")
export_schema: EnumProperty(items=get_export_schema, name="IFC Schema", update=update_export_schema) export_schema: EnumProperty(items=get_export_schema, name="IFC Schema", update=update_export_schema)
template_file: EnumProperty(items=get_template_file, name="Template File") template_file: EnumProperty(items=get_template_file, name="Template File")
# Project library UI.
library_file: EnumProperty(items=get_library_file, name="Library File", update=update_library_file) library_file: EnumProperty(items=get_library_file, name="Library File", update=update_library_file)
selected_project_library: EnumProperty(
items=get_project_libaries,
name="Project Library",
description="Project library to display elements from",
update=update_selected_project_library,
)
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)
queried_obj_root: bpy.props.PointerProperty(type=bpy.types.Object) queried_obj_root: bpy.props.PointerProperty(type=bpy.types.Object)
@@ -317,7 +336,10 @@ class BIMProjectProperties(PropertyGroup):
active_link_index: int active_link_index: int
export_schema: str export_schema: str
template_file: str template_file: str
library_file: str library_file: str
selected_project_library: Union[Literal["*", "-"], 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]
queried_obj_root: Union[bpy.types.Object, None] queried_obj_root: Union[bpy.types.Object, None]
@@ -367,6 +367,7 @@ class BIM_PT_project_library(Panel):
row = self.layout.row() row = self.layout.row()
row.label(text="No Assets Found", icon="ERROR") row.label(text="No Assets Found", icon="ERROR")
return return
self.layout.prop(self.props, "selected_project_library", text="")
row = self.layout.row(align=True) row = self.layout.row(align=True)
row.label(text=self.props.active_library_element or "Top Level Assets") row.label(text=self.props.active_library_element or "Top Level Assets")
if self.props.active_library_element: if self.props.active_library_element:
+40 -1
View File
@@ -34,7 +34,7 @@ import bonsai.tool as tool
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
from ifcopenshell.api.project.append_asset import APPENDABLE_ASSET_TYPES from ifcopenshell.api.project.append_asset import APPENDABLE_ASSET_TYPES
from pathlib import Path from pathlib import Path
from typing import Optional, Union, TYPE_CHECKING from typing import Optional, Union, TYPE_CHECKING, Generator, Callable
if TYPE_CHECKING: if TYPE_CHECKING:
from bonsai.bim.module.project.prop import BIMProjectProperties from bonsai.bim.module.project.prop import BIMProjectProperties
@@ -294,3 +294,42 @@ class Project(bonsai.core.tool.Project):
if references_to_remove: if references_to_remove:
for reference in references_to_remove: for reference in references_to_remove:
ifcopenshell.api.document.remove_reference(ifc_file, reference) ifcopenshell.api.document.remove_reference(ifc_file, reference)
@classmethod
def get_filter_for_active_library(
cls,
) -> Callable[[list[ifcopenshell.entity_instance]], Generator[ifcopenshell.entity_instance, None, None]]:
props = cls.get_project_props()
library_file = IfcStore.library_file
assert library_file
if props.selected_project_library == "*":
def condition(elements: list[ifcopenshell.entity_instance]):
yield from elements
elif props.selected_project_library == "-":
def condition(elements: list[ifcopenshell.entity_instance]):
for element in elements:
if not getattr(element, "HasContext", False):
yield element
else:
project_library = library_file.by_id(int(props.selected_project_library))
project_library_rels = set(project_library.Declares)
if project_library_rels:
def condition(elements: list[ifcopenshell.entity_instance]):
for element in elements:
for rel in getattr(element, "HasContext", ()):
if rel in project_library_rels:
yield element
break
else:
def condition(elements: list[ifcopenshell.entity_instance]):
pass
return condition