0
$\begingroup$

I'm studying the Blender Python API and trying to run the following simple script:

import bpy

bpy.ops.mesh.primitive_cube_add(enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(1, 1, 1))
bpy.ops.object.editmode_toggle()
bpy.ops.mesh.select_all(action="SELECT")
# bpy.ops.uv.smart_project() # This does work
bpy.ops.uv.project_from_view() # But this does not work
bpy.ops.object.editmode_toggle()

However, this gave me an error as follows:

Python: Traceback (most recent call last):
  File "\Text", line 7, in <module>
  File "C:\Program Files\Blender Foundation\Blender 4.0\4.0\scripts\modules\bpy\ops.py", line 109, in __call__
    ret = _op_call(self.idname_py(), kw)
RuntimeError: Operator bpy.ops.uv.project_from_view.poll() failed, context is incorrect

Interestingly, bpy.ops.uv.smart_project() works without the error. What 'context' should be required to run project_from_view correctly?

My environment is:

  • Windows 10
  • Blender 4.0
$\endgroup$
0

2 Answers 2

1
$\begingroup$

The issue is resolved thanks to the sweet and juicy code from https://gist.github.com/robgithub/d5045fac793102549b11d88c7122080a. But the code is outdated, so the following changes are required (i.e., EDITED flags):

def unwrap_from_view(obj_name):
    bpy.context.view_layer.objects.active = bpy.data.objects[obj_name]
    bpy.context.object.name = obj_name

    bpy.ops.object.editmode_toggle()
    bpy.ops.mesh.select_all(action="SELECT")
    for oWindow in bpy.context.window_manager.windows:
        oScreen = oWindow.screen
        for oArea in oScreen.areas:
            if oArea.type == 'VIEW_3D':  
                for oRegion in oArea.regions:
                    if oRegion.type == 'WINDOW':
                        context_override = bpy.context.copy()  # EDITED
                        override = {
                            'window': oWindow, 
                            'screen': oScreen, 
                            'area': oArea, 
                            'region': oRegion, 
                            'scene': bpy.context.scene, 
                            'edit_object': bpy.context.edit_object, 
                            'active_object': bpy.context.active_object, 
                            'selected_objects': bpy.context.selected_objects
                        }
                        for k, v in override.items():  # EDITED
                            context_override[k] = v
                        with bpy.context.temp_override(**context_override):  # EDITED
                            bpy.ops.uv.project_from_view(camera_bounds=True, correct_aspect=False, scale_to_bounds=False)
    bpy.ops.object.editmode_toggle()
$\endgroup$
1
$\begingroup$

Why not keep it simple. Read more about context override here.

area_type = 'VIEW_3D'
areas  = [area for area in bpy.context.window.screen.areas if area.type == area_type]

with bpy.context.temp_override(
    window=bpy.context.window,
    area=areas[0],
    region=[region for region in areas[0].regions if region.type == 'WINDOW'][0],
    screen=bpy.context.window.screen
):
    bpy.ops.uv.project_from_view(camera_bounds=True, correct_aspect=False, scale_to_bounds=False)
$\endgroup$

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