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):
cls.data = {}
cls.data["project_libraries"] = cls.project_libraries()
# After .project_libraries().
cls.data["project_libraries_enum"] = cls.project_libraries_enum()
cls.is_loaded = True
@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}
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:
linked_data = {}
@@ -214,10 +214,15 @@ class RefreshLibrary(bpy.types.Operator):
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()):
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.name = importable_type
return {"FINISHED"}
@@ -225,7 +230,7 @@ class ChangeLibraryElement(bpy.types.Operator):
bl_idname = "bim.change_library_element"
bl_label = "Change Library Element"
bl_options = {"REGISTER", "UNDO"}
element_name: bpy.props.StringProperty()
element_name: bpy.props.StringProperty(description="IFC class to select")
if TYPE_CHECKING:
element_name: str
@@ -242,7 +247,9 @@ class ChangeLibraryElement(bpy.types.Operator):
crumb = self.props.library_breadcrumb.add()
crumb.name = self.element_name
filter_elements = tool.Project.get_filter_for_active_library()
elements = self.library_file.by_type(self.element_name)
elements = list(filter_elements(elements))
[ifc_classes.add(e.is_a()) for e in elements]
self.props.library_elements.clear()
+23 -1
View File
@@ -21,7 +21,7 @@ import bpy
import ifcopenshell.util.element
import ifcopenshell.util.placement
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.prop import StrProperty, ObjProperty
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__())
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:
self.filter_categories.clear()
if self.filter_mode == "NONE":
@@ -260,7 +270,16 @@ class BIMProjectProperties(PropertyGroup):
active_link_index: IntProperty(name="Active Link Index")
export_schema: EnumProperty(items=get_export_schema, name="IFC Schema", update=update_export_schema)
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)
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)
queried_obj: 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
export_schema: str
template_file: str
library_file: str
selected_project_library: Union[Literal["*", "-"], str]
use_relative_project_path: bool
queried_obj: 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.label(text="No Assets Found", icon="ERROR")
return
self.layout.prop(self.props, "selected_project_library", text="")
row = self.layout.row(align=True)
row.label(text=self.props.active_library_element or "Top Level Assets")
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 ifcopenshell.api.project.append_asset import APPENDABLE_ASSET_TYPES
from pathlib import Path
from typing import Optional, Union, TYPE_CHECKING
from typing import Optional, Union, TYPE_CHECKING, Generator, Callable
if TYPE_CHECKING:
from bonsai.bim.module.project.prop import BIMProjectProperties
@@ -294,3 +294,42 @@ class Project(bonsai.core.tool.Project):
if references_to_remove:
for reference in references_to_remove:
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