forked from bartvdbraak/blender
4e2143f639
Patch provied by gsrb3d bug tracker #7061 Kent
230 lines
6.0 KiB
Python
230 lines
6.0 KiB
Python
# This is not to be used directly, vertexGradientPick can be used externaly
|
|
|
|
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()
|
|
|
|
eps= 0.0001
|
|
def vertexGradientPick(ob, MODE):
|
|
#MODE 0 == VWEIGHT, 1 == VCOL
|
|
|
|
me= ob.getData(mesh=1)
|
|
if not me.faceUV: me.faceUV= True
|
|
|
|
Window.DrawProgressBar (0.0, '')
|
|
|
|
mousedown_wait()
|
|
|
|
if MODE==0:
|
|
act_group= me.activeGroup
|
|
if act_group == None:
|
|
mousedown_wait()
|
|
Draw.PupMenu('Error, mesh has no active group.')
|
|
return
|
|
|
|
# Loop until click
|
|
Window.DrawProgressBar (0.25, 'Click to set gradient start')
|
|
mouseup()
|
|
|
|
obmat= ob.matrixWorld
|
|
screen_x, screen_y = Window.GetMouseCoords()
|
|
mouseInView, OriginA, DirectionA = mouseViewRay(screen_x, screen_y, obmat)
|
|
if not mouseInView or not OriginA:
|
|
return
|
|
|
|
# get the mouse weight
|
|
|
|
if MODE==0:
|
|
pickValA= BPyMesh.pickMeshGroupWeight(me, act_group, OriginA, DirectionA)
|
|
if MODE==1:
|
|
pickValA= BPyMesh.pickMeshGroupVCol(me, OriginA, DirectionA)
|
|
|
|
Window.DrawProgressBar (0.75, 'Click to set gradient end')
|
|
mouseup()
|
|
|
|
TOALPHA= Window.GetKeyQualifiers() & Window.Qual.SHIFT
|
|
|
|
screen_x, screen_y = Window.GetMouseCoords()
|
|
mouseInView, OriginB, DirectionB = mouseViewRay(screen_x, screen_y, obmat)
|
|
if not mouseInView or not OriginB:
|
|
return
|
|
|
|
if not TOALPHA: # Only get a second opaque value if we are not blending to alpha
|
|
if MODE==0: pickValB= BPyMesh.pickMeshGroupWeight(me, act_group, OriginB, DirectionB)
|
|
else:
|
|
pickValB= BPyMesh.pickMeshGroupVCol(me, OriginB, DirectionB)
|
|
else:
|
|
if MODE==0: pickValB= 0.0
|
|
else: pickValB= [0.0, 0.0, 0.0] # Dummy value
|
|
|
|
# Neither points touched a face
|
|
if pickValA == pickValB == None:
|
|
return
|
|
|
|
# clicking on 1 non face is fine. just set the weight to 0.0
|
|
if pickValA==None:
|
|
pickValA= 0.0
|
|
|
|
# swap A/B
|
|
OriginA, OriginB= OriginB, OriginA
|
|
DirectionA, DirectionB= DirectionB, DirectionA
|
|
pickValA, pickValB= pickValA, pickValB
|
|
|
|
TOALPHA= True
|
|
|
|
if pickValB==None:
|
|
pickValB= 0.0
|
|
TOALPHA= True
|
|
|
|
# set up 2 lines so we can measure their distances and calc the gradient
|
|
|
|
# make a line 90d to the grad in screenspace.
|
|
if (OriginA-OriginB).length <= eps: # Persp view. same origin different direction
|
|
cross_grad= CrossVecs(DirectionA, DirectionB)
|
|
ORTHO= False
|
|
|
|
else: # Ortho - Same direction, different origin
|
|
cross_grad= CrossVecs(DirectionA, OriginA-OriginB)
|
|
ORTHO= True
|
|
|
|
cross_grad.normalize()
|
|
cross_grad= cross_grad * 100
|
|
|
|
lineA= (OriginA, OriginA+(DirectionA*100))
|
|
lineB= (OriginB, OriginB+(DirectionB*100))
|
|
|
|
if not ORTHO:
|
|
line_angle= AngleBetweenVecs(lineA[1], lineB[1])/2
|
|
line_mid= (lineA[1]+lineB[1])*0.5
|
|
|
|
VSEL= [False] * (len(me.verts))
|
|
|
|
# Get the selected faces and apply the selection to the verts.
|
|
for f in me.faces:
|
|
if f.sel:
|
|
for v in f.v:
|
|
VSEL[v.index]= True
|
|
groupNames, vWeightDict= BPyMesh.meshWeight2Dict(me)
|
|
|
|
|
|
|
|
def grad_weight_from_co(v):
|
|
'''
|
|
Takes a vert and retuens its gradient radio between A and B
|
|
'''
|
|
|
|
if not VSEL[v.index]: # Not bart of a selected face?
|
|
return None, None
|
|
|
|
v_co= v.co
|
|
# make a line 90d to the 2 lines the user clicked.
|
|
vert_line= (v_co - cross_grad, v_co + cross_grad)
|
|
|
|
xA= LineIntersect(vert_line[0], vert_line[1], lineA[0], lineA[1])
|
|
xB= LineIntersect(vert_line[0], vert_line[1], lineB[0], lineB[1])
|
|
|
|
if not xA or not xB: # Should never happen but support it anyhow
|
|
return None, None
|
|
|
|
wA= (xA[0]-xA[1]).length
|
|
wB= (xB[0]-xB[1]).length
|
|
|
|
wTot= wA+wB
|
|
if not wTot: # lines are on the same point.
|
|
return None, None
|
|
|
|
'''
|
|
Get the length of the line between both intersections on the
|
|
2x view lines.
|
|
if the dist between lineA+VertLine and lineB+VertLine is
|
|
greater then the lenth between lineA and lineB intersection points, it means
|
|
that the verts are not inbetween the 2 lines.
|
|
'''
|
|
lineAB_length= (xA[1]-xB[1]).length
|
|
|
|
# normalzie
|
|
wA= wA/wTot
|
|
wB= wB/wTot
|
|
|
|
if ORTHO: # Con only use line length method with parelelle lines
|
|
if wTot > lineAB_length+eps:
|
|
# vert is outside the range on 1 side. see what side of the grad
|
|
if wA>wB: wA, wB= 1.0, 0.0
|
|
else: wA, wB= 0.0, 1.0
|
|
else:
|
|
# PERSP, lineA[0] is the same origin as lineB[0]
|
|
|
|
# Either xA[0] or xB[0] can be used instead of a possible x_mid between the 2
|
|
# as long as the point is inbetween lineA and lineB it dosent matter.
|
|
a= AngleBetweenVecs(lineA[0]-xA[0], line_mid)
|
|
if a>line_angle:
|
|
# vert is outside the range on 1 side. see what side of the grad
|
|
if wA>wB: wA, wB= 1.0, 0.0
|
|
else: wA, wB= 0.0, 1.0
|
|
|
|
return wA, wB
|
|
|
|
|
|
grad_weights= [grad_weight_from_co(v) for v in me.verts]
|
|
|
|
|
|
if MODE==0:
|
|
for v in me.verts:
|
|
i= v.index
|
|
if VSEL[i]:
|
|
wA, wB = grad_weights[i]
|
|
if wA != None: # and wB
|
|
if TOALPHA:
|
|
# Do alpha by using the exiting weight for
|
|
try: pickValB= vWeightDict[i][act_group]
|
|
except: pickValB= 0.0 # The weights not there? assume zero
|
|
# Mix2 2 opaque weights
|
|
vWeightDict[i][act_group]= pickValB*wA + pickValA*wB
|
|
|
|
else: # MODE==1 VCol
|
|
for f in me.faces:
|
|
if f.sel:
|
|
f_v= f.v
|
|
for i in xrange(len(f_v)):
|
|
v= f_v[i]
|
|
wA, wB = grad_weights[v.index]
|
|
|
|
c= f.col[i]
|
|
|
|
if TOALPHA:
|
|
pickValB= c.r, c.g, c.b
|
|
|
|
c.r = int(pickValB[0]*wA + pickValA[0]*wB)
|
|
c.g = int(pickValB[1]*wA + pickValA[1]*wB)
|
|
c.b = int(pickValB[2]*wA + pickValA[2]*wB)
|
|
|
|
|
|
|
|
|
|
# Copy weights back to the mesh.
|
|
BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict)
|
|
Window.DrawProgressBar (1.0, '')
|
|
|
|
|