forked from bartvdbraak/blender
f631c2d49e
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.
171 lines
3.9 KiB
Python
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() |