0
$\begingroup$

enter image description here

I need to change all the bone's location and rotation on the right skeleton to match with the left skeleton, but I'm hoping there's a better way than manually fixing each bone here. Thanks!

$\endgroup$
5
  • $\begingroup$ Have you seen the special menus such as copy pose .. paste pose? I think in pose mode for the bone? This may be done by name. I am leaving some act of discovery for you. $\endgroup$ Commented Dec 12, 2020 at 21:47
  • $\begingroup$ Have you ever used a driver? These can also be used for bone rotation. So for some ranges of frames you might use a driver to force the rotation of the index finger of one armature to be [related] to the index finger of a different armature. Or both index fingers can be related to a non renderable [set] of bones. $\endgroup$ Commented Dec 12, 2020 at 21:48
  • $\begingroup$ blender.stackexchange.com/questions/38484/… $\endgroup$ Commented Dec 12, 2020 at 21:52
  • $\begingroup$ actually his question is not about pose position but rest position, he wants the second armature to have the same rest position as the first one, meaning the bones in Edit pose being at the exact same location/rotation, which is not the same as copying a pose $\endgroup$
    – moonboots
    Commented Dec 13, 2020 at 5:31
  • $\begingroup$ @moonboots is right, i did try copy pose / paste pose but it didn't work, and I've never used a driver in blender either if you could specify on how to use them? Otherwise I just need to somehow copy all of the location and rotation data of all the bones on the left skeleton and paste them for the corresponding bones on the right so they have the same rest position. $\endgroup$
    – HoofMcPoof
    Commented Dec 13, 2020 at 20:36

1 Answer 1

2
$\begingroup$

first select object which you want to be clone and then select the reference object and use the script below:

import bpy

ref_ob = bpy.context.object
other_ob = [ob for ob in bpy.data.objects if ob.select_get()]
other_ob.remove(ref_ob)
other_ob = other_ob[0]

bpy.context.view_layer.objects.active = other_ob

bpy.ops.object.mode_set(mode='OBJECT')
for bone in ref_ob.pose.bones:
    if bone.name in other_ob.pose.bones:
        bpy.ops.object.mode_set(mode='POSE')
        other_ob.pose.bones[bone.name].matrix = bone.matrix
        bpy.ops.object.mode_set(mode='OBJECT')
Rotation-only snippet:

in order to copy just rotations, use this code:

import bpy

ref_ob = bpy.context.object
other_ob = [ob for ob in bpy.data.objects if ob.select_get()]
other_ob.remove(ref_ob)
other_ob = other_ob[0]

bpy.context.view_layer.objects.active = other_ob

#store parents and delink
parent_store = dict()
bone_names = [bone.name for bone in other_ob.pose.bones] 
for bn in bone_names:
    parent = other_ob.pose.bones[bn].parent
    parent_val = '' if parent is None else parent.name
    parent_store[bn] = parent_val
    bpy.ops.object.mode_set(mode = 'EDIT')
    other_ob.data.edit_bones[bn].parent = None
    bpy.ops.object.mode_set(mode='POSE')

#copy desired transforms
bpy.ops.object.mode_set(mode='OBJECT')

for bone in ref_ob.pose.bones:
    if bone.name in other_ob.pose.bones:
        bpy.ops.object.mode_set(mode='POSE')
        _mat = other_ob.pose.bones[bone.name].matrix.copy()
        _pos   = _mat.to_translation()
        _scale = _mat.to_scale()
        _rot   = bone.matrix.to_quaternion()
        T = _mat.Translation(_pos)
        R = _rot.to_matrix().to_4x4()
        S = _mat.Diagonal(_scale.to_4d())
        other_ob.pose.bones[bone.name].matrix = T @ R @ S
        bpy.ops.object.mode_set(mode='OBJECT')

bpy.ops.object.mode_set(mode='POSE')
bpy.ops.pose.armature_apply(selected=False)

#restore parents
bpy.ops.object.mode_set(mode = 'EDIT')

for bone in other_ob.pose.bones:
    _name = bone.name
    par_name = parent_store[bone.name]
    _parent = None if par_name == '' else other_ob.data.edit_bones[par_name]
    other_ob.data.edit_bones[_name].parent = _parent

bpy.ops.object.mode_set(mode='OBJECT')
$\endgroup$
9
  • $\begingroup$ Thanks for the script, it's very useful for me. But would you be able to get the script to ignore bones which aren't in both rigs? Right now it causes it to fail. $\endgroup$
    – Candle
    Commented Mar 7, 2021 at 14:46
  • $\begingroup$ @Smail I have added the exception you needed $\endgroup$ Commented Mar 7, 2021 at 15:07
  • $\begingroup$ Wow, speedy work. Thank you! You've saved a lot of hours clicking one by one. $\endgroup$
    – Candle
    Commented Mar 7, 2021 at 16:55
  • $\begingroup$ Thanks for the script! I would be sooo appreciative if you could add a version that only copies the rotation rather than all transforms. My skeletons are different scales and the bones are placed a bit differently so I only need to copy the bone rotations from one to the other. Is that even possible? $\endgroup$
    – AOK
    Commented Jun 9, 2022 at 17:39
  • $\begingroup$ @AOK I've added a snippet for copying only rotations. let me know if it doesn't work for you $\endgroup$ Commented Jun 10, 2022 at 9:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .