AuthoringData.data["relating_type_data"]

Simplify lots of data keys to just one dictionary relating_type_data, so it will be easier to maintain it and update if needed.
This commit is contained in:
Andrej730
2025-02-25 11:18:54 +05:00
parent dcc681ac74
commit b49cc6c5e9
6 changed files with 44 additions and 74 deletions
@@ -136,8 +136,8 @@ class CoveringToolUI:
if AuthoringData.data["ifc_classes"]: if AuthoringData.data["ifc_classes"]:
if cls.props.ifc_class: if cls.props.ifc_class:
box = cls.layout.box() box = cls.layout.box()
if AuthoringData.data["type_thumbnail"]: if thumbnail := AuthoringData.data["relating_type_data"].get("thumbnail"):
box.template_icon(icon_value=AuthoringData.data["type_thumbnail"], scale=5) box.template_icon(icon_value=thumbnail, scale=5)
else: else:
op = box.operator("bim.load_type_thumbnails", text="Load Thumbnails", icon="FILE_REFRESH") op = box.operator("bim.load_type_thumbnails", text="Load Thumbnails", icon="FILE_REFRESH")
op.ifc_class = cls.props.ifc_class op.ifc_class = cls.props.ifc_class
@@ -175,14 +175,14 @@ class Hotkey(bpy.types.Operator, tool.Ifc.Operator):
element = tool.Ifc.get_entity(active_obj) element = tool.Ifc.get_entity(active_obj)
container = tool.Root.get_default_container() container = tool.Root.get_default_container()
if AuthoringData.data["predefined_type"] == "FLOORING": if AuthoringData.data["relating_type_data"].get("predefined_type") == "FLOORING":
if element and bpy.context.selected_objects and element.is_a("IfcWall"): if element and bpy.context.selected_objects and element.is_a("IfcWall"):
bpy.ops.bim.add_instance_flooring_coverings_from_walls() bpy.ops.bim.add_instance_flooring_coverings_from_walls()
elif container: elif container:
bpy.ops.bim.add_instance_flooring_covering_from_cursor() bpy.ops.bim.add_instance_flooring_covering_from_cursor()
else: else:
bpy.ops.bim.add_constr_type_instance() bpy.ops.bim.add_constr_type_instance()
elif AuthoringData.data["predefined_type"] == "CEILING": elif AuthoringData.data["relating_type_data"].get("predefined_type") == "CEILING":
if element and bpy.context.selected_objects and element.is_a("IfcWall"): if element and bpy.context.selected_objects and element.is_a("IfcWall"):
bpy.ops.bim.add_instance_ceiling_coverings_from_walls() bpy.ops.bim.add_instance_ceiling_coverings_from_walls()
elif container: elif container:
+28 -55
View File
@@ -26,7 +26,7 @@ from ifcopenshell.util.doc import get_entity_doc, get_predefined_type_doc
import bonsai.tool as tool import bonsai.tool as tool
from math import degrees from math import degrees
from natsort import natsorted from natsort import natsorted
from typing import Union, Optional from typing import Union, Optional, Any
def refresh(): def refresh():
@@ -43,7 +43,7 @@ def refresh():
class AuthoringData: class AuthoringData:
data = {} data = {}
type_thumbnails = {} type_thumbnails: dict[int, int] = {}
types_per_page = 9 types_per_page = 9
is_loaded = False is_loaded = False
@@ -58,13 +58,10 @@ class AuthoringData:
# Make sure .ifc_classes() was run before next lines # Make sure .ifc_classes() was run before next lines
cls.data["type_elements"] = cls.type_elements() cls.data["type_elements"] = cls.type_elements()
cls.data["type_elements_filtered"] = cls.type_elements_filtered() cls.data["type_elements_filtered"] = cls.type_elements_filtered()
# After .type_elements().
cls.data["relating_type_id"] = cls.relating_type_id() cls.data["relating_type_id"] = cls.relating_type_id()
# Make sure .relating_type_id() was run before next lines # Make sure .relating_type_id() was run before next lines
cls.data["relating_type_id_current"] = cls.relating_type_id_current() cls.data["relating_type_data"] = cls.relating_type_data()
cls.data["relating_type_name"] = cls.relating_type_name()
cls.data["relating_type_description"] = cls.relating_type_description()
cls.data["relating_type_material_usage"] = cls.relating_type_material_usage()
cls.data["predefined_type"] = cls.predefined_type()
# Make sure .type_elements_filtered() was run before next lines # Make sure .type_elements_filtered() was run before next lines
cls.data["total_types"] = cls.total_types() cls.data["total_types"] = cls.total_types()
cls.data["total_pages"] = cls.total_pages() # Only after .total_types() cls.data["total_pages"] = cls.total_pages() # Only after .total_types()
@@ -72,7 +69,6 @@ class AuthoringData:
cls.data["prev_page"] = cls.prev_page() cls.data["prev_page"] = cls.prev_page()
cls.data["paginated_relating_types"] = cls.paginated_relating_types() cls.data["paginated_relating_types"] = cls.paginated_relating_types()
cls.data["type_thumbnail"] = cls.type_thumbnail() # Only after .relating_type_id_current()
cls.data["materials"] = cls.materials() cls.data["materials"] = cls.materials()
cls.data["is_voidable_element"] = cls.is_voidable_element() cls.data["is_voidable_element"] = cls.is_voidable_element()
cls.data["has_visible_openings"] = cls.has_visible_openings() cls.data["has_visible_openings"] = cls.has_visible_openings()
@@ -109,10 +105,6 @@ class AuthoringData:
version = tool.Ifc.get_schema() version = tool.Ifc.get_schema()
return [(c, c, get_entity_doc(version, c).get("description", "")) for c in sorted(names)] return [(c, c, get_entity_doc(version, c).get("description", "")) for c in sorted(names)]
@classmethod
def type_thumbnail(cls):
return cls.type_thumbnails.get(int(cls.data["relating_type_id_current"] or 0), 0)
@classmethod @classmethod
def materials(cls): def materials(cls):
results = [("0", "None", "No material")] results = [("0", "None", "No material")]
@@ -150,7 +142,7 @@ class AuthoringData:
def type_elements_filtered(cls): def type_elements_filtered(cls):
search_query = cls.props.search_name.lower() search_query = cls.props.search_name.lower()
def filter_element(element): def filter_element(element: ifcopenshell.entity_instance) -> bool:
if search_query in (element.Name or "Unnamed").lower(): if search_query in (element.Name or "Unnamed").lower():
return True return True
if search_query in (element.Description or "").lower(): if search_query in (element.Description or "").lower():
@@ -170,21 +162,24 @@ class AuthoringData:
elements = cls.data["type_elements_filtered"] elements = cls.data["type_elements_filtered"]
elements = elements[(cls.props.type_page - 1) * cls.types_per_page : cls.props.type_page * cls.types_per_page] elements = elements[(cls.props.type_page - 1) * cls.types_per_page : cls.props.type_page * cls.types_per_page]
for element in elements: for element in elements:
predefined_type = ifcopenshell.util.element.get_predefined_type(element) results.append(cls.get_type_data(element))
if predefined_type == "NOTDEFINED":
predefined_type = None
results.append(
{
"id": element.id(),
"ifc_class": element.is_a(),
"name": element.Name or "Unnamed",
"description": element.Description or "No Description",
"predefined_type": predefined_type,
"icon_id": cls.type_thumbnails.get(element.id(), None) or 0,
}
)
return results return results
@classmethod
def get_type_data(cls, element: ifcopenshell.entity_instance) -> dict[str, Any]:
predefined_type = ifcopenshell.util.element.get_predefined_type(element)
if predefined_type == "NOTDEFINED":
predefined_type = None
data = {
"id": element.id(),
"ifc_class": element.is_a(),
"name": element.Name or "Unnamed",
"description": element.Description or "No Description",
"predefined_type": predefined_type,
"icon_id": cls.type_thumbnails.get(element.id(), 0),
}
return data
@classmethod @classmethod
def is_voidable_element(cls): def is_voidable_element(cls):
if active_object := tool.Blender.get_active_object(): if active_object := tool.Blender.get_active_object():
@@ -313,38 +308,16 @@ class AuthoringData:
return [(str(e.id()), e.Name or "Unnamed", e.Description or "") for e in elements] return [(str(e.id()), e.Name or "Unnamed", e.Description or "") for e in elements]
@classmethod @classmethod
def relating_type_id_current(cls): def relating_type_data(cls) -> dict[str, Any]:
relating_type_id = tool.Blender.get_enum_safe(cls.props, "relating_type_id") relating_type_id = tool.Blender.get_enum_safe(cls.props, "relating_type_id")
relating_type_id_data = cls.data["relating_type_id"] relating_type_id_data = cls.data["relating_type_id"]
if not relating_type_id and relating_type_id_data:
relating_type_id = relating_type_id_data[0][0]
return relating_type_id
@classmethod
def relating_type_name(cls):
if relating_type_id := cls.data["relating_type_id_current"]:
return tool.Ifc.get().by_id(int(relating_type_id)).Name or "Unnamed"
@classmethod
def relating_type_description(cls):
if relating_type_id := cls.data["relating_type_id_current"]:
return tool.Ifc.get().by_id(int(relating_type_id)).Description or "No description"
@classmethod
def relating_type_material_usage(cls):
if relating_type_id := cls.data["relating_type_id_current"]:
return tool.Model.get_usage_type(tool.Ifc.get().by_id(int(relating_type_id)))
@classmethod
def predefined_type(cls):
relating_type_id = tool.Blender.get_enum_safe(cls.props, "relating_type_id")
if relating_type_id is None: if relating_type_id is None:
return if not relating_type_id_data:
relating_type = tool.Ifc.get().by_id(int(relating_type_id)) return {}
if not hasattr(relating_type, "PredefinedType"): relating_type_id = relating_type_id_data[0][0]
return ifc_file = tool.Ifc.get()
predefined_type = relating_type.PredefinedType relating_type = ifc_file.by_id(int(relating_type_id))
return predefined_type return cls.get_type_data(relating_type)
@classmethod @classmethod
def selected_material_usages(cls): def selected_material_usages(cls):
@@ -646,8 +646,8 @@ class LoadTypeThumbnails(bpy.types.Operator):
queue = queue[offset : offset + 9] queue = queue[offset : offset + 9]
# The active type may be in another page than the active one : # The active type may be in another page than the active one :
if relating_type_id_current := AuthoringData.data["relating_type_id_current"]: if relating_type_id_current := AuthoringData.data["relating_type_data"].get("id"):
active_element = tool.Ifc.get_entity_by_id(int(relating_type_id_current)) active_element = tool.Ifc.get_entity_by_id(relating_type_id_current)
if active_element and active_element not in queue: if active_element and active_element not in queue:
queue.append(active_element) queue.append(active_element)
+2 -4
View File
@@ -60,7 +60,7 @@ def update_ifc_class(self, context):
AuthoringData.data["ifc_class_current"] = self.ifc_class AuthoringData.data["ifc_class_current"] = self.ifc_class
AuthoringData.data["type_elements"] = AuthoringData.type_elements() AuthoringData.data["type_elements"] = AuthoringData.type_elements()
AuthoringData.data["relating_type_id"] = AuthoringData.relating_type_id() AuthoringData.data["relating_type_id"] = AuthoringData.relating_type_id()
AuthoringData.data["type_thumbnail"] = AuthoringData.type_thumbnail() AuthoringData.data["relating_type_data"] = AuthoringData.relating_type_data()
if tool.Blender.get_enum_safe(self, "relating_type_id") is None: if tool.Blender.get_enum_safe(self, "relating_type_id") is None:
self["relating_type_id"] = 0 self["relating_type_id"] = 0
@@ -73,9 +73,7 @@ def update_ifc_class(self, context):
def update_relating_type_id(self, context): def update_relating_type_id(self, context):
AuthoringData.data["relating_type_id"] = AuthoringData.relating_type_id() AuthoringData.data["relating_type_id"] = AuthoringData.relating_type_id()
AuthoringData.data["relating_type_name"] = AuthoringData.relating_type_name() AuthoringData.data["relating_type_data"] = AuthoringData.relating_type_data()
AuthoringData.data["type_thumbnail"] = AuthoringData.type_thumbnail()
AuthoringData.data["predefined_type"] = AuthoringData.predefined_type()
self.type_page = [e[0] for e in AuthoringData.data["relating_type_id"]].index(self.relating_type_id) // 9 + 1 self.type_page = [e[0] for e in AuthoringData.data["relating_type_id"]].index(self.relating_type_id) // 9 + 1
+1 -3
View File
@@ -166,9 +166,7 @@ class LaunchTypeManager(bpy.types.Operator):
row2.operator("bim.set_active_type", text="", emboss=False).relating_type = relating_type["id"] row2.operator("bim.set_active_type", text="", emboss=False).relating_type = relating_type["id"]
row2.operator("bim.set_active_type", text="", emboss=False).relating_type = relating_type["id"] row2.operator("bim.set_active_type", text="", emboss=False).relating_type = relating_type["id"]
row2.operator("bim.set_active_type", text="", emboss=False).relating_type = relating_type["id"] row2.operator("bim.set_active_type", text="", emboss=False).relating_type = relating_type["id"]
is_current_relating_type = str(relating_type["id"]) == str( is_current_relating_type = relating_type["id"] == AuthoringData.data["relating_type_data"].get("id")
AuthoringData.data["relating_type_id_current"]
)
if is_current_relating_type: if is_current_relating_type:
active_row = row2.row() active_row = row2.row()
active_row.alignment = "CENTER" active_row.alignment = "CENTER"
@@ -674,12 +674,13 @@ class CreateObjectUI:
if not (ifc_class := AuthoringData.data["ifc_class_current"]): if not (ifc_class := AuthoringData.data["ifc_class_current"]):
return return
relating_type_data = AuthoringData.data["relating_type_data"]
box = cls.layout.box() box = cls.layout.box()
row = box.row(align=True) row = box.row(align=True)
thumbnail: int = AuthoringData.data["type_thumbnail"] thumbnail: int = relating_type_data["icon_id"]
row.template_icon(icon_value=thumbnail) row.template_icon(icon_value=thumbnail)
row.operator("bim.launch_type_manager", text=AuthoringData.data["relating_type_name"], emboss=False) row.operator("bim.launch_type_manager", text=relating_type_data["name"], emboss=False)
row.operator( row.operator(
"bim.launch_type_manager", "bim.launch_type_manager",
icon=tool.Blender.TYPE_MANAGER_ICON, icon=tool.Blender.TYPE_MANAGER_ICON,
@@ -693,7 +694,7 @@ class CreateObjectUI:
row.alignment = "CENTER" row.alignment = "CENTER"
row.operator( row.operator(
"bim.launch_type_manager", "bim.launch_type_manager",
text=AuthoringData.data["relating_type_description"], text=relating_type_data["description"],
emboss=False, emboss=False,
) )
@@ -718,7 +719,7 @@ class CreateObjectUI:
row.alignment = "CENTER" row.alignment = "CENTER"
row.operator( row.operator(
"bim.launch_type_manager", "bim.launch_type_manager",
text=AuthoringData.data["predefined_type"], text=AuthoringData.data["relating_type_data"].get("predefined_type"),
emboss=False, emboss=False,
) )
@@ -870,7 +871,7 @@ class EditObjectUI:
) )
row = cls.layout.row(align=True) if ui_context != "TOOL_HEADER" else row row = cls.layout.row(align=True) if ui_context != "TOOL_HEADER" else row
add_layout_hotkey_operator(row, "Rotate 90", "S_R", "Rotate the selected Element by 90 degrees", ui_context) add_layout_hotkey_operator(row, "Rotate 90", "S_R", "Rotate the selected Element by 90 degrees", ui_context)
if AuthoringData.data["relating_type_material_usage"] == "LAYER3": if AuthoringData.data["relating_type_data"].get("usage") == "LAYER3":
row = cls.layout.row(align=True) if ui_context != "TOOL_HEADER" else row row = cls.layout.row(align=True) if ui_context != "TOOL_HEADER" else row
add_layout_hotkey_operator( add_layout_hotkey_operator(
row, row,
@@ -884,7 +885,7 @@ class EditObjectUI:
if "LAYER2" in AuthoringData.data["selected_material_usages"]: if "LAYER2" in AuthoringData.data["selected_material_usages"]:
row = cls.layout.row(align=True) if ui_context != "TOOL_HEADER" else row row = cls.layout.row(align=True) if ui_context != "TOOL_HEADER" else row
add_layout_hotkey_operator(cls.layout, "Extend Wall To Slab", "S_E", "", ui_context) add_layout_hotkey_operator(cls.layout, "Extend Wall To Slab", "S_E", "", ui_context)
if AuthoringData.data["relating_type_material_usage"] == "LAYER2": if AuthoringData.data["relating_type_data"].get("usage") == "LAYER2":
row = cls.layout.row(align=True) if ui_context != "TOOL_HEADER" else row row = cls.layout.row(align=True) if ui_context != "TOOL_HEADER" else row
add_layout_hotkey_operator( add_layout_hotkey_operator(
row, row,