Bonsai - cache get_user and get_application for a speed-up

This commit is contained in:
Andrej730
2025-06-17 18:31:11 +05:00
parent 71d469a271
commit 21f5363c74
+42 -2
View File
@@ -24,6 +24,7 @@ import ifcopenshell.util.unit
import ifcopenshell.api.owner.settings
import bonsai.bim
import bonsai.tool as tool
import weakref
from bpy.app.handlers import persistent
from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.model.data import AuthoringData
@@ -257,24 +258,61 @@ def redo_post(scene: bpy.types.Scene) -> None:
tool.Ifc.rebuild_element_maps()
# Cache is important as those entities will be retrieved very often,
# for every IfcOwnerHistory creation or update.
class SettingsCache:
APPLICATION_ID: Union[int, None] = None
USER_ID: Union[int, None] = None
_file: Union[weakref.ReferenceType[ifcopenshell.file], None] = None
@classmethod
def get_file(cls) -> Union[ifcopenshell.file, None]:
if cls._file is None:
return None
return cls._file()
@classmethod
def set_file(cls, file: ifcopenshell.file) -> None:
cls._file = weakref.ref(file)
def get_application(ifc: ifcopenshell.file) -> ifcopenshell.entity_instance:
# TODO: cache this for even faster application retrieval. It honestly makes a difference on long scripts.
if SettingsCache.get_file() is ifc and SettingsCache.APPLICATION_ID is not None:
try:
app = ifc.by_id(SettingsCache.APPLICATION_ID)
return app
except RuntimeError:
pass
# Use only main part from the version to avoid flooding advanced users projects with IfcApplications.
version = tool.Blender.get_bonsai_version().split("-")[0]
for element in ifc.by_type("IfcApplication"):
if element.ApplicationIdentifier == "Bonsai" and element.Version == version:
return element
return ifcopenshell.api.owner.add_application(
application = ifcopenshell.api.owner.add_application(
ifc,
version=version,
application_full_name="Bonsai",
application_identifier="Bonsai",
)
SettingsCache.APPLICATION_ID = application.id()
SettingsCache.set_file(ifc)
return application
def get_user(ifc: ifcopenshell.file) -> Union[ifcopenshell.entity_instance, None]:
# TODO: cache this for even faster application retrieval. It honestly makes a difference on long scripts.
if SettingsCache.get_file() is ifc and SettingsCache.USER_ID is not None:
try:
user = ifc.by_id(SettingsCache.USER_ID)
return user
except RuntimeError:
pass
if pao := next(iter(ifc.by_type("IfcPersonAndOrganization")), None):
SettingsCache.USER_ID = pao.id()
SettingsCache.set_file(ifc)
return pao
elif ifc.schema == "IFC2X3":
if (person := next(iter(ifc.by_type("IfcPerson")), None)) is None:
@@ -282,6 +320,8 @@ def get_user(ifc: ifcopenshell.file) -> Union[ifcopenshell.entity_instance, None
if (organization := next(iter(ifc.by_type("IfcOrganization")), None)) is None:
organization = ifcopenshell.api.owner.add_organisation(ifc)
pao = ifcopenshell.api.owner.add_person_and_organisation(ifc, person=person, organisation=organization)
SettingsCache.USER_ID = pao.id()
SettingsCache.set_file(ifc)
return pao