From cf0903e9b6df7f15451028164d497d7cdccc81d1 Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Mon, 8 May 2023 13:20:22 -0400 Subject: [PATCH 01/12] [Blender Kitsu] Create Enforce Naming Operator --- .../addons/blender_kitsu/anim/ops.py | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/scripts-blender/addons/blender_kitsu/anim/ops.py b/scripts-blender/addons/blender_kitsu/anim/ops.py index 2e7b6ddd..4776d3c0 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ops.py +++ b/scripts-blender/addons/blender_kitsu/anim/ops.py @@ -233,7 +233,100 @@ class KITSU_OT_anim_check_action_names(bpy.types.Operator): row.label(text="", icon="FORWARD") row.label(text=name) +class KITSU_OT_anim_enforce_naming_convention(bpy.types.Operator): + bl_idname = "kitsu.anim_enforce_naming_convention" + bl_label = "Set Name Conventions" + bl_options = {"REGISTER", "UNDO"} + bl_description = ("Fix Naming of Scene, Output Collection, Actions, and optionally F`ind and Replace`.") + remove_str: bpy.props.StringProperty(name="Find and Replace", default="",) + rename_scene: bpy.props.BoolProperty(name="Rename Scene", default=True) + rename_output_col: bpy.props.BoolProperty(name="Rename Output Collection", default=True) + rename_actions: bpy.props.BoolProperty(name="Rename Actions", default=True) + find_replace: bpy.props.BoolProperty(name="Find and Replace", default=False) + + + def invoke(self, context, event): + return context.window_manager.invoke_props_dialog(self, width=500) + + def draw(self, context): + layout = self.layout + layout.prop(self, "rename_scene") + layout.prop(self, "rename_actions") + layout.prop(self, "rename_output_col") + layout.prop(self, "find_replace") + if self.find_replace: + layout.prop(self, "remove_str") + + def rename_datablock(self, data_block, replace:str): + if data_block is None: + return + if replace in data_block.name: + data_block.name = data_block.name.replace(replace,"") + return (data_block.name) + + def get_version_from_string(self, string:str): + try: + numbers = string.split( + ".v")[-1] + if ".001" in numbers: + numbers = int(numbers.replace(".001", ""))+1 + int_numbers = int(numbers) + return str(int_numbers) + except AttributeError: + return "001" + + def execute(self, context:bpy.types.Context): + shot_base_name = bpy.path.basename(bpy.data.filepath).replace(".anim.blend","") + active_shot = cache.shot_active_get() + addon_prefs = bpy.context.preferences.addons["blender_kitsu"].preferences + scene_col = context.scene.collection + anim_suffix = "anim.output" + + if self.find_replace: + for col in scene_col.children_recursive: + self.rename_datablock(col, self.remove_str) + for obj in col.objects: + self.rename_datablock(obj, self.remove_str) + self.rename_datablock(obj.data, self.remove_str) + + if self.rename_output_col: + output_cols = [col for col in context.scene.collection.children_recursive if anim_suffix in col.name] + if len(output_cols) != 1: + self.report( + {"INFO"}, + f"Animation Output Collection could not be found", + ) + + return {"CANCELLED"} + output_col = output_cols[0] + output_col.name = f"{shot_base_name}.{anim_suffix}" + + # Rename Scene + if self.rename_scene: + context.scene.name = f"{shot_base_name}.anim" + + # Rename Actions + if self.rename_actions: + for obj in [obj for obj in bpy.data.objects if obj.type == "ARMATURE"]: + base_name = obj.name.split( + addon_prefs.shot_builder_armature_prefix)[-1] + # Cerate Action if None Exists + if obj.animation_data is None or obj.animation_data.action is None: + new_action = bpy.data.actions.new( + f"{addon_prefs.shot_builder_action_prefix}{base_name}.{active_shot.name}.v001") + new_action.use_fake_user = True + obj.animation_data_create() + obj.animation_data.action = new_action + obj.animation_data.action.name = f"{addon_prefs.shot_builder_action_prefix}{base_name}.{active_shot.name}.v001" + bpy.ops.kitsu.anim_check_action_names() + self.report( + {"INFO"}, + f"Naming Conventions Enforced", + ) + return {"FINISHED"} + + class KITSU_OT_anim_update_output_coll(bpy.types.Operator): bl_idname = "kitsu.anim_update_output_coll" bl_label = "Update Output Collection" @@ -295,6 +388,7 @@ classes = [ KITSU_OT_anim_quick_duplicate, KITSU_OT_anim_check_action_names, KITSU_OT_anim_update_output_coll, + KITSU_OT_anim_enforce_naming_convention, ] -- 2.30.2 From 8b4c0841fa7d45ff07515e601624158f1f914f07 Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Mon, 8 May 2023 13:20:51 -0400 Subject: [PATCH 02/12] [Blender_Kitsu] Add Enforce Naming to UI --- scripts-blender/addons/blender_kitsu/anim/ui.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts-blender/addons/blender_kitsu/anim/ui.py b/scripts-blender/addons/blender_kitsu/anim/ui.py index e3630cf8..75c1f1ef 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ui.py +++ b/scripts-blender/addons/blender_kitsu/anim/ui.py @@ -97,6 +97,9 @@ class KITSU_PT_vi3d_anim_tools(bpy.types.Panel): text="Check Action Names", ) + row = box.row(align=True) + row.operator("kitsu.anim_enforce_naming_convention", icon="SORTALPHA") + # ---------REGISTER ----------. -- 2.30.2 From 4909040cdfe206fcd08d675c31efdd404b50740e Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Mon, 8 May 2023 14:09:49 -0400 Subject: [PATCH 03/12] [Blender_Kitsu] Add `Remove Override Collections` Operator --- .../addons/blender_kitsu/anim/ops.py | 18 +++++++++++++++++- .../addons/blender_kitsu/anim/ui.py | 4 ++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/scripts-blender/addons/blender_kitsu/anim/ops.py b/scripts-blender/addons/blender_kitsu/anim/ops.py index 4776d3c0..f189d184 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ops.py +++ b/scripts-blender/addons/blender_kitsu/anim/ops.py @@ -326,7 +326,22 @@ class KITSU_OT_anim_enforce_naming_convention(bpy.types.Operator): ) return {"FINISHED"} - +class KITSU_OT_remove_override_hidden_collections(bpy.types.Operator): + bl_idname = "kitsu.remove_override_hidden_collections" + bl_label = "Cleanup Override Collections" + bl_options = {"REGISTER", "UNDO"} + bl_description = ("Unlink any Collection with Name 'OVERRIDE_HIDDEN' from current scene") + + def execute(self, context): + remove_name = 'OVERRIDE_HIDDEN' + scene_cols = context.scene.collection.children + cols = [col for col in scene_cols if remove_name in col.name] + for col in cols: + scene_cols.unlink(col) + self.report({"INFO"}, f"Removed Collection '{col.name}'",) + return {"FINISHED"} + + class KITSU_OT_anim_update_output_coll(bpy.types.Operator): bl_idname = "kitsu.anim_update_output_coll" bl_label = "Update Output Collection" @@ -389,6 +404,7 @@ classes = [ KITSU_OT_anim_check_action_names, KITSU_OT_anim_update_output_coll, KITSU_OT_anim_enforce_naming_convention, + KITSU_OT_remove_override_hidden_collections ] diff --git a/scripts-blender/addons/blender_kitsu/anim/ui.py b/scripts-blender/addons/blender_kitsu/anim/ui.py index 75c1f1ef..5bd0ea92 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ui.py +++ b/scripts-blender/addons/blender_kitsu/anim/ui.py @@ -99,6 +99,10 @@ class KITSU_PT_vi3d_anim_tools(bpy.types.Panel): row = box.row(align=True) row.operator("kitsu.anim_enforce_naming_convention", icon="SORTALPHA") + + row = box.row(align=True) + row.operator("kitsu.remove_override_hidden_collections", icon="OUTLINER_COLLECTION") + # ---------REGISTER ----------. -- 2.30.2 From 0eca5c0123780a507b4f9bf47d0cd064f083571a Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Mon, 8 May 2023 14:15:34 -0400 Subject: [PATCH 04/12] [Blender_Kitsu] Remove Un-used Collections in `Update Output Collection` --- scripts-blender/addons/blender_kitsu/anim/ops.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts-blender/addons/blender_kitsu/anim/ops.py b/scripts-blender/addons/blender_kitsu/anim/ops.py index f189d184..bfe2b0b7 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ops.py +++ b/scripts-blender/addons/blender_kitsu/anim/ops.py @@ -369,6 +369,10 @@ class KITSU_OT_anim_update_output_coll(bpy.types.Operator): missing: List[bpy.types.Collection] = [] output_coll_childs = list(opsdata.traverse_collection_tree(output_coll)) + # Clear Out Output Collection before Starting + for collection in output_coll.children: + output_coll.children.unlink(collection) + # Check if all found asset colls are in output coll. for coll in asset_colls: if coll in output_coll_childs: -- 2.30.2 From e2a3476d7ec4a5b806f787262526ed0bb644de9f Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Mon, 8 May 2023 14:21:58 -0400 Subject: [PATCH 05/12] [Blender_Kitsu] Check Actions: add action if none exists --- .../addons/blender_kitsu/anim/ops.py | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/scripts-blender/addons/blender_kitsu/anim/ops.py b/scripts-blender/addons/blender_kitsu/anim/ops.py index bfe2b0b7..e464758c 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ops.py +++ b/scripts-blender/addons/blender_kitsu/anim/ops.py @@ -117,10 +117,25 @@ class KITSU_OT_anim_check_action_names(bpy.types.Operator): return bool(cache.shot_active_get()) def execute(self, context: bpy.types.Context) -> Set[str]: + active_shot = cache.shot_active_get() + addon_prefs = bpy.context.preferences.addons["blender_kitsu"].preferences + existing_action_names = [a.name for a in bpy.data.actions] failed = [] succeeded = [] + for obj in [obj for obj in bpy.data.objects if obj.type == "ARMATURE"]: + # Cerate Action if None Exists + if obj.animation_data is None or obj.animation_data.action is None: + base_name = obj.name.split( + addon_prefs.shot_builder_armature_prefix)[-1] + new_action = bpy.data.actions.new( + f"{addon_prefs.shot_builder_action_prefix}{base_name}.{active_shot.name}.v001") + new_action.use_fake_user = True + obj.animation_data_create() + obj.animation_data.action = new_action + obj.animation_data.action.name = f"{addon_prefs.shot_builder_action_prefix}{base_name}.{active_shot.name}.v001" + # Rename actions. for action, name in self.wrong: if name in existing_action_names: @@ -278,8 +293,6 @@ class KITSU_OT_anim_enforce_naming_convention(bpy.types.Operator): def execute(self, context:bpy.types.Context): shot_base_name = bpy.path.basename(bpy.data.filepath).replace(".anim.blend","") - active_shot = cache.shot_active_get() - addon_prefs = bpy.context.preferences.addons["blender_kitsu"].preferences scene_col = context.scene.collection anim_suffix = "anim.output" @@ -308,17 +321,6 @@ class KITSU_OT_anim_enforce_naming_convention(bpy.types.Operator): # Rename Actions if self.rename_actions: - for obj in [obj for obj in bpy.data.objects if obj.type == "ARMATURE"]: - base_name = obj.name.split( - addon_prefs.shot_builder_armature_prefix)[-1] - # Cerate Action if None Exists - if obj.animation_data is None or obj.animation_data.action is None: - new_action = bpy.data.actions.new( - f"{addon_prefs.shot_builder_action_prefix}{base_name}.{active_shot.name}.v001") - new_action.use_fake_user = True - obj.animation_data_create() - obj.animation_data.action = new_action - obj.animation_data.action.name = f"{addon_prefs.shot_builder_action_prefix}{base_name}.{active_shot.name}.v001" bpy.ops.kitsu.anim_check_action_names() self.report( {"INFO"}, -- 2.30.2 From b12e3f8352b1f1bd705aed55d0afae85ba306421 Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Mon, 8 May 2023 15:07:00 -0400 Subject: [PATCH 06/12] [Blender_Kitsu] Remove rename_actions from Naming Conventions --- scripts-blender/addons/blender_kitsu/anim/ops.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/scripts-blender/addons/blender_kitsu/anim/ops.py b/scripts-blender/addons/blender_kitsu/anim/ops.py index e464758c..d25c7a42 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ops.py +++ b/scripts-blender/addons/blender_kitsu/anim/ops.py @@ -257,7 +257,6 @@ class KITSU_OT_anim_enforce_naming_convention(bpy.types.Operator): remove_str: bpy.props.StringProperty(name="Find and Replace", default="",) rename_scene: bpy.props.BoolProperty(name="Rename Scene", default=True) rename_output_col: bpy.props.BoolProperty(name="Rename Output Collection", default=True) - rename_actions: bpy.props.BoolProperty(name="Rename Actions", default=True) find_replace: bpy.props.BoolProperty(name="Find and Replace", default=False) @@ -319,9 +318,6 @@ class KITSU_OT_anim_enforce_naming_convention(bpy.types.Operator): if self.rename_scene: context.scene.name = f"{shot_base_name}.anim" - # Rename Actions - if self.rename_actions: - bpy.ops.kitsu.anim_check_action_names() self.report( {"INFO"}, f"Naming Conventions Enforced", -- 2.30.2 From 787149b39dd6d12cbfa46c7288063d6fcdede388 Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Mon, 8 May 2023 15:43:42 -0400 Subject: [PATCH 07/12] [Blender_Kitsu] Fix "Update Output Collection" --- scripts-blender/addons/blender_kitsu/anim/ops.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts-blender/addons/blender_kitsu/anim/ops.py b/scripts-blender/addons/blender_kitsu/anim/ops.py index d25c7a42..4183f5b9 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ops.py +++ b/scripts-blender/addons/blender_kitsu/anim/ops.py @@ -370,6 +370,7 @@ class KITSU_OT_anim_update_output_coll(bpy.types.Operator): # Clear Out Output Collection before Starting for collection in output_coll.children: output_coll.children.unlink(collection) + bpy.context.view_layer.update() # Check if all found asset colls are in output coll. for coll in asset_colls: -- 2.30.2 From cad7abe80057202c42c9340477de5da33aac1771 Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Mon, 8 May 2023 15:44:38 -0400 Subject: [PATCH 08/12] [Blender_Kitsu] Skip Naming Enforce if Linked - Skip if data_block has library directly - Remove no-op code --- scripts-blender/addons/blender_kitsu/anim/ops.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/scripts-blender/addons/blender_kitsu/anim/ops.py b/scripts-blender/addons/blender_kitsu/anim/ops.py index 4183f5b9..7f5c4fde 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ops.py +++ b/scripts-blender/addons/blender_kitsu/anim/ops.py @@ -273,22 +273,12 @@ class KITSU_OT_anim_enforce_naming_convention(bpy.types.Operator): layout.prop(self, "remove_str") def rename_datablock(self, data_block, replace:str): - if data_block is None: + # Return Early if data_block is linked but not overriden + if data_block is None or data_block.library is not None: return if replace in data_block.name: data_block.name = data_block.name.replace(replace,"") return (data_block.name) - - def get_version_from_string(self, string:str): - try: - numbers = string.split( - ".v")[-1] - if ".001" in numbers: - numbers = int(numbers.replace(".001", ""))+1 - int_numbers = int(numbers) - return str(int_numbers) - except AttributeError: - return "001" def execute(self, context:bpy.types.Context): shot_base_name = bpy.path.basename(bpy.data.filepath).replace(".anim.blend","") -- 2.30.2 From 2399f825ce4a070e56ee5dc229499d24dedfe27f Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Mon, 8 May 2023 16:02:58 -0400 Subject: [PATCH 09/12] [Blender_Kitsu] "Update Output Collection" Link Camera --- scripts-blender/addons/blender_kitsu/anim/ops.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts-blender/addons/blender_kitsu/anim/ops.py b/scripts-blender/addons/blender_kitsu/anim/ops.py index 7f5c4fde..1a07b863 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ops.py +++ b/scripts-blender/addons/blender_kitsu/anim/ops.py @@ -383,6 +383,12 @@ class KITSU_OT_anim_update_output_coll(bpy.types.Operator): output_coll.children.link(coll) logger.info("%s linked in %s", coll.name, output_coll.name) + # Ensure Camera Rig is Linked + for coll in [col for col in bpy.data.collections]: + if coll.override_library: + if coll.override_library.hierarchy_root.name == "CA-camera_rig": + output_coll.children.link(coll) + self.report( {"INFO"}, f"Found Asset Collections: {len(asset_colls)} | Added to output collection: {len(parents)}", -- 2.30.2 From c35575170ea49708009c2e2801d180e4fd4210d6 Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Mon, 8 May 2023 16:03:21 -0400 Subject: [PATCH 10/12] [Blender_Kitsu] "Update Output Collection" Fix Execution Order --- scripts-blender/addons/blender_kitsu/anim/ops.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts-blender/addons/blender_kitsu/anim/ops.py b/scripts-blender/addons/blender_kitsu/anim/ops.py index 1a07b863..45d21c7e 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ops.py +++ b/scripts-blender/addons/blender_kitsu/anim/ops.py @@ -353,15 +353,18 @@ class KITSU_OT_anim_update_output_coll(bpy.types.Operator): active_shot = cache.shot_active_get() output_coll_name = opsdata.get_output_coll_name(active_shot) output_coll = bpy.data.collections[output_coll_name] - asset_colls = opsdata.find_asset_collections_in_scene(context.scene) - missing: List[bpy.types.Collection] = [] - output_coll_childs = list(opsdata.traverse_collection_tree(output_coll)) # Clear Out Output Collection before Starting for collection in output_coll.children: output_coll.children.unlink(collection) bpy.context.view_layer.update() + + asset_colls = opsdata.find_asset_collections_in_scene(context.scene) + missing: List[bpy.types.Collection] = [] + output_coll_childs = list(opsdata.traverse_collection_tree(output_coll)) + + # Check if all found asset colls are in output coll. for coll in asset_colls: if coll in output_coll_childs: -- 2.30.2 From 2eb7d45460915924b2857c0c50db0fbac94b3c45 Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Mon, 8 May 2023 16:23:56 -0400 Subject: [PATCH 11/12] [Blender_Kitsu] Add TODO to Enforce Convention --- scripts-blender/addons/blender_kitsu/anim/ops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts-blender/addons/blender_kitsu/anim/ops.py b/scripts-blender/addons/blender_kitsu/anim/ops.py index 45d21c7e..b6472c86 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ops.py +++ b/scripts-blender/addons/blender_kitsu/anim/ops.py @@ -389,7 +389,7 @@ class KITSU_OT_anim_update_output_coll(bpy.types.Operator): # Ensure Camera Rig is Linked for coll in [col for col in bpy.data.collections]: if coll.override_library: - if coll.override_library.hierarchy_root.name == "CA-camera_rig": + if coll.override_library.hierarchy_root.name == "CA-camera_rig": #TODO Fix this hack to be generic output_coll.children.link(coll) self.report( -- 2.30.2 From e51f720524a66c1c73fbd4ffd283585ee1709a17 Mon Sep 17 00:00:00 2001 From: Nick Alberelli Date: Tue, 9 May 2023 10:48:03 -0400 Subject: [PATCH 12/12] [Blender_Kitsu] Rename 'Remove Override Collection' to 'Find and Unlink Collections' - Rename Operator - Remove from UI - Allow User to pass any string - Enforce Black Formatting --- .../addons/blender_kitsu/anim/ops.py | 93 +++++++++++++------ .../addons/blender_kitsu/anim/ui.py | 4 - 2 files changed, 65 insertions(+), 32 deletions(-) diff --git a/scripts-blender/addons/blender_kitsu/anim/ops.py b/scripts-blender/addons/blender_kitsu/anim/ops.py index b6472c86..59a2a30c 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ops.py +++ b/scripts-blender/addons/blender_kitsu/anim/ops.py @@ -52,7 +52,6 @@ class KITSU_OT_anim_quick_duplicate(bpy.types.Operator): ) def execute(self, context: bpy.types.Context) -> Set[str]: - act_coll = context.view_layer.active_layer_collection.collection shot_active = cache.shot_active_get() amount = context.window_manager.kitsu.quick_duplicate_amount @@ -127,10 +126,10 @@ class KITSU_OT_anim_check_action_names(bpy.types.Operator): for obj in [obj for obj in bpy.data.objects if obj.type == "ARMATURE"]: # Cerate Action if None Exists if obj.animation_data is None or obj.animation_data.action is None: - base_name = obj.name.split( - addon_prefs.shot_builder_armature_prefix)[-1] + base_name = obj.name.split(addon_prefs.shot_builder_armature_prefix)[-1] new_action = bpy.data.actions.new( - f"{addon_prefs.shot_builder_action_prefix}{base_name}.{active_shot.name}.v001") + f"{addon_prefs.shot_builder_action_prefix}{base_name}.{active_shot.name}.v001" + ) new_action.use_fake_user = True obj.animation_data_create() obj.animation_data.action = new_action @@ -248,17 +247,26 @@ class KITSU_OT_anim_check_action_names(bpy.types.Operator): row.label(text="", icon="FORWARD") row.label(text=name) + class KITSU_OT_anim_enforce_naming_convention(bpy.types.Operator): bl_idname = "kitsu.anim_enforce_naming_convention" bl_label = "Set Name Conventions" bl_options = {"REGISTER", "UNDO"} - bl_description = ("Fix Naming of Scene, Output Collection, Actions, and optionally F`ind and Replace`.") + bl_description = "Fix Naming of Scene, Output Collection, Actions, and optionally Find and remove a given string" - remove_str: bpy.props.StringProperty(name="Find and Replace", default="",) + remove_str: bpy.props.StringProperty( + name="Find and Replace", + default="", + ) rename_scene: bpy.props.BoolProperty(name="Rename Scene", default=True) - rename_output_col: bpy.props.BoolProperty(name="Rename Output Collection", default=True) - find_replace: bpy.props.BoolProperty(name="Find and Replace", default=False) - + rename_output_col: bpy.props.BoolProperty( + name="Rename Output Collection", default=True + ) + find_replace: bpy.props.BoolProperty( + name="Find and Remove", + default=False, + description="Remove this string from Collection, Object and Object Data names. Used to remove suffixes from file names such as '.001'", + ) def invoke(self, context, event): return context.window_manager.invoke_props_dialog(self, width=500) @@ -272,16 +280,16 @@ class KITSU_OT_anim_enforce_naming_convention(bpy.types.Operator): if self.find_replace: layout.prop(self, "remove_str") - def rename_datablock(self, data_block, replace:str): + def rename_datablock(self, data_block, replace: str): # Return Early if data_block is linked but not overriden if data_block is None or data_block.library is not None: return if replace in data_block.name: - data_block.name = data_block.name.replace(replace,"") - return (data_block.name) + data_block.name = data_block.name.replace(replace, "") + return data_block.name - def execute(self, context:bpy.types.Context): - shot_base_name = bpy.path.basename(bpy.data.filepath).replace(".anim.blend","") + def execute(self, context: bpy.types.Context): + shot_base_name = bpy.path.basename(bpy.data.filepath).replace(".anim.blend", "") scene_col = context.scene.collection anim_suffix = "anim.output" @@ -293,7 +301,11 @@ class KITSU_OT_anim_enforce_naming_convention(bpy.types.Operator): self.rename_datablock(obj.data, self.remove_str) if self.rename_output_col: - output_cols = [col for col in context.scene.collection.children_recursive if anim_suffix in col.name] + output_cols = [ + col + for col in context.scene.collection.children_recursive + if anim_suffix in col.name + ] if len(output_cols) != 1: self.report( {"INFO"}, @@ -302,7 +314,7 @@ class KITSU_OT_anim_enforce_naming_convention(bpy.types.Operator): return {"CANCELLED"} output_col = output_cols[0] - output_col.name = f"{shot_base_name}.{anim_suffix}" + output_col.name = f"{shot_base_name}.{anim_suffix}" # Rename Scene if self.rename_scene: @@ -314,19 +326,44 @@ class KITSU_OT_anim_enforce_naming_convention(bpy.types.Operator): ) return {"FINISHED"} -class KITSU_OT_remove_override_hidden_collections(bpy.types.Operator): - bl_idname = "kitsu.remove_override_hidden_collections" - bl_label = "Cleanup Override Collections" + +class KITSU_OT_unlink_collection_with_string(bpy.types.Operator): + bl_idname = "kitsu.unlink_collection_with_string" + bl_label = "Find and Unlink Collections" bl_options = {"REGISTER", "UNDO"} - bl_description = ("Unlink any Collection with Name 'OVERRIDE_HIDDEN' from current scene") + bl_description = ( + "Unlink any Collection with a given name. By default name is 'OVERRIDE_HIDDEN'" + ) + + remove_collection_string: bpy.props.StringProperty( + name="Find in Name", + default='OVERRIDE_HIDDEN', + description="Search for this string withing current scene's collections. Collection will be unlinked if it matches given string'", + ) + + def invoke(self, context, event): + return context.window_manager.invoke_props_dialog(self, width=500) + + def draw(self, context): + layout = self.layout + layout.prop(self, "remove_collection_string") def execute(self, context): - remove_name = 'OVERRIDE_HIDDEN' scene_cols = context.scene.collection.children - cols = [col for col in scene_cols if remove_name in col.name] + cols = [col for col in scene_cols if self.remove_collection_string in col.name] + cleaned = False for col in cols: + cleaned = True scene_cols.unlink(col) - self.report({"INFO"}, f"Removed Collection '{col.name}'",) + self.report( + {"INFO"}, + f"Removed Collection '{col.name}'", + ) + if not cleaned: + self.report( + {"INFO"}, + f"No Collections found containing name '{self.remove_collection_string}'", + ) return {"FINISHED"} @@ -359,12 +396,10 @@ class KITSU_OT_anim_update_output_coll(bpy.types.Operator): output_coll.children.unlink(collection) bpy.context.view_layer.update() - asset_colls = opsdata.find_asset_collections_in_scene(context.scene) missing: List[bpy.types.Collection] = [] output_coll_childs = list(opsdata.traverse_collection_tree(output_coll)) - # Check if all found asset colls are in output coll. for coll in asset_colls: if coll in output_coll_childs: @@ -388,8 +423,10 @@ class KITSU_OT_anim_update_output_coll(bpy.types.Operator): # Ensure Camera Rig is Linked for coll in [col for col in bpy.data.collections]: - if coll.override_library: - if coll.override_library.hierarchy_root.name == "CA-camera_rig": #TODO Fix this hack to be generic + if coll.override_library: + if ( + coll.override_library.hierarchy_root.name == "CA-camera_rig" + ): # TODO Fix this hack to be generic output_coll.children.link(coll) self.report( @@ -406,7 +443,7 @@ classes = [ KITSU_OT_anim_check_action_names, KITSU_OT_anim_update_output_coll, KITSU_OT_anim_enforce_naming_convention, - KITSU_OT_remove_override_hidden_collections + KITSU_OT_unlink_collection_with_string, ] diff --git a/scripts-blender/addons/blender_kitsu/anim/ui.py b/scripts-blender/addons/blender_kitsu/anim/ui.py index 5bd0ea92..75c1f1ef 100644 --- a/scripts-blender/addons/blender_kitsu/anim/ui.py +++ b/scripts-blender/addons/blender_kitsu/anim/ui.py @@ -99,10 +99,6 @@ class KITSU_PT_vi3d_anim_tools(bpy.types.Panel): row = box.row(align=True) row.operator("kitsu.anim_enforce_naming_convention", icon="SORTALPHA") - - row = box.row(align=True) - row.operator("kitsu.remove_override_hidden_collections", icon="OUTLINER_COLLECTION") - # ---------REGISTER ----------. -- 2.30.2