57 KiB
57 KiB
DLM_OT_migrator_remove_original class implementation (2026-03-10 16:22Z)
User
Read the DLM_OT_migrator_remove_original class from T:\Dynamic-Link-Manager\ui\operators.py and show me its current implementation. Also show any utility functions that might help find which collection contains an object.
Agent (model accounts/fireworks/models/kimi-k2p5, mode Agent)
Thought Process
The user wants me to:- Read the DLM_OT_migrator_remove_original class from T:\Dynamic-Link-Manager\ui\operators.py
- Show any utility functions that might help find which collection contains an object
Let me start by reading the operators.py file to find this class and any utility functions.
Tool use: **run_terminal_command_v2** • Run command: cat "T:\Dynamic-Link-Manager\ui\operators.py"
cat "T:\Dynamic-Link-Manager\ui\operators.py"
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
import bpy
import os
from bpy.types import Operator
from bpy.props import StringProperty, BoolProperty
from bpy.props import StringProperty, IntProperty
ADDON_NAME = __package__.rsplit(".", 1)[0] if "." in __package__ else __package__
def _prefs(context):
return context.preferences.addons.get(ADDON_NAME)
class DLM_OT_replace_linked_asset(Operator):
bl_idname = "dlm.replace_linked_asset"
bl_label = "Replace Linked Asset"
bl_description = "Open file browser to replace the linked asset with another file"
bl_options = {"REGISTER", "UNDO"}
filepath: StringProperty(name="File Path", description="Path to the new asset file", subtype="FILE_PATH")
def execute(self, context):
obj = context.active_object
if not obj:
self.report({"ERROR"}, "No object selected")
return {"CANCELLED"}
if getattr(obj, "library", None):
self.report({"INFO"}, f"Object '{obj.name}' is linked from: {obj.library.filepath}")
return {"FINISHED"}
if obj.data and getattr(obj.data, "library", None) and obj.data.library:
self.report({"INFO"}, f"Object '{obj.name}' has linked data from: {obj.data.library.filepath}")
return {"FINISHED"}
if obj.type == "ARMATURE" and obj.data and obj.data.name in bpy.data.armatures:
ad = bpy.data.armatures[obj.data.name]
if getattr(ad, "library", None) and ad.library:
self.report({"INFO"}, f"Armature '{obj.name}' data is linked from: {ad.library.filepath}")
return {"FINISHED"}
self.report({"ERROR"}, "Selected object is not a linked asset")
return {"CANCELLED"}
def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"}
class DLM_OT_scan_linked_assets(Operator):
bl_idname = "dlm.scan_linked_assets"
bl_label = "Scan Linked Libraries"
bl_description = "Scan the current file for linked libraries and list their status"
bl_options = {"REGISTER"}
def execute(self, context):
from ..ops import library
return library.scan_linked_assets(context, self.report)
class DLM_OT_find_libraries_in_folders(Operator):
bl_idname = "dlm.find_libraries_in_folders"
bl_label = "Find Libraries in Folders"
bl_description = "Search addon search paths for missing library blend files"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
from ..ops import library
return library.find_libraries_in_folders(context, self.report, ADDON_NAME)
class DLM_OT_open_linked_file(Operator):
bl_idname = "dlm.open_linked_file"
bl_label = "Open Linked File"
bl_description = "Open the selected linked blend file in a new Blender instance"
bl_options = {"REGISTER"}
filepath: StringProperty(name="File Path", default="")
def execute(self, context):
if not self.filepath:
self.report({"ERROR"}, "No file path specified")
return {"CANCELLED"}
try:
bpy.ops.wm.path_open(filepath=self.filepath)
self.report({"INFO"}, f"Opening linked file: {self.filepath}")
except Exception as e:
self.report({"ERROR"}, f"Failed to open linked file: {e}")
return {"CANCELLED"}
return {"FINISHED"}
class DLM_OT_add_search_path(Operator):
bl_idname = "dlm.add_search_path"
bl_label = "Add Search Path"
bl_description = "Add a new folder to the list of search paths for finding libraries"
bl_options = {"REGISTER"}
def execute(self, context):
prefs = _prefs(context)
if prefs:
p = prefs.preferences.search_paths.add()
p.path = "//"
self.report({"INFO"}, f"Added search path: {p.path}")
return {"FINISHED"}
class DLM_OT_remove_search_path(Operator):
bl_idname = "dlm.remove_search_path"
bl_label = "Remove Search Path"
bl_description = "Remove the selected search path from the list"
bl_options = {"REGISTER"}
index: IntProperty(name="Index", default=0)
def execute(self, context):
prefs = _prefs(context)
if prefs and prefs.preferences.search_paths and 0 <= self.index < len(prefs.preferences.search_paths):
prefs.preferences.search_paths.remove(self.index)
self.report({"INFO"}, f"Removed search path at index {self.index}")
return {"FINISHED"}
class DLM_OT_attempt_relink(Operator):
bl_idname = "dlm.attempt_relink"
bl_label = "Attempt Relink"
bl_description = "Try to relink missing libraries using the configured search paths"
bl_options = {"REGISTER"}
def execute(self, context):
from ..ops import library
return library.attempt_relink(context, self.report, ADDON_NAME)
class DLM_OT_browse_search_path(Operator):
bl_idname = "dlm.browse_search_path"
bl_label = "Browse Search Path"
bl_description = "Browse to set the folder for the selected search path"
bl_options = {"REGISTER"}
index: IntProperty(name="Index", default=0)
filepath: StringProperty(name="Search Path", subtype="DIR_PATH")
def execute(self, context):
prefs = _prefs(context)
if prefs and prefs.preferences.search_paths and 0 <= self.index < len(prefs.preferences.search_paths):
prefs.preferences.search_paths[self.index].path = self.filepath
self.report({"INFO"}, f"Updated search path {self.index + 1}: {self.filepath}")
return {"FINISHED"}
def invoke(self, context, event):
prefs = _prefs(context)
if prefs and prefs.preferences.search_paths and 0 <= self.index < len(prefs.preferences.search_paths):
self.filepath = prefs.preferences.search_paths[self.index].path
context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"}
class DLM_OT_reload_libraries(Operator):
bl_idname = "dlm.reload_libraries"
bl_label = "Reload Libraries"
bl_description = "Reload all linked libraries (or fallback manual reload)"
bl_options = {"REGISTER"}
def execute(self, context):
try:
bpy.ops.outliner.lib_operation(type="RELOAD")
self.report({"INFO"}, "Library reload operation completed")
except Exception:
try:
for lib in bpy.data.libraries:
if lib.filepath and os.path.exists(bpy.path.abspath(lib.filepath)):
lib.reload()
self.report({"INFO"}, "Libraries reloaded manually")
except Exception as e:
self.report({"ERROR"}, f"Failed to reload libraries: {e}")
return {"CANCELLED"}
return {"FINISHED"}
class DLM_OT_make_paths_relative(Operator):
bl_idname = "dlm.make_paths_relative"
bl_label = "Make Paths Relative"
bl_description = "Convert all internal file paths to relative"
bl_options = {"REGISTER"}
def execute(self, context):
try:
bpy.ops.file.make_paths_relative()
self.report({"INFO"}, "All file paths made relative")
except Exception as e:
self.report({"ERROR"}, f"Failed to make paths relative: {e}")
return {"CANCELLED"}
return {"FINISHED"}
class DLM_OT_make_paths_absolute(Operator):
bl_idname = "dlm.make_paths_absolute"
bl_label = "Make Paths Absolute"
bl_description = "Convert all internal file paths to absolute"
bl_options = {"REGISTER"}
def execute(self, context):
try:
bpy.ops.file.make_paths_absolute()
self.report({"INFO"}, "All file paths made absolute")
except Exception as e:
self.report({"ERROR"}, f"Failed to make paths absolute: {e}")
return {"CANCELLED"}
return {"FINISHED"}
class DLM_OT_relocate_single_library(Operator):
bl_idname = "dlm.relocate_single_library"
bl_label = "Relocate Library"
bl_description = "Point the selected library to a new blend file and reload"
bl_options = {"REGISTER", "UNDO"}
target_filepath: StringProperty(name="Current Library Path", default="")
filepath: StringProperty(name="New Library File", subtype="FILE_PATH", default="")
def execute(self, context):
if not self.target_filepath or not self.filepath:
self.report({"ERROR"}, "No target or new file specified")
return {"CANCELLED"}
abs_match = bpy.path.abspath(self.target_filepath) if self.target_filepath else ""
library = None
for lib in bpy.data.libraries:
try:
if lib.filepath and bpy.path.abspath(lib.filepath) == abs_match:
library = lib
break
except Exception:
if lib.filepath == self.target_filepath:
library = lib
break
if not library:
self.report({"ERROR"}, "Could not resolve the selected library")
return {"CANCELLED"}
try:
library.filepath = self.filepath
library.reload()
self.report({"INFO"}, f"Relocated to: {self.filepath}")
except Exception as e:
self.report({"ERROR"}, f"Failed to relocate: {e}")
return {"CANCELLED"}
return {"FINISHED"}
def invoke(self, context, event):
if self.target_filepath:
try:
self.filepath = bpy.path.abspath(self.target_filepath)
except Exception:
self.filepath = self.target_filepath
context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"}
def _get_migrator_pair(context):
"""Return (orig, rep) from scene props (manual or automatic). (None, None) if invalid."""
from ..ops.migrator import get_pair_manual, get_pair_automatic
props = getattr(context.scene, "dynamic_link_manager", None)
if not props:
return None, None
use_auto = getattr(props, "migrator_mode", False)
orig, rep = get_pair_automatic(context) if use_auto else get_pair_manual(context)
return orig, rep
class DLM_OT_migrator_copy_attributes(Operator):
bl_idname = "dlm.migrator_copy_attributes"
bl_label = "CopyAttr"
bl_description = "Copy object and armature attributes from original to replacement character"
bl_icon = "COPY_ID"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
orig, rep = _get_migrator_pair(context)
if not orig or not rep or orig == rep:
self.report({"ERROR"}, "No valid character pair (set Original/Replacement or enable Automatic).")
return {"CANCELLED"}
try:
from ..ops.migrator import run_copy_attr
run_copy_attr(orig, rep)
self.report({"INFO"}, "Copy attributes done.")
return {"FINISHED"}
except Exception as e:
self.report({"ERROR"}, str(e))
return {"CANCELLED"}
class DLM_OT_migrator_migrate_nla(Operator):
bl_idname = "dlm.migrator_migrate_nla"
bl_label = "MigNLA"
bl_description = "Migrate NLA tracks and strips from original to replacement character"
bl_icon = "NLA"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
orig, rep = _get_migrator_pair(context)
if not orig or not rep or orig == rep:
self.report({"ERROR"}, "No valid character pair.")
return {"CANCELLED"}
try:
from ..ops.migrator import run_mig_nla
run_mig_nla(orig, rep, report=self.report)
return {"FINISHED"}
except Exception as e:
self.report({"ERROR"}, str(e))
return {"CANCELLED"}
class DLM_OT_migrator_custom_properties(Operator):
bl_idname = "dlm.migrator_custom_properties"
bl_label = "MigCustProps"
bl_description = "Copy custom properties from original to replacement character"
bl_icon = "PROPERTIES"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
orig, rep = _get_migrator_pair(context)
if not orig or not rep or orig == rep:
self.report({"ERROR"}, "No valid character pair.")
return {"CANCELLED"}
try:
from ..ops.migrator import run_mig_cust_props
run_mig_cust_props(orig, rep)
self.report({"INFO"}, "Custom properties done.")
return {"FINISHED"}
except Exception as e:
self.report({"ERROR"}, str(e))
return {"CANCELLED"}
class DLM_OT_migrator_bone_constraints(Operator):
bl_idname = "dlm.migrator_bone_constraints"
bl_label = "MigBoneConst"
bl_description = "Migrate bone constraints from original to replacement armature"
bl_icon = "CONSTRAINT_BONE"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
orig, rep = _get_migrator_pair(context)
if not orig or not rep or orig == rep:
self.report({"ERROR"}, "No valid character pair.")
return {"CANCELLED"}
try:
from ..ops.migrator import run_mig_bone_const
orig_to_rep = {orig: rep}
run_mig_bone_const(orig, rep, orig_to_rep)
self.report({"INFO"}, "Bone constraints done.")
return {"FINISHED"}
except Exception as e:
self.report({"ERROR"}, str(e))
return {"CANCELLED"}
class DLM_OT_migrator_retarget_relations(Operator):
bl_idname = "dlm.migrator_retarget_relations"
bl_label = "RetargRelatives"
bl_description = "Retarget parent/child and other relations to the replacement character"
bl_icon = "ORIENTATION_PARENT"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
orig, rep = _get_migrator_pair(context)
if not orig or not rep or orig == rep:
self.report({"ERROR"}, "No valid character pair.")
return {"CANCELLED"}
try:
from ..ops.migrator import run_retarg_relatives
from ..utils import descendants
rep_descendants = descendants(rep)
orig_to_rep = {orig: rep}
run_retarg_relatives(orig, rep, rep_descendants, orig_to_rep)
self.report({"INFO"}, "Retarget relations done.")
return {"FINISHED"}
except Exception as e:
self.report({"ERROR"}, str(e))
return {"CANCELLED"}
class DLM_OT_migrator_basebody_shapekeys(Operator):
bl_idname = "dlm.migrator_basebody_shapekeys"
bl_label = "MigBBodyShapeKeys"
bl_description = "Migrate base body mesh shape key values from original to replacement"
bl_icon = "SHAPEKEY_DATA"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
orig, rep = _get_migrator_pair(context)
if not orig or not rep or orig == rep:
self.report({"ERROR"}, "No valid character pair.")
return {"CANCELLED"}
try:
from ..ops.migrator import run_mig_bbody_shapekeys
from ..utils import descendants
rep_descendants = descendants(rep)
run_mig_bbody_shapekeys(orig, rep, rep_descendants, context)
self.report({"INFO"}, "Migrate BaseBody shapekeys done.")
return {"FINISHED"}
except Exception as e:
self.report({"ERROR"}, str(e))
return {"CANCELLED"}
class DLM_OT_migrator_fk_rotations(Operator):
bl_idname = "dlm.migrator_fk_rotations"
bl_label = "MigFKRot"
bl_description = "Copy FK arm and finger rotations from original to replacement (uses constraints)"
bl_icon = "BONE_DATA"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
orig, rep = _get_migrator_pair(context)
if not orig or not rep or orig == rep:
self.report({"ERROR"}, "No valid character pair.")
return {"CANCELLED"}
try:
from ..ops.fk_rotations import copy_fk_rotations
ok, msg = copy_fk_rotations(context, orig, rep)
if ok:
self.report({"INFO"}, msg)
return {"FINISHED"}
else:
self.report({"ERROR"}, msg)
return {"CANCELLED"}
except Exception as e:
self.report({"ERROR"}, str(e))
return {"CANCELLED"}
class DLM_OT_migrator_fk_rotations_bake(Operator):
bl_idname = "dlm.migrator_fk_rotations_bake"
bl_label = "Bake MigFKRot"
bl_description = "Bake FK rotations to keyframes using nla.bake (similar to tweak tools)"
bl_icon = "KEYFRAME"
bl_options = {"REGISTER", "UNDO"}
track_name: StringProperty(name="NLA Track", description="Optional NLA track name for frame range", default="")
post_clean: BoolProperty(name="Post-clean", description="Clean curves after bake", default=False)
def execute(self, context):
orig, rep = _get_migrator_pair(context)
if not orig or not rep or orig == rep:
self.report({"ERROR"}, "No valid character pair.")
return {"CANCELLED"}
try:
from ..ops.fk_rotations import bake_fk_rotations
ok, msg = bake_fk_rotations(context, orig, rep, track_name=self.track_name or None, post_clean=self.post_clean)
if ok:
self.report({"INFO"}, msg)
return {"FINISHED"}
else:
self.report({"ERROR"}, msg)
return {"CANCELLED"}
except Exception as e:
self.report({"ERROR"}, str(e))
return {"CANCELLED"}
class DLM_OT_migrator_fk_rotations_remove(Operator):
bl_idname = "dlm.migrator_fk_rotations_remove"
bl_label = "Remove MigFKRot"
bl_description = "Remove FK rotation COPY_TRANSFORMS constraints (similar to tweak_remove_arm)"
bl_icon = "X"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
orig, rep = _get_migrator_pair(context)
if not orig or not rep or orig == rep:
self.report({"ERROR"}, "No valid character pair.")
return {"CANCELLED"}
try:
from ..ops.fk_rotations import remove_fk_rotations
ok, msg = remove_fk_rotations(context, rep)
if ok:
self.report({"INFO"}, msg)
return {"FINISHED"}
else:
self.report({"ERROR"}, msg)
return {"CANCELLED"}
except Exception as e:
self.report({"ERROR"}, str(e))
return {"CANCELLED"}
class DLM_OT_migrator_remove_original(Operator):
bl_idname = "dlm.migrator_remove_original"
bl_label = "Remove Original"
bl_description = "Delete the original character armature and its data from the scene"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
orig, rep = _get_migrator_pair(context)
if not orig:
self.report({"WARNING"}, "No original character selected")
return {"CANCELLED"}
if orig == rep:
self.report({"ERROR"}, "Original and replacement cannot be the same object")
return {"CANCELLED"}
name = orig.name
try:
# Remove from scene
bpy.data.objects.remove(orig, do_unlink=True)
# Clear the property
context.scene.dynamic_link_manager.original_character = None
self.report({"INFO"}, f"Removed original character: {name}")
except Exception as e:
self.report({"ERROR"}, f"Failed to remove original: {e}")
return {"CANCELLED"}
return {"FINISHED"}
class DLM_OT_picker_original_character(Operator):
bl_idname = "dlm.picker_original_character"
bl_label = "Pick Original"
bl_description = "Set the original character armature from the active object"
bl_options = {"REGISTER"}
def execute(self, context):
obj = context.active_object
if not obj or obj.type != "ARMATURE":
self.report({"WARNING"}, "Select an armature")
return {"CANCELLED"}
context.scene.dynamic_link_manager.original_character = obj
self.report({"INFO"}, f"Original: {obj.name}")
return {"FINISHED"}
class DLM_OT_picker_replacement_character(Operator):
bl_idname = "dlm.picker_replacement_character"
bl_label = "Pick Replacement"
bl_description = "Set the replacement character armature from the active object"
bl_options = {"REGISTER"}
def execute(self, context):
obj = context.active_object
if not obj or obj.type != "ARMATURE":
self.report({"WARNING"}, "Select an armature")
return {"CANCELLED"}
context.scene.dynamic_link_manager.replacement_character = obj
self.report({"INFO"}, f"Replacement: {obj.name}")
return {"FINISHED"}
def _tweak_poll(context):
orig, rep = _get_migrator_pair(context)
return orig is not None and rep is not None
class DLM_OT_tweak_add_arm(Operator):
bl_idname = "dlm.tweak_add_arm"
bl_label = "Add Arm Tweaks"
bl_description = "Add tweak bone constraints to arm bones on the replacement character"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return _tweak_poll(context)
def execute(self, context):
orig, rep = _get_migrator_pair(context)
from ..ops import tweak_tools
tweak_tools.add_tweak_constraints(orig, rep, "arm")
self.report({"INFO"}, "Arm tweak constraints added.")
return {"FINISHED"}
class DLM_OT_tweak_remove_arm(Operator):
bl_idname = "dlm.tweak_remove_arm"
bl_label = "Remove Arm Tweaks"
bl_description = "Remove arm tweak constraints from the replacement character"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return _tweak_poll(context)
def execute(self, context):
orig, rep = _get_migrator_pair(context)
from ..ops import tweak_tools
n = tweak_tools.remove_tweak_constraints(orig, rep, "arm")
self.report({"INFO"}, f"Removed {n} arm tweak constraints.")
return {"FINISHED"}
class DLM_OT_tweak_bake_arm(Operator):
bl_idname = "dlm.tweak_bake_arm"
bl_label = "Bake Arm Tweaks"
bl_description = "Bake arm tweak constraints to keyframes and optionally remove constraints"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return _tweak_poll(context)
def execute(self, context):
orig, rep = _get_migrator_pair(context)
props = context.scene.dynamic_link_manager
from ..ops import tweak_tools
ok, msg = tweak_tools.bake_tweak_constraints(
context, orig, rep, "arm",
getattr(props, "tweak_nla_track_name", "") or "",
getattr(props, "tweak_bake_post_clean", False),
)
if ok:
self.report({"INFO"}, msg)
return {"FINISHED"}
self.report({"ERROR"}, msg)
return {"CANCELLED"}
class DLM_OT_tweak_add_leg(Operator):
bl_idname = "dlm.tweak_add_leg"
bl_label = "Add Leg Tweaks"
bl_description = "Add tweak bone constraints to leg bones on the replacement character"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return _tweak_poll(context)
def execute(self, context):
orig, rep = _get_migrator_pair(context)
from ..ops import tweak_tools
tweak_tools.add_tweak_constraints(orig, rep, "leg")
self.report({"INFO"}, "Leg tweak constraints added.")
return {"FINISHED"}
class DLM_OT_tweak_remove_leg(Operator):
bl_idname = "dlm.tweak_remove_leg"
bl_label = "Remove Leg Tweaks"
bl_description = "Remove leg tweak constraints from the replacement character"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return _tweak_poll(context)
def execute(self, context):
orig, rep = _get_migrator_pair(context)
from ..ops import tweak_tools
n = tweak_tools.remove_tweak_constraints(orig, rep, "leg")
self.report({"INFO"}, f"Removed {n} leg tweak constraints.")
return {"FINISHED"}
class DLM_OT_tweak_bake_leg(Operator):
bl_idname = "dlm.tweak_bake_leg"
bl_label = "Bake Leg Tweaks"
bl_description = "Bake leg tweak constraints to keyframes and optionally remove constraints"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return _tweak_poll(context)
def execute(self, context):
orig, rep = _get_migrator_pair(context)
props = context.scene.dynamic_link_manager
from ..ops import tweak_tools
ok, msg = tweak_tools.bake_tweak_constraints(
context, orig, rep, "leg",
getattr(props, "tweak_nla_track_name", "") or "",
getattr(props, "tweak_bake_post_clean", False),
)
if ok:
self.report({"INFO"}, msg)
return {"FINISHED"}
self.report({"ERROR"}, msg)
return {"CANCELLED"}
class DLM_OT_tweak_add_both(Operator):
bl_idname = "dlm.tweak_add_both"
bl_label = "Add Arm & Leg Tweaks"
bl_description = "Add tweak bone constraints to both arm and leg bones"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return _tweak_poll(context)
def execute(self, context):
orig, rep = _get_migrator_pair(context)
from ..ops import tweak_tools
tweak_tools.add_tweak_constraints(orig, rep, "both")
self.report({"INFO"}, "Arm & leg tweak constraints added.")
return {"FINISHED"}
class DLM_OT_tweak_remove_both(Operator):
bl_idname = "dlm.tweak_remove_both"
bl_label = "Remove Arm & Leg Tweaks"
bl_description = "Remove all arm and leg tweak constraints from the replacement character"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return _tweak_poll(context)
def execute(self, context):
orig, rep = _get_migrator_pair(context)
from ..ops import tweak_tools
n = tweak_tools.remove_tweak_constraints(orig, rep, "both")
self.report({"INFO"}, f"Removed {n} tweak constraints.")
return {"FINISHED"}
class DLM_OT_tweak_bake_both(Operator):
bl_idname = "dlm.tweak_bake_both"
bl_label = "Bake Arm & Leg Tweaks"
bl_description = "Bake all arm and leg tweak constraints to keyframes and optionally remove constraints"
bl_options = {"REGISTER", "UNDO"}
@classmethod
def poll(cls, context):
return _tweak_poll(context)
def execute(self, context):
orig, rep = _get_migrator_pair(context)
props = context.scene.dynamic_link_manager
from ..ops import tweak_tools
ok, msg = tweak_tools.bake_tweak_constraints(
context, orig, rep, "both",
getattr(props, "tweak_nla_track_name", "") or "",
getattr(props, "tweak_bake_post_clean", False),
)
if ok:
self.report({"INFO"}, msg)
return {"FINISHED"}
self.report({"ERROR"}, msg)
return {"CANCELLED"}
OPERATOR_CLASSES = [
DLM_OT_replace_linked_asset,
DLM_OT_scan_linked_assets,
DLM_OT_find_libraries_in_folders,
DLM_OT_open_linked_file,
DLM_OT_add_search_path,
DLM_OT_remove_search_path,
DLM_OT_browse_search_path,
DLM_OT_attempt_relink,
DLM_OT_reload_libraries,
DLM_OT_make_paths_relative,
DLM_OT_make_paths_absolute,
DLM_OT_relocate_single_library,
DLM_OT_migrator_remove_original,
DLM_OT_picker_original_character,
DLM_OT_picker_replacement_character,
DLM_OT_migrator_copy_attributes,
DLM_OT_migrator_migrate_nla,
DLM_OT_migrator_custom_properties,
DLM_OT_migrator_bone_constraints,
DLM_OT_migrator_retarget_relations,
DLM_OT_migrator_basebody_shapekeys,
DLM_OT_tweak_add_arm,
DLM_OT_tweak_remove_arm,
DLM_OT_tweak_bake_arm,
DLM_OT_tweak_add_leg,
DLM_OT_tweak_remove_leg,
DLM_OT_tweak_bake_leg,
DLM_OT_tweak_add_both,
DLM_OT_tweak_remove_both,
DLM_OT_tweak_bake_both,
DLM_OT_migrator_fk_rotations,
DLM_OT_migrator_fk_rotations_bake,
DLM_OT_migrator_fk_rotations_remove,
]
Thought Process
Let me search for the DLM_OT_migrator_remove_original class more specifically and look for the _get_migrator_pair function which is used to get the original and replacement objects. I also need to find utility functions that help find which collection contains an object.Let me search for these patterns in the file.
Let me search for more specific sections, including the _get_migrator_pair function and any collection-related utilities.
Tool use: **run_terminal_command_v2** • Run command: rg "def _get_migrator_pair|def .*collection.*object|DLM_OT_migrator_remove_original" "T:\Dynamic-Link-Manager\ui\operators.py" -A 20
rg "def _get_migrator_pair|def .*collection.*object|DLM_OT_migrator_remove_original" "T:\Dynamic-Link-Manager\ui\operators.py" -A 20
rg: C:\Users\Nathan\AppData\Local\Temp\ps-script-4c7a9963-de74-435a-877d-ea6ffb008b73.ps1:113
Line |
113 | rg "def _get_migrator_pair|def .*collection.*object|DLM_OT_migrator_r .
| ~~
| The term 'rg' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the
| spelling of the name, or if a path was included, verify that the path is correct and try again.
Thought Process
rg (ripgrep) is not available on Windows by default. Let me use PowerShell's Select-String instead.Tool use: **run_terminal_command_v2** • Run command: Select-String -Path "T:\Dynamic-Link-Manager\ui\operators.py" -Pattern "_get_migrator_pair|collection.*object|DLM_OT_migrator_remove_original" -Context 0,15
Select-String -Path "T:\Dynamic-Link-Manager\ui\operators.py" -Pattern "_get_migrator_pair|collection.*object|DLM_OT_migrator_remove_original" -Context 0,15
> ui\operators.py:258:def _get_migrator_pair(context):
ui\operators.py:259: """Return (orig, rep) from scene props (manual or automatic). (None, None) if invalid."""
ui\operators.py:260: from ..ops.migrator import get_pair_manual, get_pair_automatic
ui\operators.py:261:
ui\operators.py:262: props = getattr(context.scene, "dynamic_link_manager", None)
ui\operators.py:263: if not props:
ui\operators.py:264: return None, None
ui\operators.py:265: use_auto = getattr(props, "migrator_mode", False)
ui\operators.py:266: orig, rep = get_pair_automatic(context) if use_auto else get_pair_manual(context)
ui\operators.py:267: return orig, rep
ui\operators.py:268:
ui\operators.py:269:
ui\operators.py:270:class DLM_OT_migrator_copy_attributes(Operator):
ui\operators.py:271: bl_idname = "dlm.migrator_copy_attributes"
ui\operators.py:272: bl_label = "CopyAttr"
ui\operators.py:273: bl_description = "Copy object and armature attributes from original to replacement character"
> ui\operators.py:278: orig, rep = _get_migrator_pair(context)
ui\operators.py:279: if not orig or not rep or orig == rep:
ui\operators.py:280: self.report({"ERROR"}, "No valid character pair (set Original/Replacement or enable
Automatic).")
ui\operators.py:281: return {"CANCELLED"}
ui\operators.py:282: try:
ui\operators.py:283: from ..ops.migrator import run_copy_attr
ui\operators.py:284: run_copy_attr(orig, rep)
ui\operators.py:285: self.report({"INFO"}, "Copy attributes done.")
ui\operators.py:286: return {"FINISHED"}
ui\operators.py:287: except Exception as e:
ui\operators.py:288: self.report({"ERROR"}, str(e))
ui\operators.py:289: return {"CANCELLED"}
ui\operators.py:290:
ui\operators.py:291:
ui\operators.py:292:class DLM_OT_migrator_migrate_nla(Operator):
ui\operators.py:293: bl_idname = "dlm.migrator_migrate_nla"
> ui\operators.py:300: orig, rep = _get_migrator_pair(context)
ui\operators.py:301: if not orig or not rep or orig == rep:
ui\operators.py:302: self.report({"ERROR"}, "No valid character pair.")
ui\operators.py:303: return {"CANCELLED"}
ui\operators.py:304: try:
ui\operators.py:305: from ..ops.migrator import run_mig_nla
ui\operators.py:306: run_mig_nla(orig, rep, report=self.report)
ui\operators.py:307: return {"FINISHED"}
ui\operators.py:308: except Exception as e:
ui\operators.py:309: self.report({"ERROR"}, str(e))
ui\operators.py:310: return {"CANCELLED"}
ui\operators.py:311:
ui\operators.py:312:
ui\operators.py:313:class DLM_OT_migrator_custom_properties(Operator):
ui\operators.py:314: bl_idname = "dlm.migrator_custom_properties"
ui\operators.py:315: bl_label = "MigCustProps"
> ui\operators.py:321: orig, rep = _get_migrator_pair(context)
ui\operators.py:322: if not orig or not rep or orig == rep:
ui\operators.py:323: self.report({"ERROR"}, "No valid character pair.")
ui\operators.py:324: return {"CANCELLED"}
ui\operators.py:325: try:
ui\operators.py:326: from ..ops.migrator import run_mig_cust_props
ui\operators.py:327: run_mig_cust_props(orig, rep)
ui\operators.py:328: self.report({"INFO"}, "Custom properties done.")
ui\operators.py:329: return {"FINISHED"}
ui\operators.py:330: except Exception as e:
ui\operators.py:331: self.report({"ERROR"}, str(e))
ui\operators.py:332: return {"CANCELLED"}
ui\operators.py:333:
ui\operators.py:334:
ui\operators.py:335:class DLM_OT_migrator_bone_constraints(Operator):
ui\operators.py:336: bl_idname = "dlm.migrator_bone_constraints"
> ui\operators.py:343: orig, rep = _get_migrator_pair(context)
ui\operators.py:344: if not orig or not rep or orig == rep:
ui\operators.py:345: self.report({"ERROR"}, "No valid character pair.")
ui\operators.py:346: return {"CANCELLED"}
ui\operators.py:347: try:
ui\operators.py:348: from ..ops.migrator import run_mig_bone_const
ui\operators.py:349: orig_to_rep = {orig: rep}
ui\operators.py:350: run_mig_bone_const(orig, rep, orig_to_rep)
ui\operators.py:351: self.report({"INFO"}, "Bone constraints done.")
ui\operators.py:352: return {"FINISHED"}
ui\operators.py:353: except Exception as e:
ui\operators.py:354: self.report({"ERROR"}, str(e))
ui\operators.py:355: return {"CANCELLED"}
ui\operators.py:356:
ui\operators.py:357:
ui\operators.py:358:class DLM_OT_migrator_retarget_relations(Operator):
> ui\operators.py:366: orig, rep = _get_migrator_pair(context)
ui\operators.py:367: if not orig or not rep or orig == rep:
ui\operators.py:368: self.report({"ERROR"}, "No valid character pair.")
ui\operators.py:369: return {"CANCELLED"}
ui\operators.py:370: try:
ui\operators.py:371: from ..ops.migrator import run_retarg_relatives
ui\operators.py:372: from ..utils import descendants
ui\operators.py:373: rep_descendants = descendants(rep)
ui\operators.py:374: orig_to_rep = {orig: rep}
ui\operators.py:375: run_retarg_relatives(orig, rep, rep_descendants, orig_to_rep)
ui\operators.py:376: self.report({"INFO"}, "Retarget relations done.")
ui\operators.py:377: return {"FINISHED"}
ui\operators.py:378: except Exception as e:
ui\operators.py:379: self.report({"ERROR"}, str(e))
ui\operators.py:380: return {"CANCELLED"}
ui\operators.py:381:
> ui\operators.py:391: orig, rep = _get_migrator_pair(context)
ui\operators.py:392: if not orig or not rep or orig == rep:
ui\operators.py:393: self.report({"ERROR"}, "No valid character pair.")
ui\operators.py:394: return {"CANCELLED"}
ui\operators.py:395: try:
ui\operators.py:396: from ..ops.migrator import run_mig_bbody_shapekeys
ui\operators.py:397: from ..utils import descendants
ui\operators.py:398: rep_descendants = descendants(rep)
ui\operators.py:399: run_mig_bbody_shapekeys(orig, rep, rep_descendants, context)
ui\operators.py:400: self.report({"INFO"}, "Migrate BaseBody shapekeys done.")
ui\operators.py:401: return {"FINISHED"}
ui\operators.py:402: except Exception as e:
ui\operators.py:403: self.report({"ERROR"}, str(e))
ui\operators.py:404: return {"CANCELLED"}
ui\operators.py:405:
ui\operators.py:406:
> ui\operators.py:415: orig, rep = _get_migrator_pair(context)
ui\operators.py:416: if not orig or not rep or orig == rep:
ui\operators.py:417: self.report({"ERROR"}, "No valid character pair.")
ui\operators.py:418: return {"CANCELLED"}
ui\operators.py:419: try:
ui\operators.py:420: from ..ops.fk_rotations import copy_fk_rotations
ui\operators.py:421: ok, msg = copy_fk_rotations(context, orig, rep)
ui\operators.py:422: if ok:
ui\operators.py:423: self.report({"INFO"}, msg)
ui\operators.py:424: return {"FINISHED"}
ui\operators.py:425: else:
ui\operators.py:426: self.report({"ERROR"}, msg)
ui\operators.py:427: return {"CANCELLED"}
ui\operators.py:428: except Exception as e:
ui\operators.py:429: self.report({"ERROR"}, str(e))
ui\operators.py:430: return {"CANCELLED"}
> ui\operators.py:444: orig, rep = _get_migrator_pair(context)
ui\operators.py:445: if not orig or not rep or orig == rep:
ui\operators.py:446: self.report({"ERROR"}, "No valid character pair.")
ui\operators.py:447: return {"CANCELLED"}
ui\operators.py:448: try:
ui\operators.py:449: from ..ops.fk_rotations import bake_fk_rotations
ui\operators.py:450: ok, msg = bake_fk_rotations(context, orig, rep, track_name=self.track_name or None,
post_clean=self.post_clean)
ui\operators.py:451: if ok:
ui\operators.py:452: self.report({"INFO"}, msg)
ui\operators.py:453: return {"FINISHED"}
ui\operators.py:454: else:
ui\operators.py:455: self.report({"ERROR"}, msg)
ui\operators.py:456: return {"CANCELLED"}
ui\operators.py:457: except Exception as e:
ui\operators.py:458: self.report({"ERROR"}, str(e))
ui\operators.py:459: return {"CANCELLED"}
> ui\operators.py:470: orig, rep = _get_migrator_pair(context)
ui\operators.py:471: if not orig or not rep or orig == rep:
ui\operators.py:472: self.report({"ERROR"}, "No valid character pair.")
ui\operators.py:473: return {"CANCELLED"}
ui\operators.py:474: try:
ui\operators.py:475: from ..ops.fk_rotations import remove_fk_rotations
ui\operators.py:476: ok, msg = remove_fk_rotations(context, rep)
ui\operators.py:477: if ok:
ui\operators.py:478: self.report({"INFO"}, msg)
ui\operators.py:479: return {"FINISHED"}
ui\operators.py:480: else:
ui\operators.py:481: self.report({"ERROR"}, msg)
ui\operators.py:482: return {"CANCELLED"}
ui\operators.py:483: except Exception as e:
ui\operators.py:484: self.report({"ERROR"}, str(e))
ui\operators.py:485: return {"CANCELLED"}
> ui\operators.py:490:class DLM_OT_migrator_remove_original(Operator):
ui\operators.py:491: bl_idname = "dlm.migrator_remove_original"
ui\operators.py:492: bl_label = "Remove Original"
ui\operators.py:493: bl_description = "Delete the original character armature and its data from the scene"
ui\operators.py:494: bl_options = {"REGISTER", "UNDO"}
ui\operators.py:495:
ui\operators.py:496: def execute(self, context):
> ui\operators.py:497: orig, rep = _get_migrator_pair(context)
ui\operators.py:498: if not orig:
ui\operators.py:499: self.report({"WARNING"}, "No original character selected")
ui\operators.py:500: return {"CANCELLED"}
ui\operators.py:501: if orig == rep:
ui\operators.py:502: self.report({"ERROR"}, "Original and replacement cannot be the same object")
ui\operators.py:503: return {"CANCELLED"}
ui\operators.py:504:
ui\operators.py:505: name = orig.name
ui\operators.py:506: try:
ui\operators.py:507: # Remove from scene
ui\operators.py:508: bpy.data.objects.remove(orig, do_unlink=True)
ui\operators.py:509: # Clear the property
ui\operators.py:510: context.scene.dynamic_link_manager.original_character = None
ui\operators.py:511: self.report({"INFO"}, f"Removed original character: {name}")
ui\operators.py:512: except Exception as e:
> ui\operators.py:552: orig, rep = _get_migrator_pair(context)
ui\operators.py:553: return orig is not None and rep is not None
ui\operators.py:554:
ui\operators.py:555:
ui\operators.py:556:class DLM_OT_tweak_add_arm(Operator):
ui\operators.py:557: bl_idname = "dlm.tweak_add_arm"
ui\operators.py:558: bl_label = "Add Arm Tweaks"
ui\operators.py:559: bl_description = "Add tweak bone constraints to arm bones on the replacement character"
ui\operators.py:560: bl_options = {"REGISTER", "UNDO"}
ui\operators.py:561:
ui\operators.py:562: @classmethod
ui\operators.py:563: def poll(cls, context):
ui\operators.py:564: return _tweak_poll(context)
ui\operators.py:565:
ui\operators.py:566: def execute(self, context):
> ui\operators.py:567: orig, rep = _get_migrator_pair(context)
ui\operators.py:568: from ..ops import tweak_tools
ui\operators.py:569: tweak_tools.add_tweak_constraints(orig, rep, "arm")
ui\operators.py:570: self.report({"INFO"}, "Arm tweak constraints added.")
ui\operators.py:571: return {"FINISHED"}
ui\operators.py:572:
ui\operators.py:573:
ui\operators.py:574:class DLM_OT_tweak_remove_arm(Operator):
ui\operators.py:575: bl_idname = "dlm.tweak_remove_arm"
ui\operators.py:576: bl_label = "Remove Arm Tweaks"
ui\operators.py:577: bl_description = "Remove arm tweak constraints from the replacement character"
ui\operators.py:578: bl_options = {"REGISTER", "UNDO"}
ui\operators.py:579:
ui\operators.py:580: @classmethod
ui\operators.py:581: def poll(cls, context):
ui\operators.py:582: return _tweak_poll(context)
> ui\operators.py:585: orig, rep = _get_migrator_pair(context)
ui\operators.py:586: from ..ops import tweak_tools
ui\operators.py:587: n = tweak_tools.remove_tweak_constraints(orig, rep, "arm")
ui\operators.py:588: self.report({"INFO"}, f"Removed {n} arm tweak constraints.")
ui\operators.py:589: return {"FINISHED"}
ui\operators.py:590:
ui\operators.py:591:
ui\operators.py:592:class DLM_OT_tweak_bake_arm(Operator):
ui\operators.py:593: bl_idname = "dlm.tweak_bake_arm"
ui\operators.py:594: bl_label = "Bake Arm Tweaks"
ui\operators.py:595: bl_description = "Bake arm tweak constraints to keyframes and optionally remove constraints"
ui\operators.py:596: bl_options = {"REGISTER", "UNDO"}
ui\operators.py:597:
ui\operators.py:598: @classmethod
ui\operators.py:599: def poll(cls, context):
ui\operators.py:600: return _tweak_poll(context)
> ui\operators.py:603: orig, rep = _get_migrator_pair(context)
ui\operators.py:604: props = context.scene.dynamic_link_manager
ui\operators.py:605: from ..ops import tweak_tools
ui\operators.py:606: ok, msg = tweak_tools.bake_tweak_constraints(
ui\operators.py:607: context, orig, rep, "arm",
ui\operators.py:608: getattr(props, "tweak_nla_track_name", "") or "",
ui\operators.py:609: getattr(props, "tweak_bake_post_clean", False),
ui\operators.py:610: )
ui\operators.py:611: if ok:
ui\operators.py:612: self.report({"INFO"}, msg)
ui\operators.py:613: return {"FINISHED"}
ui\operators.py:614: self.report({"ERROR"}, msg)
ui\operators.py:615: return {"CANCELLED"}
ui\operators.py:616:
ui\operators.py:617:
ui\operators.py:618:class DLM_OT_tweak_add_leg(Operator):
> ui\operators.py:629: orig, rep = _get_migrator_pair(context)
ui\operators.py:630: from ..ops import tweak_tools
ui\operators.py:631: tweak_tools.add_tweak_constraints(orig, rep, "leg")
ui\operators.py:632: self.report({"INFO"}, "Leg tweak constraints added.")
ui\operators.py:633: return {"FINISHED"}
ui\operators.py:634:
ui\operators.py:635:
ui\operators.py:636:class DLM_OT_tweak_remove_leg(Operator):
ui\operators.py:637: bl_idname = "dlm.tweak_remove_leg"
ui\operators.py:638: bl_label = "Remove Leg Tweaks"
ui\operators.py:639: bl_description = "Remove leg tweak constraints from the replacement character"
ui\operators.py:640: bl_options = {"REGISTER", "UNDO"}
ui\operators.py:641:
ui\operators.py:642: @classmethod
ui\operators.py:643: def poll(cls, context):
ui\operators.py:644: return _tweak_poll(context)
> ui\operators.py:647: orig, rep = _get_migrator_pair(context)
ui\operators.py:648: from ..ops import tweak_tools
ui\operators.py:649: n = tweak_tools.remove_tweak_constraints(orig, rep, "leg")
ui\operators.py:650: self.report({"INFO"}, f"Removed {n} leg tweak constraints.")
ui\operators.py:651: return {"FINISHED"}
ui\operators.py:652:
ui\operators.py:653:
ui\operators.py:654:class DLM_OT_tweak_bake_leg(Operator):
ui\operators.py:655: bl_idname = "dlm.tweak_bake_leg"
ui\operators.py:656: bl_label = "Bake Leg Tweaks"
ui\operators.py:657: bl_description = "Bake leg tweak constraints to keyframes and optionally remove constraints"
ui\operators.py:658: bl_options = {"REGISTER", "UNDO"}
ui\operators.py:659:
ui\operators.py:660: @classmethod
ui\operators.py:661: def poll(cls, context):
ui\operators.py:662: return _tweak_poll(context)
> ui\operators.py:665: orig, rep = _get_migrator_pair(context)
ui\operators.py:666: props = context.scene.dynamic_link_manager
ui\operators.py:667: from ..ops import tweak_tools
ui\operators.py:668: ok, msg = tweak_tools.bake_tweak_constraints(
ui\operators.py:669: context, orig, rep, "leg",
ui\operators.py:670: getattr(props, "tweak_nla_track_name", "") or "",
ui\operators.py:671: getattr(props, "tweak_bake_post_clean", False),
ui\operators.py:672: )
ui\operators.py:673: if ok:
ui\operators.py:674: self.report({"INFO"}, msg)
ui\operators.py:675: return {"FINISHED"}
ui\operators.py:676: self.report({"ERROR"}, msg)
ui\operators.py:677: return {"CANCELLED"}
ui\operators.py:678:
ui\operators.py:679:
ui\operators.py:680:class DLM_OT_tweak_add_both(Operator):
> ui\operators.py:691: orig, rep = _get_migrator_pair(context)
ui\operators.py:692: from ..ops import tweak_tools
ui\operators.py:693: tweak_tools.add_tweak_constraints(orig, rep, "both")
ui\operators.py:694: self.report({"INFO"}, "Arm & leg tweak constraints added.")
ui\operators.py:695: return {"FINISHED"}
ui\operators.py:696:
ui\operators.py:697:
ui\operators.py:698:class DLM_OT_tweak_remove_both(Operator):
ui\operators.py:699: bl_idname = "dlm.tweak_remove_both"
ui\operators.py:700: bl_label = "Remove Arm & Leg Tweaks"
ui\operators.py:701: bl_description = "Remove all arm and leg tweak constraints from the replacement character"
ui\operators.py:702: bl_options = {"REGISTER", "UNDO"}
ui\operators.py:703:
ui\operators.py:704: @classmethod
ui\operators.py:705: def poll(cls, context):
ui\operators.py:706: return _tweak_poll(context)
> ui\operators.py:709: orig, rep = _get_migrator_pair(context)
ui\operators.py:710: from ..ops import tweak_tools
ui\operators.py:711: n = tweak_tools.remove_tweak_constraints(orig, rep, "both")
ui\operators.py:712: self.report({"INFO"}, f"Removed {n} tweak constraints.")
ui\operators.py:713: return {"FINISHED"}
ui\operators.py:714:
ui\operators.py:715:
ui\operators.py:716:class DLM_OT_tweak_bake_both(Operator):
ui\operators.py:717: bl_idname = "dlm.tweak_bake_both"
ui\operators.py:718: bl_label = "Bake Arm & Leg Tweaks"
ui\operators.py:719: bl_description = "Bake all arm and leg tweak constraints to keyframes and optionally remove
constraints"
ui\operators.py:720: bl_options = {"REGISTER", "UNDO"}
ui\operators.py:721:
ui\operators.py:722: @classmethod
ui\operators.py:723: def poll(cls, context):
ui\operators.py:724: return _tweak_poll(context)
> ui\operators.py:727: orig, rep = _get_migrator_pair(context)
ui\operators.py:728: props = context.scene.dynamic_link_manager
ui\operators.py:729: from ..ops import tweak_tools
ui\operators.py:730: ok, msg = tweak_tools.bake_tweak_constraints(
ui\operators.py:731: context, orig, rep, "both",
ui\operators.py:732: getattr(props, "tweak_nla_track_name", "") or "",
ui\operators.py:733: getattr(props, "tweak_bake_post_clean", False),
ui\operators.py:734: )
ui\operators.py:735: if ok:
ui\operators.py:736: self.report({"INFO"}, msg)
ui\operators.py:737: return {"FINISHED"}
ui\operators.py:738: self.report({"ERROR"}, msg)
ui\operators.py:739: return {"CANCELLED"}
ui\operators.py:740:
ui\operators.py:741:
ui\operators.py:742:OPERATOR_CLASSES = [
> ui\operators.py:755: DLM_OT_migrator_remove_original,
ui\operators.py:756: DLM_OT_picker_original_character,
ui\operators.py:757: DLM_OT_picker_replacement_character,
ui\operators.py:758: DLM_OT_migrator_copy_attributes,
ui\operators.py:759: DLM_OT_migrator_migrate_nla,
ui\operators.py:760: DLM_OT_migrator_custom_properties,
ui\operators.py:761: DLM_OT_migrator_bone_constraints,
ui\operators.py:762: DLM_OT_migrator_retarget_relations,
ui\operators.py:763: DLM_OT_migrator_basebody_shapekeys,
ui\operators.py:764: DLM_OT_tweak_add_arm,
ui\operators.py:765: DLM_OT_tweak_remove_arm,
ui\operators.py:766: DLM_OT_tweak_bake_arm,
ui\operators.py:767: DLM_OT_tweak_add_leg,
ui\operators.py:768: DLM_OT_tweak_remove_leg,
ui\operators.py:769: DLM_OT_tweak_bake_leg,
ui\operators.py:770: DLM_OT_tweak_add_both,
Thought Process
Now I need to find the exact line number for DLM_OT_migrator_remove_original class. Let me search for it specifically with more context.Tool use: **run_terminal_command_v2** • Run command: Select-String -Path "T:\Dynamic-Link-Manager\ui\operators.py" -Pattern "class DLM_OT_migrator_remove_original" -Context 0,25
Select-String -Path "T:\Dynamic-Link-Manager\ui\operators.py" -Pattern "class DLM_OT_migrator_remove_original" -Context 0,25
> ui\operators.py:490:class DLM_OT_migrator_remove_original(Operator):
ui\operators.py:491: bl_idname = "dlm.migrator_remove_original"
ui\operators.py:492: bl_label = "Remove Original"
ui\operators.py:493: bl_description = "Delete the original character armature and its data from the scene"
ui\operators.py:494: bl_options = {"REGISTER", "UNDO"}
ui\operators.py:495:
ui\operators.py:496: def execute(self, context):
ui\operators.py:497: orig, rep = _get_migrator_pair(context)
ui\operators.py:498: if not orig:
ui\operators.py:499: self.report({"WARNING"}, "No original character selected")
ui\operators.py:500: return {"CANCELLED"}
ui\operators.py:501: if orig == rep:
ui\operators.py:502: self.report({"ERROR"}, "Original and replacement cannot be the same object")
ui\operators.py:503: return {"CANCELLED"}
ui\operators.py:504:
ui\operators.py:505: name = orig.name
ui\operators.py:506: try:
ui\operators.py:507: # Remove from scene
ui\operators.py:508: bpy.data.objects.remove(orig, do_unlink=True)
ui\operators.py:509: # Clear the property
ui\operators.py:510: context.scene.dynamic_link_manager.original_character = None
ui\operators.py:511: self.report({"INFO"}, f"Removed original character: {name}")
ui\operators.py:512: except Exception as e:
ui\operators.py:513: self.report({"ERROR"}, f"Failed to remove original: {e}")
ui\operators.py:514: return {"CANCELLED"}
ui\operators.py:515: return {"FINISHED"}
Thought Process
Now I have the class. Let me also check for utility functions that might help find which collection contains an object. Let me search in the utils directory or check for any collection-related utilities.Now let me search for utility functions that help find collections containing objects.
Tool use: **run_terminal_command_v2** • Run command: Select-String -Path "T:\Dynamic-Link-Manager" -Filter "*.py" -Pattern "def .*collection|collection.*object|objects.*collection|find_collection" -Recurse
Select-String -Path "T:\Dynamic-Link-Manager" -Filter "*.py" -Pattern "def .*collection|collection.*object|objects.*collection|find_collection" -Recurse
Select-String: C:\Users\Nathan\AppData\Local\Temp\ps-script-9851db49-1073-4a74-a36d-ca9976789164.ps1:113
Line |
113 | Select-String -Path "T:\Dynamic-Link-Manager" -Filter "*.py" -Pattern .
| ~~~~~~~
| A parameter cannot be found that matches parameter name 'Filter'.
Thought Process
Let me try a different approach - use Get-ChildItem with Select-String.Tool use: **run_terminal_command_v2** • Run command: Get-ChildItem -Path "T:\Dynamic-Link-Manager" -Filter "*.py" -Recurse | Select-String -Pattern "def .*collection|find_collection|object.*collection|collection.*object" | Select-Object -First 30
Get-ChildItem -Path "T:\Dynamic-Link-Manager" -Filter "*.py" -Recurse | Select-String -Pattern "def .*collection|find_collection|object.*collection|collection.*object" | Select-Object -First 30
ops\library.py:64: for idb in list(bpy.data.objects) + list(bpy.data.meshes) + list(bpy.data.armatures) +
list(bpy.data.materials) + list(bpy.data.node_groups) + list(bpy.data.images) + list(bpy.data.texts) +
list(bpy.data.collections) + list(bpy.data.cameras) + list(bpy.data.lights):
ops\migrator.py:462: """Retarget relations: parents, constraint targets, Armature modifiers to rep. Skip objects in
orig's hierarchy (linked collection)."""
ops\migrator.py:502:def _objects_in_collection_recursive(coll):
ops\migrator.py:503: """Yield all objects in collection and nested collections."""
ops\migrator.py:507: yield from _objects_in_collection_recursive(child)
ops\migrator.py:532: found, candidates = gather_candidates(_objects_in_collection_recursive(coll))
utils\__init__.py:24:def collection_containing_armature(armature):