diff --git a/src/bonsai/bonsai/bim/module/geometry/operator.py b/src/bonsai/bonsai/bim/module/geometry/operator.py index 0ed5c4cdd6..87e1abeb36 100644 --- a/src/bonsai/bonsai/bim/module/geometry/operator.py +++ b/src/bonsai/bonsai/bim/module/geometry/operator.py @@ -843,6 +843,7 @@ class OverrideDelete(bpy.types.Operator): return self.execute(context) def draw(self, context): + assert self.layout row = self.layout.row() row.prop(self, "is_batch", text="Enable Faster Deletion") if self.is_batch: diff --git a/src/bonsai/bonsai/bim/module/pset/prop.py b/src/bonsai/bonsai/bim/module/pset/prop.py index 4533907cdb..bce071b85e 100644 --- a/src/bonsai/bonsai/bim/module/pset/prop.py +++ b/src/bonsai/bonsai/bim/module/pset/prop.py @@ -60,7 +60,7 @@ def blender_formatted_enum_from_psets(psets: list[ifcopenshell.entity_instance]) # TODO: unsafe? -def get_pset_name(self, context): +def get_pset_name(self: "PsetProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS: pset_type = repr(self) prop_type = pset_type.split(".")[-1] results = [] @@ -81,6 +81,8 @@ def get_pset_name(self, context): results = get_profile_pset_names(self, context) elif prop_type == "WorkSchedulePsetProperties": results = get_work_schedule_pset_names(self, context) + + items: list[tool.Blender.BLENDER_ENUM_ITEM] items = [("BBIM_CUSTOM", "Custom Pset", "Create a property set without using a template.")] bprops = tool.Bsdd.get_bsdd_props() dictionaries = [(d.uri, f"bSDD: {d.name}", "") for d in bprops.dictionaries if d.is_active] diff --git a/src/bonsai/bonsai/bim/module/sequence/operator.py b/src/bonsai/bonsai/bim/module/sequence/operator.py index 9784279f86..aaaffaa9f9 100644 --- a/src/bonsai/bonsai/bim/module/sequence/operator.py +++ b/src/bonsai/bonsai/bim/module/sequence/operator.py @@ -41,7 +41,7 @@ class EnableStatusFilters(bpy.types.Operator): bl_label = "Enable Status Filters" def execute(self, context): - props = context.scene.BIMStatusProperties + props = tool.Sequence.get_status_props() props.is_enabled = True hidden_statuses = {s.name for s in props.statuses if not s.is_visible} @@ -78,7 +78,7 @@ class DisableStatusFilters(bpy.types.Operator): bl_description = "Deactivate status filters panel.\nCan be used to refresh the displayed statuses" def execute(self, context): - props = context.scene.BIMStatusProperties + props = tool.Sequence.get_status_props() all_statuses = {s.name for s in props.statuses} tool.Sequence.set_visibility_by_status(all_statuses) @@ -92,7 +92,7 @@ class ActivateStatusFilters(bpy.types.Operator): bl_description = "Filter and display objects based on currently selected IFC statuses" def execute(self, context): - props = context.scene.BIMStatusProperties + props = tool.Sequence.get_status_props() visible_statuses = {s.name for s in props.statuses if s.is_visible} tool.Sequence.set_visibility_by_status(visible_statuses) @@ -106,7 +106,6 @@ class SelectStatusFilter(bpy.types.Operator): name: bpy.props.StringProperty() def execute(self, context): - props = context.scene.BIMStatusProperties query = f"IfcProduct, /Pset_.*Common/.Status={self.name} + IfcProduct, EPset_Status.Status={self.name}" if self.name == "No Status": query = f"IfcProduct, /Pset_.*Common/.Status=NULL, EPset_Status.Status=NULL" diff --git a/src/bonsai/bonsai/bim/module/sequence/ui.py b/src/bonsai/bonsai/bim/module/sequence/ui.py index c996ad9d54..7cdc03b8d0 100644 --- a/src/bonsai/bonsai/bim/module/sequence/ui.py +++ b/src/bonsai/bonsai/bim/module/sequence/ui.py @@ -51,7 +51,8 @@ class BIM_PT_status(Panel): return tool.Ifc.get() def draw(self, context): - self.props = context.scene.BIMStatusProperties + self.props = tool.Sequence.get_status_props() + assert self.layout if not self.props.is_enabled: row = self.layout.row() diff --git a/src/bonsai/bonsai/bim/ui.py b/src/bonsai/bonsai/bim/ui.py index 980d8c1232..3659fe1d2c 100644 --- a/src/bonsai/bonsai/bim/ui.py +++ b/src/bonsai/bonsai/bim/ui.py @@ -423,7 +423,7 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences): layout.prop(dprops, "classes_to_wireframe") layout.prop(dprops, "classes_no_cut") - def draw_decorator_colors(self, layout, context): + def draw_decorator_colors(self, layout: bpy.types.UILayout, context: bpy.types.Context) -> None: layout.row().prop(self, "decorations_colour") layout.row().prop(self, "decorator_color_selected") layout.row().prop(self, "decorator_color_unselected") @@ -431,7 +431,7 @@ class BIM_ADDON_preferences(bpy.types.AddonPreferences): layout.row().prop(self, "decorator_color_error") layout.row().prop(self, "decorator_color_background") - def draw_other_settings(self, layout, context): + def draw_other_settings(self, layout: bpy.types.UILayout, context: bpy.types.Context) -> None: layout.prop(self, "opening_focus_opacity") props = tool.Project.get_project_props() layout.prop(props, "should_disable_undo_on_save") diff --git a/src/bonsai/bonsai/tool/blender.py b/src/bonsai/bonsai/tool/blender.py index 51989b0a21..74cdc5f0ec 100644 --- a/src/bonsai/bonsai/tool/blender.py +++ b/src/bonsai/bonsai/tool/blender.py @@ -85,7 +85,7 @@ class Blender(bonsai.core.tool.Blender): OBJECT_TYPES_THAT_SUPPORT_EDIT_GPENCIL_MODE = ("GPENCIL",) TYPE_MANAGER_ICON = "LIGHTPROBE_VOLUME" - BLENDER_ENUM_ITEM = Union[tuple[str, str, str], tuple[str, str, str, int], tuple[str, str, str, str, int]] + BLENDER_ENUM_ITEM = Union[tuple[str, str, str], tuple[str, str, str, int], tuple[str, str, str, str, int], None] """ Options: diff --git a/src/bonsai/bonsai/tool/bsdd.py b/src/bonsai/bonsai/tool/bsdd.py index 7f090546b5..e43bd24d28 100644 --- a/src/bonsai/bonsai/tool/bsdd.py +++ b/src/bonsai/bonsai/tool/bsdd.py @@ -164,7 +164,7 @@ class Bsdd(bonsai.core.tool.Bsdd): @classmethod def get_related_ifc_entities(cls) -> list[str]: active_object = bpy.context.active_object - related_ifc_entities = [] + related_ifc_entities: list[str] = [] if cls.should_filter_ifc_class() and active_object: if element := tool.Ifc.get_entity(active_object): ifc_class = element.is_a() diff --git a/src/bonsai/bonsai/tool/geometry.py b/src/bonsai/bonsai/tool/geometry.py index 48a3327e6b..8655388d51 100644 --- a/src/bonsai/bonsai/tool/geometry.py +++ b/src/bonsai/bonsai/tool/geometry.py @@ -1148,7 +1148,9 @@ class Geometry(bonsai.core.tool.Geometry): if is_global and element.is_a("IfcTypeProduct"): ocurrences = ifcopenshell.util.element.get_types(element) for occurrence in ocurrences: - cls.recreate_object_with_data(tool.Ifc.get_object(occurrence), data) + obj_ = tool.Ifc.get_object(occurrence) + assert isinstance(obj_, bpy.types.Object) + cls.recreate_object_with_data(obj_, data) tool.Ifc.unlink(element=element) diff --git a/src/bonsai/bonsai/tool/sequence.py b/src/bonsai/bonsai/tool/sequence.py index 30164d8704..c0c5f260c5 100644 --- a/src/bonsai/bonsai/tool/sequence.py +++ b/src/bonsai/bonsai/tool/sequence.py @@ -29,10 +29,9 @@ import isodate import ifcopenshell import ifcopenshell.api.group import ifcopenshell.ifcopenshell_wrapper as W -import ifcopenshell.util.sequence import ifcopenshell.util.date -import ifcopenshell.util.element -import ifcopenshell.util.unit +import ifcopenshell.util.selector +import ifcopenshell.util.sequence import bonsai.core.tool import bonsai.tool as tool import bonsai.bim.helper @@ -45,7 +44,12 @@ from mathutils import Color if TYPE_CHECKING: import bonsai.bim.prop - from bonsai.bim.module.sequence.prop import BIMTaskTreeProperties, BIMWorkScheduleProperties, BIMAnimationProperties + from bonsai.bim.module.sequence.prop import ( + BIMTaskTreeProperties, + BIMWorkScheduleProperties, + BIMAnimationProperties, + BIMStatusProperties, + ) class Sequence(bonsai.core.tool.Sequence): @@ -64,6 +68,11 @@ class Sequence(bonsai.core.tool.Sequence): def get_work_schedule_props(cls) -> BIMWorkScheduleProperties: return bpy.context.scene.BIMWorkScheduleProperties + @classmethod + def get_status_props(cls) -> BIMStatusProperties: + assert (scene := bpy.context.scene) + return scene.BIMStatusProperties # pyright: ignore[reportAttributeAccessIssue] + @classmethod def get_work_plan_attributes(cls) -> dict[str, Any]: import bonsai.bim.module.sequence.helper as helper @@ -1790,7 +1799,8 @@ class Sequence(bonsai.core.tool.Sequence): return isodate.date_isoformat(datetime_) @classmethod - def set_visibility_by_status(cls, visible_statuses: list[str]) -> None: + def set_visibility_by_status(cls, visible_statuses: set[str]) -> None: + assert bpy.context.view_layer query = [] for name in visible_statuses: if name == "No Status":