mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 17:58:20 +00:00
Fix #2968. Deletions are no longer postponed. Should fix or reveal a lot of sync errors.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user