d93ef474703f005cc26aafb28bcba404ca7013eb
[blender.git] / release / scripts / unweld044.py
1 #!BPY
2 """ Registration info for Blender menus: <- these words are ignored
3 Name: 'UnWeld'
4 Blender: 232
5 Group: 'Mesh'
6 Tip: 'Unweld all faces from a selected and common vertex. Made vertex bevelling.'
7 """
8
9 # $Id$
10 #
11 # ------------------------------------------
12 # Un-Weld script 0.4.4 beta
13 #
14 # split all faces from one selected vertex
15 # (c) 2004 J-M Soler released under Blender Artistic License
16 #----------------------------------------------
17 # Official Page :
18 # http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_faces2vertex.htm#exemple 
19 # Communicate problems and errors on:
20 # http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender 
21 #----------------------------------------------
22 # Blender Artistic License
23 # http://download.blender.org/documentation/html/x21254.html
24 #---------------------------------------------
25 # Changelog
26 #----------------------------------------------
27 # 25/05 :
28 # -- separate choise, normal (same place) or spread at random, middle of the face
29 # -- works on several vertices too
30 # -- Quite vertex bevelling on <<lone>> vertex : create hole in faces around this
31 # vertex
32 # 03/06 :
33 # -- a sort of "bevelled vertex" extrusion controled by horizontal mouse
34 # displacement. just a beta test to the mouse control.
35 #----------------------------------------------
36 # Page officielle :
37 #   http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_faces2vertex.htm#exemple
38 # Communiquer les problemes et erreurs sur:
39 #   http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
40 # Blender Artistic License
41 #    http://download.blender.org/documentation/html/x21254.html
42 #--------------------------------------------- 
43 # Changelog
44 #----------------------------------------------
45 #      25/05 :
46 #           -- separation du choix, normal ou dispersion hasardeuse, milieu de face
47 #           -- sommets multiples / 
48 #           -- Quite vertex bevelling on lone vertex : create hole in faces around the
49 #              vertex 
50 #     03/06 :
51 #           -- a sort of "bevelled vertex" extrusion controled by horizontal mouse
52 #              displacement
53 #----------------------------------------------
54
55 import Blender
56 from Blender import Noise
57 from Blender.Draw import *
58 from Blender.BGL import *
59
60 Nr=Noise.random
61 decal=0.03
62 t=[0.0,0.0,0.0]
63 pl=[]
64 orig=[]
65
66 DEBUG = 0
67 SUBSURF=0
68 DIM=Create(1.0)
69
70 def  Tampon(v,t):
71       for n in range(len(v)): t[n]=t[n]+v[n]
72       return t
73    
74 def  freeTampon(t):
75       for n in range(3): t[n]=0.0
76       return t
77
78 def  TamponMoyen(t,f):      
79       for n in range(3): t[n]/=len(f)
80       return t
81
82 def  appliqueMoyenne(v,t):
83       for n in range(len(v)): v[n]=t[n]
84       return v
85
86 def docF(f0,f):
87       try:
88           f0.mat=f.mat
89           f0.uv=f.uv 
90           f0.col=f.col
91           f0.image=f.image
92           return f0
93       except:
94           pass    
95
96 def listConnecterFace(me,lebon):
97                listf2v={}
98                #tri des faces connectees aux sommets selectionnes                           
99                for f in me.faces:
100                  for v in f.v:
101                    if v==lebon:
102                       if v.index not in listf2v.keys():
103                           listf2v[me.verts.index(v)]=[f]
104                       elif f not in listf2v[me.verts.index(v)]:
105                          listf2v[me.verts.index(v)].append(f)
106                return listf2v
107
108 def creerFaceSupplementaire(me,lebon,listf2v):
109                global t
110                for f in listf2v[lebon.index]:
111                   f0=Blender.NMesh.Face()
112                   if result==3: t=freeTampon(t)
113                   for v in f.v:
114                      if result==3: t=Tampon(v,t)
115                      if v!=lebon:
116                         f0.append(v)
117                      else:
118                         if result==2:                           
119                            nv=Blender.NMesh.Vert(lebon.co[0]+Nr()*decal,lebon.co[1]+Nr()*decal,lebon.co[2]+Nr()*decal)
120                         else:
121                            nv=Blender.NMesh.Vert(lebon.co[0],lebon.co[1],lebon.co[2])
122                         me.verts.append(nv)
123                         f0.append(me.verts[me.verts.index(nv)])
124                         localise=me.verts.index(nv)                          
125                      docF(f0,f)   
126                      
127                   if result==3:
128                          t=TamponMoyen(t,f0.v)
129                          me.verts[localise]=appliqueMoyenne(me.verts[localise],t)
130                   me.faces.append(f0)                  
131                del me.verts[me.verts.index(lebon)]
132                for f in listf2v[lebon.index]:
133                   del me.faces[me.faces.index(f)]
134                return me
135
136 def collecte_edge(listf2v,me,lebon):
137       back=0
138       edgelist = []
139       vertlist = []
140       if DEBUG : print listf2v    
141       for face in listf2v[lebon.index]:
142           if len(face.v) == 4:
143               vlist = [0,1,2,3,0]
144           elif len(face.v) == 3:
145               vlist = [0,1,2,0]
146           else:
147               vlist = [0,1]
148           for i in range(len(vlist)-1):              
149               vert0 = min(face.v[vlist[i]].index,face.v[vlist[i+1]].index)
150               vert1 = max(face.v[vlist[i]].index,face.v[vlist[i+1]].index)              
151               edgeinlist = 0
152               if vert0==lebon.index or vert1==lebon.index:                 
153                  for edge in edgelist:
154                     if ((edge[0]==vert0) and (edge[1]==vert1)):
155                         edgeinlist = 1
156                         edge[2] = edge[2]+1
157                         edge.append(me.faces.index(face))
158                         break                  
159                  if edgeinlist==0:
160                     edge = [vert0,vert1,1,me.faces.index(face)]
161                     edgelist.append(edge)
162                     
163       for  edge in edgelist:
164         #print edge
165         if len(edge)==4:
166                    del edgelist[edgelist.index(edge)]
167                            
168       edges=len(edgelist)
169       if DEBUG : print 'number of edges : ',edges," Edge list : " ,edgelist    
170       return edges, edgelist     
171
172 MouseClickG= Blender.Draw.LEFTMOUSE
173 MouseClickD= Blender.Draw.RIGHTMOUSE
174 MouseClickM= Blender.Draw.MIDDLEMOUSE
175
176 mouse_x=1
177 mouse_y=1
178
179 x=1
180 y=1
181
182 debut=0
183
184 def D():
185   size=Buffer(GL_FLOAT, 4)
186   glGetFloatv(GL_SCISSOR_BOX, size)
187   size= size.list 
188   glColor3f(0.1, 0.1, 0.15)
189   glRasterPos2f(10, size[3]-16)
190   Text("Quit = Qkey")
191   glRasterPos2f(10, size[3]-36)
192   Text("Mouse to the Rigth = Increase")
193   glRasterPos2f(10, size[3]-56)
194   Text("Mouse to the Left = Decrease")
195
196 def E(evt,val):
197  global mouse_x,x,pl,orig,me,debut
198  global mouse_y,y, MouseClickG,MouseClickD,MouseClickM
199  if (evt== QKEY): Exit()
200  
201  if (evt == MOUSEX): 
202        mouse_x = val
203        pos=x-mouse_x
204        x=mouse_x
205        if pos==0:
206           pos=1
207        deplace(pl,orig,abs(pos)/pos)
208  
209  if (evt == MOUSEY): mouse_y = val
210
211 def BE(evt):
212  pass
213
214
215 def deplace(pl,orig,n):
216     global me, OBJECT
217     for p in pl:
218        #print p, orig,len(me.verts) 
219        me.verts[p].co[0]+=n*orig[0]
220        me.verts[p].co[1]+=n*orig[1]
221        me.verts[p].co[2]+=n*orig[2]
222     me.update()
223     Blender.Redraw()
224
225
226 def VertexBevel(result):
227               global t,pl, orig,me,  SUBSURF
228               unique=0
229               for v in me.verts:
230                   if v.sel==1:
231                      lebon=v   
232                      unique+=1
233
234               if  unique==1:
235                     edges=0
236                     edgelist=[]
237                     vertlist=[]
238                     orig=lebon.no[:]
239                     listf2v=listConnecterFace(me,lebon)
240                     edges, edgelist = collecte_edge(listf2v,me,lebon)
241                     for f in listf2v[lebon.index]:
242                        f0=Blender.NMesh.Face()
243                        for v in f.v:
244                           if v!=lebon:
245                              f0.append(v)
246                           else:
247                               nv=Blender.NMesh.Vert(lebon.co[0],lebon.co[1],lebon.co[2])                           
248                               nv.sel=1 
249                               me.verts.append(nv)
250                               f0.append(me.verts[me.verts.index(nv)])
251                               for e in edgelist:
252                                  if e[-1]==me.faces.index(f) or e[-2]==me.faces.index(f):
253                                      if me.verts.index(nv) not in e:
254                                         e.insert(0,me.verts.index(nv))
255                        docF(f0,f)               
256                        me.faces.append(f0)                       
257                        vertlist.append([me.verts.index(nv),me.faces.index(f)])
258                     for e in  edgelist :
259                         del e[e.index(lebon.index)]
260                         f0=Blender.NMesh.Face()
261                         for n in range(3): 
262                            f0.v.append(me.verts[e[n]])
263                         me.faces.append(f0);
264                      
265                     for ve in vertlist:
266                          t=freeTampon(t)
267                          for v in me.faces[ve[1]].v:
268                               t=Tampon(v,t)                     
269                          t=TamponMoyen(t,me.faces[ve[1]].v)
270                          ve.append(t[:])        
271                          me.verts[ve[0]]=appliqueMoyenne(me.verts[ve[0]],t)
272
273                     def swap(x,y):
274                         return y,x
275
276                     p=[[edgelist[0][0],edgelist[0][1]]] 
277                     while len(p)!=len(edgelist): 
278                       for n in range(1,len(edgelist)) :
279                            if p[-1][1]== edgelist[n][0]:
280                               p.append([edgelist[n][0],edgelist[n][1]])
281                               n+=1
282                            elif p[-1][1]== edgelist[n][1]:
283                               edgelist[n][0],edgelist[n][1]=swap(edgelist[n][0],edgelist[n][1])
284                               p.append([edgelist[n][0],edgelist[n][1]])
285                               n+=1
286                     if len(p)%2==0:
287                           P0=p[:(len(p))/2] ; P1=p[len(p)/2:]; P1.reverse()
288                           for s in range(len(P0)-1):
289                              f0=Blender.NMesh.Face()
290                              table=[P0[s][0],P0[s][1],P1[s+1][0],P1[s+1][1]]
291                              for t in table:f0.v.append(me.verts[t])
292                              me.faces.append(f0) 
293                     elif len(p) >3 :   
294                           P0=p[:(len(p)-1)/2];P1=p[(len(p)-1)/2:-1]; P1.reverse()
295                           for s in range(len(P0)-1):
296                              f0=Blender.NMesh.Face()
297                              table=[P0[s][0],P0[s][1],P1[s+1][0],P1[s+1][1]]
298                              for t in table:f0.v.append(me.verts[t])
299                              me.faces.append(f0) 
300                           f0=Blender.NMesh.Face()
301                           table=[p[-1][0],P0[0][0],P1[-1][1]]
302                           for t in table:f0.v.append(me.verts[t])
303                           me.faces.append(f0) 
304
305                     elif len(p) ==3 :   
306                           if DEBUG :print P0,P1      
307                           f0=Blender.NMesh.Face()
308                           table=[p[0][0],p[0][1],p[1][1]]
309                           for t in table:f0.v.append(me.verts[t])
310                           me.faces.append(f0) 
311
312                     for f in listf2v[lebon.index]:
313                        del me.faces[me.faces.index(f)]  
314                     del me.verts[me.verts.index(lebon)]
315                     me.update()
316
317                     if me.mode&Blender.NMesh.Modes['SUBSURF']:
318                        me.mode-=Blender.NMesh.Modes['SUBSURF']
319                        SUBSURF=1 
320                        me.update()
321                        OBJECT[0].makeDisplayList() 
322
323                     if result==5:
324                        pl=[]
325                        for s in me.verts:
326                            if s.sel==1:
327                               pl.append(s.index)
328                        Blender.Draw.Register(D,E,BE)
329
330                     """
331                     if SUBSURF==1 :
332                        me.mode+=Blender.NMesh.Modes['SUBSURF']
333                        me.update()
334                        OBJECT[0].makeDisplayList() 
335                     """  
336               else:
337                   name = " It could leave only one selected vertex %t | ok %x1 ?"
338                   result = Blender.Draw.PupMenu(name)
339
340 OBJECT=Blender.Object.GetSelected()
341
342 if len(OBJECT)!=0:
343    if  OBJECT[0].getType()=='Mesh':
344        name = "Un-Weld, OK ? %t| unbind points %x1| with noise ? %x2| middle face ? %x3| static bevel vertex ? %x4| moving bevel vertex ? %x5|"
345        result = Blender.Draw.PupMenu(name)
346        if result:
347            me=OBJECT[0].getData()
348            unique=0
349            if result<4:
350               #tri des sommets selectionnes
351               for v in me.verts:
352                   if v.sel==1:
353                     lebon=v    
354                     if DEBUG : print lebon
355                     #dictionnaires des faces connectees aux sommets selectionnes
356                     listf2v=listConnecterFace(me,lebon)
357                     me=creerFaceSupplementaire(me,lebon,listf2v)
358                     OBJECT[0].link(me)
359                     OBJECT[0].makeDisplayList()
360            else:
361                VertexBevel(result)
362                OBJECT[0].makeDisplayList()
363                     
364    else:
365        name = "Nothing to do! Are you sure ?"
366        result = Blender.Draw.PupMenu(name)
367
368