Scripts:
[blender.git] / release / scripts / mod_ai2obj.py
1 """
2 #----------------------------------------------
3 # (c) jm soler juillet 2004, released under Blender Artistic Licence 
4 #    for the Blender 2.34 Python Scripts Bundle.
5 #----------------------------------------------
6 # Page officielle :
7 #   http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_ai.htm
8 # Communiquer les problemes et erreurs sur:
9 #   http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender
10 #
11 # 0.1.1 : 2004/08/03, bug in boudingbox reading when Value are negative
12 #
13 """
14 SHARP_IMPORT=0
15 SCALE=1
16 DEVELOPPEMENT=0
17
18 import sys
19 #oldpath=sys.path
20 import Blender
21 BLversion=Blender.Get('version')
22
23 try:
24     import nt
25     os=nt
26     os.sep='\\'
27
28 except:    
29     import posix
30     os=posix
31     os.sep='/'
32     
33 def isdir(path):
34     try:
35         st = os.stat(path)
36         return 1 
37     except:
38         return 0
39     
40 def split(pathname):
41          if pathname.find(os.sep)!=-1:
42              k0=pathname.split(os.sep)
43          else:
44             if os.sep=='/':
45                 k0=pathname.split('\\')
46             else:
47                 k0=pathname.split('/') 
48
49          directory=pathname.replace(k0[len(k0)-1],'')
50          Name=k0[len(k0)-1]
51          return directory, Name
52         
53 def join(l0,l1):        
54      return  l0+os.sep+l1
55     
56 os.isdir=isdir
57 os.split=split
58 os.join=join
59
60 def filtreFICHIER(nom):
61      f=open(nom,'rU')
62      t=f.readlines()
63      f.close()
64      
65      if len(t)>1: 
66           return t   
67      else:
68          name = "OK?%t| Not a valid file or an empty file ... "  # if no %xN int is set, indices start from 1
69          result = Draw.PupMenu(name)
70           
71          return 'false'
72         
73 #===============================
74 # Data
75 #===============================
76 #===============================
77 # Blender Curve Data
78 #===============================
79 objBEZIER=0
80 objSURFACE=5
81 typBEZIER3D=1  #3D
82 typBEZIER2D=9  #2D
83
84 class Bez:
85       def __init__(self):
86            self.co=[]
87            self.ha=[0,0]
88            
89 class ITEM:
90       def __init__(self):
91                self.type        =  typBEZIER3D,         
92                self.pntsUV      =  [0,0]              
93                self.resolUV     =  [32,0]             
94                self.orderUV     =  [0,0]              
95                self.flagUV      =  [0,0]              
96                self.Origine     =  [0.0,0.0]
97                self.beziers_knot = []
98
99 class COURBE:
100       def __init__(self):
101               self.magic_number='3DG3'              
102               self.type            =  objBEZIER     
103               self.number_of_items =  0             
104               self.ext1_ext2       =  [0,0]         
105               self.matrix          =  """0.0 0.0 1.0 0.0
106 0.0 1.0 0.0 0.0
107 0.0 0.0 1.0 0.0
108 0.0 0.0 0.0 1.0 """ 
109               self.ITEM            = {}
110
111 courbes=COURBE()
112
113 PATTERN={}
114
115 BOUNDINGBOX={'rec':[],'coef':1.0}
116 npat=0
117 #=====================================================================
118 #======== name of the curve in teh courbes dictionnary ===============
119 #=====================================================================
120 n0=0
121
122 #=====================================================================
123 #====================== current Point ================================
124 #=====================================================================
125 CP=[0.0,0.0] #currentPoint
126
127 #=====================================================================
128 #===== to compare last position to the original move to displacement =
129 #=====  needed for cyclic efinition  =================================
130 #=====================================================================
131 def test_egalitedespositions(f1,f2):
132     if f1[0]==f2[0] and f1[1]==f2[1]:
133        return Blender.TRUE
134     else:
135        return Blender.FALSE
136
137
138 def Open_GEOfile(dir,nom):
139     if BLversion>=233:
140        in_editmode = Blender.Window.EditMode()
141        if in_editmode: Blender.Window.EditMode(0)
142        Blender.Load(dir+nom+'OOO.obj', 1)
143        BO=Blender.Object.Get()
144        BO[-1].RotY=0.0
145        BO[-1].makeDisplayList() 
146        Blender.Window.RedrawAll()
147     else:
148        print "Not yet implemented"
149
150 def create_GEOtext(courbes):
151     global SCALE, B, BOUNDINGBOX
152     r=BOUNDINGBOX['rec']
153
154     if SCALE==1:
155        SCALE=1.0
156     elif SCALE==2:
157        SCALE=r[2]-r[0]
158     elif SCALE==3:
159        SCALE=r[3]-r[1]
160  
161     t=[]
162     t.append(courbes.magic_number+'\n')
163     t.append(str(courbes.type)+'\n')
164     t.append(str(courbes.number_of_items)+'\n')
165     t.append(str(courbes.ext1_ext2[0])+' '+str(courbes.ext1_ext2[1])+'\n')
166     t.append(courbes.matrix+'\n')
167     
168     for k in courbes.ITEM.keys():
169         t.append("%s\n"%courbes.ITEM[k].type)
170         t.append("%s %s \n"%(courbes.ITEM[k].pntsUV[0],courbes.ITEM[k].pntsUV[1]))
171         t.append("%s %s \n"%(courbes.ITEM[k].resolUV[0],courbes.ITEM[k].resolUV[1]))
172         t.append("%s %s \n"%(courbes.ITEM[k].orderUV[0],courbes.ITEM[k].orderUV[1]))
173         t.append("%s %s \n"%(courbes.ITEM[k].flagUV[0],courbes.ITEM[k].flagUV[1]))
174
175         flag =courbes.ITEM[k].flagUV[0]
176
177         for k2 in range(flag,len(courbes.ITEM[k].beziers_knot)):
178            k1 =courbes.ITEM[k].beziers_knot[k2]
179            t.append("%4f 0.0 %4f \n"%(float(k1.co[0])/SCALE,float(k1.co[1])/SCALE))
180            t.append("%4f 0.0 %4f \n"%(float(k1.co[2])/SCALE,float(k1.co[3])/SCALE))
181            t.append("%4f 0.0 %4f \n"%(float(k1.co[4])/SCALE,float(k1.co[5])/SCALE))
182            t.append(str(k1.ha[0])+' '+str(k1.ha[1])+'\n')
183     return t
184
185 def save_GEOfile(dir,nom,t):
186      f=open(dir+nom+'OOO.obj','w')
187      f.writelines(t)
188      f.close()
189      #warning = "REMINDER : %t | Do not forget to rename your blender file NOW ! %x1"
190      #result = Blender.Draw.PupMenu(warning)
191
192
193 #=====================================================================
194 #=====      AI format   :  DEBUT             =========================
195 #=====================================================================
196 def mouvement_vers(l,n0,CP):
197     if n0 in courbes.ITEM.keys():
198        #if  test_egalitedespositions(courbes.ITEM[n0].Origine,CP):
199        #   courbes.ITEM[n0].flagUV[0]=1 
200        n0+=1
201     else:
202        CP=[l[-3].replace('d',''),l[-2]] 
203     #i=
204     courbes.ITEM[n0]=ITEM() 
205     courbes.ITEM[n0].Origine=[l[-3].replace('d',''),l[-2]] 
206     
207     B=Bez()
208     B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]]
209     B.ha=[0,0]    
210     courbes.ITEM[n0].beziers_knot.append(B)       
211
212     return  courbes,n0,CP     
213        
214 def courbe_vers_c(l,l2, n0,CP): #c,C
215
216     B=Bez()
217     B.co=[l[2],l[3],l[4],l[5],l[0],l[1]]
218
219     if len(courbes.ITEM[n0].beziers_knot)==1:
220        CP=[l[0],l[1]]
221        courbes.ITEM[n0].Origine=[l[0],l[1]]
222
223     if l[-1]=='C':  
224         B.ha=[2,2]
225     else:
226         B.ha=[0,0]
227
228     courbes.ITEM[n0].beziers_knot.append(B)
229     if len(l2)>1 and l2[-1] in Actions.keys():
230        B.co[-2]=l2[0]
231        B.co[-1]=l2[1]
232     else:
233        #B.co[-2]=courbes.ITEM[n0].beziers_knot[-1].co[0]
234        #B.co[-1]=courbes.ITEM[n0].beziers_knot[-].co[1]            
235
236        B.co[-2]=CP[0]
237        B.co[-1]=CP[1]
238     return  courbes,n0,CP
239      
240      
241 def courbe_vers_v(l,n0,CP): #v-V
242     B=Bez()
243     B.co=[l[2],l[3],l[0],l[1],l[2],l[3]]
244     if l[-1]=='V':  
245         B.ha=[2,2]
246     else:
247         B.ha=[0,0]
248     courbes.ITEM[n0].beziers_knot.append(B)    
249     CP=[l[0],l[1]]    
250     return  courbes,n0,CP
251          
252 def courbe_vers_y(l,n0,CP): #y
253     B=Bez()
254     B.co=[l[2],l[3],l[0],l[1],l[2],l[3]]
255     if l[-1]=='Y':  
256         B.ha=[2,2]
257     else:
258         B.ha=[0,0]
259     courbes.ITEM[n0].beziers_knot.append(B)    
260     CP=[l[2],l[3]]        
261     return  courbes,n0,CP
262      
263       
264 def ligne_tracee_l(l,n0,CP):
265     B=Bez()
266     B.co=[l[0],l[1],l[0],l[1],l[0],l[1]]
267     if l[-1]=='L':  
268         B.ha=[2,2]
269     else:
270         B.ha=[0,0]
271     courbes.ITEM[n0].beziers_knot.append(B)    
272     CP=[l[0],l[1]]
273     return  courbes,n0,CP    
274      
275 Actions=   {     "C" : courbe_vers_c,
276                  "c" : courbe_vers_c,
277                  "V" : courbe_vers_v,
278                  "v" : courbe_vers_v,
279                  "Y" : courbe_vers_y,
280                  "y" : courbe_vers_y,
281                  "m" : mouvement_vers,
282                  "l" : ligne_tracee_l,
283                  "L" : ligne_tracee_l}
284      
285 TAGcourbe=Actions.keys()
286                  
287 def pik_pattern(t,l):
288     global npat, PATTERN, BOUNDINGBOX
289     while t[l].find('%%EndSetup')!=0:   
290           if t[l].find('%%BoundingBox:')!=-1:
291              t[l]=t[l][t[l].find(':')+1:]    
292              l0=t[l].split()
293              BOUNDINGBOX['rec']=[float(l0[-4]),float(l0[-3]),float(l0[-2]),float(l0[-1])]
294              r=BOUNDINGBOX['rec']
295              BOUNDINGBOX['coef']=(r[3]-r[1])/(r[2]-r[0])
296           #print l,
297           if  t[l].find('BeginPattern')!=-1:
298               nomPattern=t[l][t[l].find('(')+1:t[l].find(')')]
299               PATTERN[nomPattern]={}
300
301           if  t[l].find('BeginPatternLayer')!=-1:
302                npat+=1
303                PATTERN[nomPattern][npat]=[]
304                while t[l].find('EndPatternLayer')==-1:
305                      #print t[l] 
306                      PATTERN[nomPattern][npat].append(l) 
307                      l+=1   
308           if l+1<len(t):
309              l=l+1
310           else:
311              return 1,l
312     return 1,l
313              
314 def scan_FILE(nom):
315   global CP, courbes, SCALE
316   dir,name=split(nom)
317   name=name.split('.')
318   n0=0
319   result=0
320   t=filtreFICHIER(nom)
321   
322   if nom.upper().find('.AI')!=-1 and t!='false':
323       if not SHARP_IMPORT:
324             warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3" 
325             SCALE = Blender.Draw.PupMenu(warning)
326          
327       npat=0
328       l=0
329       do=0
330       while l <len(t)-1 :
331            if not do:
332               do,l=pik_pattern(t,l)
333            #print 'len(t)',len(t)        
334            t[l].replace('\n','') 
335            if t[l][0]!='%':
336                 l0=t[l].split()
337                 if l0[-1] in TAGcourbe:
338                     if l0[-1] in ['C','c']:
339                        l2=t[l+1].split()
340                        courbes,n0,CP=Actions[l0[-1]](l0,l2,n0,CP)
341                     else: 
342                        courbes,n0,CP=Actions[l0[-1]](l0,n0,CP)
343            l=l+1; #print l                    
344       t=[]
345       courbes.number_of_items=len(courbes.ITEM.keys())
346       for k in courbes.ITEM.keys():
347          courbes.ITEM[k].pntsUV[0] =len(courbes.ITEM[k].beziers_knot)
348
349          if  test_egalitedespositions(courbes.ITEM[k].Origine,
350                                       [courbes.ITEM[k].beziers_knot[-1].co[-2],
351                                        courbes.ITEM[k].beziers_knot[-1].co[-1]]):
352               courbes.ITEM[k].flagUV[0]=1 
353               courbes.ITEM[k].pntsUV[0] -=1
354
355       if courbes.number_of_items>0:
356          if len(PATTERN.keys() )>0:
357             #print len(PATTERN.keys() )
358             warning = "Pattern list (for info not used): %t| "
359             p0=1
360             for P in PATTERN.keys():
361                 warning+="%s %%x%s|"%(P,p0)
362                 p0+=1 
363             Padd = Blender.Draw.PupMenu(warning)
364             
365          t=create_GEOtext(courbes)
366          save_GEOfile(dir,name[0],t)
367          Open_GEOfile(dir,name[0])
368       else:
369           pass
370 #=====================================================================
371 #====================== AI format mouvements =========================
372 #=====================================================================
373 #=========================================================          
374 # une sorte de contournement qui permet d'utiliser la fonction
375 # et de documenter les variables Window.FileSelector
376 #=========================================================
377 def fonctionSELECT(nom):
378     scan_FILE(nom)
379
380 if DEVELOPPEMENT==1:
381     Blender.Window.FileSelector (fonctionSELECT, 'SELECT AI FILE')
382 #sys.path=oldpath