diff --git a/src/bonsai/bonsai/bim/module/debug/__init__.py b/src/bonsai/bonsai/bim/module/debug/__init__.py index 629bb05dc6..1e19ff678a 100644 --- a/src/bonsai/bonsai/bim/module/debug/__init__.py +++ b/src/bonsai/bonsai/bim/module/debug/__init__.py @@ -36,6 +36,7 @@ classes = ( operator.ProfileImportIFC, operator.PurgeHdf5Cache, operator.PurgeUnusedElementsByClass, + operator.PurgeUnusedObjects, operator.RestartBlender, operator.RewindInspector, operator.SelectExpressFile, diff --git a/src/bonsai/bonsai/bim/module/debug/operator.py b/src/bonsai/bonsai/bim/module/debug/operator.py index 44c4eef5da..83ee47d07f 100644 --- a/src/bonsai/bonsai/bim/module/debug/operator.py +++ b/src/bonsai/bonsai/bim/module/debug/operator.py @@ -32,6 +32,8 @@ import ifcopenshell.util.representation import ifcopenshell.util.unit import bonsai.tool as tool import bonsai.core.debug as core +import bonsai.core.profile +import bonsai.core.type import bonsai.bim.handler import bonsai.bim.import_ifc as import_ifc from pathlib import Path @@ -608,6 +610,57 @@ class PurgeUnusedElementsByClass(bpy.types.Operator, tool.Ifc.Operator): tool.Ifc.get().write(self.filepath) +class PurgeUnusedObjects(bpy.types.Operator, tool.Ifc.Operator): + bl_idname = "bim.purge_unused_objects" + bl_label = "Purge Unused Objects" + bl_options = {"REGISTER", "UNDO"} + + object_type: bpy.props.EnumProperty( + name="Object Type", + items=( + ("TYPE", "Type", ""), + ("PROFILE", "Profile", ""), + ("STYLE", "Style", ""), + ("MATERIAL", "Material", ""), + ), + ) + + def _execute(self, context): + object_type = self.object_type + if object_type == "TYPE": + purged = bonsai.core.type.purge_unused_types(tool.Ifc, tool.Type, tool.Geometry) + elif object_type == "PROFILE": + purged = bonsai.core.profile.purge_unused_profiles(tool.Ifc, tool.Profile) + elif object_type == "STYLE": + purged = tool.Debug.purge_unused_class("IfcPresentationStyle") + elif object_type == "MATERIAL": + ifc_file = tool.Ifc.get() + is_ifc2x3 = ifc_file.schema == "IFC2X3" + if is_ifc2x3: + purged = tool.Debug.purge_unused_class("IfcMaterial") + else: + purged = tool.Debug.purge_unused_class("IfcMaterialDefinition") + else: + self.report({"ERROR"}, f"Invalid object type {object_type}.") + return {"CANCELLED"} + + self.report({"INFO"}, f"{purged} unused {object_type.lower()}s were purged.") + + if purged == 0: + return + + scene = context.scene + if object_type == "PROFILE": + if scene.BIMProfileProperties.is_editing: + bpy.ops.bim.load_profiles() + elif object_type == "STYLE": + if scene.BIMStylesProperties.is_editing: + bpy.ops.bim.load_styles() + elif object_type == "MATERIAL": + if scene.BIMMaterialProperties.is_editing: + bpy.ops.bim.load_materials() + + class PipInstall(bpy.types.Operator): bl_idname = "bim.pip_install" bl_label = "Pip Install" diff --git a/src/bonsai/bonsai/bim/module/profile/__init__.py b/src/bonsai/bonsai/bim/module/profile/__init__.py index d06bc1c78c..a9a4895884 100644 --- a/src/bonsai/bonsai/bim/module/profile/__init__.py +++ b/src/bonsai/bonsai/bim/module/profile/__init__.py @@ -30,7 +30,6 @@ classes = ( operator.EnableEditingArbitraryProfile, operator.EnableEditingProfile, operator.LoadProfiles, - operator.PurgeUnusedProfiles, operator.RemoveProfileDef, prop.Profile, prop.BIMProfileProperties, diff --git a/src/bonsai/bonsai/bim/module/profile/operator.py b/src/bonsai/bonsai/bim/module/profile/operator.py index ba5c0f168a..15e4b9ea7a 100644 --- a/src/bonsai/bonsai/bim/module/profile/operator.py +++ b/src/bonsai/bonsai/bim/module/profile/operator.py @@ -264,18 +264,3 @@ class EditArbitraryProfile(bpy.types.Operator, tool.Ifc.Operator): props.active_arbitrary_profile_id = 0 model_profile.DumbProfileRegenerator().regenerate_from_profile_def(profile) - - -class PurgeUnusedProfiles(bpy.types.Operator, tool.Ifc.Operator): - bl_idname = "bim.purge_unused_profiles" - bl_label = "Purge Unused Profiles" - bl_options = {"REGISTER", "UNDO"} - - def _execute(self, context): - props = context.scene.BIMProfileProperties - purged_profiles = core.purge_unused_profiles(tool.Ifc, tool.Profile) - self.report({"INFO"}, f"{purged_profiles} profiles were purged.") - - if props.is_editing: - refresh() - bpy.ops.bim.load_profiles() diff --git a/src/bonsai/bonsai/bim/module/project/ui.py b/src/bonsai/bonsai/bim/module/project/ui.py index 1b476ba1e4..9004f5a84d 100644 --- a/src/bonsai/bonsai/bim/module/project/ui.py +++ b/src/bonsai/bonsai/bim/module/project/ui.py @@ -519,5 +519,7 @@ class BIM_PT_purge(Panel): def draw(self, context): layout = self.layout - layout.operator("bim.purge_unused_profiles") - layout.operator("bim.purge_unused_types") + layout.operator("bim.purge_unused_objects", text="Purge Unused Profiles").object_type = "PROFILE" + layout.operator("bim.purge_unused_objects", text="Purge Unused Types").object_type = "TYPE" + layout.operator("bim.purge_unused_objects", text="Purge Unused Styles").object_type = "STYLE" + layout.operator("bim.purge_unused_objects", text="Purge Unused Materials").object_type = "MATERIAL" diff --git a/src/bonsai/bonsai/bim/module/style/operator.py b/src/bonsai/bonsai/bim/module/style/operator.py index 22dd98b7ba..ebfbec53af 100644 --- a/src/bonsai/bonsai/bim/module/style/operator.py +++ b/src/bonsai/bonsai/bim/module/style/operator.py @@ -460,7 +460,8 @@ class LoadStyles(bpy.types.Operator, tool.Ifc.Operator): style_type: bpy.props.StringProperty() def _execute(self, context): - core.load_styles(tool.Style, style_type=self.style_type) + style_type = self.style_type if self.style_type else context.scene.BIMStylesProperties.style_type + core.load_styles(tool.Style, style_type=style_type) class SelectByStyle(bpy.types.Operator, tool.Ifc.Operator): diff --git a/src/bonsai/bonsai/bim/module/type/__init__.py b/src/bonsai/bonsai/bim/module/type/__init__.py index 445c9e1e28..f0e5546740 100644 --- a/src/bonsai/bonsai/bim/module/type/__init__.py +++ b/src/bonsai/bonsai/bim/module/type/__init__.py @@ -26,7 +26,6 @@ classes = ( operator.DisableEditingType, operator.DuplicateType, operator.EnableEditingType, - operator.PurgeUnusedTypes, operator.RemoveType, operator.RenameType, operator.SelectSimilarType, diff --git a/src/bonsai/bonsai/bim/module/type/operator.py b/src/bonsai/bonsai/bim/module/type/operator.py index c72cebcf71..be652058ab 100644 --- a/src/bonsai/bonsai/bim/module/type/operator.py +++ b/src/bonsai/bonsai/bim/module/type/operator.py @@ -555,13 +555,3 @@ class DuplicateType(bpy.types.Operator, tool.Ifc.Operator): context.scene.BIMModelProperties.ifc_class = new.is_a() context.scene.BIMModelProperties.relating_type_id = str(new_obj.BIMObjectProperties.ifc_definition_id) return {"FINISHED"} - - -class PurgeUnusedTypes(bpy.types.Operator, tool.Ifc.Operator): - bl_idname = "bim.purge_unused_types" - bl_label = "Purge Unused Types" - bl_options = {"REGISTER", "UNDO"} - - def _execute(self, context): - purged_types = core.purge_unused_types(tool.Ifc, tool.Type, tool.Geometry) - self.report({"INFO"}, f"{purged_types} types were purged.") diff --git a/src/bonsai/bonsai/tool/debug.py b/src/bonsai/bonsai/tool/debug.py index 99bf884aa9..5451cae5b6 100644 --- a/src/bonsai/bonsai/tool/debug.py +++ b/src/bonsai/bonsai/tool/debug.py @@ -97,3 +97,15 @@ class Debug(bonsai.core.tool.Debug): print(f"{class_string: <50} {unused[ifc_class]: >5}") return sum(unused.values()) + + @classmethod + def purge_unused_class(cls, ifc_class: str) -> int: + ifc_file = tool.Ifc.get() + elements = ifc_file.by_type(ifc_class) + i = 0 + for element in elements: + if ifc_file.get_total_inverses(element) != 0: + continue + ifcopenshell.util.element.remove_deep(ifc_file, element) + i += 1 + return i