blender/release/scripts/uvcalc_quad_clickproj.py
Campbell Barton f631c2d49e new Uv-Calculation tool,
Click project, a nifty 3 click way to use a face to set a projection aurientation and then 2 more clicks for the U and V scales
with realtime updating as you move the mouse
should be faster then using view project all the time because you dont have to line the view up with the faces.
2006-12-14 19:36:37 +00:00

171 lines
3.9 KiB
Python

#!BPY
""" Registration info for Blender menus: <- these words are ignored
Name: 'Click Project from face'
Blender: 242
Group: 'UVCalculation'
Tooltip: 'click'
"""
import Blender
import BPyMesh
import BPyWindow
mouseViewRay= BPyWindow.mouseViewRay
from Blender import Mathutils, Window, Scene, Draw, sys
from Blender.Mathutils import CrossVecs, Vector, Intersect, LineIntersect, AngleBetweenVecs
LMB= Window.MButs['L']
def mouseup():
# Loop until click
mouse_buttons = Window.GetMouseButtons()
while not mouse_buttons & LMB:
sys.sleep(10)
mouse_buttons = Window.GetMouseButtons()
while mouse_buttons & LMB:
sys.sleep(10)
mouse_buttons = Window.GetMouseButtons()
def mousedown_wait():
# If the menu has just been pressed dont use its mousedown,
mouse_buttons = Window.GetMouseButtons()
while mouse_buttons & LMB:
mouse_buttons = Window.GetMouseButtons()
def main():
scn = Scene.GetCurrent()
ob = scn.objects.active
if not ob or ob.type!='Mesh':
return
mousedown_wait()
Window.DrawProgressBar (0.0, '')
Window.DrawProgressBar (0.1, '(1 of 3) Click on a face corner')
# wait for a click
mouseup()
Window.DrawProgressBar (0.2, '(2 of 3 ) Click confirms the U coords')
mousedown_wait()
obmat= ob.matrixWorld
screen_x, screen_y = Window.GetMouseCoords()
mouseInView, OriginA, DirectionA = mouseViewRay(screen_x, screen_y, obmat)
if not mouseInView or not OriginA:
Window.DrawProgressBar (1.0, '')
return
me = ob.getData(mesh=1)
SELECT_FLAG = Blender.Mesh.FaceFlags['SELECT']
me_faces_sel = [ f for f in me.faces if f.flag & SELECT_FLAG ]
del SELECT_FLAG
f, isect, side = BPyMesh.pickMeshRayFace(me, OriginA, DirectionA)
f_no = f.no
if not f:
Window.DrawProgressBar (1.0, '')
return
# find the vertex thats closest
best_v= None
best_length = 10000000
vi1 = None
for i, v in enumerate(f.v):
l = (v.co-isect).length
if l < best_length:
best_v = v
best_length = l
vi1 = i
# now find the 2 edges in the face that connect to v
if len(f)==4:
if vi1==0: vi2, vi3= 3,1
if vi1==1: vi2, vi3= 0,2
if vi1==2: vi2, vi3= 1,3
if vi1==3: vi2, vi3= 2,0
else:
if vi1==0: vi2, vi3= 2,1
if vi1==1: vi2, vi3= 0,2
if vi1==2: vi2, vi3= 1,0
loc1 =f.v[vi1].co
loc2 =f.v[vi2].co
loc3 =f.v[vi3].co
line1_len = (loc2-loc1).length
line2_len = (loc3-loc1).length
# tmat = Mathutils.TranslationMatrix(-loc1)
Window.SetCursorPos(loc1.x, loc1.y, loc1.z)
MODE = 0 # firstclick, 1, secondclick
mouse_buttons = Window.GetMouseButtons()
Window.SetCursorPos(loc1.x, loc1.y, loc1.z)
while 1:
if mouse_buttons & LMB:
if MODE == 0:
mousedown_wait()
Window.DrawProgressBar (0.8, '(3 of 3 ) Click confirms the V coords')
MODE = 1 # second click
else:
break
mouse_buttons = Window.GetMouseButtons()
screen_x, screen_y = Window.GetMouseCoords()
mouseInView, OriginA, DirectionA = mouseViewRay(screen_x, screen_y, obmat)
if not mouseInView:
continue
d1_pair = Mathutils.LineIntersect(OriginA, OriginA+DirectionA, loc1, loc2)
d2_pair = Mathutils.LineIntersect(OriginA, OriginA+DirectionA, loc1, loc3)
if MODE == 0:
d1 = (d1_pair[0]-d1_pair[1]).length
d2 = (d2_pair[0]-d2_pair[1]).length
if d1<d2:
loc_to_use = loc2
y_dist = line2_len
x_dist = (d1_pair[1]-loc1).length
else:
loc_to_use = loc3
y_dist = line1_len
x_dist = (d2_pair[1]-loc1).length
line_x = loc_to_use - loc1
line_y = Mathutils.CrossVecs(line_x, f_no)
line_x.length = 1/x_dist
line_y.length = 1/y_dist
else:
if d1<d2: line_y.length = 1/(d2_pair[1]-loc1).length
else: line_y.length = 1/(d1_pair[1]-loc1).length
# Make a matrix
project_mat = Mathutils.Matrix(line_x, line_y, f_no)
project_mat.resize4x4()
for f in me_faces_sel:
f.uv = [project_mat * (v.co-loc1) for v in f]
Window.Redraw(Window.Types.VIEW3D)
Window.DrawProgressBar (1.0, '')
if __name__=='__main__':
main()