From 02e102f2d25d6f9de28f29e990d4391459b1d5d8 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 5 Apr 2024 12:14:03 +0500 Subject: [PATCH] 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. --- src/blenderbim/blenderbim/bim/export_ifc.py | 4 ++-- .../blenderbim/bim/module/drawing/operator.py | 2 +- src/blenderbim/blenderbim/tool/collector.py | 13 ++++++++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/export_ifc.py b/src/blenderbim/blenderbim/bim/export_ifc.py index 0ce4bd99c6..5efaefa4b1 100644 --- a/src/blenderbim/blenderbim/bim/export_ifc.py +++ b/src/blenderbim/blenderbim/bim/export_ifc.py @@ -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) diff --git a/src/blenderbim/blenderbim/bim/module/drawing/operator.py b/src/blenderbim/blenderbim/bim/module/drawing/operator.py index 9b575796dc..6d02ca5aa2 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/operator.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/operator.py @@ -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() diff --git a/src/blenderbim/blenderbim/tool/collector.py b/src/blenderbim/blenderbim/tool/collector.py index be90f0c701..095d56ea1d 100644 --- a/src/blenderbim/blenderbim/tool/collector.py +++ b/src/blenderbim/blenderbim/tool/collector.py @@ -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(