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