Cosmetic change: the FFMPEG options for HD sound/movie are hidden behind
[blender.git] / release / scripts / __vertex_gradient__.py
1 #!BPY
2 """
3 Name: 'Weight Gradient...'
4 Blender: 241
5 Group: 'VertPaint'
6 Tooltip: 'Grad.'
7 """
8
9 __author__ = ["Campbell Barton"]
10 __url__ = ("blender", "elysiun", "http://members.iinet.net.au/~cpbarton/ideasman/")
11 __version__ = "0.1"
12 import Blender
13 import BPyMesh
14 import BPyWindow
15
16
17 reload(BPyWindow)
18 reload(BPyMesh)
19 mouseViewRay= BPyWindow.mouseViewRay
20 from Blender import Mathutils, Window, Scene, Draw, sys
21 from Blender.Mathutils import CrossVecs, Vector, Intersect, LineIntersect, AngleBetweenVecs
22 LMB= Window.MButs['L']
23
24 def mouseup():
25         # Loop until click
26         mouse_buttons = Window.GetMouseButtons()
27         while not mouse_buttons & LMB:
28                 sys.sleep(10)
29                 mouse_buttons = Window.GetMouseButtons()
30         while mouse_buttons & LMB:
31                 sys.sleep(10)
32                 mouse_buttons = Window.GetMouseButtons()
33
34 def mousedown_wait():
35         # If the menu has just been pressed dont use its mousedown,
36         mouse_buttons = Window.GetMouseButtons()
37         while mouse_buttons & LMB:
38                 mouse_buttons = Window.GetMouseButtons()
39
40 eps= 0.0001
41 def vertexGradientPick(ob, MODE):
42         #MODE 0 == VWEIGHT,  1 == VCOL 
43         
44         me= ob.getData(mesh=1)
45         if not me.faceUV:       me.faceUV= True
46         
47         Window.DrawProgressBar (0.0, '')
48         
49         mousedown_wait()
50         
51         if MODE==0:
52                 act_group= me.activeGroup
53                 if act_group == None:
54                         mousedown_wait()
55                         Draw.PupMenu('Error, mesh has no active group.')
56                         return
57         
58         # Loop until click
59         Window.DrawProgressBar (0.25, 'Click to set gradient start')
60         mouseup()
61         
62         obmat= ob.matrixWorld
63         screen_x, screen_y = Window.GetMouseCoords()
64         mouseInView, OriginA, DirectionA = mouseViewRay(screen_x, screen_y, obmat)
65         if not mouseInView or not OriginA:
66                 return
67         
68         # get the mouse weight
69         
70         if MODE==0:
71                 pickValA= BPyMesh.pickMeshGroupWeight(me, act_group, OriginA, DirectionA)
72         if MODE==1:
73                 pickValA= BPyMesh.pickMeshGroupVCol(me, OriginA, DirectionA)
74         
75         Window.DrawProgressBar (0.75, 'Click to set gradient end')
76         mouseup()
77         
78         TOALPHA= Window.GetKeyQualifiers() & Window.Qual.SHIFT
79         
80         screen_x, screen_y = Window.GetMouseCoords()
81         mouseInView, OriginB, DirectionB = mouseViewRay(screen_x, screen_y, obmat)
82         if not mouseInView or not OriginB:
83                 return
84         
85         if not TOALPHA: # Only get a second opaque value if we are not blending to alpha
86                 if MODE==0:     pickValB= BPyMesh.pickMeshGroupWeight(me, act_group, OriginB, DirectionB)
87                 else:
88                         pickValB= BPyMesh.pickMeshGroupVCol(me, OriginB, DirectionB)
89         else:
90                 if MODE==0: pickValB= 0.0
91                 else: pickValB= [0.0, 0.0, 0.0] # Dummy value
92         
93         # Neither points touched a face
94         if pickValA == pickValB == None:
95                 return
96         
97         # clicking on 1 non face is fine. just set the weight to 0.0
98         if pickValA==None:
99                 pickValA= 0.0
100                 
101                 # swap A/B
102                 OriginA, OriginB= OriginB, OriginA
103                 DirectionA, DirectionB= DirectionB, DirectionA
104                 pickValA, pickValB= pickValA, pickValB
105                 
106                 TOALPHA= True
107                 
108         if pickValB==None:
109                 pickValB= 0.0
110                 TOALPHA= True
111         
112         
113         # set up 2 lines so we can measure their distances and calc the gradient
114         
115         # make a line 90d to the grad in screenspace.
116         if (OriginA-OriginB).length <= eps: # Persp view. same origin different direction
117                 cross_grad= CrossVecs(DirectionA, DirectionB)
118                 ORTHO= False
119                 
120         else: # Ortho - Same direction, different origin
121                 cross_grad= CrossVecs(DirectionA, OriginA-OriginB)
122                 ORTHO= True
123                 
124         cross_grad= cross_grad.normalize() * 100
125         
126         lineA= (OriginA, OriginA+(DirectionA*100))
127         lineB= (OriginB, OriginB+(DirectionB*100))
128         
129         if not ORTHO:
130                 line_angle= AngleBetweenVecs(lineA[1], lineB[1])/2
131                 line_mid= (lineA[1]+lineB[1])*0.5
132         
133         FSEL= Blender.Mesh.FaceFlags.SELECT
134
135         VSEL= [False] * (len(me.verts))
136         
137         # Get the selected faces and apply the selection to the verts.
138         for f in me.faces:
139                 if f.flag & FSEL:
140                         for v in f.v:
141                                 VSEL[v.index]= True
142         groupNames, vWeightDict= BPyMesh.meshWeight2Dict(me)
143         
144         
145         
146         def grad_weight_from_co(v):
147                 '''
148                 Takes a vert and retuens its gradient radio between A and B
149                 '''
150                 
151                 if not VSEL[v.index]: # Not bart of a selected face?
152                         return None, None
153                 
154                 v_co= v.co
155                 # make a line 90d to the 2 lines the user clicked.
156                 vert_line= (v_co - cross_grad, v_co + cross_grad)
157                 
158                 xA= LineIntersect(vert_line[0], vert_line[1], lineA[0], lineA[1])
159                 xB= LineIntersect(vert_line[0], vert_line[1], lineB[0], lineB[1])
160                 
161                 if not xA or not xB: # Should never happen but support it anyhow
162                         return None, None
163                 
164                 wA= (xA[0]-xA[1]).length
165                 wB= (xB[0]-xB[1]).length
166                 
167                 wTot= wA+wB
168                 if not wTot: # lines are on the same point.
169                         return None, None
170                 
171                 '''
172                 Get the length of the line between both intersections on the 
173                 2x view lines.
174                 if the dist between  lineA+VertLine and lineB+VertLine is 
175                 greater then the lenth between lineA and lineB intersection points, it means
176                 that the verts are not inbetween the 2 lines.
177                 '''
178                 lineAB_length= (xA[1]-xB[1]).length
179                 
180                 # normalzie
181                 wA= wA/wTot
182                 wB= wB/wTot
183                 
184                 if ORTHO: # Con only use line length method with parelelle lines
185                         if wTot > lineAB_length+eps:
186                                 # vert is outside the range on 1 side. see what side of the grad
187                                 if wA>wB:               wA, wB= 1.0, 0.0
188                                 else:                   wA, wB= 0.0, 1.0
189                 else:
190                         # PERSP, lineA[0] is the same origin as lineB[0]
191                         
192                         # Either xA[0] or xB[0]  can be used instead of a possible x_mid between the 2
193                         # as long as the point is inbetween lineA and lineB it dosent matter.
194                         a= AngleBetweenVecs(lineA[0]-xA[0], line_mid)
195                         if a>line_angle:
196                                 # vert is outside the range on 1 side. see what side of the grad
197                                 if wA>wB:               wA, wB= 1.0, 0.0
198                                 else:                   wA, wB= 0.0, 1.0
199                 
200                 return wA, wB
201                 
202         
203         grad_weights= [grad_weight_from_co(v) for v in me.verts]
204         
205         
206         if MODE==0:
207                 for v in me.verts:
208                         i= v.index
209                         if VSEL[i]:
210                                 wA, wB = grad_weights[i]
211                                 if wA != None: # and wB 
212                                         if TOALPHA:
213                                                 # Do alpha by using the exiting weight for 
214                                                 try:            pickValB= vWeightDict[i][act_group]
215                                                 except: pickValB= 0.0 # The weights not there? assume zero
216                                         # Mix2 2 opaque weights
217                                         vWeightDict[i][act_group]= pickValB*wA + pickValA*wB
218         
219         else: # MODE==1 VCol
220                 for f in me.faces:
221                         if f.flag & FSEL:
222                                 f_v= f.v
223                                 for i in xrange(len(f_v)):
224                                         v= f_v[i]
225                                         wA, wB = grad_weights[v.index]
226                                         
227                                         c= f.col[i]
228                                         
229                                         if TOALPHA:
230                                                 pickValB= c.r, c.g, c.b
231                                         
232                                         c.r = int(pickValB[0]*wA + pickValA[0]*wB)
233                                         c.g = int(pickValB[1]*wA + pickValA[1]*wB)
234                                         c.b = int(pickValB[2]*wA + pickValA[2]*wB)
235                                         
236         
237         
238         
239         # Copy weights back to the mesh.
240         BPyMesh.dict2MeshWeight(me, groupNames, vWeightDict)
241         Window.DrawProgressBar (1.0, '')
242
243