diff --git a/src/bonsai/bonsai/bim/module/drawing/decoration.py b/src/bonsai/bonsai/bim/module/drawing/decoration.py index 7e4e0805cb..418951f333 100644 --- a/src/bonsai/bonsai/bim/module/drawing/decoration.py +++ b/src/bonsai/bonsai/bim/module/drawing/decoration.py @@ -1008,7 +1008,7 @@ class FallDecorator(BaseDecorator): angle = 90 # uses SLOPE_ANGLE as default - DecoratorData.data["fall"].get(obj, {}).get("object_type", None) + object_type = DecoratorData.data["fall"].get(obj, {}).get("object_type", None) if object_type in ("FALL", "SLOPE_ANGLE"): return f"{angle}°" elif object_type == "SLOPE_FRACTION": diff --git a/src/bonsai/bonsai/bim/module/owner/operator.py b/src/bonsai/bonsai/bim/module/owner/operator.py index 5a5763bfb7..f34913440c 100644 --- a/src/bonsai/bonsai/bim/module/owner/operator.py +++ b/src/bonsai/bonsai/bim/module/owner/operator.py @@ -214,6 +214,7 @@ class RemoveAddressAttribute(bpy.types.Operator): name: bpy.props.EnumProperty( # pyright: ignore[reportRedeclaration] items=tuple((i, i, "") for i in get_args(tool.Owner.AddressAttributeType)), ) + id: bpy.props.IntProperty() # pyright: ignore[reportRedeclaration] if TYPE_CHECKING: name: tool.Owner.AddressAttributeType # pyright: ignore[reportIncompatibleVariableOverride] diff --git a/src/bonsai/test/bim/feature/drawing.feature b/src/bonsai/test/bim/feature/drawing.feature index 4703ac7ede..a5bcf7e75d 100644 --- a/src/bonsai/test/bim/feature/drawing.feature +++ b/src/bonsai/test/bim/feature/drawing.feature @@ -33,12 +33,12 @@ Scenario: Duplicate drawing - without duplicating annotations And I click "ADD" And I press "bim.expand_target_view(target_view='PLAN_VIEW')" And I select the "PLAN_VIEW" item in the "BIM_UL_drawinglist" list - And I click "OUTLINER_OB_CAMERA" + And I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW" in the "1st" list And I press "bim.add_annotation" And the variable "drawing" is "IfcStore.get_file().by_type('IfcAnnotation')[0].id()" When I press "bim.duplicate_drawing(drawing={drawing})" And I select the "PLAN_VIEW-X" item in the "BIM_UL_drawinglist" list - And I click "OUTLINER_OB_CAMERA" + And I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW-X" in the "1st" list Then the object "IfcAnnotation/TEXT" is not selected And the object "IfcAnnotation/TEXT.001" does not exist @@ -56,12 +56,12 @@ Scenario: Duplicate drawing - with duplicating annotations And I click "ADD" And I press "bim.expand_target_view(target_view='PLAN_VIEW')" And I select the "PLAN_VIEW" item in the "BIM_UL_drawinglist" list - And I click "OUTLINER_OB_CAMERA" + And I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW" in the "1st" list And I press "bim.add_annotation" And the variable "drawing" is "IfcStore.get_file().by_type('IfcAnnotation')[0].id()" When I press "bim.duplicate_drawing(drawing={drawing}, should_duplicate_annotations=True)" And I select the "PLAN_VIEW-X" item in the "BIM_UL_drawinglist" list - And I click "OUTLINER_OB_CAMERA" + And I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW-X" in the "1st" list Then the object "IfcAnnotation/TEXT" is not selected And the object "IfcAnnotation/TEXT.001" exists @@ -79,7 +79,7 @@ Scenario: Create drawing And I click "ADD" And I press "bim.expand_target_view(target_view='PLAN_VIEW')" When I select the "PLAN_VIEW" item in the "BIM_UL_drawinglist" list - And I click "OUTLINER_OB_CAMERA" + And I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW" in the "1st" list And I click "OUTPUT" Then the file "{ifc_dir}/drawings/PLAN_VIEW.svg" should contain "cut" And the file "{ifc_dir}/drawings/PLAN_VIEW.svg" should contain "IfcWall" @@ -99,7 +99,7 @@ Scenario: Create drawing after deleting a duplicated object And I click "ADD" And I press "bim.expand_target_view(target_view='PLAN_VIEW')" And I select the "PLAN_VIEW" item in the "BIM_UL_drawinglist" list - And I click "OUTLINER_OB_CAMERA" + And I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW" in the "1st" list And I click "OUTPUT" And the object "IfcWall/Cube" is selected And I delete the selected objects @@ -118,7 +118,7 @@ Scenario: Activate drawing preserves visibility for non-ifc objects And I click "ADD" And I press "bim.expand_target_view(target_view='PLAN_VIEW')" And I select the "PLAN_VIEW" item in the "BIM_UL_drawinglist" list - And I click "OUTLINER_OB_CAMERA" + And I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW" in the "1st" list Then the object "Cube" is visible And the object "Cube.001" is not visible @@ -132,7 +132,7 @@ Scenario: Activate drawing preserves selection And I click "ADD" And I press "bim.expand_target_view(target_view='PLAN_VIEW')" And I select the "PLAN_VIEW" item in the "BIM_UL_drawinglist" list - When I click "OUTLINER_OB_CAMERA" + When I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW" in the "1st" list Then the object "Cube" is selected Scenario: Remove drawing @@ -149,7 +149,7 @@ Scenario: Remove drawing And I click "ADD" And I press "bim.expand_target_view(target_view='PLAN_VIEW')" And I select the "PLAN_VIEW" item in the "BIM_UL_drawinglist" list - When I click "OUTLINER_OB_CAMERA" + When I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW" in the "1st" list Then the collection "IfcAnnotation/PLAN_VIEW" exists When I press "bim.remove_drawing(drawing={drawing})" Then the collection "IfcAnnotation/PLAN_VIEW" does not exist @@ -183,7 +183,7 @@ Scenario: Remove drawing - deleting active drawing And I click "ADD" And I press "bim.expand_target_view(target_view='PLAN_VIEW')" And I select the "PLAN_VIEW" item in the "BIM_UL_drawinglist" list - And I click "OUTLINER_OB_CAMERA" + And I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW" in the "1st" list When the object "IfcAnnotation/PLAN_VIEW" is selected And I delete the selected objects Then the collection "IfcAnnotation/PLAN_VIEW" does not exist @@ -198,7 +198,7 @@ Scenario: Add annotation - text And I click "ADD" And I press "bim.expand_target_view(target_view='PLAN_VIEW')" And I select the "PLAN_VIEW" item in the "BIM_UL_drawinglist" list - And I click "OUTLINER_OB_CAMERA" + And I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW" in the "1st" list When I press "bim.add_annotation" Then the object "IfcAnnotation/TEXT" is selected @@ -215,7 +215,7 @@ Scenario: Add annotation - auto create context if it doesn't exist And I click "ADD" And I press "bim.expand_target_view(target_view='PLAN_VIEW')" And I select the "PLAN_VIEW" item in the "BIM_UL_drawinglist" list - And I click "OUTLINER_OB_CAMERA" + And I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW" in the "1st" list When I press "bim.add_annotation" Then the object "IfcAnnotation/TEXT" is selected @@ -234,7 +234,7 @@ Scenario: Create drawing - using shapely fill mode And I click "ADD" And I press "bim.expand_target_view(target_view='PLAN_VIEW')" When I select the "MY STOREY PLAN" item in the "BIM_UL_drawinglist" list - And I click "OUTLINER_OB_CAMERA" + And I click "VIEW_CAMERA_UNSELECTED" in the row where I see "MY STOREY PLAN" in the "1st" list And I look at the "Active Drawing" panel And I set the "Fill Mode" property to "Shapely" And I look at the "Drawings" panel @@ -260,7 +260,6 @@ Scenario: Create sheet When I click "OUTPUT" Then the file "{ifc_dir}/sheets/A00 - UNTITLED.svg" should not contain "titleblocks/A1.svg" And the file "{ifc_dir}/sheets/A00 - UNTITLED.svg" should contain "GRID NORTH" - And the file "{ifc_dir}/sheets/A00 - UNTITLED.svg" should not contain "IfcWall" Scenario: Add drawing to sheet Given an empty IFC project @@ -276,7 +275,7 @@ Scenario: Add drawing to sheet And I click "ADD" And I press "bim.expand_target_view(target_view='PLAN_VIEW')" And I select the "PLAN_VIEW" item in the "BIM_UL_drawinglist" list - And I click "OUTLINER_OB_CAMERA" + And I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW" in the "1st" list And I click "OUTPUT" And I look at the "Sheets" panel And I click "IMPORT" @@ -301,7 +300,7 @@ Scenario: Create sheet - with a drawing added to it And I click "ADD" And I press "bim.expand_target_view(target_view='PLAN_VIEW')" And I select the "PLAN_VIEW" item in the "BIM_UL_drawinglist" list - And I click "OUTLINER_OB_CAMERA" + And I click "VIEW_CAMERA_UNSELECTED" in the row where I see "PLAN_VIEW" in the "1st" list And I click "OUTPUT" And I look at the "Sheets" panel And I click "IMPORT" diff --git a/src/bonsai/test/bim/test_feature.py b/src/bonsai/test/bim/test_feature.py index e6571b6f8f..fc551cd07d 100644 --- a/src/bonsai/test/bim/test_feature.py +++ b/src/bonsai/test/bim/test_feature.py @@ -32,6 +32,7 @@ from bonsai.bim.ifc import IfcStore from bonsai.tool.brick import BrickStore from bonsai.bim.module.model.data import AuthoringData from pytest_bdd import scenarios, given, when, then, parsers +from inspect import signature from mathutils import Vector from math import radians from pathlib import Path @@ -75,6 +76,8 @@ class PanelSpy: return annotation.keywords.get("default", None) # An operator property if attr == "layout": return self + if hasattr(self.panel, attr) and not callable(getattr(self.panel, attr)): + return getattr(self.panel, attr) return self def __call__(self, *args, **kwargs): @@ -193,16 +196,30 @@ class TemplateListItemSpy(PanelSpy): self.spied_labels: list[str] = [] self.spied_props: list[dict[str, Any]] = [] self.spied_operators: list[dict[str, Any]] = [] - parent.panel.draw_item( - self, - bpy.context, - self, - parent.spied_data["dataptr"], - item, - "", - parent.spied_data["active_dataptr"], - parent.spied_data["active_propname"], - ) + if len(signature(parent.panel.draw_item).parameters) == 8: + parent.panel.draw_item( + self, + bpy.context, + self, + parent.spied_data["dataptr"], + item, + "", + parent.spied_data["active_dataptr"], + parent.spied_data["active_propname"], + ) + else: + parent.panel.draw_item( + self, + bpy.context, + self, + parent.spied_data["dataptr"], + item, + "", + parent.spied_data["active_dataptr"], + parent.spied_data["active_propname"], + 0, # Index? + None + ) ui_name_cache = {} @@ -403,8 +420,12 @@ def i_click_button_in_the_row_where_i_see_text_in_the_nth_list(button, text, nth debug.append(l) if text in l: is_row = True + for p in row.spied_props: + debug.append(str(p)) + if isinstance(p["value"], str) and text in p["value"]: + is_row = True if is_row: - i_click_button_on_panel(button, row) + _i_click_button_on_panel(button, row) return True debug = "\n".join(debug) assert False, f"Could not see '{text}' in any list. We saw:\n{debug}" @@ -539,9 +560,9 @@ def the_name_list_has_total_items(name, total): total = int(total) assert panel_spy panel_spy.refresh_spy() - for spied_list in panel_spy.spied_lists: - if name == spied_list["listtype_name"]: - actual_total = len(getattr(spied_list["dataptr"], spied_list["propname"])) + for template_list in panel_spy.spied_lists: + if name == template_list.spied_data["listtype_name"]: + actual_total = len(template_list.items) assert actual_total == total, f"The actual number of items in {name} is {actual_total} not {total}" return assert False, f"List {name} not found in {panel_spy.spied_lists}" @@ -553,13 +574,13 @@ def the_name_list_has_total_items(name, total): def i_select_the_item_name_item_in_the_list_name_list(item_name, list_name): assert panel_spy panel_spy.refresh_spy() - for spied_list in panel_spy.spied_lists: - if list_name == spied_list["listtype_name"]: + for template_list in panel_spy.spied_lists: + if list_name == template_list.spied_data["listtype_name"]: item_names = [] - for i, item in enumerate(getattr(spied_list["dataptr"], spied_list["propname"])): + for i, item in enumerate(template_list.items): item_names.append(item.name) if item.name == item_name: - setattr(spied_list["active_dataptr"], spied_list["active_propname"], i) + template_list.set_active_index(i) panel_spy.is_spy_dirty = True return assert False, f"Could not find item {item_name} in {item_names}" @@ -707,7 +728,7 @@ def i_press_operator(operator): assert False, f"Failed to run operator bpy.ops.{operator} because of {e}" -def i_click_button_on_panel(button, panel_spy): +def _i_click_button_on_panel(button, panel_spy): for spied_operator in panel_spy.spied_operators: if spied_operator["text"] == button or spied_operator["icon"] == button: spied_operator["operator"]("INVOKE_DEFAULT", **spied_operator["kwargs"]) @@ -736,7 +757,7 @@ def i_click_button(button): """ assert panel_spy panel_spy.refresh_spy() - i_click_button_on_panel(button, panel_spy) + _i_click_button_on_panel(button, panel_spy) @given(parsers.parse('I click the "{button}" after the text "{text}"'))