IfcStore.unlink_element breaking change

Previously there was a problem with this method that it might confuse Blender objects copied from other sessions (or even from the current session but a few steps back) from current IFC objects and might unlink them accidentally.

Option to provide either element or obj was more of a convenience feature but now they have a different meaning to clearly distinguish between unlinking ifc element and unlinking some blender object without touching any ifc elements.
This commit is contained in:
Andrej730
2024-06-11 12:20:16 +05:00
parent 6630db21ee
commit 3df75e9af3
+36 -30
View File
@@ -218,12 +218,10 @@ class IfcStore:
existing_obj = IfcStore.id_map.get(element.id(), None) existing_obj = IfcStore.id_map.get(element.id(), None)
if existing_obj == obj: if existing_obj == obj:
return return
elif existing_obj: # TODO: When does this occur?
try: elif existing_obj and tool.Blender.is_valid_data_block(existing_obj):
existing_obj.name IfcStore.unlink_element(obj=existing_obj)
IfcStore.unlink_element(element=element, obj=existing_obj)
except:
pass
IfcStore.id_map[element.id()] = obj IfcStore.id_map[element.id()] = obj
if hasattr(element, "GlobalId"): if hasattr(element, "GlobalId"):
IfcStore.guid_map[element.GlobalId] = obj IfcStore.guid_map[element.GlobalId] = obj
@@ -291,44 +289,52 @@ class IfcStore:
def unlink_element( def unlink_element(
element: Optional[ifcopenshell.entity_instance] = None, obj: Optional[IFC_CONNECTED_TYPE] = None element: Optional[ifcopenshell.entity_instance] = None, obj: Optional[IFC_CONNECTED_TYPE] = None
) -> None: ) -> None:
if element is None: """Unlink IFC `element` or Blender `obj`.
try:
element = tool.Ifc.get_entity(obj)
except:
pass
If element is provided then it will be unlinked from the related Blender object.
Blender object's IFC information is also will be purged.
If Blender object is provided then all IFC information will be purged from this object.
Method won't be searching for related IFC elements as Blender object might come from
different Blender session and there might be an ids/guids clash.
Only one argument must be provided and other should be omitted as they have different meaning.
:raises TypeError: If both arguments or no arguments provided.
"""
if not bool(element) ^ bool(obj):
raise TypeError("Only one argument must be provided - element or obj.")
if obj:
if isinstance(obj, bpy.types.Material):
obj.BIMMaterialProperties.ifc_style_id = 0
obj.BIMObjectProperties.ifc_definition_id = 0
return
assert element # Type checker.
if obj is None: if obj is None:
try: try:
potential_obj = IfcStore.id_map[element.id()] potential_obj = IfcStore.id_map[element.id()]
potential_obj.name if tool.Blender.is_valid_data_block(potential_obj):
obj = potential_obj obj = potential_obj
except: except:
pass pass
try: try:
if element: del IfcStore.id_map[element.id()]
del IfcStore.id_map[element.id()]
else:
del IfcStore.id_map[obj.BIMObjectProperties.ifc_definition_id]
except: except:
pass pass
try: if global_id := getattr(element, "GlobalId", None):
if element and hasattr(element, "GlobalId"): try:
del IfcStore.guid_map[element.GlobalId] del IfcStore.guid_map[global_id]
except: except:
pass pass
if element and element.is_a("IfcSurfaceStyle"):
obj.BIMMaterialProperties.ifc_style_id = 0
elif obj:
obj.BIMObjectProperties.ifc_definition_id = 0
if IfcStore.history: if IfcStore.history:
data = {} data = {}
if element: data["id"] = element.id()
data["id"] = element.id() data["guid"] = global_id
data["guid"] = getattr(element, "GlobalId", None)
if obj: if obj:
data["obj"] = obj.name data["obj"] = obj.name
IfcStore.history[-1]["operations"].append( IfcStore.history[-1]["operations"].append(