diff --git a/src/blenderbim/blenderbim/bim/module/model/opening.py b/src/blenderbim/blenderbim/bim/module/model/opening.py index b98c264336..f37243c40c 100644 --- a/src/blenderbim/blenderbim/bim/module/model/opening.py +++ b/src/blenderbim/blenderbim/bim/module/model/opening.py @@ -668,17 +668,17 @@ class RemoveBooleans(Operator, tool.Ifc.Operator, AddObjectHelper): except: continue - boolean = None + boolean_id = None for inverse in tool.Ifc.get().get_inverse(item): if inverse.is_a("IfcBooleanResult"): - boolean = inverse + boolean_id = inverse.id() break ifcopenshell.api.run("geometry.remove_boolean", tool.Ifc.get(), item=item) if obj.data.BIMMeshProperties.obj: upstream_obj = obj.data.BIMMeshProperties.obj element = tool.Ifc.get_entity(upstream_obj) - bbim_boolean_updates.setdefault(element, []).append(boolean) + bbim_boolean_updates.setdefault(element, []).append(boolean_id) body = ifcopenshell.util.representation.get_representation(element, "Model", "Body", "MODEL_VIEW") if body: blenderbim.core.geometry.switch_representation( @@ -692,8 +692,8 @@ class RemoveBooleans(Operator, tool.Ifc.Operator, AddObjectHelper): ) bpy.data.objects.remove(obj) - for element, booleans in bbim_boolean_updates.items(): - tool.Model.unmark_manual_booleans(element, booleans) + for element, boolean_ids in bbim_boolean_updates.items(): + tool.Model.unmark_manual_booleans(element, boolean_ids) tool.Blender.set_active_object(upstream_obj) return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/bim/module/void/operator.py b/src/blenderbim/blenderbim/bim/module/void/operator.py index 815389c73f..5914049d02 100644 --- a/src/blenderbim/blenderbim/bim/module/void/operator.py +++ b/src/blenderbim/blenderbim/bim/module/void/operator.py @@ -259,8 +259,10 @@ class BooleansMarkAsManual(bpy.types.Operator): if self.mark_as_manual: tool.Model.mark_manual_booleans(element, booleans) else: - tool.Model.unmark_manual_booleans(element, booleans) + tool.Model.unmark_manual_booleans(element, [b.id() for b in booleans]) - self.report({"INFO"}, f"{len(booleans)} were marked as {'manual' if self.mark_as_manual else 'automatic'}") + self.report( + {"INFO"}, f"{len(booleans)} booleans were marked as {'manual' if self.mark_as_manual else 'automatic'}" + ) blenderbim.bim.handler.refresh_ui_data() return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/tool/model.py b/src/blenderbim/blenderbim/tool/model.py index 038b245c71..8d36618305 100644 --- a/src/blenderbim/blenderbim/tool/model.py +++ b/src/blenderbim/blenderbim/tool/model.py @@ -521,11 +521,12 @@ class Model(blenderbim.core.tool.Model): ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Data": data}) @classmethod - def unmark_manual_booleans(cls, element, booleans): + def unmark_manual_booleans(cls, element, boolean_ids): + # NOTE: we use use boolean_ids instead of boolean entities + # so it will be possible to unmark manual booleans after they already was deleted pset = ifcopenshell.util.element.get_pset(element, "BBIM_Boolean") if not pset: return - boolean_ids = [b.id() for b in booleans] data = set(json.loads(pset["Data"])) data -= set(boolean_ids) data = list(data) diff --git a/src/blenderbim/test/tool/test_model.py b/src/blenderbim/test/tool/test_model.py index 1a7f914ff3..96f310da11 100644 --- a/src/blenderbim/test/tool/test_model.py +++ b/src/blenderbim/test/tool/test_model.py @@ -21,6 +21,7 @@ import ifcopenshell import blenderbim.core.tool import blenderbim.tool as tool import numpy as np +import json from test.bim.bootstrap import NewFile from blenderbim.tool.model import Model as subject from ifcopenshell.util.shape_builder import V @@ -108,6 +109,37 @@ class TestGetManualBooleans(NewFile): assert len(subject.get_manual_booleans(element)) == 2 +class TestMarkManualBooleans(NewFile): + def test_run(self): + ifc = ifcopenshell.file() + tool.Ifc.set(ifc) + + element = ifc.createIfcWall() + boolean = ifc.createIfcBooleanClippingResult() + subject.mark_manual_booleans(element, [boolean]) + pset = ifcopenshell.util.element.get_pset(element, "BBIM_Boolean") + assert pset + value = json.loads(pset["Data"]) + assert set(value) == {boolean.id()} + + +class TestUnmarkManualBooleans(NewFile): + def test_run(self): + ifc = ifcopenshell.file() + tool.Ifc.set(ifc) + + element = ifc.createIfcWall() + boolean = ifc.createIfcBooleanClippingResult() + boolean2 = ifc.createIfcBooleanClippingResult() + subject.mark_manual_booleans(element, [boolean, boolean2]) + subject.unmark_manual_booleans(element, [boolean.id()]) + + pset = ifcopenshell.util.element.get_pset(element, "BBIM_Boolean") + assert pset + value = json.loads(pset["Data"]) + assert set(value) == {boolean2.id()} + + class TestStairCalculatedParams(NewFile): def compare_data(self, pset_data, expected_calculated_data): calculated_data = subject.get_active_stair_calculated_params(pset_data)