Collector.sync skip_unlinking option #4500

To speed up the drawing process in large projects and reduce time on syncing stage I've found that if object is already assigned to it's parent collection (both as part of blender collection and in IFC) we can skip assigning stage significantly reducing time on syncing in general (from 20-25 secs -> 9 secs).

The only thing we'll be missing in that case that object won't be unlinked from other unrelated blender collections which shouldn't break anything in the case of drawing generation.
This commit is contained in:
Andrej730
2024-04-05 12:14:03 +05:00
parent ec0dcb7f8c
commit 02e102f2d2
3 changed files with 15 additions and 4 deletions
+2 -2
View File
@@ -87,7 +87,7 @@ class IfcExporter:
self.get_application_name(), tool.Blender.get_blenderbim_version()
)
def sync_all_objects(self) -> list[ifcopenshell.entity_instance]:
def sync_all_objects(self, skip_unlinking=False) -> list[ifcopenshell.entity_instance]:
results: list[ifcopenshell.entity_instance] = []
self.unit_scale = ifcopenshell.util.unit.calculate_unit_scale(self.file)
for ifc_definition_id in list(IfcStore.id_map.keys()):
@@ -97,7 +97,7 @@ class IfcExporter:
continue
if obj.library:
continue
tool.Collector.sync(obj)
tool.Collector.sync(obj, skip_unlinking)
result = self.sync_object_placement(obj)
if result:
results.append(result)
@@ -497,7 +497,7 @@ class CreateDrawing(bpy.types.Operator):
# All very hackish whilst prototyping
exporter = blenderbim.bim.export_ifc.IfcExporter(None)
exporter.file = tool.Ifc.get()
invalidated_elements = exporter.sync_all_objects()
invalidated_elements = exporter.sync_all_objects(skip_unlinking=True)
invalidated_elements += exporter.sync_edited_objects()
invalidated_guids = [e.GlobalId for e in invalidated_elements if hasattr(e, "GlobalId")]
cache = IfcStore.get_cache()
+12 -1
View File
@@ -28,11 +28,15 @@ from typing import Union
class Collector(blenderbim.core.tool.Collector):
@classmethod
def sync(cls, obj: bpy.types.Object) -> None:
def sync(cls, obj: bpy.types.Object, skip_unlinking=False) -> None:
"""Sync object IFC state (assigned containter / aggregate) with the collection it's currently in.
Then subsequently run `Collector.assign` (if state has changed)
to link them to collections / unlink from anything unrelated collections.
If `skip_unlinking` is `True` then method won't try to assign parent object
if it's already assigned in IFC saving some time.
But it has a downside not unlinking object from unrelated collections.
"""
# This is the reverse of assign. It reads the Blender collection and figures out its IFC hierarchy
element = tool.Ifc.get_entity(obj)
@@ -76,6 +80,13 @@ class Collector(blenderbim.core.tool.Collector):
return
parent = tool.Ifc.get_entity(parent_obj)
if skip_unlinking:
previous_parent = ifcopenshell.util.element.get_container(
element, should_get_direct=True
) or ifcopenshell.util.element.get_aggregate(element)
if parent == previous_parent:
return
if parent:
# This is lazy, but works. One of these will succeed, the other will fail silently.
blenderbim.core.spatial.assign_container(