From a48d7743378e827b9e4c3c8e9b3418918597722e Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Mon, 3 Feb 2025 12:53:08 +0500 Subject: [PATCH] typing --- .../bonsai/bim/module/drawing/__init__.py | 2 +- .../bonsai/bim/module/drawing/operator.py | 2 +- src/bonsai/bonsai/bim/module/drawing/prop.py | 68 +++++++++++++- .../bonsai/bim/module/geometry/operator.py | 12 +-- src/bonsai/bonsai/bim/module/geometry/prop.py | 12 ++- .../bonsai/bim/module/project/operator.py | 2 +- .../bonsai/bim/module/system/operator.py | 10 +- src/bonsai/bonsai/bim/module/system/prop.py | 19 ++++ src/bonsai/bonsai/bim/module/system/ui.py | 4 +- src/bonsai/bonsai/core/system.py | 44 +++++---- src/bonsai/bonsai/tool/drawing.py | 30 +++--- src/bonsai/bonsai/tool/geometry.py | 6 +- src/bonsai/bonsai/tool/system.py | 92 ++++++++++++------- 13 files changed, 222 insertions(+), 81 deletions(-) diff --git a/src/bonsai/bonsai/bim/module/drawing/__init__.py b/src/bonsai/bonsai/bim/module/drawing/__init__.py index 83dd36f5ce..a98d5038e8 100644 --- a/src/bonsai/bonsai/bim/module/drawing/__init__.py +++ b/src/bonsai/bonsai/bim/module/drawing/__init__.py @@ -100,7 +100,7 @@ classes = ( prop.Sheet, prop.DocProperties, prop.BIMCameraProperties, - prop.Literal, + prop.LiteralProps, prop.BIMTextProperties, prop.BIMAssignedProductProperties, prop.BIMAnnotationProperties, diff --git a/src/bonsai/bonsai/bim/module/drawing/operator.py b/src/bonsai/bonsai/bim/module/drawing/operator.py index 27e4f5d332..534e8c4ab1 100644 --- a/src/bonsai/bonsai/bim/module/drawing/operator.py +++ b/src/bonsai/bonsai/bim/module/drawing/operator.py @@ -1686,7 +1686,7 @@ class RemoveDrawingFromSheet(bpy.types.Operator, tool.Ifc.Operator): return False if active_item.reference_type == "TITLEBLOCK": - cls.poll_message_set("No effect deleting this.") + cls.poll_message_set("No effect deleting titleblock reference.") return False return True diff --git a/src/bonsai/bonsai/bim/module/drawing/prop.py b/src/bonsai/bonsai/bim/module/drawing/prop.py index 594d34757c..5fc5769c30 100644 --- a/src/bonsai/bonsai/bim/module/drawing/prop.py +++ b/src/bonsai/bonsai/bim/module/drawing/prop.py @@ -44,6 +44,7 @@ from bpy.props import ( CollectionProperty, BoolVectorProperty, ) +from typing import TYPE_CHECKING, Literal diagram_scales_enum = [] @@ -294,12 +295,25 @@ class Drawing(PropertyGroup): is_drawing: BoolProperty(name="Is Drawing", default=False) is_expanded: BoolProperty(name="Is Expanded", default=True) + if TYPE_CHECKING: + ifc_definition_id: int + name: str + target_view: str + is_selected: bool + is_drawing: bool + is_expanded: bool + class Document(PropertyGroup): ifc_definition_id: IntProperty(name="IFC Definition ID") name: StringProperty(name="Name", update=update_document_name) identification: StringProperty(name="Identification") + if TYPE_CHECKING: + ifc_definition_id: int + name: str + identification: str + class Sheet(PropertyGroup): ifc_definition_id: IntProperty(name="IFC Definition ID") @@ -310,6 +324,15 @@ class Sheet(PropertyGroup): reference_type: StringProperty(name="Reference Type") is_expanded: BoolProperty(name="Is Expanded", default=False) + if TYPE_CHECKING: + ifc_definition_id: int + identification: str + name: str + is_sheet: bool + is_selected: bool + reference_type: str + is_expanded: bool + class DrawingStyle(PropertyGroup): name: StringProperty(name="Name", get=get_drawing_style_name, set=set_drawing_style_name) @@ -408,6 +431,47 @@ class DocProperties(PropertyGroup): description="Upon import, these classes will display as wireframe.\nEx: IfcVirtualelement, IfcSpace", ) + if TYPE_CHECKING: + should_use_underlay_cache: bool + should_use_linework_cache: bool + should_use_annotation_cache: bool + is_editing_drawings: bool + is_editing_schedules: bool + is_editing_references: bool + target_view: Literal["PLAN_VIEW", "ELEVATION_VIEW", "SECTION_VIEW", "REFLECTED_PLAN_VIEW", "MODEL_VIEW"] + location_hint: str + drawings: bpy.types.bpy_prop_collection_idprop[Drawing] + active_drawing_id: int + active_drawing_index: int + current_drawing_index: int + schedules: bpy.types.bpy_prop_collection_idprop[Document] + active_schedule_index: int + references: bpy.types.bpy_prop_collection_idprop[Document] + active_reference_index: int + titleblock: str + is_editing_sheets: bool + sheets: bpy.types.bpy_prop_collection_idprop[Sheet] + active_sheet_index: int + ifc_files: bpy.types.bpy_prop_collection_idprop[StrProperty] + drawing_styles: bpy.types.bpy_prop_collection_idprop[DrawingStyle] + should_draw_decorations: bool + sheets_dir: str + layouts_dir: str + titleblocks_dir: str + drawings_dir: str + stylesheet_path: str + schedules_stylesheet_path: str + markers_path: str + symbols_path: str + patterns_path: str + shadingstyles_path: str + shadingstyle_default: str + drawing_font: str + magic_font_scale: float + imperial_precision: str + tolerance: float + classes_to_wireframe: str + class BIMCameraProperties(PropertyGroup): linework_mode: EnumProperty( @@ -490,7 +554,7 @@ BOX_ALIGNMENT_POSITIONS = [ ] -class Literal(PropertyGroup): +class LiteralProps(PropertyGroup): def set_box_alignment(self, new_value): markers = new_value.count(True) if not markers: @@ -535,7 +599,7 @@ class Literal(PropertyGroup): class BIMTextProperties(PropertyGroup): is_editing: BoolProperty(name="Is Editing", default=False) - literals: CollectionProperty(name="Literals", type=Literal) + literals: CollectionProperty(name="Literals", type=LiteralProps) font_size: EnumProperty( items=[ ("1.8", "1.8 - Small", ""), diff --git a/src/bonsai/bonsai/bim/module/geometry/operator.py b/src/bonsai/bonsai/bim/module/geometry/operator.py index c1380fced9..ff12939e0c 100644 --- a/src/bonsai/bonsai/bim/module/geometry/operator.py +++ b/src/bonsai/bonsai/bim/module/geometry/operator.py @@ -1075,7 +1075,7 @@ class OverrideDuplicateMove(bpy.types.Operator): @staticmethod def duplicate_item(obj: bpy.types.Object) -> None: - props = bpy.context.scene.BIMGeometryProperties + props = tool.Geometry.get_geometry_props() item = tool.Ifc.get().by_id(obj.data.BIMMeshProperties.ifc_definition_id) new_item = ifcopenshell.util.element.copy_deep(tool.Ifc.get(), item) new_obj = obj.copy() @@ -2750,17 +2750,17 @@ class ImportRepresentationItems(bpy.types.Operator, tool.Ifc.Operator): def _execute(self, context): obj = context.active_object assert obj - props = context.scene.BIMGeometryProperties + props = tool.Geometry.get_geometry_props() if previous_obj := props.representation_obj: previous_obj.hide_set(False) props.representation_obj = obj obj.hide_set(True) tool.Geometry.lock_object(obj) - context.scene.BIMGeometryProperties.is_changing_mode = True - if context.scene.BIMGeometryProperties.mode != "ITEM": - context.scene.BIMGeometryProperties.mode = "ITEM" - context.scene.BIMGeometryProperties.is_changing_mode = False + props.is_changing_mode = True + if props.mode != "ITEM": + props.mode = "ITEM" + props.is_changing_mode = False tool.Loader.load_settings() diff --git a/src/bonsai/bonsai/bim/module/geometry/prop.py b/src/bonsai/bonsai/bim/module/geometry/prop.py index 12d84ebb20..2ab4ec5efe 100644 --- a/src/bonsai/bonsai/bim/module/geometry/prop.py +++ b/src/bonsai/bonsai/bim/module/geometry/prop.py @@ -32,7 +32,7 @@ from bpy.props import ( FloatVectorProperty, CollectionProperty, ) -from typing import Optional, TYPE_CHECKING +from typing import Optional, TYPE_CHECKING, Union def get_contexts(self, context): @@ -302,3 +302,13 @@ class BIMGeometryProperties(PropertyGroup): type=bpy.types.Object, poll=is_object_valid_for_representation_copy, ) + + if TYPE_CHECKING: + should_use_presentation_style_assignment: bool + should_force_faceted_brep: bool + should_force_triangulation: bool + is_changing_mode: bool + mode: str + representation_obj: Union[bpy.types.Object, None] + item_objs: bpy.types.bpy_prop_collection_idprop[RepresentationItemObject] + representation_from_object: Union[bpy.types.Object, None] diff --git a/src/bonsai/bonsai/bim/module/project/operator.py b/src/bonsai/bonsai/bim/module/project/operator.py index 20eb4a1f5d..5c22da6d8c 100644 --- a/src/bonsai/bonsai/bim/module/project/operator.py +++ b/src/bonsai/bonsai/bim/module/project/operator.py @@ -1243,7 +1243,7 @@ class LoadLink(bpy.types.Operator): os.remove(blend_filepath) if not blend_filepath.exists(): - pprops = bpy.context.scene.BIMProjectProperties + pprops = tool.Project.get_project_props() gprops = bpy.context.scene.BIMGeoreferenceProperties code = f""" diff --git a/src/bonsai/bonsai/bim/module/system/operator.py b/src/bonsai/bonsai/bim/module/system/operator.py index ab93f43c4f..4ef3c255f7 100644 --- a/src/bonsai/bonsai/bim/module/system/operator.py +++ b/src/bonsai/bonsai/bim/module/system/operator.py @@ -337,7 +337,7 @@ class LoadZones(bpy.types.Operator): bl_options = {"REGISTER", "UNDO"} def _execute(self, context): - props = bpy.context.scene.BIMZoneProperties + props = tool.System.get_zone_props() props.zones.clear() for zone in tool.Ifc.get().by_type("IfcZone"): new = props.zones.add() @@ -354,7 +354,7 @@ class UnloadZones(bpy.types.Operator): bl_options = {"REGISTER", "UNDO"} def _execute(self, context): - props = bpy.context.scene.BIMZoneProperties + props = tool.System.get_zone_props() props.is_loaded = False return {"FINISHED"} @@ -386,7 +386,7 @@ class EnableEditingZone(bpy.types.Operator): zone: bpy.props.IntProperty() def execute(self, context): - props = bpy.context.scene.BIMZoneProperties + props = tool.System.get_zone_props() props.attributes.clear() bonsai.bim.helper.import_attributes2(tool.Ifc.get().by_id(self.zone), props.attributes) props.is_editing = self.zone @@ -399,7 +399,7 @@ class DisableEditingZone(bpy.types.Operator, tool.Ifc.Operator): bl_options = {"REGISTER", "UNDO"} def execute(self, context): - props = bpy.context.scene.BIMZoneProperties + props = tool.System.get_zone_props() props.is_editing = 0 return {"FINISHED"} @@ -410,7 +410,7 @@ class EditZone(bpy.types.Operator, tool.Ifc.Operator): bl_options = {"REGISTER", "UNDO"} def _execute(self, context): - props = bpy.context.scene.BIMZoneProperties + props = tool.System.get_zone_props() zone = tool.Ifc.get().by_id(props.is_editing) attributes = bonsai.bim.helper.export_attributes(props.attributes) ifcopenshell.api.run("system.edit_system", tool.Ifc.get(), system=zone, attributes=attributes) diff --git a/src/bonsai/bonsai/bim/module/system/prop.py b/src/bonsai/bonsai/bim/module/system/prop.py index 91586a2224..3e14bf74e5 100644 --- a/src/bonsai/bonsai/bim/module/system/prop.py +++ b/src/bonsai/bonsai/bim/module/system/prop.py @@ -31,6 +31,7 @@ from bpy.props import ( FloatVectorProperty, CollectionProperty, ) +from typing import TYPE_CHECKING def get_system_class(self, context): @@ -71,6 +72,17 @@ class BIMSystemProperties(PropertyGroup): name="Should Draw Decorations", description="Toggle system decorations", update=toggle_decorations ) + if TYPE_CHECKING: + system_attributes: bpy.types.bpy_prop_collection_idprop[Attribute] + is_editing: bool + is_adding: bool + systems: bpy.types.bpy_prop_collection_idprop[System] + active_system_index: int + active_system_id: int + edited_system_id: int + system_class: str + should_draw_decorations: bool + class BIMZoneProperties(PropertyGroup): attributes: CollectionProperty(name="Attributes", type=Attribute) @@ -78,3 +90,10 @@ class BIMZoneProperties(PropertyGroup): is_editing: IntProperty(name="Is Editing", default=0) zones: CollectionProperty(name="Zones", type=Zone) active_zone_index: IntProperty(name="Active Zone Index") + + if TYPE_CHECKING: + attributes: bpy.types.bpy_prop_collection_idprop[Attribute] + is_loaded: bool + is_editing: int + zones: bpy.types.bpy_prop_collection_idprop[Zone] + active_zone_index: int diff --git a/src/bonsai/bonsai/bim/module/system/ui.py b/src/bonsai/bonsai/bim/module/system/ui.py index 2bd49feb7d..b09181c327 100644 --- a/src/bonsai/bonsai/bim/module/system/ui.py +++ b/src/bonsai/bonsai/bim/module/system/ui.py @@ -350,7 +350,7 @@ class BIM_PT_zones(Panel): def draw(self, context): if not ZonesData.is_loaded: ZonesData.load() - self.props = context.scene.BIMZoneProperties + self.props = tool.System.get_zone_props() row = self.layout.row(align=True) row.label(text="{} Zones Found".format(ZonesData.data["total_zones"]), icon="SEQ_STRIP_META") @@ -394,7 +394,7 @@ class BIM_PT_active_object_zones(Panel): def draw(self, context): if not ActiveObjectZonesData.is_loaded: ActiveObjectZonesData.load() - self.props = context.scene.BIMZoneProperties + self.props = tool.System.get_zone_props() for zone in ActiveObjectZonesData.data["zones"]: row = self.layout.row() diff --git a/src/bonsai/bonsai/core/system.py b/src/bonsai/bonsai/core/system.py index 7e6d0b7164..2acd1d21d4 100644 --- a/src/bonsai/bonsai/core/system.py +++ b/src/bonsai/bonsai/core/system.py @@ -16,58 +16,68 @@ # You should have received a copy of the GNU General Public License # along with Bonsai. If not, see . +from __future__ import annotations +from typing import TYPE_CHECKING, Optional -def load_systems(system): +if TYPE_CHECKING: + import bpy + import ifcopenshell + import bonsai.tool as tool + + +def load_systems(system: tool.System) -> None: system.import_systems() system.enable_system_editing_ui() system.disable_editing_system() -def disable_system_editing_ui(system): +def disable_system_editing_ui(system: tool.System) -> None: system.disable_editing_system() system.disable_system_editing_ui() -def add_system(ifc, system, ifc_class=None): +def add_system(ifc: tool.Ifc, system: tool.System, ifc_class: str) -> None: ifc.run("system.add_system", ifc_class=ifc_class) system.import_systems() -def edit_system(ifc, system_tool, system=None): +def edit_system(ifc: tool.Ifc, system_tool: tool.System, system: ifcopenshell.entity_instance) -> None: attributes = system_tool.export_system_attributes() ifc.run("system.edit_system", system=system, attributes=attributes) system_tool.disable_editing_system() system_tool.import_systems() -def remove_system(ifc, system_tool, system=None): +def remove_system(ifc: tool.Ifc, system_tool: tool.System, system: ifcopenshell.entity_instance) -> None: ifc.run("system.remove_system", system=system) system_tool.import_systems() -def enable_editing_system(system_tool, system=None): +def enable_editing_system(system_tool: tool.System, system: ifcopenshell.entity_instance) -> None: system_tool.import_system_attributes(system) system_tool.set_active_edited_system(system) -def disable_editing_system(system): +def disable_editing_system(system: tool.System) -> None: system.disable_editing_system() -def assign_system(ifc, system=None, product=None): +def assign_system(ifc: tool.Ifc, system: ifcopenshell.entity_instance, product: ifcopenshell.entity_instance) -> None: ifc.run("system.assign_system", products=[product], system=system) -def unassign_system(ifc, system=None, product=None): +def unassign_system(ifc: tool.Ifc, system: ifcopenshell.entity_instance, product: ifcopenshell.entity_instance) -> None: ifc.run("system.unassign_system", products=[product], system=system) -def select_system_products(system_tool, system=None): +def select_system_products(system_tool: tool.System, system: ifcopenshell.entity_instance) -> None: system_tool.select_system_products(system) system_tool.set_active_system(system) -def show_ports(ifc, system, spatial, element=None): +def show_ports( + ifc: tool.Ifc, system: tool.System, spatial: tool.Spatial, element: ifcopenshell.entity_instance +) -> None: obj = ifc.get_object(element) if obj and ifc.is_moved(obj): system.run_geometry_edit_object_placement(obj=obj) @@ -77,7 +87,7 @@ def show_ports(ifc, system, spatial, element=None): spatial.select_products(ports) -def hide_ports(ifc, system, element=None): +def hide_ports(ifc: tool.Ifc, system: tool.System, element: ifcopenshell.entity_instance) -> None: obj = ifc.get_object(element) if obj and ifc.is_moved(obj): system.run_geometry_edit_object_placement(obj=obj) @@ -91,27 +101,27 @@ def hide_ports(ifc, system, element=None): system.delete_element_objects(ports) -def add_port(ifc, system, element=None): +def add_port(ifc: tool.Ifc, system: tool.System, element: ifcopenshell.entity_instance) -> None: system.load_ports(element, system.get_ports(element)) obj = system.create_empty_at_cursor_with_element_orientation(element) port = system.run_root_assign_class(obj=obj, ifc_class="IfcDistributionPort", should_add_representation=False) ifc.run("system.assign_port", element=element, port=port) -def remove_port(ifc, system, port=None): +def remove_port(ifc: tool.Ifc, system: tool.System, port: ifcopenshell.entity_instance) -> None: system.delete_element_objects([port]) ifc.run("root.remove_product", product=port) -def connect_port(ifc, port1=None, port2=None): +def connect_port(ifc: tool.Ifc, port1: ifcopenshell.entity_instance, port2: ifcopenshell.entity_instance) -> None: ifc.run("system.connect_port", port1=port1, port2=port2) -def disconnect_port(ifc, port=None): +def disconnect_port(ifc: tool.Ifc, port: ifcopenshell.entity_instance) -> None: ifc.run("system.disconnect_port", port=port) -def set_flow_direction(ifc, system, port=None, direction=None): +def set_flow_direction(ifc: tool.Ifc, system: tool.System, port: ifcopenshell.entity_instance, direction: str) -> None: port2 = system.get_connected_port(port) if not port2: return diff --git a/src/bonsai/bonsai/tool/drawing.py b/src/bonsai/bonsai/tool/drawing.py index 5345d073a6..b75717044a 100644 --- a/src/bonsai/bonsai/tool/drawing.py +++ b/src/bonsai/bonsai/tool/drawing.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with Bonsai. If not, see . +from __future__ import annotations import os import re import collections @@ -34,6 +35,7 @@ import subprocess import numpy as np import bonsai.core.tool import bonsai.core.geometry +import bonsai.core.type import bonsai.tool as tool import ifcopenshell.api import ifcopenshell.api.document @@ -49,9 +51,13 @@ from shapely.ops import unary_union from lxml import etree from mathutils import Vector, Matrix from fractions import Fraction -from typing import Optional, Union, Iterable, Any, Literal, Sequence +from typing import Optional, Union, Iterable, Any, Literal, Sequence, TYPE_CHECKING from pathlib import Path +if TYPE_CHECKING: + from bonsai.bim.module.drawing.prop import DocProperties, Sheet + from bonsai.bim.module.drawing.prop import Drawing as DrawingProperties + class Drawing(bonsai.core.tool.Drawing): ANNOTATION_DATA_TYPE = Literal["empty", "curve", "mesh"] @@ -81,6 +87,10 @@ class Drawing(bonsai.core.tool.Drawing): } # fmt: on + @classmethod + def get_document_props(cls) -> DocProperties: + return bpy.context.scene.DocProperties + @classmethod def canonicalise_class_name(cls, name: str) -> str: return re.sub("[^0-9a-zA-Z]+", "", name) @@ -820,7 +830,7 @@ class Drawing(bonsai.core.tool.Drawing): @classmethod def import_documents(cls, document_type: DOCUMENT_TYPE) -> None: - dprops = bpy.context.scene.DocProperties + dprops = cls.get_document_props() if document_type == "SCHEDULE": documents_collection = dprops.schedules elif document_type == "REFERENCE": @@ -839,7 +849,7 @@ class Drawing(bonsai.core.tool.Drawing): @classmethod def import_sheets(cls) -> None: - props = bpy.context.scene.DocProperties + props = cls.get_document_props() expanded_sheets = {s.ifc_definition_id for s in props.sheets if s.is_expanded} if not hasattr(cls, "sheet_selected_states"): cls.sheet_selected_states = {} @@ -879,13 +889,13 @@ class Drawing(bonsai.core.tool.Drawing): new.reference_type = reference_description @classmethod - def get_active_sheet(cls, context: bpy.types.Context) -> bpy.types.PropertyGroup: - props = context.scene.DocProperties + def get_active_sheet(cls, context: bpy.types.Context) -> Sheet: + props = cls.get_document_props() return next(s for s in props.sheets[: props.active_sheet_index + 1][::-1] if s.is_sheet) @classmethod - def get_active_drawing_item(cls) -> Union[bpy.types.PropertyGroup, None]: - props = bpy.context.scene.DocProperties + def get_active_drawing_item(cls) -> Union[DrawingProperties, None]: + props = cls.get_document_props() drawing_index = props.active_drawing_index if len(props.drawings) > drawing_index >= 0: item = props.drawings[drawing_index] @@ -893,10 +903,8 @@ class Drawing(bonsai.core.tool.Drawing): return item @classmethod - def get_active_sheet_item( - cls, *, is_sheet: bool = False, reference_type: str = "" - ) -> Union[bpy.types.PropertyGroup, None]: - props = bpy.context.scene.DocProperties + def get_active_sheet_item(cls, *, is_sheet: bool = False, reference_type: str = "") -> Union[Sheet, None]: + props = cls.get_document_props() sheet_index = props.active_sheet_index if len(props.sheets) > sheet_index >= 0: item = props.sheets[sheet_index] diff --git a/src/bonsai/bonsai/tool/geometry.py b/src/bonsai/bonsai/tool/geometry.py index 133189b184..cc951596e3 100644 --- a/src/bonsai/bonsai/tool/geometry.py +++ b/src/bonsai/bonsai/tool/geometry.py @@ -57,10 +57,14 @@ from typing_extensions import TypeIs if TYPE_CHECKING: from bonsai.bim.prop import Attribute - from bonsai.bim.module.geometry.prop import BIMObjectGeometryProperties + from bonsai.bim.module.geometry.prop import BIMObjectGeometryProperties, BIMGeometryProperties class Geometry(bonsai.core.tool.Geometry): + @classmethod + def get_geometry_props(cls) -> BIMGeometryProperties: + return bpy.context.scene.BIMGeometryProperties + @classmethod def get_object_geometry_props(cls, object: bpy.types.Object) -> BIMObjectGeometryProperties: return object.BIMGeometryProperties diff --git a/src/bonsai/bonsai/tool/system.py b/src/bonsai/bonsai/tool/system.py index d9cf2e517a..51334be3a2 100644 --- a/src/bonsai/bonsai/tool/system.py +++ b/src/bonsai/bonsai/tool/system.py @@ -16,6 +16,7 @@ # You should have received a copy of the GNU General Public License # along with Bonsai. If not, see . +from __future__ import annotations import bpy import ifcopenshell.util.element import ifcopenshell.util.system @@ -31,11 +32,30 @@ from mathutils import Matrix, Vector from bonsai.bim.module.system.data import ObjectSystemData, SystemDecorationData from bonsai.bim.module.drawing.decoration import profile_consequential from enum import Enum +from typing import TYPE_CHECKING, Optional, Any, Union + +if TYPE_CHECKING: + from bonsai.bim.module.system.prop import BIMSystemProperties, BIMZoneProperties class System(bonsai.core.tool.System): @classmethod - def add_ports(cls, obj, add_start_port=True, add_end_port=True, end_port_pos=None, offset_end_port=None): + def get_system_props(cls) -> BIMSystemProperties: + return bpy.context.scene.BIMSystemProperties + + @classmethod + def get_zone_props(cls) -> BIMZoneProperties: + return bpy.context.scene.BIMZoneProperties + + @classmethod + def add_ports( + cls, + obj: bpy.types.Object, + add_start_port: bool = True, + add_end_port: bool = True, + end_port_pos: Optional[Vector] = None, + offset_end_port: Optional[Vector] = None, + ) -> list[ifcopenshell.entity_instance]: def add_port(mep_element, matrix): port = tool.Ifc.run("system.add_port", element=mep_element) port.FlowDirection = "NOTDEFINED" @@ -66,7 +86,7 @@ class System(bonsai.core.tool.System): return ports @classmethod - def create_empty_at_cursor_with_element_orientation(cls, element): + def create_empty_at_cursor_with_element_orientation(cls, element: ifcopenshell.entity_instance) -> bpy.types.Object: element_obj = tool.Ifc.get_object(element) obj = bpy.data.objects.new("Port", None) obj.matrix_world = element_obj.matrix_world @@ -75,38 +95,38 @@ class System(bonsai.core.tool.System): return obj @classmethod - def delete_element_objects(cls, elements): + def delete_element_objects(cls, elements: list[ifcopenshell.entity_instance]) -> None: for element in elements: obj = tool.Ifc.get_object(element) if obj: bpy.data.objects.remove(obj) @classmethod - def disable_editing_system(cls): - bpy.context.scene.BIMSystemProperties.edited_system_id = 0 + def disable_editing_system(cls) -> None: + cls.get_system_props().edited_system_id = 0 @classmethod - def disable_system_editing_ui(cls): - bpy.context.scene.BIMSystemProperties.is_editing = False + def disable_system_editing_ui(cls) -> None: + cls.get_system_props().is_editing = False @classmethod - def enable_system_editing_ui(cls): - bpy.context.scene.BIMSystemProperties.is_editing = True + def enable_system_editing_ui(cls) -> None: + cls.get_system_props().is_editing = True @classmethod - def export_system_attributes(cls): - return bonsai.bim.helper.export_attributes(bpy.context.scene.BIMSystemProperties.system_attributes) + def export_system_attributes(cls) -> dict[str, Any]: + return bonsai.bim.helper.export_attributes(cls.get_system_props().system_attributes) @classmethod - def get_connected_port(cls, port): + def get_connected_port(cls, port: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]: return ifcopenshell.util.system.get_connected_port(port) @classmethod - def get_ports(cls, element): + def get_ports(cls, element: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]: return ifcopenshell.util.system.get_ports(element) @classmethod - def get_port_relating_element(cls, port): + def get_port_relating_element(cls, port: ifcopenshell.entity_instance) -> ifcopenshell.entity_instance: if tool.Ifc.get_schema() == "IFC2X3": element = port.ContainedIn[0].RelatedElement else: @@ -114,7 +134,7 @@ class System(bonsai.core.tool.System): return element @classmethod - def get_port_predefined_type(cls, mep_element): + def get_port_predefined_type(cls, mep_element: ifcopenshell.entity_instance) -> str: split_camel_case = lambda x: re.findall("[A-Z][^A-Z]*", x) mep_class = mep_element.is_a() if mep_class.endswith("Type"): @@ -125,20 +145,20 @@ class System(bonsai.core.tool.System): return class_name @classmethod - def import_system_attributes(cls, system): - props = bpy.context.scene.BIMSystemProperties + def import_system_attributes(cls, system: ifcopenshell.entity_instance) -> None: + props = cls.get_system_props() props.system_attributes.clear() bonsai.bim.helper.import_attributes2(system, props.system_attributes) @classmethod - def get_systems(cls): + def get_systems(cls) -> list[ifcopenshell.entity_instance]: if tool.Ifc.get_schema() == "IFC2X3": return tool.Ifc.get().by_type("IfcSystem") + tool.Ifc.get().by_type("IfcZone") return tool.Ifc.get().by_type("IfcSystem") @classmethod - def import_systems(cls): - props = bpy.context.scene.BIMSystemProperties + def import_systems(cls) -> None: + props = cls.get_system_props() props.systems.clear() for system in cls.get_systems(): if system.is_a() in ["IfcStructuralAnalysisModel"]: @@ -179,7 +199,7 @@ class System(bonsai.core.tool.System): port_obj.matrix_parent_inverse = obj.matrix_world.inverted() @classmethod - def run_geometry_edit_object_placement(cls, obj=None): + def run_geometry_edit_object_placement(cls, obj: bpy.types.Object) -> None: return bonsai.core.geometry.edit_object_placement(tool.Ifc, tool.Geometry, tool.Surveyor, obj=obj) @classmethod @@ -205,24 +225,24 @@ class System(bonsai.core.tool.System): ) @classmethod - def select_system_products(cls, system): + def select_system_products(cls, system: ifcopenshell.entity_instance) -> None: tool.Spatial.select_products(ifcopenshell.util.system.get_system_elements(system)) @classmethod - def set_active_edited_system(cls, system): - bpy.context.scene.BIMSystemProperties.edited_system_id = system.id() + def set_active_edited_system(cls, system: ifcopenshell.entity_instance) -> None: + cls.get_system_props().edited_system_id = system.id() @classmethod - def set_active_system(cls, system): - bpy.context.scene.BIMSystemProperties.active_system_id = system.id() + def set_active_system(cls, system: ifcopenshell.entity_instance) -> None: + cls.get_system_props().active_system_id = system.id() @classmethod - def get_active_system(cls): - system_props = bpy.context.scene.BIMSystemProperties + def get_active_system(cls) -> Union[ifcopenshell.entity_instance, None]: + system_props = cls.get_system_props() return tool.Ifc.get_entity_by_id(system_props.active_system_id) @classmethod - def get_decoration_data(cls): + def get_decoration_data(cls) -> dict[str, Any]: all_vertices = [] preview_edges = [] special_vertices = [] @@ -367,7 +387,11 @@ class System(bonsai.core.tool.System): return decoration_data @classmethod - def get_connected_elements(cls, element, traversed_elements=None): + def get_connected_elements( + cls, + element: ifcopenshell.entity_instance, + traversed_elements: Optional[set[ifcopenshell.entity_instance]] = None, + ) -> set[ifcopenshell.entity_instance]: """Recursively retrieves all connected elements to the given `element`. `traversed_elements` is a set to store connected elements fetched recursively, @@ -387,17 +411,19 @@ class System(bonsai.core.tool.System): return traversed_elements @classmethod - def is_mep_element(cls, element): + def is_mep_element(cls, element: ifcopenshell.entity_instance) -> bool: return element.is_a("IfcFlowSegment") or element.is_a("IfcFlowFitting") @classmethod - def get_flow_element_controls(cls, element): + def get_flow_element_controls(cls, element: ifcopenshell.entity_instance) -> list[ifcopenshell.entity_instance]: if not element.HasControlElements: return [] return [control for control in element.HasControlElements[0].RelatedControlElements] @classmethod - def get_flow_control_flow_element(cls, element): + def get_flow_control_flow_element( + cls, element: ifcopenshell.entity_instance + ) -> Union[ifcopenshell.entity_instance, None]: if not element.AssignedToFlowElement: return return element.AssignedToFlowElement[0].RelatingFlowElement