diff --git a/interface/ops.py b/interface/ops.py index b1df849..91e8773 100644 --- a/interface/ops.py +++ b/interface/ops.py @@ -92,6 +92,7 @@ ("nd.seams", 'UV_DATA', None, None, False), ("nd.triangulate", 'MOD_TRIANGULATE', None, None, False), ("nd.apply_modifiers", 'ORPHAN_DATA', None, None, False), + ("nd.clean_utils", 'MOD_FLUIDSIM', None, None, False), None, # Separator ("nd.flare", 'LIGHT_AREA', "Flare (Lighting)", None, False), ] diff --git a/lib/collections.py b/lib/collections.py index 439c48a..51e5ef8 100644 --- a/lib/collections.py +++ b/lib/collections.py @@ -54,6 +54,16 @@ def get_utils_layer(): return None +def get_all_util_objects(): + data = get_utils_layer() + + if data is None: + return [] + + layer, collection = data + return collection.all_objects + + def hide_utils_collection(hide): data = get_utils_layer() if data is not None: diff --git a/utils/__init__.py b/utils/__init__.py index 8d6ed54..5f86eea 100644 --- a/utils/__init__.py +++ b/utils/__init__.py @@ -28,6 +28,7 @@ from . import flare from . import snap_align from . import triangulate +from . import clean_utils registerables = ( @@ -40,6 +41,7 @@ flare, snap_align, triangulate, + clean_utils, ) diff --git a/utils/clean_utils.py b/utils/clean_utils.py new file mode 100644 index 0000000..ff5cbe5 --- /dev/null +++ b/utils/clean_utils.py @@ -0,0 +1,73 @@ +# ███╗ ██╗██████╗ +# ████╗ ██║██╔══██╗ +# ██╔██╗ ██║██║ ██║ +# ██║╚██╗██║██║ ██║ +# ██║ ╚████║██████╔╝ +# ╚═╝ ╚═══╝╚═════╝ +# +# “Commons Clause” License Condition v1.0 +# +# See LICENSE for license details. If you did not receive a copy of the license, +# it may be obtained at https://github.com/hugemenace/nd/blob/main/LICENSE. +# +# Software: ND Blender Addon +# License: MIT +# Licensor: T.S. & I.J. (HugeMenace) +# +# --- +# Contributors: Tristo (HM) +# --- + +import bpy +from .. lib.collections import get_all_util_objects + + +class ND_OT_clean_utils(bpy.types.Operator): + bl_idname = "nd.clean_utils" + bl_label = "Clean Utils" + bl_description = "Removes unused boolean modifiers and utility objects" + + + @classmethod + def poll(cls, context): + return context.mode == 'OBJECT' + + + def invoke(self, context, event): + while self.remove_utils() > 0: + continue + + return {'FINISHED'} + + + def remove_utils(self): + removed_object_count = 0 + + active_util_object_names = set() + all_scene_objects = [obj for obj in bpy.data.objects if obj.type == 'MESH'] + all_util_objects = get_all_util_objects() + + for obj in all_scene_objects: + mods = list(obj.modifiers) + for mod in mods: + if mod.type != 'BOOLEAN': + continue + if mod.object: + active_util_object_names.add(mod.object.name) + continue + obj.modifiers.remove(mod) + + for obj in all_util_objects: + if obj.name not in active_util_object_names: + bpy.data.objects.remove(obj, do_unlink=True) + removed_object_count += 1 + + return removed_object_count + + +def register(): + bpy.utils.register_class(ND_OT_clean_utils) + + +def unregister(): + bpy.utils.unregister_class(ND_OT_clean_utils)