1
$\begingroup$

I tried to perform a batch operation by using blender CLI. I want to rotate a mesh by X axis with -90d, and then place the mesh to world origin, the operation I performed in the GUI is:

  1. press keys: R, X, -90
  2. switch to 'Edit Mode' from object mode
  3. select all the mesh by press A
  4. Shift+S > cursor to world origin
  5. Shift+S > Selection to curson (keep offset) I tried to convert the GUI opreation to python command, like follow:
import bpy

import math

obj = bpy.data.objects.get("halfface")

obj.rotation_euler[0] += math.radians(-90)

bpy.ops.object.select_all(action='DESELECT')

obj.select_set(True)

bpy.context.view_layer.objects.active = obj

bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)

bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='BOUNDS')

obj.location = (0, 0, 0)

bpy.ops.object.mode_set(mode='EDIT')

bpy.ops.mesh.select_all(action='SELECT')

bpy.ops.view3d.snap_selected_to_cursor(use_offset=True)

bpy.ops.object.mode_set(mode='OBJECT')

But it gave me an error like this

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "D:\SomeData\testdata\skullblend\skull.py", line 36, in <module>
    bpy.ops.view3d.snap_selected_to_cursor(use_offset=True)
  File "D:\OtherSoftware\blender\4.0\scripts\modules\bpy\ops.py", line 109, in __call__
    ret = _op_call(self.idname_py(), kw)
RuntimeError: Operator bpy.ops.view3d.snap_selected_to_cursor.poll() failed, context is incorrect`

And the last step "selection to cursor (keep offset)" not work.

Can anyone gave me some advice ? I really confused about the context Really appreciate for any help !

$\endgroup$

1 Answer 1

0
$\begingroup$

The operator needs a View 3D context.

import bpy

import math

import typing

def call_with_override(override: typing.Dict[str, typing.Any], func: typing.Callable, *args, **kwargs):

    if bpy.app.version > (3, 2, 0):
        with bpy.context.temp_override(**override):
            result = func(*args, **kwargs)
    else:
        result = func(override, *args, **kwargs)

    if 'CANCELLED' in result:
        raise Exception(f"The operator has been cancelled: {repr(func)}")

    return result


def get_view3d():
    for window_manager in bpy.data.window_managers:
        for window in window_manager.windows:
            for area in window.screen.areas:
                if area.type == 'VIEW_3D':
                    for region in area.regions:
                        if region.type == 'WINDOW':
                            return dict(window=window, workspace=window.workspace, screen=window.screen, area=area, region=region)

    raise Exception('View3D context not found.')


def call_in_view3d(func: typing.Callable, *args, **kwargs):
    return call_with_override(get_view3d(), func, *args, **kwargs)


obj = bpy.data.objects[0]

obj.rotation_euler[0] += math.radians(-90)

bpy.ops.object.select_all(action='DESELECT')

obj.select_set(True)

bpy.context.view_layer.objects.active = obj

bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)

bpy.ops.object.origin_set(type='ORIGIN_CURSOR', center='BOUNDS')

obj.location = (0, 0, 0)

bpy.ops.object.mode_set(mode='EDIT')

bpy.ops.mesh.select_all(action='SELECT')

call_in_view3d(bpy.ops.view3d.snap_selected_to_cursor, use_offset=True)

bpy.ops.object.mode_set(mode='OBJECT')

Although in this case you should consider a lower level API approach by moving the vertices themselves, some bpy.ops operators are much easier to utilize or have no alternatives.

$\endgroup$

You must log in to answer this question.

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