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