diff --git a/src/blenderbim/blenderbim/bim/__init__.py b/src/blenderbim/blenderbim/bim/__init__.py index 6f443a243e..38e699764e 100644 --- a/src/blenderbim/blenderbim/bim/__init__.py +++ b/src/blenderbim/blenderbim/bim/__init__.py @@ -111,6 +111,7 @@ classes = [ prop.PsetQto, prop.GlobalId, prop.BIMObjectProperties, + prop.BIMCollectionProperties, prop.BIMMaterialProperties, prop.BIMMeshProperties, ui.BIM_PT_section_plane, @@ -158,6 +159,7 @@ def register(): bpy.app.handlers.load_post.append(handler.loadIfcStore) bpy.app.handlers.save_post.append(handler.ensureIfcExported) bpy.types.Scene.BIMProperties = bpy.props.PointerProperty(type=prop.BIMProperties) + bpy.types.Collection.BIMCollectionProperties = bpy.props.PointerProperty(type=prop.BIMCollectionProperties) bpy.types.Object.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties) bpy.types.Material.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties) bpy.types.Material.BIMMaterialProperties = bpy.props.PointerProperty(type=prop.BIMMaterialProperties) @@ -184,6 +186,7 @@ def unregister(): bpy.app.handlers.load_post.remove(handler.loadIfcStore) bpy.app.handlers.save_post.remove(handler.ensureIfcExported) del bpy.types.Scene.BIMProperties + del bpy.types.Collection.BIMCollectionProperties del bpy.types.Object.BIMObjectProperties del bpy.types.Material.BIMObjectProperties del bpy.types.Material.BIMMaterialProperties diff --git a/src/blenderbim/blenderbim/bim/import_ifc.py b/src/blenderbim/blenderbim/bim/import_ifc.py index 7fd16aa3d7..901574e690 100644 --- a/src/blenderbim/blenderbim/bim/import_ifc.py +++ b/src/blenderbim/blenderbim/bim/import_ifc.py @@ -1337,8 +1337,9 @@ class IfcImporter: "{}/{}".format(self.project["ifc"].is_a(), self.project["ifc"].Name) ) obj = self.create_product(self.project["ifc"]) - if obj: - self.project["blender"].objects.link(obj) + self.project["blender"].objects.link(obj) + self.project["blender"].BIMCollectionProperties.obj = obj + obj.BIMObjectProperties.collection = self.project["blender"] def create_collections(self): if self.ifc_import_settings.collection_mode == "DECOMPOSITION": @@ -1673,6 +1674,8 @@ class IfcImporter: return elif element.GlobalId in self.collections: collection = self.collections[element.GlobalId] + collection.BIMCollectionProperties.obj = obj + obj.BIMObjectProperties.collection = collection collection.name = obj.name return collection.objects.link(obj) elif getattr(element, "Decomposes", None): @@ -1687,7 +1690,10 @@ class IfcImporter: elif element.is_a("IfcGridAxis"): return elif element.GlobalId in self.collections: - return self.collections[element.GlobalId].objects.link(obj) + collection = self.collections[element.GlobalId] + collection.BIMCollectionProperties.obj = obj + obj.BIMObjectProperties.collection = collection + return collection.objects.link(obj) elif element.is_a("IfcTypeObject"): return self.type_collection.objects.link(obj) elif element.is_a("IfcStructuralMember"): diff --git a/src/blenderbim/blenderbim/bim/prop.py b/src/blenderbim/blenderbim/bim/prop.py index 744ae2aea8..3aa001bac4 100644 --- a/src/blenderbim/blenderbim/bim/prop.py +++ b/src/blenderbim/blenderbim/bim/prop.py @@ -409,7 +409,12 @@ class GlobalId(PropertyGroup): name: StringProperty(name="Name") +class BIMCollectionProperties(PropertyGroup): + obj: PointerProperty(type=bpy.types.Object) + + class BIMObjectProperties(PropertyGroup): + collection: PointerProperty(type=bpy.types.Collection) ifc_definition_id: IntProperty(name="IFC Definition ID") blender_offset_type: EnumProperty( items=[(o, o, "") for o in ["NONE", "OBJECT_PLACEMENT", "CARTESIAN_POINT"]], diff --git a/src/blenderbim/blenderbim/tool/collector.py b/src/blenderbim/blenderbim/tool/collector.py index 288d8af991..bad7dfb22a 100644 --- a/src/blenderbim/blenderbim/tool/collector.py +++ b/src/blenderbim/blenderbim/tool/collector.py @@ -59,17 +59,18 @@ class Collector(blenderbim.core.tool.Collector): parent_collection = collection break - if parent_collection: - parent_obj = bpy.data.objects.get(parent_collection.name) - parent = tool.Ifc.get_entity(parent_obj) - if parent: - # This is lazy, but works. One of these will succeed, the other will fail silently. - blenderbim.core.spatial.assign_container( - tool.Ifc, tool.Collector, tool.Spatial, structure_obj=parent_obj, element_obj=obj - ) - blenderbim.core.aggregate.assign_object( - tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=parent_obj, related_obj=obj - ) + if not parent_collection: + return + + parent = tool.Ifc.get_entity(parent_collection.BIMCollectionProperties.obj) + if parent: + # This is lazy, but works. One of these will succeed, the other will fail silently. + blenderbim.core.spatial.assign_container( + tool.Ifc, tool.Collector, tool.Spatial, structure_obj=parent_obj, element_obj=obj + ) + blenderbim.core.aggregate.assign_object( + tool.Ifc, tool.Aggregate, tool.Collector, relating_obj=parent_obj, related_obj=obj + ) @classmethod def assign(cls, obj): @@ -100,18 +101,21 @@ class Collector(blenderbim.core.tool.Collector): @classmethod def _get_own_collection(cls, element, obj): + if obj.BIMObjectProperties.collection: + return obj.BIMObjectProperties.collection + if element.is_a("IfcProject"): - return bpy.data.collections.get(obj.name) or bpy.data.collections.new(obj.name) + return cls._create_own_collection(obj) if tool.Ifc.get_schema() == "IFC2X3": if element.is_a("IfcSpatialStructureElement"): - return bpy.data.collections.get(obj.name) or bpy.data.collections.new(obj.name) + return cls._create_own_collection(obj) else: if element.is_a("IfcSpatialStructureElement") or element.is_a("IfcExternalSpatialStructureElement"): - return bpy.data.collections.get(obj.name) or bpy.data.collections.new(obj.name) + return cls._create_own_collection(obj) if element.is_a("IfcGrid"): - return bpy.data.collections.get(obj.name) or bpy.data.collections.new(obj.name) + return cls._create_own_collection(obj) if element.is_a("IfcGridAxis"): if element.PartOfU: @@ -125,7 +129,7 @@ class Collector(blenderbim.core.tool.Collector): axes = "WAxes" grid_obj = tool.Ifc.get_object(grid) if grid_obj: - grid_col = bpy.data.collections.get(grid_obj.name) + grid_col = cls._get_own_collection(grid, grid_obj) axes_col = [c for c in grid_col.children if axes in c.name] if axes_col: return axes_col[0] @@ -144,7 +148,7 @@ class Collector(blenderbim.core.tool.Collector): return bpy.data.collections.get("Connections") or bpy.data.collections.new("Connections") if getattr(element, "IsDecomposedBy", None): - return bpy.data.collections.get(obj.name) or bpy.data.collections.new(obj.name) + return cls._create_own_collection(obj) @classmethod def _get_collection(cls, element, obj): @@ -180,14 +184,14 @@ class Collector(blenderbim.core.tool.Collector): if aggregate: aggregate_obj = tool.Ifc.get_object(aggregate) if aggregate_obj: - collection = bpy.data.collections.get(aggregate_obj.name) + collection = aggregate_obj.BIMObjectProperties.collection if collection: return collection container = ifcopenshell.util.element.get_container(element) if container: container_obj = tool.Ifc.get_object(container) - collection = bpy.data.collections.get(container_obj.name) + collection = container_obj.BIMObjectProperties.collection if collection: return collection @@ -208,3 +212,10 @@ class Collector(blenderbim.core.tool.Collector): project_obj = tool.Ifc.get_object(tool.Ifc.get().by_type("IfcProject")[0]) project_obj.users_collection[0].children.link(collection) return collection + + @classmethod + def _create_own_collection(cls, obj): + collection = bpy.data.collections.new(obj.name) + obj.BIMObjectProperties.collection = collection + collection.BIMCollectionProperties.obj = obj + return collection diff --git a/src/blenderbim/test/tool/test_collector.py b/src/blenderbim/test/tool/test_collector.py index 5e954e353f..f4d6b8740a 100644 --- a/src/blenderbim/test/tool/test_collector.py +++ b/src/blenderbim/test/tool/test_collector.py @@ -153,6 +153,7 @@ class TestAssign(NewFile): tool.Ifc.link(space_element, space_obj) space_collection = bpy.data.collections.new("IfcSpace/Name") bpy.context.scene.collection.children.link(space_collection) + space_obj.BIMObjectProperties.collection = space_collection space_collection.objects.link(space_obj) ifcopenshell.api.run( "aggregate.assign_object",