0

How to edit bones transformations while staying in blender "data" approach. (no use of context) getting this error : AttributeError: bpy_struct: attribute "matrix_local" from "Bone" is read-only

A_obj = data.objects['A']
B_obj = data.objects['B']

bonesA = A_obj.data.bones bonesB = B_obj.data.bones

for boneA, boneB in zip(bonesA,bonesB): if (boneA.name == boneB.name): boneB.matrix_local = boneA.matrix_local

barakooda
  • 183
  • 7
  • The matrix_local of an armature bone is defined by the head, tail and roll of an edit bone. – batFINGER Aug 18 '21 at 14:38
  • @batFINGER sorry to hijack a thread, but matrix_local doesn't seem to update unless I toggle edit mode. Should we call an update method before trying to read it? – Ron Jensen Aug 18 '21 at 15:57
  • The head tail and roll of an edit bone define the matrix local of the bone. eg b.head == b.matrix_local.translation and b.tail == b.matrix_local @ Vector((0, b.length, 0)) Any changes are not written back to data while in edit mode. (Whereas mesh has an update_from_editmode method, to do this) not aware of an update method other than toggle edit mode, for bones. – batFINGER Aug 18 '21 at 16:21

2 Answers2

1

As far as I understand now, modify armatures possible only with context related approach. this is my current solution.

A_obj = data.objects['A']
B_obj = data.objects['B']

bonesA = A_obj.data.bones bonesB = B_obj.data.bones

B_obj.select_set(True) bpy.context.view_layer.objects.active = B_obj bpy.ops.object.mode_set(mode='EDIT')

bones_b = B_obj.data.edit_bones for bone in bones_b:

try:
    print (bonesA[bone.name].name)
    print(bone)
    target_bone = bonesA[bone.name]

    bone.matrix = target_bone.matrix_local
    bone.matrix = target_bone.matrix_local

except:
    print ("removed " ,bone.name)
    bones_b.remove(bone)

barakooda
  • 183
  • 7
1

Copy a new one.

For the case where the desired result in target identical to source could simply assign it the same bones as the other with a copy of A's armature data, this will not only copy all edit bone transforms, but also all relations, parent, connected etc.

B_obj.data = A_obj.data.copy()

or even use the same armature

B_obj.data = A_obj.data

Converting Space.

Can see issues with simply copying local matrices from to when bone names match but not much else does.

To allow for changes in space between the rigs, like for example rig b having a different origin to rig a. see Python, How to get pose bone to rotate with another pose bone from a different armature? Finding Rotational difference re using convert_space to create matrices to copy from one rig to another. eg in this case to take the local matrix of bone A and convert it to a local space matrix of bone B

batFINGER
  • 84,216
  • 10
  • 108
  • 233