Adjusting constraints on a bone in pose mode

So, my python and coding knowledge is very… thin. Hence I use AI.

As such, I’ve gone from AI code that doesn’t really work, to it finally telling me that it’s not actually possible.

import bpy

# get the armature object and set to edit mode
armature_obj = bpy.data.objects['metarig']
bpy.context.view_layer.objects.active = armature_obj
bpy.ops.object.mode_set(mode='POSE')

# Get the bone data
bone_name = 'DEF-pec.R'
bone = armature_obj.pose.bones[bone_name]

# Reset the stretch-to constraint for the specified bone
bpy.ops.constraint.stretchto_reset(constraint='Stretch To', owner='BONE')

# return to object mode
bpy.ops.object.mode_set(mode='OBJECT')

The code above ‘works’ in that it resets the Stretch To constraint, which is what I want. The part that doesn’t work is it won’t do it on the ‘DEF-pec.R’ bone. In fact it won’t do it on any bone that I specify.

If I run that script, it either does nothing, or if I’ve manually selected a bone in Pose mode (which has the constraint), then the script will actually reset it.

Now AI tells me, that using Python, you can’t actually ‘select’ bones in pose mode, which is a little annoying, since I actually have around 6 bones, all with a Stretch To constraint and I’d like a little python script that on running would just reset them all. Rather then me having to do it manually each time.

So, is AI right, there’s no real way to do it using Python?

You need to set the active bone before calling the stretchto_reset operator.

armature_obj.data.bones.active = bone
bpy.ops.constraint.stretchto_reset(constraint='Stretch To', owner='BONE'

(Also there doesn’t seem to be any issue with selecting bones while in pose mode. You would just need to set select equal to True
bone.select = True
but it looks the stretchto_reset operator only works if the bone is active.)

Thanks for the reply, but unfortunately that doesn’t work and gives an error, in Blender 4.2.1 at least:

TypeError: BPy_PropertyRNA - Attribute (setattr): ArmatureBones.active expected a Bone type, not PoseBone

The ‘bone.select = True’ also actually gives an error:

AttributeError: ‘PoseBone’ object has no attribute ‘select’

Try getting a Bone instead of a PoseBone (honestly don’t know what exactly the difference is, but I tested with a Bone).

So try bone = armature_obj.data.bones[bone_name] instead of bone = armature_obj.pose.bones[bone_name].

I actually just did some more digging and found like a decade old reference, that would you believe, actually works.

So a full working code is now:

import bpy

# get the armature object and set to edit mode
armature_obj = bpy.data.objects['metarig']
bpy.context.view_layer.objects.active = armature_obj
bpy.ops.object.mode_set(mode='POSE')

# Get the bone data
bone_name = 'DEF-pec.R'

# Reset the stretch-to constraint for the specified bone
# Set the pose bone object
armature_obj.data.bones.active = armature_obj.pose.bones[bone_name].bone

bpy.ops.constraint.stretchto_reset(constraint='Stretch To', owner='BONE')

# return to object mode
bpy.ops.object.mode_set(mode='OBJECT')

I guess what it’s doing is sort making the background ‘edit’ mode bone to be active, which in turns makes the same bone active in pose mode.

Bit of a round a way of doing it, but seems to work at this stage.

1 Like