Added a vertex gradient tool. got the ok from willian to add if its well tested, can do vertex gradient and weight gradient- uses __vertex_gradient__.py which manages to do both.

This commit is contained in:
Campbell Barton 2006-07-06 13:34:53 +00:00
parent d13ad8fe94
commit 14a67d2a3c
3 changed files with 314 additions and 0 deletions

@ -0,0 +1,243 @@
#!BPY
"""
Name: 'Weight Gradient...'
Blender: 241
Group: 'VertPaint'
Tooltip: 'Grad.'
"""
__author__ = ["Campbell Barton"]
__url__ = ("blender", "elysiun", "http://members.iinet.net.au/~cpbarton/ideasman/")
__version__ = "0.1"
import Blender
import BPyMesh
import BPyWindow
reload(BPyWindow)
reload(BPyMesh)
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, '')

@ -0,0 +1,29 @@
#!BPY
"""
Name: 'VCol Gradient...'
Blender: 241
Group: 'VertexPaint'
Tooltip: 'Click on the start and end grad points for the mesh for selected faces.'
"""
__author__ = ["Campbell Barton"]
__url__ = ("blender", "elysiun", "http://members.iinet.net.au/~cpbarton/ideasman/")
__version__ = "0.1"
import __vertex_gradient__
reload(__vertex_gradient__)
import Blender
def main():
scn= Blender.Scene.GetCurrent()
ob= scn.getActiveObject()
if not ob or ob.getType() != 'Mesh':
Blender.Draw.PupMenu('Error, no active mesh object, aborting.')
return
__vertex_gradient__.vertexGradientPick(ob, 1)
if __name__ == '__main__':
main()

@ -0,0 +1,42 @@
#!BPY
"""
Name: 'Weight Gradient...'
Blender: 241
Group: 'WeightPaint'
Tooltip: 'Click on the start and end grad points for the mesh for selected faces.'
"""
__author__ = ["Campbell Barton"]
__url__ = ("blender", "elysiun", "http://members.iinet.net.au/~cpbarton/ideasman/")
__version__ = "0.1"
__bpydoc__=\
'''
This script is used to fill the selected faces with a gradient
To use the script, switch to "Face Select" mode then "Vertex Paint" mode
Select the faces you wish to apply the gradient to.
Click twice on the mesh to set the start and end points of the gradient.
The color under the mouse will be used for the start and end blend colors.
Note:
Holding Shift or clicking outside the mesh on the second click will blend the first colour to nothing.
'''
import __vertex_gradient__
reload(__vertex_gradient__)
import Blender
def main():
scn= Blender.Scene.GetCurrent()
ob= scn.getActiveObject()
if not ob or ob.getType() != 'Mesh':
Blender.Draw.PupMenu('Error, no active mesh object, aborting.')
return
# MODE 0 == VCOL
# MODE 1 == WEIGHT
MODE= 0
__vertex_gradient__.vertexGradientPick(ob, MODE)
if __name__ == '__main__':
main()