6
$\begingroup$

I am trying to figure out how to rotate UVs in mesh while Blender is in Background mode without windows, so some parts are not accessible.

Right now I am using bpy.ops.mesh.uvs_rotate() > this works, but it is just in 90 degrees, so I am not able to set UV rotation in specific degree.

bpy.ops.object.editmode_toggle()
bpy.ops.uv.smart_project(angle_limit=66, island_margin=0, user_area_weight=0)
bpy.ops.uv.reset()
bpy.ops.mesh.uvs_rotate()

On this http://blenderartists.org/forum/showthread.php?267997-Rotate-the-uv-s-of-a-selected-object-instead-of-the-object-itself there is written, that I should use bpy.ops.transform.rotate(value=math.radians(45)) while being in bpy.context.area.type = 'IMAGE_EDITOR'.

The problem with this is that when I run blender like

blender --python-console --background

>>> import bpy
>>> bpy.context.area.type
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'type'
>>> 

It seems that object bpy.context.area.type is not possible to change, because it does not exist. In overall our code, we try to not use this. But it case of UV I am not able to figure out how to do it without this. I know that there is a lot of problems with these context.

So how should I rotate UV without context. Is it possible? Or is there a different way how to rotate image on separate object by specific degree?

$\endgroup$

3 Answers 3

5
$\begingroup$

you can do the math yourself , if nothing is available : rotate all the points around the center of the image (0.5, 0.5)

import bpy
from math import cos, sin, radians


def make_rotation_transformation(angle, origin=(0, 0)):
    cos_theta, sin_theta = cos(angle), sin(angle)
    x0, y0 = origin    
    def xform(point):
        x, y = point[0] - x0, point[1] - y0
        return (x * cos_theta - y * sin_theta + x0,
                x * sin_theta + y * cos_theta + y0)
    return xform


ob = bpy.context.object
rad = radians(30)
anchor = (0.5, 0.5)

rot = make_rotation_transformation(rad, anchor)

UVmap = ob.data.uv_layers.active
for v in ob.data.loops :
     UVmap.data[v.index].uv = rot(UVmap.data[v.index].uv ) 

the make_rotation_transformation is from this answer by @200-success

$\endgroup$
3
  • $\begingroup$ Hello, so that bpy.ops.transform.rotate(value=math.radians(45)) and bpy.context.area is not possible to use and data much be changed manually? $\endgroup$
    – alfonz
    Commented Apr 27, 2015 at 4:02
  • 1
    $\begingroup$ @alfonz context depend on the UI area you are in , and since there is no UI the context is None alsotransform.rotate() depends on the context so both are not accessible (AFAIK) $\endgroup$
    – Chebhou
    Commented Apr 27, 2015 at 9:37
  • $\begingroup$ Works like a charm ❤️ $\endgroup$
    – Yaroslav
    Commented Nov 14 at 16:57
2
$\begingroup$

Numpy Version with aspect ratio

This question came up wrt How to rotate UV and preserve the correct aspect ratio?

Thought I would also post here.

  • Using numpy and foreach_get and foreach_set will be noticably quicker for large meshes. It is quite likely numpy didn't ship with blender when question was asked / answered.
  • Deals with aspect ratio.

Code.

import bpy
from mathutils import Matrix, Vector
import numpy as np

ob = bpy.context.object
me = ob.data
uvlayer = me.uv_layers.active

pivot = Vector((0.5, 0.5))
angle = np.radians(30)
# aspect ratio from object
# p = ob.dimensions.y / ob.dimensions.x
# square
p = 1
# aspect rotate
R = Matrix((
            (np.cos(angle), np.sin(angle) / p),
            (-p * np.sin(angle), np.cos(angle)),
        ))
    
uvs = np.empty(2 * len(me.loops))
uvlayer.data.foreach_get("uv", uvs)

# shear rotate about origin, translate to pivot
uvs = np.dot(
        uvs.reshape((-1, 2)) - pivot, 
        R) + pivot
# write the new UV's back
uvlayer.data.foreach_set("uv", uvs.ravel())
# update mesh to display changes.
me.update()
$\endgroup$
0
$\begingroup$

It may be possible if you select the screen. It is not a smart way...

It is valid only for the selected surface.

import bpy


for screen in bpy.data.screens:
    if screen.name =='UV Editing':
        print(screen.name)
        for area in screen.areas:
            if area.type == 'IMAGE_EDITOR':
                override = {'area': area, 'region': area.regions} 
                #override context
try:
    bpy.ops.transform.rotate(
        override,value=0.785398, 
        orient_axis='Z',
        )
    
except NameError:
    print("Please open 'UV Editing' Tab")
$\endgroup$

You must log in to answer this question.

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