forked from bartvdbraak/blender
531cd7c0fc
updated bvh import which was modified to account for that. as well as other minor changes.
233 lines
6.1 KiB
Python
Executable File
233 lines
6.1 KiB
Python
Executable File
# 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
|
|
|
|
FSEL= Blender.Mesh.FaceFlags.SELECT
|
|
|
|
VSEL= [False] * (len(me.verts))
|
|
|
|
# Get the selected faces and apply the selection to the verts.
|
|
for f in me.faces:
|
|
if f.flag & FSEL:
|
|
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.flag & FSEL:
|
|
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, '')
|
|
|
|
|