Skip to content

Commit 9508858

Browse files
committed
New unassign aggregate feature.
1 parent 3aa36dd commit 9508858

11 files changed

Lines changed: 115 additions & 7 deletions

File tree

src/blenderbim/blenderbim/bim/module/aggregate/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
classes = (
2323
operator.AssignObject,
24+
operator.UnassignObject,
2425
operator.EnableEditingAggregate,
2526
operator.DisableEditingAggregate,
2627
operator.AddAggregate,

src/blenderbim/blenderbim/bim/module/aggregate/data.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ class AggregateData:
1313

1414
@classmethod
1515
def load(cls):
16-
cls.data = {"has_aggregate": cls.has_aggregate(), "label": cls.get_label()}
16+
cls.data = {
17+
"has_aggregate": cls.has_aggregate(),
18+
"label": cls.get_label(),
19+
"relating_object_id": cls.get_relating_object_id(),
20+
}
1721
cls.is_loaded = True
1822

1923
@classmethod
@@ -25,3 +29,9 @@ def get_label(cls):
2529
aggregate = ifcopenshell.util.element.get_aggregate(tool.Ifc.get_entity(bpy.context.active_object))
2630
if aggregate:
2731
return f"{aggregate.is_a()}/{aggregate.Name or ''}"
32+
33+
@classmethod
34+
def get_relating_object_id(cls):
35+
aggregate = ifcopenshell.util.element.get_aggregate(tool.Ifc.get_entity(bpy.context.active_object))
36+
if aggregate:
37+
return aggregate.id()

src/blenderbim/blenderbim/bim/module/aggregate/operator.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,22 @@ def _execute(self, context):
4747
)
4848

4949

50+
class UnassignObject(bpy.types.Operator, Operator):
51+
bl_idname = "bim.unassign_object"
52+
bl_label = "Unassign Object"
53+
bl_options = {"REGISTER", "UNDO"}
54+
relating_object: bpy.props.IntProperty()
55+
related_object: bpy.props.IntProperty()
56+
57+
def _execute(self, context):
58+
core.unassign_object(
59+
tool.Ifc,
60+
tool.Collector,
61+
relating_obj=tool.Ifc.get_object(tool.Ifc.get().by_id(self.relating_object)),
62+
related_obj=tool.Ifc.get_object(tool.Ifc.get().by_id(self.related_object)),
63+
)
64+
65+
5066
class EnableEditingAggregate(bpy.types.Operator, Operator):
5167
bl_idname = "bim.enable_editing_aggregate"
5268
bl_label = "Enable Editing Aggregate"

src/blenderbim/blenderbim/bim/module/aggregate/ui.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@ def draw(self, context):
6060
row = self.layout.row(align=True)
6161
if AggregateData.data["has_aggregate"]:
6262
row.label(text=AggregateData.data["label"])
63+
row.operator("bim.enable_editing_aggregate", icon="GREASEPENCIL", text="")
64+
row.operator("bim.add_aggregate", icon="ADD", text="")
65+
op = row.operator("bim.unassign_object", icon="X", text="")
66+
op.relating_object = AggregateData.data["relating_object_id"]
67+
op.related_object = context.active_object.BIMObjectProperties.ifc_definition_id
6368
else:
6469
row.label(text="No Aggregate Found")
65-
row.operator("bim.enable_editing_aggregate", icon="GREASEPENCIL", text="")
66-
row.operator("bim.add_aggregate", icon="ADD", text="")
70+
row.operator("bim.enable_editing_aggregate", icon="GREASEPENCIL", text="")
71+
row.operator("bim.add_aggregate", icon="ADD", text="")

src/blenderbim/blenderbim/core/aggregate.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,10 @@ def assign_object(ifc, aggregator, collector, relating_obj=None, related_obj=Non
1616
collector.assign(related_obj)
1717
aggregator.disable_editing(related_obj)
1818
return rel
19+
20+
21+
def unassign_object(ifc, collector, relating_obj=None, related_obj=None):
22+
rel = ifc.run("aggregate.unassign_object", product=ifc.get_entity(related_obj))
23+
collector.assign(relating_obj)
24+
collector.assign(related_obj)
25+
return rel

src/blenderbim/blenderbim/tool/collector.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ def assign(cls, obj):
4343
object_collection.objects.link(obj)
4444

4545
if collection_collection and collection_collection.children.find(object_collection.name) == -1:
46+
if bpy.context.scene.collection.children.find(object_collection.name) != -1:
47+
bpy.context.scene.collection.children.unlink(object_collection)
4648
for collection in bpy.data.collections:
4749
if collection.children.find(object_collection.name) != -1:
4850
collection.children.unlink(object_collection)

src/blenderbim/test/bim/feature/aggregate.feature

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ Scenario: Assign object
2323
And the variable "related_object" is "tool.Ifc.get().by_type('IfcBuildingStorey')[0].id()"
2424
When I press "bim.assign_object(relating_object={relating_object}, related_object={related_object})"
2525
Then the object "IfcSite/My Site" is in the collection "IfcSite/My Site"
26-
Then the object "IfcBuildingStorey/My Storey" is in the collection "IfcBuildingStorey/My Storey"
27-
Then the collection "IfcBuildingStorey/My Storey" is in the collection "IfcSite/My Site"
26+
And the object "IfcBuildingStorey/My Storey" is in the collection "IfcBuildingStorey/My Storey"
27+
And the collection "IfcBuildingStorey/My Storey" is in the collection "IfcSite/My Site"
2828

29+
Scenario: Unassign object
30+
Given an empty IFC project
31+
And the object "IfcBuildingStorey/My Storey" is selected
32+
And I press "bim.enable_editing_aggregate"
33+
And the variable "relating_object" is "tool.Ifc.get().by_type('IfcSite')[0].id()"
34+
And the variable "related_object" is "tool.Ifc.get().by_type('IfcBuildingStorey')[0].id()"
35+
And I press "bim.assign_object(relating_object={relating_object}, related_object={related_object})"
36+
And the object "IfcBuildingStorey/My Storey" is selected
37+
When I press "bim.unassign_object(relating_object={relating_object}, related_object={related_object})"
38+
Then the object "IfcSite/My Site" is in the collection "IfcSite/My Site"
39+
And the object "IfcBuildingStorey/My Storey" is in the collection "IfcBuildingStorey/My Storey"
40+
And the collection "IfcBuildingStorey/My Storey" is in the collection "IfcProject/My Project"

src/blenderbim/test/core/test_aggregate.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,12 @@ def test_run(self, ifc, aggregator, collector):
2929
subject.assign_object(ifc, aggregator, collector, relating_obj="relating_obj", related_obj="related_obj")
3030
== "rel"
3131
)
32+
33+
34+
class TestUnassignObject:
35+
def test_run(self, ifc, collector):
36+
ifc.get_entity("related_obj").should_be_called().will_return("related_object")
37+
ifc.run("aggregate.unassign_object", product="related_object").should_be_called().will_return("rel")
38+
collector.assign("relating_obj").should_be_called()
39+
collector.assign("related_obj").should_be_called()
40+
assert subject.unassign_object(ifc, collector, relating_obj="relating_obj", related_obj="related_obj") == "rel"

src/blenderbim/test/tool/test_collector.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,21 @@ def test_in_decomposition_mode_projects_are_placed_in_a_collection_of_the_same_n
9999
subject.assign(element_obj)
100100
assert len(element_obj.users_collection) == 1
101101
assert element_obj.users_collection[0].name == element_obj.name
102+
103+
def test_in_decomposition_mode_existing_collections_are_reassigned_to_the_correct_place_in_the_hierarchy(self):
104+
bpy.ops.bim.create_project()
105+
space_obj = bpy.data.objects.new("IfcSpace/Name", None)
106+
space_element = tool.Ifc.get().createIfcSpace()
107+
tool.Ifc.link(space_element, space_obj)
108+
space_collection = bpy.data.collections.new("IfcSpace/Name")
109+
bpy.context.scene.collection.children.link(space_collection)
110+
space_collection.objects.link(space_obj)
111+
ifcopenshell.api.run(
112+
"aggregate.assign_object",
113+
tool.Ifc.get(),
114+
relating_object=tool.Ifc.get().by_type("IfcSite")[0],
115+
product=space_element,
116+
)
117+
subject.assign(space_obj)
118+
assert bpy.context.scene.collection.children.find(space_collection.name) == -1
119+
assert bpy.data.collections.get("IfcSite/My Site").children.find(space_collection.name) != -1

src/ifcopenshell-python/ifcopenshell/api/aggregate/unassign_object.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ class Usecase:
66
def __init__(self, file, **settings):
77
self.file = file
88
self.settings = {
9-
"relating_object": None,
109
"product": None,
1110
}
1211
for key, value in settings.items():
1312
self.settings[key] = value
1413

1514
def execute(self):
1615
for rel in self.settings["product"].Decomposes or []:
17-
if not rel.is_a("IfcRelAggregates") or rel.RelatingObject != self.settings["relating_object"]:
16+
if not rel.is_a("IfcRelAggregates"):
1817
continue
1918
if len(rel.RelatedObjects) == 1:
2019
return self.file.remove(rel)

0 commit comments

Comments
 (0)