Fix #3069. WARNING: dangerous change. Objects that have their own collection now have a pointer to that collection. This fixes a variety of subtle sync bugs.

This commit is contained in:
Dion Moult
2023-06-01 16:58:01 +10:00
parent d2d6a9e7d4
commit 804dbee2c3
5 changed files with 48 additions and 22 deletions
@@ -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)
@@ -195,6 +197,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
+9 -3
View File
@@ -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"):
+5
View File
@@ -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"]],
+30 -19
View File
@@ -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
@@ -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",