diff --git a/src/blenderbim/blenderbim/bim/module/project/operator.py b/src/blenderbim/blenderbim/bim/module/project/operator.py index 53a7a17236..12749d5508 100644 --- a/src/blenderbim/blenderbim/bim/module/project/operator.py +++ b/src/blenderbim/blenderbim/bim/module/project/operator.py @@ -3,6 +3,7 @@ import logging import ifcopenshell import ifcopenshell.api import bpy +import blenderbim.bim.handler from blenderbim.bim.ifc import IfcStore from blenderbim.bim import import_ifc @@ -232,9 +233,11 @@ class AppendLibraryElement(bpy.types.Operator): element = ifcopenshell.api.run( "project.append_asset", IfcStore.get_file(), + library=IfcStore.library_file, element=IfcStore.library_file.by_id(self.definition), ) self.import_type_from_ifc(element) + blenderbim.bim.handler.purge_module_data() return {"FINISHED"} def import_type_from_ifc(self, element): diff --git a/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py b/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py index 42e59d4bb1..76c2bd7e81 100644 --- a/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py +++ b/src/ifcopenshell-python/ifcopenshell/api/project/append_asset.py @@ -5,14 +5,22 @@ import ifcopenshell.api class Usecase: def __init__(self, file, **settings): self.file = file - self.settings = {"element": None} + self.settings = {"library": None, "element": None} for key, value in settings.items(): self.settings[key] = value def execute(self): - element = self.file.add(self.settings["element"]) - for rel in self.settings["element"].HasAssociations: - self.file.add(rel) + self.added_elements = set() + if self.settings["element"].is_a("IfcTypeProduct"): + return self.append_type_product() + + def append_type_product(self): + self.whitelisted_inverse_attributes = { + "IfcObjectDefinition": ["HasAssociations"], + "IfcMaterialDefinition": ["HasExternalReferences", "HasProperties"], + "IfcRepresentationItem": ["StyledByItem"], + } + element = self.add_element(self.settings["element"]) self.existing_contexts = self.file.by_type("IfcGeometricRepresentationContext") added_contexts = [e for e in self.file.traverse(element) if e.is_a("IfcGeometricRepresentationContext")] for added_context in added_contexts: @@ -26,6 +34,24 @@ class Usecase: ifcopenshell.util.element.remove_deep(self.file, added_context) return element + def add_element(self, element): + if element.id() == 0 or element.id() in self.added_elements: + return + new = self.file.add(element) + self.added_elements.add(element.id()) + self.add_inverse(element) + for subelement in self.settings["library"].traverse(element): + self.add_inverse(subelement) + return new + + def add_inverse(self, element): + inverse_attributes = [] + [inverse_attributes.extend(v) for k, v in self.whitelisted_inverse_attributes.items() if element.is_a(k)] + inverse_attributes = set(inverse_attributes) + for attribute in inverse_attributes: + for inverse in getattr(element, attribute, []): + self.add_element(inverse) + def get_equivalent_existing_context(self, added_context): for context in self.existing_contexts: if context.is_a() != added_context.is_a():