From 2d061f63fb5cc25352a4ecf8271d0a3938bd1b7f Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Fri, 8 Jan 2021 11:41:54 +1100 Subject: [PATCH] WIP port add aggregate and remove container. See #1222. --- .../bim/module/aggregate/__init__.py | 1 + .../bim/module/aggregate/operator.py | 32 ++++++++-- .../blenderbim/bim/module/aggregate/ui.py | 1 + .../blenderbim/bim/module/root/operator.py | 2 +- .../blenderbim/bim/module/spatial/__init__.py | 1 + .../blenderbim/bim/module/spatial/operator.py | 61 +++++++++++++++++-- .../bim/module/spatial/remove_container.py | 20 ++++++ .../blenderbim/bim/module/spatial/ui.py | 3 + 8 files changed, 108 insertions(+), 13 deletions(-) create mode 100644 src/ifcblenderexport/blenderbim/bim/module/spatial/remove_container.py diff --git a/src/ifcblenderexport/blenderbim/bim/module/aggregate/__init__.py b/src/ifcblenderexport/blenderbim/bim/module/aggregate/__init__.py index 253c4f35c5..d70cecd453 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/aggregate/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/module/aggregate/__init__.py @@ -5,6 +5,7 @@ classes = ( operator.AssignObject, operator.EnableEditingAggregate, operator.DisableEditingAggregate, + operator.AddAggregate, ui.BIM_PT_aggregate, ) diff --git a/src/ifcblenderexport/blenderbim/bim/module/aggregate/operator.py b/src/ifcblenderexport/blenderbim/bim/module/aggregate/operator.py index 7644e12699..861b114179 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/aggregate/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/module/aggregate/operator.py @@ -28,15 +28,19 @@ class AssignObject(bpy.types.Operator): Data.load(props.ifc_definition_id) bpy.ops.bim.disable_editing_aggregate(obj=related_object.name) - related_collection = bpy.data.collections.get(related_object.name) - if related_collection: - relating_collection = bpy.data.collections.get(relating_object.name) - self.remove_collection(bpy.context.scene.collection, related_collection) + spatial_collection = bpy.data.collections.get(related_object.name) + relating_collection = bpy.data.collections.get(relating_object.name) + if spatial_collection: + self.remove_collection(bpy.context.scene.collection, spatial_collection) for collection in bpy.data.collections: if collection == relating_collection: - collection.children.link(related_collection) + collection.children.link(spatial_collection) continue - self.remove_collection(collection, related_collection) + self.remove_collection(collection, spatial_collection) + else: + for collection in related_object.users_collection: + collection.objects.unlink(related_object) + relating_collection.objects.link(related_object) return {"FINISHED"} def remove_collection(self, parent, child): @@ -65,3 +69,19 @@ class DisableEditingAggregate(bpy.types.Operator): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object obj.BIMObjectProperties.is_editing_aggregate = False return {"FINISHED"} + + +class AddAggregate(bpy.types.Operator): + bl_idname = "bim.add_aggregate" + bl_label = "Add Aggregate" + obj: bpy.props.StringProperty() + + def execute(self, context): + obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object + aggregate_collection = bpy.data.collections.new("IfcElementAssembly/Assembly") + bpy.context.scene.collection.children.link(aggregate_collection) + aggregate = bpy.data.objects.new("Assembly", None) + aggregate_collection.objects.link(aggregate) + bpy.ops.bim.assign_class(obj=aggregate.name, ifc_class="IfcElementAssembly") + bpy.ops.bim.assign_object(related_object=obj.name, relating_object=aggregate.name) + return {"FINISHED"} diff --git a/src/ifcblenderexport/blenderbim/bim/module/aggregate/ui.py b/src/ifcblenderexport/blenderbim/bim/module/aggregate/ui.py index 57beab793c..c6b5c3475d 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/aggregate/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/module/aggregate/ui.py @@ -41,3 +41,4 @@ class BIM_PT_aggregate(Panel): name = "This object is not part of an aggregation" row.label(text=name) row.operator("bim.enable_editing_aggregate", icon="GREASEPENCIL", text="") + row.operator("bim.add_aggregate", icon="ADD", text="") diff --git a/src/ifcblenderexport/blenderbim/bim/module/root/operator.py b/src/ifcblenderexport/blenderbim/bim/module/root/operator.py index 8f15853a81..36ae83103f 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/root/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/module/root/operator.py @@ -152,7 +152,7 @@ class AssignClass(bpy.types.Operator): def assign_potential_spatial_container(self, obj): for collection in obj.users_collection: - if "Ifc" not in collection.name: + if "Ifc" not in collection.name or collection.name == obj.name: continue bpy.ops.bim.assign_container(relating_structure=collection.name, related_element=obj.name) break diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/__init__.py b/src/ifcblenderexport/blenderbim/bim/module/spatial/__init__.py index 75182506a1..cc5e0ef745 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/spatial/__init__.py +++ b/src/ifcblenderexport/blenderbim/bim/module/spatial/__init__.py @@ -3,6 +3,7 @@ from . import ui, operator classes = ( operator.AssignContainer, + operator.RemoveContainer, operator.EnableEditingContainer, operator.DisableEditingContainer, ui.BIM_PT_spatial, diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/operator.py b/src/ifcblenderexport/blenderbim/bim/module/spatial/operator.py index 3edb2bc2a2..fa7e87a9f0 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/spatial/operator.py +++ b/src/ifcblenderexport/blenderbim/bim/module/spatial/operator.py @@ -1,5 +1,6 @@ import bpy import blenderbim.bim.module.spatial.assign_container as assign_container +import blenderbim.bim.module.spatial.remove_container as remove_container from blenderbim.bim.ifc import IfcStore from blenderbim.bim.module.spatial.data import Data @@ -12,9 +13,13 @@ class AssignContainer(bpy.types.Operator): def execute(self, context): self.file = IfcStore.get_file() - related_element = bpy.data.objects.get(self.related_element) if self.related_element else bpy.context.active_object + related_element = ( + bpy.data.objects.get(self.related_element) if self.related_element else bpy.context.active_object + ) props = related_element.BIMObjectProperties - relating_structure = bpy.data.objects.get(self.relating_structure) if self.relating_structure else props.relating_structure + relating_structure = ( + bpy.data.objects.get(self.relating_structure) if self.relating_structure else props.relating_structure + ) if not relating_structure or not relating_structure.BIMObjectProperties.ifc_definition_id: return {"FINISHED"} assign_container.Usecase( @@ -27,12 +32,25 @@ class AssignContainer(bpy.types.Operator): Data.load(props.ifc_definition_id) bpy.ops.bim.disable_editing_container(obj=related_element.name) - for collection in related_element.users_collection: - collection.objects.unlink(related_element) - collection = bpy.data.collections.get(relating_structure.name) - collection.objects.link(related_element) + aggregate_collection = bpy.data.collections.get(related_element.name) + relating_collection = bpy.data.collections.get(relating_structure.name) + if aggregate_collection: + self.remove_collection(bpy.context.scene.collection, aggregate_collection) + for collection in bpy.data.collections: + self.remove_collection(collection, aggregate_collection) + relating_collection.children.link(aggregate_collection) + else: + for collection in related_element.users_collection: + collection.objects.unlink(related_element) + relating_collection.objects.link(related_element) return {"FINISHED"} + def remove_collection(self, parent, child): + try: + parent.children.unlink(child) + except: + pass + class EnableEditingContainer(bpy.types.Operator): bl_idname = "bim.enable_editing_container" @@ -53,3 +71,34 @@ class DisableEditingContainer(bpy.types.Operator): obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object obj.BIMObjectProperties.is_editing_container = False return {"FINISHED"} + + +class RemoveContainer(bpy.types.Operator): + bl_idname = "bim.remove_container" + bl_label = "Remvoe Container" + obj: bpy.props.StringProperty() + + def execute(self, context): + obj = bpy.data.objects.get(self.obj) if self.obj else bpy.context.active_object + props = obj.BIMObjectProperties + self.file = IfcStore.get_file() + remove_container.Usecase(self.file, {"product": self.file.by_id(props.ifc_definition_id)}).execute() + Data.load(props.ifc_definition_id) + + aggregate_collection = bpy.data.collections.get(obj.name) + if aggregate_collection: + self.remove_collection(bpy.context.scene.collection, aggregate_collection) + for collection in bpy.data.collections: + self.remove_collection(collection, spatial_collection) + bpy.context.scene.collection.children.link(aggregate_collection) + else: + for collection in obj.users_collection: + collection.objects.unlink(obj) + bpy.context.scene.collection.objects.link(obj) + return {"FINISHED"} + + def remove_collection(self, parent, child): + try: + parent.children.unlink(child) + except: + pass diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/remove_container.py b/src/ifcblenderexport/blenderbim/bim/module/spatial/remove_container.py new file mode 100644 index 0000000000..57b9a75af3 --- /dev/null +++ b/src/ifcblenderexport/blenderbim/bim/module/spatial/remove_container.py @@ -0,0 +1,20 @@ +import ifcopenshell + + +class Usecase: + def __init__(self, file, settings=None): + self.file = file + self.settings = {"product": None} + for key, value in settings.items(): + self.settings[key] = value + + def execute(self): + contained_in_structure = self.settings["product"].ContainedInStructure + + if contained_in_structure: + related_elements = list(contained_in_structure[0].RelatedElements) + related_elements.remove(self.settings["product"]) + if related_elements: + contained_in_structure[0].RelatedElements = related_elements + else: + self.file.remove(contained_in_structure) diff --git a/src/ifcblenderexport/blenderbim/bim/module/spatial/ui.py b/src/ifcblenderexport/blenderbim/bim/module/spatial/ui.py index 41ac16c034..7e953f3e9c 100644 --- a/src/ifcblenderexport/blenderbim/bim/module/spatial/ui.py +++ b/src/ifcblenderexport/blenderbim/bim/module/spatial/ui.py @@ -11,6 +11,8 @@ class BIM_PT_spatial(Panel): @classmethod def poll(cls, context): + if not context.active_object: + return False props = context.active_object.BIMObjectProperties if not props.ifc_definition_id: return False @@ -41,3 +43,4 @@ class BIM_PT_spatial(Panel): name = "This object is not spatially contained" row.label(text=name) row.operator("bim.enable_editing_container", icon="GREASEPENCIL", text="") + row.operator("bim.remove_container", icon="X", text="")