1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
|
# 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= cross_grad.normalize() * 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, '')
|