1
$\begingroup$

How do I snap the cursor to selected bone?(python)

bpy.ops.view3d.snap_cursor_to_selected() doesn't work

arm = bpy.data.objects['Armature']
empty = bpy.data.objects['Empty']
context.scene.objects.active = arm
#do snapping here
bpy.ops.object.mode_set(mode='EDIT')
bone = arm.data.edit_bones['Bone']
bone.head.xyz = empty.location
bpy.ops.object.mode_set(mode='OBJECT') 

Only adds to the armature :(

$\endgroup$
1
  • 1
    $\begingroup$ bpy.data.scenes['Scene'].cursor.location = some_vector ? $\endgroup$
    – lemon
    Feb 2, 2020 at 13:56

1 Answer 1

3
$\begingroup$

Set cursor

Given an example of snapping cursor to active edit bone. ie armature object is ob = context.object and the active edit bone is bone = context.active_bone

The cursor is in scene, global or world coordinates. Bones are in local space. Multiply local space coordinates by object world matrix to get global coordinates.

An operator that begins with bpy.ops.view3d is designed to run in the 3d view. Running from py console or text editor most likely will produce an invalid context error.

However it is simplest to set the values directly

In 2.7x

Set Scene.cursor_location in edit mode to active bone

scene = context.scene
bone = context.active_bone
scene.cursor_location = context.object.matrix_world * bone.matrix.translation

Snap to Selected requires summing all selected bones locations and dividing by their number to get an average location.

I have used bone.matrix.translation which is the equivalent of bone.head.

from mathutils import Vector
local_loc = sum([b.matrix.translation for b in context.selected_bones, Vector()) / len(context.selected_bones)
# and then setting 
scene.cursor_location = context.object.matrix_world * local_loc

Alternatively from using context could for example snap to edit bone "Bone" of the armature object "Armature"

ob = scene.objects.get("Armature") # by name
if ob and ob.type == 'ARMATURE': # check exists and is armature.
    bone = ob.data.edit_bones.get("Bone")

In 2.8x can set both the translation and rotation of the Scene.cursor object by setting the matrix property

scene = context.scene
bone = context.active_bone
scene.cursor.matrix = context.object.matrix_world @ bone.matrix.translation

scene.tag_update() # updates location and rotation of cursor to bone head as soon as view is  redrawn.
$\endgroup$

You must log in to answer this question.

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