2
$\begingroup$

I would like to snap the 3D-cusor to an object. After that I would like to copy another object to the position of the 3D-cursor. The code is as follow:

Code sample:

for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
        ctx = bpy.context.copy()
        ctx['area'] = area
        ctx['region'] = area.regions[-1]
        bpy.ops.view3d.view_selected(ctx)
        bpy.ops.view3d.snap_cursor_to_selected()
        obj.select = False
        new_obj.select = True
        bpy.context.scene.objects.active = new_obj
        bpy.ops.view3d.snap_selected_to_cursor(use_offset=False)
        break

Python error is:

RuntimeError: Operator bpy.ops.view3d.snap_cursor_to_selected.poll() failed, context is incorrect

Modified code sample:

for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
        ctx = bpy.context.copy()
        ctx['area'] = area
        ctx['region'] = area.regions[-1]
        bpy.ops.view3d.view_selected(ctx)
        bpy.ops.view3d.snap_cursor_to_selected(ctx, use_offset=False)
        obj.select = False
        new_obj.select = True
        bpy.context.scene.objects.active = new_obj
        bpy.ops.view3d.snap_selected_to_cursor(use_offset=False)
        break

Python message:

TypeError: Converting py args to operator properties: : keyword "use_offset" unrecognized

I use Blender 2.77a. What can I do? Many thanks for our help.

$\endgroup$
9
  • $\begingroup$ related : blender.stackexchange.com/questions/6101/… $\endgroup$
    – Chebhou
    Commented May 29, 2016 at 16:57
  • $\begingroup$ please edit your original post to add info $\endgroup$
    – Chebhou
    Commented May 29, 2016 at 17:22
  • 1
    $\begingroup$ override all operators : snap_cursor_to_selected(ctx) and so on $\endgroup$
    – Chebhou
    Commented May 29, 2016 at 17:35
  • $\begingroup$ I do that. But I receive the same error message. $\endgroup$ Commented May 29, 2016 at 17:45
  • $\begingroup$ did you did this bpy.ops.view3d.snap_selected_to_cursor(ctx, use_offset=False) also ? $\endgroup$
    – Chebhou
    Commented May 29, 2016 at 17:55

2 Answers 2

7
$\begingroup$

You should override all operators that depends on context as follows :

for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
        ctx = bpy.context.copy()
        ctx['area'] = area
        ctx['region'] = area.regions[-1]
        bpy.ops.view3d.view_selected(ctx)
        bpy.ops.view3d.snap_cursor_to_selected(ctx)
        obj.select = False
        new_obj.select = True
        bpy.context.scene.objects.active = new_obj

        # take new copy of the context because it is outdated now
        ctx = bpy.context.copy()
        ctx['area'] = area
        ctx['region'] = area.regions[-1]            

        bpy.ops.view3d.snap_selected_to_cursor(ctx, use_offset=False)
        break
$\endgroup$
3
  • 1
    $\begingroup$ great, it works. Many many thanks for this support. $\endgroup$ Commented May 29, 2016 at 18:38
  • 1
    $\begingroup$ What does the -1 do please? $\endgroup$ Commented Nov 18, 2021 at 9:04
  • 1
    $\begingroup$ @Gary it gets the last element in an array $\endgroup$
    – Chebhou
    Commented Nov 30, 2021 at 7:36
0
$\begingroup$

You can move the cursor without using operators, then you don't have to get the context right.

import bpy

for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
        break

for space in area.spaces:
    if space.type == 'VIEW_3D':
        break

space.cursor_location = bpy.context.active_object.location

But then your snapping the cursor to an object, then snapping another object to the cursor, you can bypass the cursor and just set the new objects location.

new_obj.location = old_obj.location
$\endgroup$

You must log in to answer this question.

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