From 557d3429eb73ec717278d35f51dc9c463f37f053 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Sat, 3 Sep 2022 14:32:39 +1000 Subject: [PATCH] Support bulk deletion of psets on selected objects --- src/blenderbim/blenderbim/bim/helper.py | 21 ++++++ .../blenderbim/bim/module/pset/operator.py | 68 +++++++------------ src/blenderbim/test/bim/feature/pset.feature | 60 ++++++++++++++++ 3 files changed, 106 insertions(+), 43 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/helper.py b/src/blenderbim/blenderbim/bim/helper.py index 851a54713f..e1190d0f37 100644 --- a/src/blenderbim/blenderbim/bim/helper.py +++ b/src/blenderbim/blenderbim/bim/helper.py @@ -138,6 +138,27 @@ def get_enum_items(data, prop_name, context): return items +def get_obj_ifc_definition_id(context, obj, obj_type): + if obj_type == "Object": + return bpy.data.objects.get(obj).BIMObjectProperties.ifc_definition_id + elif obj_type == "Material": + return bpy.data.materials.get(obj).BIMObjectProperties.ifc_definition_id + elif obj_type == "Task": + return context.scene.BIMTaskTreeProperties.tasks[ + context.scene.BIMWorkScheduleProperties.active_task_index + ].ifc_definition_id + elif obj_type == "Resource": + return context.scene.BIMResourceTreeProperties.resources[ + context.scene.BIMResourceProperties.active_resource_index + ].ifc_definition_id + elif obj_type == "Profile": + return context.scene.BIMProfileProperties.profiles[ + context.scene.BIMProfileProperties.active_profile_index + ].ifc_definition_id + elif obj_type == "WorkSchedule": + return context.scene.BIMWorkScheduleProperties.active_work_schedule_id + + # hack to close popup # https://blender.stackexchange.com/a/202576/130742 def close_operator_panel(event): diff --git a/src/blenderbim/blenderbim/bim/module/pset/operator.py b/src/blenderbim/blenderbim/bim/module/pset/operator.py index 4e9f7705bb..aa1d7a1975 100644 --- a/src/blenderbim/blenderbim/bim/module/pset/operator.py +++ b/src/blenderbim/blenderbim/bim/module/pset/operator.py @@ -23,6 +23,7 @@ import ifcopenshell.util.unit import ifcopenshell.util.pset import ifcopenshell.util.attribute import blenderbim.bim.schema +import blenderbim.bim.helper import blenderbim.bim.handler import blenderbim.tool as tool import blenderbim.core.pset as core @@ -42,11 +43,9 @@ class Operator: def get_pset_props(context, obj, obj_type): if obj_type == "Object": - obj = bpy.data.objects.get(obj) - return obj.PsetProperties + return bpy.data.objects.get(obj).PsetProperties elif obj_type == "Material": - obj = bpy.data.materials.get(obj) - return obj.PsetProperties + return bpy.data.materials.get(obj).PsetProperties elif obj_type == "Task": return context.scene.TaskPsetProperties elif obj_type == "Resource": @@ -57,29 +56,6 @@ def get_pset_props(context, obj, obj_type): return context.scene.WorkSchedulePsetProperties -def get_pset_obj_ifc_definition_id(context, obj, obj_type): - if obj_type == "Object": - obj = bpy.data.objects.get(obj) - return obj.BIMObjectProperties.ifc_definition_id - elif obj_type == "Material": - obj = bpy.data.materials.get(obj) - return obj.BIMObjectProperties.ifc_definition_id - elif obj_type == "Task": - return context.scene.BIMTaskTreeProperties.tasks[ - context.scene.BIMWorkScheduleProperties.active_task_index - ].ifc_definition_id - elif obj_type == "Resource": - return context.scene.BIMResourceTreeProperties.resources[ - context.scene.BIMResourceProperties.active_resource_index - ].ifc_definition_id - elif obj_type == "Profile": - return context.scene.BIMProfileProperties.profiles[ - context.scene.BIMProfileProperties.active_profile_index - ].ifc_definition_id - elif obj_type == "WorkSchedule": - return context.scene.BIMWorkScheduleProperties.active_work_schedule_id - - class TogglePsetExpansion(bpy.types.Operator, Operator): bl_idname = "bim.toggle_pset_expansion" bl_label = "Toggle Pset Expansion" @@ -102,7 +78,7 @@ class EnablePsetEditing(bpy.types.Operator): def execute(self, context): self.props = get_pset_props(context, self.obj, self.obj_type) self.props.properties.clear() - ifc_definition_id = get_pset_obj_ifc_definition_id(context, self.obj, self.obj_type) + ifc_definition_id = blenderbim.bim.helper.get_obj_ifc_definition_id(context, self.obj, self.obj_type) Data.load(IfcStore.get_file(), ifc_definition_id) data = Data.psets if self.pset_id in Data.psets else Data.qtos pset_data = data[self.pset_id] @@ -243,7 +219,7 @@ class EditPset(bpy.types.Operator, Operator): def _execute(self, context): self.file = IfcStore.get_file() props = get_pset_props(context, self.obj, self.obj_type) - ifc_definition_id = get_pset_obj_ifc_definition_id(context, self.obj, self.obj_type) + ifc_definition_id = blenderbim.bim.helper.get_obj_ifc_definition_id(context, self.obj, self.obj_type) properties = {} pset_id = self.pset_id or props.active_pset_id @@ -298,18 +274,24 @@ class RemovePset(bpy.types.Operator, Operator): obj_type: bpy.props.StringProperty() def _execute(self, context): - self.file = IfcStore.get_file() - props = get_pset_props(context, self.obj, self.obj_type) - ifc_definition_id = get_pset_obj_ifc_definition_id(context, self.obj, self.obj_type) - ifcopenshell.api.run( - "pset.remove_pset", - self.file, - **{ - "product": self.file.by_id(ifc_definition_id), - "pset": self.file.by_id(self.pset_id), - }, - ) - Data.load(IfcStore.get_file(), ifc_definition_id) + if self.obj_type == "Object": + if context.selected_objects: + objects = [o.name for o in context.selected_objects] + else: + objects = [context.active_object.name] + else: + objects = [self.obj] + pset_name = tool.Ifc.get().by_id(self.pset_id).Name + for obj in objects: + props = get_pset_props(context, obj, self.obj_type) + ifc_definition_id = blenderbim.bim.helper.get_obj_ifc_definition_id(context, obj, self.obj_type) + element = tool.Ifc.get().by_id(ifc_definition_id) + pset = ifcopenshell.util.element.get_psets(element, should_inherit=False).get(pset_name, None) + if pset: + ifcopenshell.api.run( + "pset.remove_pset", tool.Ifc.get(), product=element, pset=tool.Ifc.get().by_id(pset["id"]) + ) + Data.load(IfcStore.get_file(), ifc_definition_id) class AddPset(bpy.types.Operator, Operator): @@ -330,7 +312,7 @@ class AddPset(bpy.types.Operator, Operator): else: objects = [self.obj] for obj in objects: - ifc_definition_id = get_pset_obj_ifc_definition_id(context, obj, self.obj_type) + ifc_definition_id = blenderbim.bim.helper.get_obj_ifc_definition_id(context, obj, self.obj_type) if not ifc_definition_id: continue element = tool.Ifc.get().by_id(ifc_definition_id) @@ -349,7 +331,7 @@ class AddQto(bpy.types.Operator, Operator): def _execute(self, context): self.file = IfcStore.get_file() props = get_pset_props(context, self.obj, self.obj_type) - ifc_definition_id = get_pset_obj_ifc_definition_id(context, self.obj, self.obj_type) + ifc_definition_id = blenderbim.bim.helper.get_obj_ifc_definition_id(context, self.obj, self.obj_type) ifcopenshell.api.run( "pset.add_qto", self.file, diff --git a/src/blenderbim/test/bim/feature/pset.feature b/src/blenderbim/test/bim/feature/pset.feature index 4515e57e75..c1063f85f5 100644 --- a/src/blenderbim/test/bim/feature/pset.feature +++ b/src/blenderbim/test/bim/feature/pset.feature @@ -1,6 +1,34 @@ @pset Feature: Pset +Scenario: Add pset - object + Given an empty IFC project + And I add a cube + And the object "Cube" is selected + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + And the object "IfcWall/Cube" is selected + And I set "active_object.PsetProperties.pset_name" to "Pset_WallCommon" + When I press "bim.add_pset(obj='IfcWall/Cube', obj_type='Object')" + Then nothing happens + +Scenario: Add pset - multiple objects + Given an empty IFC project + And I add a cube + And the object "Cube" is selected + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + And the object "IfcWall/Cube" is selected + And I add a cube + And the object "Cube" is selected + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + And the object "IfcWall/Cube" is selected + And additionally the object "IfcWall/Cube.001" is selected + And I set "active_object.PsetProperties.pset_name" to "Pset_WallCommon" + When I press "bim.add_pset(obj='IfcWall/Cube', obj_type='Object')" + Then nothing happens + Scenario: Enable pset editing - object Given an empty IFC project And I add a cube @@ -117,3 +145,35 @@ Scenario: Copy property to selected - copy property And I set "active_object.PsetProperties.properties[2].metadata.string_value" to "Foo" When I press "bim.copy_property_to_selection(name='FireRating')" Then nothing happens + +Scenario: Remove pset - object + Given an empty IFC project + And I add a cube + And the object "Cube" is selected + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + And the object "IfcWall/Cube" is selected + And I set "active_object.PsetProperties.pset_name" to "Pset_WallCommon" + And I press "bim.add_pset(obj='IfcWall/Cube', obj_type='Object')" + And the variable "pset" is "{ifc}.by_type('IfcPropertySet')[-1].id()" + When I press "bim.remove_pset(pset_id={pset}, obj='IfcWall/Cube', obj_type='Object')" + Then nothing happens + +Scenario: Remove pset - multiple objects + Given an empty IFC project + And I add a cube + And the object "Cube" is selected + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + And the object "IfcWall/Cube" is selected + And I add a cube + And the object "Cube" is selected + And I set "scene.BIMRootProperties.ifc_class" to "IfcWall" + And I press "bim.assign_class" + And the object "IfcWall/Cube" is selected + And additionally the object "IfcWall/Cube.001" is selected + And I set "active_object.PsetProperties.pset_name" to "Pset_WallCommon" + And I press "bim.add_pset(obj='IfcWall/Cube', obj_type='Object')" + And the variable "pset" is "{ifc}.by_type('IfcPropertySet')[-1].id()" + When I press "bim.remove_pset(pset_id={pset}, obj='IfcWall/Cube', obj_type='Object')" + Then nothing happens