I have an object with several faces, and I want to loop over the faces, adjust the view for each differently and then UV unwrap the face from the chosen view.

I managed to do it using Blender GUI but how can I automate it via a python script?

This is the code I was trying with... I keep getting either a context error or an error saying that BMFace has been removed :s

import bpy, bmesh
bm = bmesh.from_edit_mesh(bpy.data.objects['my_obj'].data)
for face in bm.faces:
    face.select = True
    if [...] : # Condition chosen to know which face this is
        q = Quaternion([...]) # Set desired corresponding view for this face
    for area in bpy.context.screen.areas:
        if area.type == 'VIEW_3D':
    for region in area.regions:
        if region.type == 'WINDOW':
    space = area.spaces[0]
    context = bpy.context.copy()
    context['area'] = area
    context['region'] = region
    context['space_data'] = space
    r3d = space.region_3d
    r3d.view_perspective = 'ORTHO'
    r3d.view_rotation = q

    for window in bpy.context.window_manager.windows:
        screen = window.screen
        for area in screen.areas:
            if area.type == 'VIEW_3D':
                for space in area.spaces:
                    if space.type == 'VIEW_3D':
                        for region in area.regions:
                            if region.type == 'WINDOW':
                                override = {'window': window, 'screen': screen, 'area': area, 'region': region}
                                bpy.ops.uv.project_from_view(override, orthographic=False, correct_aspect=True, clip_to_bounds=False, scale_to_bounds=True)
    face.select = False

Please help!


3 Answers 3


Manipulating UV coordinates in python is usually done via the bmesh interface.

I include an example from barber-pole.py

def spiralUVs(mesh, xPlus):
    # add a UV layer called "spiral" and make it slanted.
    bm = bmesh.new()


    uv_layer = bm.loops.layers.uv[0]

    nFaces = len(bm.faces)
    for fi in range(nFaces):
        x0 = fi*2/nFaces
        x1 = (fi+1)*2/nFaces
        bm.faces[fi].loops[0][uv_layer].uv = (x0, 0)
        bm.faces[fi].loops[1][uv_layer].uv = (x1, 0)
        bm.faces[fi].loops[2][uv_layer].uv = (xPlus+x1, 1)
        bm.faces[fi].loops[3][uv_layer].uv = (xPlus+x0, 1)

Some other examples that set UV texture coordinates include

  • $\begingroup$ Thanks a lot! I just got rid of this project_from_view function and set the values of the uv coordinates directly as desired :) $\endgroup$
    – Beginner
    Jan 25, 2016 at 8:28
  • $\begingroup$ For Blender 2.8 mesh.uv_textures.new("spiral") becomes mesh.uv_layers.new(name="spiral") $\endgroup$ May 6, 2022 at 18:53

You could try to create an operator that is executed in the correct context, then you don't need to search for the right one.

Something like this:

import bpy
import mathutils

def main(context):
    # Your code without context searching
    context.space_data.region_3d.view_rotation = mathutils.Quaternion((1,1,1))

class SimpleOperator(bpy.types.Operator):
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"

    def poll(cls, context):
        return context.mode == 'EDIT_MESH'

    def execute(self, context):
        return {'FINISHED'}

def register():

def unregister():

if __name__ == "__main__":

You can then execute the operator in your 3d-window (Space -> Simple Object Operator).

  • $\begingroup$ I am not used to bpy operators, but I don't see how this operator manages to be called in the correct context. Note that I need the whole thing to be fully automated in my case... no GUI at all. $\endgroup$
    – Beginner
    Jan 25, 2016 at 8:33
  • $\begingroup$ @Beginner any update if it worked for you without GUI using this? $\endgroup$ Mar 27, 2018 at 9:52

This is not a script, but it may get what you want.

Select all faces (a) then unwrap (u). In the unwrap menu, select 'reset'. This will make every face fill up the whole uv grid. Each face will be a square, and fit your texture.

Hope this helps.

  • $\begingroup$ Thanks for the advice :) but it is not applicable in my case $\endgroup$
    – Beginner
    Jan 25, 2016 at 8:35
  • $\begingroup$ Thanks very useful $\endgroup$
    – Derekcbr
    Mar 16, 2022 at 5:57

You must log in to answer this question.

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