Fix #2968. Deletions are no longer postponed. Should fix or reveal a lot of sync errors.

This commit is contained in:
Dion Moult
2023-04-13 18:38:28 +10:00
parent c4c3fc1bfa
commit cf640a971d
8 changed files with 29 additions and 54 deletions
@@ -45,7 +45,6 @@ class IfcExporter:
self.set_header()
IfcStore.update_cache()
if bpy.context.scene.BIMProjectProperties.is_authoring:
self.sync_deletions()
self.sync_all_objects()
self.sync_edited_objects()
extension = self.ifc_export_settings.output_file.split(".")[-1].lower()
@@ -87,19 +86,6 @@ class IfcExporter:
self.get_application_name(), self.get_application_version()
)
def sync_deletions(self):
results = []
for ifc_definition_id in IfcStore.deleted_ids:
try:
product = self.file.by_id(ifc_definition_id)
if hasattr(product, "GlobalId"):
results.append(product.GlobalId)
except:
continue
ifcopenshell.api.run("root.remove_product", self.file, **{"product": product})
IfcStore.deleted_ids.clear()
return results
def sync_all_objects(self):
results = []
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
-19
View File
@@ -36,7 +36,6 @@ class IfcStore:
cache_path = None
id_map = {}
guid_map = {}
deleted_ids = set()
edited_objs = set()
pset_template_path = ""
pset_template_file = None
@@ -63,7 +62,6 @@ class IfcStore:
IfcStore.cache_path = None
IfcStore.id_map = {}
IfcStore.guid_map = {}
IfcStore.deleted_ids = set()
IfcStore.edited_objs = set()
IfcStore.pset_template_path = ""
IfcStore.pset_template_file = None
@@ -278,23 +276,6 @@ class IfcStore:
data = {"id": element.id(), "obj": obj.name}
IfcStore.commit_link_element(data)
@staticmethod
def delete_element(element):
IfcStore.deleted_ids.add(element.id())
if IfcStore.history:
data = {"id": element.id()}
IfcStore.history[-1]["operations"].append(
{"rollback": IfcStore.rollback_delete_element, "commit": IfcStore.commit_delete_element, "data": data}
)
@staticmethod
def rollback_delete_element(data):
IfcStore.deleted_ids.remove(data["id"])
@staticmethod
def commit_delete_element(data):
IfcStore.deleted_ids.add(data["id"])
@staticmethod
def link_element(element, obj):
existing_obj = IfcStore.id_map.get(element.id(), None)
@@ -250,6 +250,20 @@ class UpdateRepresentation(bpy.types.Operator, Operator):
obj.data.BIMMeshProperties.ifc_definition_id = int(new_representation.id())
obj.data.name = f"{old_representation.ContextOfItems.id()}/{new_representation.id()}"
# TODO: In simple scenarios, a type has a ShapeRepresentation of ID
# 123. This is then mapped through mapped representations by
# occurrences, with no cartesian transformation. In this case, the mesh
# data is 100% shared and therefore all have the same mesh name
# referencing ID 123. (i.e. the local origins are shared). However, in
# complex scenarios, occurrences may have their own cartesian
# transformation (via MappingTarget). This will mean that occurrences
# will not share the same mesh data and will instead reference a
# different ShapeRepresentation ID. In this scenario, we have to
# propagate the obj.data back to the type itself and all sibling
# occurrences and accommodate their individual cartesian
# transformations.
core.remove_representation(tool.Ifc, tool.Geometry, obj=obj, representation=old_representation)
if obj.data.BIMMeshProperties.ifc_parameters:
core.get_representation_ifc_parameters(tool.Geometry, obj=obj)
@@ -352,7 +366,6 @@ class OverrideDeleteTrait:
return
if element.is_a("IfcAnnotation") and element.ObjectType == "DRAWING":
return blenderbim.core.drawing.remove_drawing(tool.Ifc, tool.Drawing, drawing=element)
IfcStore.delete_element(element)
if obj.users_collection and obj.users_collection[0].name == obj.name:
parent = ifcopenshell.util.element.get_aggregate(element)
if not parent:
@@ -379,6 +392,7 @@ class OverrideDeleteTrait:
self.delete_opening_element(rel.RelatedOpeningElement)
for port in ifcopenshell.util.system.get_ports(element):
self.remove_port(port)
ifcopenshell.api.run("root.remove_product", tool.Ifc.get(), product=element)
def delete_opening_element(self, element):
bpy.ops.bim.remove_opening(opening_id=element.id())
@@ -661,7 +675,7 @@ class OverrideJoin(bpy.types.Operator, Operator):
continue
element = tool.Ifc.get_entity(obj)
if element:
tool.Ifc.delete(element)
ifcopenshell.api.run("root.remove_product", tool.Ifc.get(), product=element)
bpy.ops.object.join()
bpy.ops.bim.update_representation(obj=self.target.name, ifc_representation_class="")
elif representation.RepresentationType == "SweptSolid":
@@ -699,7 +713,7 @@ class OverrideJoin(bpy.types.Operator, Operator):
tool.Ifc.get().createIfcDirection([float(n) for n in position[:, 0][:3]]),
)
items.append(copied_item)
tool.Ifc.delete(element)
ifcopenshell.api.run("root.remove_product", tool.Ifc.get(), product=element)
representation.Items = items
bpy.ops.object.join()
core.switch_representation(
@@ -719,7 +733,7 @@ class OverrideJoin(bpy.types.Operator, Operator):
continue
element = tool.Ifc.get_entity(obj)
if element:
tool.Ifc.delete(element)
ifcopenshell.api.run("root.remove_product", tool.Ifc.get(), product=element)
bpy.ops.object.join()
+2 -4
View File
@@ -347,11 +347,9 @@ def sync_references(ifc, collector, drawing_tool, drawing=None):
should_create_annotation = False
if annotation:
if ifc.is_deleted(annotation):
if reference_obj and (ifc.is_moved(reference_obj) or ifc.is_edited(reference_obj)):
should_delete_existing_annotation = True
elif reference_obj and (ifc.is_moved(reference_obj) or ifc.is_edited(reference_obj)):
should_delete_existing_annotation = True
elif not reference_obj and ifc.is_deleted(reference_element):
elif not reference_obj:
should_delete_existing_annotation = True
if reference_obj and (should_delete_existing_annotation or not annotation):
-2
View File
@@ -376,13 +376,11 @@ class Ifc:
def get_object(cls, entity): pass
def get_path(cls): pass
def get_schema(cls): pass
def is_deleted(cls, element): pass
def is_edited(cls, obj): pass
def is_moved(cls, obj): pass
def link(cls, element, obj): pass
def schema(cls): pass
def edit(cls, obj): pass
def delete(cls, element): pass
def resolve_uri(cls, uri): pass
def run(cls, command, **kwargs): pass
def set(cls, ifc): pass
+1 -1
View File
@@ -149,7 +149,7 @@ class Drawing(blenderbim.core.tool.Drawing):
@classmethod
def delete_drawing_elements(cls, elements):
for element in elements:
tool.Ifc.delete(element)
ifcopenshell.api.run("root.remove_product", tool.Ifc.get(), product=element)
obj = tool.Ifc.get_object(element)
if obj:
obj_data = obj.data
-8
View File
@@ -51,10 +51,6 @@ class Ifc(blenderbim.core.tool.Ifc):
checksum = obj.BIMMaterialProperties.shading_checksum
return checksum != repr(np.array(obj.diffuse_color).tobytes())
@classmethod
def is_deleted(cls, element):
return element.id() in IfcStore.deleted_ids
@classmethod
def is_edited(cls, obj):
return list(obj.scale) != [1.0, 1.0, 1.0] or obj in IfcStore.edited_objs
@@ -100,10 +96,6 @@ class Ifc(blenderbim.core.tool.Ifc):
def edit(cls, obj):
IfcStore.edited_objs.add(obj)
@classmethod
def delete(cls, element):
IfcStore.delete_element(element)
@classmethod
def resolve_uri(cls, uri):
if os.path.isabs(uri):
+8 -2
View File
@@ -61,6 +61,8 @@ class TestCreateCamera(NewFile):
class TestCreateSvgSheet(NewFile):
def test_run(self):
ifc = ifcopenshell.file()
ifcopenshell.api.run("root.create_entity", ifc, ifc_class="IfcProject")
tool.Ifc.set(ifc)
document = ifc.createIfcDocumentInformation(
Identification="X",
Name="FOOBAR",
@@ -87,12 +89,16 @@ class TestDeleteDrawingElements(NewFile):
collection = bpy.data.collections.new("Collection")
bpy.context.scene.collection.children.link(collection)
collection.objects.link(obj)
element = ifc.createIfcAnnotation()
element = ifc.createIfcAnnotation(GlobalId=ifcopenshell.guid.new())
tool.Ifc.link(element, obj)
element_id = element.id()
subject.delete_drawing_elements([element])
assert element_id in IfcStore.deleted_ids
try:
ifc.by_id(element_id)
assert False
except:
pass
assert not bpy.data.objects.get("Object")