0
$\begingroup$

I always use the following code to rotate the bones.

bone.rotation_euler[0] = 30.0
bone.rotation_euler[1] = 30.0
bone.rotation_euler[2] = 30.0

However, this code seems to be slow. Is there a faster way?

$\endgroup$

2 Answers 2

2
$\begingroup$

Besides setting all three at once, bone.rotation_euler = [x,y,z], if you want to change all the bones at once, you can use foreach_set to do them in a batch

data = []
for bone in bones:
    rot_x = 30.0
    rot_y = 30.0
    rot_z = 30.0
    data += [rot_x, rot_y, rot_z]
bones.foreach_set("rotation_euler", data)

However this doesn't cause an update to the armature transforms (if you're looking at the bones in the viewport, nothing changes). The only way I could find to update is a normal assignment to any bone

# Forces armature transforms to be updated
bones[0].rotation_euler = bones[0].rotation_euler

This also probably explains why assigning the rotation_euler (or other pose properties) is slow: it causes a recalculation of all armature transforms.

$\endgroup$
4
  • $\begingroup$ I try to use this script: bpy.data.objects['Armature'].pose.bones["testBone"].foreach_set("rotation_euler", [30.0,30.0,30.0]) . And I got an error: AttributeError: 'PoseBone' object has no attribute 'foreach_set' Why did it occur? $\endgroup$
    – gncc
    Dec 2, 2021 at 21:35
  • 1
    $\begingroup$ foreach_set only works if you're setting rotation_euler for all bones at once, not if you only want to do one bone. You would do bpy.data.objects['Armature'].pose.bones.foreach_set(...). $\endgroup$
    – scurest
    Dec 2, 2021 at 21:43
  • $\begingroup$ What should I do if I want each bone to have a discrete value? I get an error when I do the following for three bones bpy.data.objects['Armature'].pose.bones.foreach_set("rotation_euler", [[30.0,30.0,30.0],[20.0,20.0,20.0],[10.0,10.0,10.0]]). $\endgroup$
    – gncc
    Dec 2, 2021 at 22:11
  • $\begingroup$ The array needs to be flattened. Please read the example code I gave in my answer. $\endgroup$
    – scurest
    Dec 2, 2021 at 22:15
1
$\begingroup$

If by "slow" you mean slow to write, then how about using Python's tuple assignment:

bone.rotation_euler = 30.0, 30.0, 30.0

Since all values are the same, you can use a list multiplication:

bone.rotation_euler = [30.0]*3

And in this case you could use 30 instead of 30.0 - the value would be still converted to float:

>>> my_object.rotation_euler
Euler((40.0, 40.0, 40.0), 'XYZ')

>>> my_object.rotation_euler = [30]*3
>>> my_object.rotation_euler
Euler((30.0, 30.0, 30.0), 'XYZ')

When in console, remember you can use very effective Tab autocompletion. You can use it in text block editing too, but there it's only based on existing words in current text block.

$\endgroup$
2
  • $\begingroup$ The meaning of my statement is not that it is slow to write, but that it is a matter of calculation time. And I am not assuming that all values are the same. In the case of $\endgroup$
    – gncc
    Dec 2, 2021 at 20:52
  • $\begingroup$ Hard to say why assigning a new Euler rotation to a bone would require optimization - perhaps there's some chain or dependencies, caused by some parenting, constraints, drivers... In this case, the tuple packing technique might be 3 times faster, because you assign the new rotation once, so everything else is recalculated only once... $\endgroup$ Dec 2, 2021 at 20:55

You must log in to answer this question.

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