diff --git a/src/bonsai/bonsai/bim/import_ifc.py b/src/bonsai/bonsai/bim/import_ifc.py index 1d6ad25f1b..11b92be532 100644 --- a/src/bonsai/bonsai/bim/import_ifc.py +++ b/src/bonsai/bonsai/bim/import_ifc.py @@ -747,6 +747,7 @@ class IfcImporter: self.update_progress((percent_average / 100 * progress_range) + start_progress) shape = iterator.get() if shape: + assert isinstance(shape, W.TriangulationElement) product = self.file.by_id(shape.id) self.create_product(product, shape) results.add(product) diff --git a/src/bonsai/bonsai/bim/module/boundary/operator.py b/src/bonsai/bonsai/bim/module/boundary/operator.py index 5720d6aae5..2c6a6de2cf 100644 --- a/src/bonsai/bonsai/bim/module/boundary/operator.py +++ b/src/bonsai/bonsai/bim/module/boundary/operator.py @@ -27,6 +27,7 @@ import ifcopenshell.api import ifcopenshell.api.boundary import ifcopenshell.api.root import ifcopenshell.geom +import ifcopenshell.ifcopenshell_wrapper as W import ifcopenshell.util.element import ifcopenshell.util.placement import ifcopenshell.util.shape @@ -701,6 +702,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator): while True: tree.add_element(iterator.get_native()) shape = iterator.get() + assert isinstance(shape, W.TriangulationElement) shapes[shape.id] = { "verts": ifcopenshell.util.shape.get_vertices(shape.geometry), "faces": ifcopenshell.util.shape.get_faces(shape.geometry), diff --git a/src/bonsai/bonsai/bim/module/brick/ui.py b/src/bonsai/bonsai/bim/module/brick/ui.py index aa910c272f..2ec063a0dc 100644 --- a/src/bonsai/bonsai/bim/module/brick/ui.py +++ b/src/bonsai/bonsai/bim/module/brick/ui.py @@ -16,9 +16,18 @@ # 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 + +import bpy from bpy.types import Panel, UIList import bonsai.tool as tool + +if TYPE_CHECKING: + from bonsai.bim.module.brick.prop import Brick + from bonsai.bim.helper import prop_with_search from bonsai.bim.module.brick.data import BrickschemaData, BrickschemaReferencesData from bonsai.tool.brick import BrickStore @@ -274,7 +283,9 @@ class BIM_PT_brickschema_viewport(Panel): class BIM_UL_bricks(UIList): split_screen = False - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, context, layout: bpy.types.UILayout, data, item: Brick, icon, active_data, active_propname + ) -> None: if item: split = layout.split(factor=0.85, align=True) row = split.row() diff --git a/src/bonsai/bonsai/bim/module/cost/ui.py b/src/bonsai/bonsai/bim/module/cost/ui.py index 98701b4ef8..87e7bbb790 100644 --- a/src/bonsai/bonsai/bim/module/cost/ui.py +++ b/src/bonsai/bonsai/bim/module/cost/ui.py @@ -26,10 +26,11 @@ from bpy.types import Panel, UIList import bonsai.bim.helper import bonsai.bim.module.cost.prop as CostProp import bonsai.tool as tool -from bonsai.bim.module.cost.data import CostSchedulesData +from bonsai.bim.module.cost.data import CostItem, CostSchedulesData if TYPE_CHECKING: from bonsai.bim.module.cost.prop import BIMCostProperties, CostItemQuantity + from bonsai.bim.prop import StrProperty class BIM_PT_cost_schedules(Panel): @@ -661,7 +662,9 @@ class BIM_UL_cost_items_trait: split2.alignment = "LEFT" split2.label(text="Rate") - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, context, layout: bpy.types.UILayout, data, item: CostProp.CostItem, icon, active_data, active_propname + ) -> None: if item: self.props = tool.Cost.get_cost_props() cost_item = CostSchedulesData.data["cost_items"][item.ifc_definition_id] @@ -694,7 +697,7 @@ class BIM_UL_cost_items_trait: # TODO: reimplement "bim.copy_cost_item_values" somewhere with better UX - def draw_parent_operator(self, row, cost_item_id): + def draw_parent_operator(self, row: bpy.types.UILayout, cost_item_id: int) -> None: if self.props.active_cost_item_id: if self.props.active_cost_item_id != cost_item_id: op = row.operator("bim.change_parent_cost_item", text="", icon="LINKED", emboss=False).new_parent = ( @@ -703,7 +706,7 @@ class BIM_UL_cost_items_trait: else: row.label(text="", icon="BLANK1") - def draw_hierarchy(self, row, item): + def draw_hierarchy(self, row: bpy.types.UILayout, item: CostProp.CostItem) -> None: for i in range(0, item.level_index): row.label(text="", icon="BLANK1") if item.has_children: @@ -749,7 +752,7 @@ class BIM_UL_cost_items_trait: else: row.label(text="-") - def draw_value_column(self, layout, cost_item): + def draw_value_column(self, layout: bpy.types.UILayout, cost_item: CostItem) -> None: if cost_item["TotalAppliedValue"]: text = "{0:,.2f}".format(cost_item["TotalAppliedValue"]).replace(",", " ") if cost_item["UnitBasisValueComponent"] not in [None, 1]: @@ -760,13 +763,13 @@ class BIM_UL_cost_items_trait: else: layout.label(text="-") - def draw_total_cost_column(self, layout, cost_item): + def draw_total_cost_column(self, layout: bpy.types.UILayout, cost_item: CostItem) -> None: format_numbers = "{0:,.2f}".format(cost_item["TotalCost"]).replace(",", " ") currency = CostSchedulesData.data["currency"] text = "{} {}".format(format_numbers, currency["name"]) if currency else format_numbers layout.label(text=text) - def draw_order_operator(self, row, ifc_definition_id, cost_item): + def draw_order_operator(self, row: bpy.types.UILayout, ifc_definition_id: int, cost_item: CostItem) -> None: if cost_item["NestingIndex"] is not None: if cost_item["NestingIndex"] == 0: op = row.operator("bim.reorder_cost_item_nesting", icon="TRIA_DOWN", text="") @@ -793,12 +796,14 @@ class BIM_UL_cost_item_rates(BIM_UL_cost_items_trait, UIList): def draw_quantity_column(self, layout, cost_item): self.draw_uom_column(layout, cost_item) - def draw_total_cost_column(self, layout, cost_item): + def draw_total_cost_column(self, layout: bpy.types.UILayout, cost_item: CostItem) -> None: pass # No such thing as a total cost in a schedule of rates class BIM_UL_cost_columns(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, context, layout: bpy.types.UILayout, data, item: StrProperty, icon, active_data, active_propname + ) -> None: if item: row = layout.row(align=True) row.prop(item, "name", emboss=False, text="") @@ -806,7 +811,9 @@ class BIM_UL_cost_columns(UIList): class BIM_UL_cost_item_types(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, context, layout: bpy.types.UILayout, data, item: CostProp.CostItemType, icon, active_data, active_propname + ) -> None: props = tool.Cost.get_cost_props() cost_item = props.cost_items[props.active_cost_item_index] @@ -844,7 +851,16 @@ class BIM_UL_cost_item_quantities(UIList): class BIM_UL_product_cost_items(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, + context, + layout: bpy.types.UILayout, + data, + item: CostItemQuantity, + icon, + active_data, + active_propname, + ) -> None: if item: row = layout.row(align=True) op = row.operator("bim.highlight_product_cost_item", text="", icon="STYLUS_PRESSURE") diff --git a/src/bonsai/bonsai/bim/module/document/prop.py b/src/bonsai/bonsai/bim/module/document/prop.py index c51f7b636c..01ddf82f43 100644 --- a/src/bonsai/bonsai/bim/module/document/prop.py +++ b/src/bonsai/bonsai/bim/module/document/prop.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, Union +from typing import TYPE_CHECKING, Literal, Union import bpy from bpy.props import ( @@ -66,7 +66,7 @@ class Document(PropertyGroup): tree_depth: int has_children: bool is_expanded: bool - document_type: str + document_type: Literal["PROJECT", "INFORMATION", "REFERENCE"] class DocumentObject(PropertyGroup): diff --git a/src/bonsai/bonsai/bim/module/document/ui.py b/src/bonsai/bonsai/bim/module/document/ui.py index d618d6d966..cdcf4b2580 100644 --- a/src/bonsai/bonsai/bim/module/document/ui.py +++ b/src/bonsai/bonsai/bim/module/document/ui.py @@ -16,9 +16,18 @@ # 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 + +import bpy from bpy.types import Panel, UIList import bonsai.tool as tool + +if TYPE_CHECKING: + from bonsai.bim.module.document.prop import Document, DocumentObject + from bonsai.bim.helper import draw_attributes from bonsai.bim.module.document.data import DocumentData, ObjectDocumentData @@ -207,7 +216,9 @@ class BIM_PT_object_documents(Panel): class BIM_UL_documents(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, context, layout: bpy.types.UILayout, data, item: Document, icon, active_data, active_propname + ) -> None: if item: row = layout.row(align=True) indent_depth = 0 @@ -252,7 +263,9 @@ class BIM_UL_documents(UIList): class BIM_UL_document_objects(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, context, layout: bpy.types.UILayout, data, item: DocumentObject, icon, active_data, active_propname + ) -> None: if item: row = layout.row(align=True) row.prop(item, "name", text="", emboss=False, icon="OBJECT_DATA") diff --git a/src/bonsai/bonsai/bim/module/light/operator.py b/src/bonsai/bonsai/bim/module/light/operator.py index 41bae9179c..6ee37f2285 100644 --- a/src/bonsai/bonsai/bim/module/light/operator.py +++ b/src/bonsai/bonsai/bim/module/light/operator.py @@ -30,6 +30,7 @@ from typing import TYPE_CHECKING, Union import bpy import ifcopenshell import ifcopenshell.geom +import ifcopenshell.ifcopenshell_wrapper as W import ifcopenshell.util.geolocation import pyradiance as pr import requests @@ -106,9 +107,8 @@ class ExportOBJ(bpy.types.Operator): if iterator.initialize(): while True: shape = iterator.get() + assert isinstance(shape, W.TriangulationElement) materials = shape.geometry.materials - material_ids = shape.geometry.material_ids - # material_names = shape.geometry.material_names for material in materials: ifc_materials.append(material.name) diff --git a/src/bonsai/bonsai/bim/module/project/operator.py b/src/bonsai/bonsai/bim/module/project/operator.py index 997972ddff..bf2fc16cfd 100644 --- a/src/bonsai/bonsai/bim/module/project/operator.py +++ b/src/bonsai/bonsai/bim/module/project/operator.py @@ -2142,6 +2142,7 @@ class LoadLinkedProject(bpy.types.Operator, ImportHelper): if iterator.initialize(): while True: # Main loop. shape = iterator.get() + assert isinstance(shape, W.TriangulationElement) results.add(self.file.by_id(shape.id)) geometry = shape.geometry diff --git a/src/bonsai/bonsai/bim/module/project/ui.py b/src/bonsai/bonsai/bim/module/project/ui.py index a39102c907..98122100d2 100644 --- a/src/bonsai/bonsai/bim/module/project/ui.py +++ b/src/bonsai/bonsai/bim/module/project/ui.py @@ -255,7 +255,7 @@ class BIM_PT_project(Panel): row = self.layout.row(align=True) row.operator("bim.load_project_elements") - def draw_editing_buttons(self, context, row): + def draw_editing_buttons(self, context: object, row: bpy.types.UILayout) -> None: pprops = self.props if tool.Ifc.get(): if pprops.is_editing: diff --git a/src/bonsai/bonsai/bim/module/sequence/ui.py b/src/bonsai/bonsai/bim/module/sequence/ui.py index f758e89ef5..ebb4485e32 100644 --- a/src/bonsai/bonsai/bim/module/sequence/ui.py +++ b/src/bonsai/bonsai/bim/module/sequence/ui.py @@ -37,8 +37,11 @@ from bonsai.bim.module.sequence.data import ( if TYPE_CHECKING: from bonsai.bim.module.sequence.prop import ( BIMTaskTreeProperties, + BIMTaskTypeColor, BIMWorkScheduleProperties, Task, + TaskProduct, + TaskResource, ) from bonsai.bim.prop import Attribute @@ -815,7 +818,9 @@ class BIM_UL_task_columns(UIList): class BIM_UL_task_inputs(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, context, layout: bpy.types.UILayout, data, item: TaskProduct, icon, active_data, active_propname + ) -> None: if item: row = layout.row(align=True) op = row.operator("bim.select_product", text="", icon="RESTRICT_SELECT_OFF") @@ -825,7 +830,9 @@ class BIM_UL_task_inputs(UIList): class BIM_UL_task_resources(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, context, layout: bpy.types.UILayout, data, item: TaskResource, icon, active_data, active_propname + ) -> None: if item: row = layout.row(align=True) row.operator("bim.go_to_resource", text="", icon="STYLUS_PRESSURE").resource = item.ifc_definition_id @@ -834,7 +841,9 @@ class BIM_UL_task_resources(UIList): class BIM_UL_animation_colors(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, context, layout: bpy.types.UILayout, data, item: BIMTaskTypeColor, icon, active_data, active_propname + ) -> None: if item: row = layout.row() row.prop(item, "color", text="") @@ -842,7 +851,9 @@ class BIM_UL_animation_colors(UIList): class BIM_UL_task_outputs(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, context, layout: bpy.types.UILayout, data, item: TaskProduct, icon, active_data, active_propname + ) -> None: if item: row = layout.row(align=True) op = row.operator("bim.select_product", text="", icon="RESTRICT_SELECT_OFF") @@ -851,7 +862,9 @@ class BIM_UL_task_outputs(UIList): class BIM_UL_product_input_tasks(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, context, layout: bpy.types.UILayout, data, item: TaskProduct, icon, active_data, active_propname + ) -> None: if item: row = layout.row(align=True) op = row.operator("bim.go_to_task", text="", icon="STYLUS_PRESSURE") @@ -861,7 +874,9 @@ class BIM_UL_product_input_tasks(UIList): class BIM_UL_product_output_tasks(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, context, layout: bpy.types.UILayout, data, item: TaskProduct, icon, active_data, active_propname + ) -> None: if item: row = layout.row(align=True) op = row.operator("bim.go_to_task", text="", icon="STYLUS_PRESSURE") diff --git a/src/bonsai/bonsai/bim/module/spatial/ui.py b/src/bonsai/bonsai/bim/module/spatial/ui.py index 69d9068f85..dd0510eede 100644 --- a/src/bonsai/bonsai/bim/module/spatial/ui.py +++ b/src/bonsai/bonsai/bim/module/spatial/ui.py @@ -357,7 +357,7 @@ class BIM_UL_elements(UIList): super().__init__(*args, **kwargs) self.use_filter_show = True - def draw_toggle(self, row: bpy.types.UILayout, is_expanded: bool, index: int): + def draw_toggle(self, row: bpy.types.UILayout, is_expanded: bool, index: int) -> None: icon_id = "DISCLOSURE_TRI_DOWN" if is_expanded else "DISCLOSURE_TRI_RIGHT" row.operator("bim.toggle_container_element", text="", emboss=False, icon=icon_id).element_index = index diff --git a/src/bonsai/bonsai/bim/module/void/ui.py b/src/bonsai/bonsai/bim/module/void/ui.py index 37415eb978..5fec870891 100644 --- a/src/bonsai/bonsai/bim/module/void/ui.py +++ b/src/bonsai/bonsai/bim/module/void/ui.py @@ -29,6 +29,8 @@ from bonsai.bim.module.void.data import BooleansData, VoidsData if TYPE_CHECKING: import bpy.stub_internal.rna_enums as rna_enums + from bonsai.bim.module.void.prop import Boolean + OPENING_ICON = "SELECT_SUBTRACT" FILLING_ICON = "SELECT_INTERSECT" @@ -175,7 +177,9 @@ class BIM_PT_booleans(Panel): class BIM_UL_booleans(UIList): - def draw_item(self, context, layout, data, item, icon, active_data, active_propname): + def draw_item( + self, context, layout: bpy.types.UILayout, data, item: Boolean, icon, active_data, active_propname + ) -> None: if item: if item.operator == "DIFFERENCE": icon = "SELECT_DIFFERENCE" diff --git a/src/bonsai/bonsai/bim/ui.py b/src/bonsai/bonsai/bim/ui.py index bee0594afc..526b757031 100644 --- a/src/bonsai/bonsai/bim/ui.py +++ b/src/bonsai/bonsai/bim/ui.py @@ -1032,7 +1032,6 @@ class BIM_PT_tabs(Panel): if not UIData.is_loaded: UIData.load() aprops = tool.Blender.get_active_area_props(context) - addon_prefs = tool.Blender.get_addon_preferences() row = self.layout.row() row.alignment = "CENTER" @@ -1119,7 +1118,9 @@ class BIM_PT_tabs(Panel): op = row.operator("bim.open_uri", text="", icon="QUESTION") op.uri = "https://docs.bonsaibim.org/guides/troubleshooting.html#incompatible-blender-features" - def draw_tab_entry(self, row, icon, tab_name, enabled=True, highlight=True): + def draw_tab_entry( + self, row: bpy.types.UILayout, icon: int | str, tab_name: str, enabled: bool = True, highlight: bool = True + ) -> None: tab_entry = row.row(align=True) if isinstance(icon, int): tab_entry.operator("bim.set_tab", text="", emboss=highlight, icon_value=icon).tab = tab_name